diff options
Diffstat (limited to 'lib/megaco/test')
58 files changed, 149096 insertions, 0 deletions
diff --git a/lib/megaco/test/Makefile b/lib/megaco/test/Makefile new file mode 100644 index 0000000000..a6f50f87c4 --- /dev/null +++ b/lib/megaco/test/Makefile @@ -0,0 +1,611 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1999-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% + +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../vsn.mk +VSN=$(MEGACO_VSN) + + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/megaco_test + +ifeq ($(findstring win32,$(TARGET)),win32) + +MAKEFILE_SRC = Makefile.win32.src + +else + +MAKEFILE_SRC = Makefile.src + +endif + +ifeq ($(TT_DIR),) +TT_DIR = /tmp +endif + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +include modules.mk + +HRL_FILES = megaco_test_lib.hrl + +ERL_FILES = $(MODULES:%=%.erl) + +TARGET_FILES = $(MODULES:%=%.$(EMULATOR)) + +COVER_SPEC_FILE = megaco.cover + +APP_CASES = app appup + +CODEC_CASES = codec1 codec2 codec3a codec3b codec3c + +MISC_CASES = tid sdp dm conf udp tcp ex timer flex + +OP_CASES = mess mib mreq pending trans actions load + +ALL_CASES = $(APP_CASES) $(CODEC_CASES) $(MISC_CASES) $(OP_CASES) + + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- + +include ../src/app/megaco.mk + +ifeq ($(USE_MEGACO_TEST_CODE),true) +ERL_COMPILE_FLAGS += -DMEGACO_TEST_CODE=mona_lisa_spelar_doom +endif + +ifeq ($(USE_MEGACO_HIPE),true) +ERL_COMPILE_FLAGS += +native -Dmegaco_hipe_special=true +endif + +ERL_COMPILE_FLAGS += \ + $(MEGACO_ERL_COMPILE_FLAGS) \ + -pa $(ERL_TOP)/lib/test_server/ebin \ + -I$(ERL_TOP)/lib/test_server/include + +ERL_PATH = -pa ../../megaco/examples/simple \ + -pa ../../megaco/ebin \ + -pa ../../et/ebin + +ifndef SUITE +SUITE = megaco_SUITE +endif + +ESTOP = -s init stop + +ifeq ($(DONT_STOP),true) +MAYBE_ESTOP = +else +MAYBE_ESTOP = $(ESTOP) +endif + +ETVIEW = -s et_viewer +ifeq ($(USE_ET_VIEWER),true) +MAYBE_ETVIEW = +else +MAYBE_ETVIEW = $(ETVIEW) +endif + +ifeq ($(MERL),) +MERL = erl +endif + +ARGS += -noshell + +ifeq ($(DISABLE_TC_TIMEOUT),true) +ARGS += -megaco_test_timeout +endif + + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +tests debug opt: $(TARGET_FILES) + +clean: + rm -f $(TARGET_FILES) + rm -f errs core *~ + +docs: + +info: + @echo "ERL_COMPILE_FLAGS = $(ERL_COMPILE_FLAGS)" + @echo "ERL = $(ERL)" + @echo "MERL = $(MERL)" + @echo "" + + +# ---------------------------------------------------- +# Special Targets +# ---------------------------------------------------- + +aall: make + @echo "make sure epmd is new" + @epmd -kill > /dev/null + @echo "Running all app sub-suites separatelly" + @for i in $(APP_CASES); do \ + echo "SUITE: $$i"; \ + clearmake -V $$i > $$i.log; \ + done + echo "done" + +call: make + @echo "make sure epmd is new" + @epmd -kill > /dev/null + @echo "Running all codec sub-suites separatelly" + @for i in $(CODEC_CASES); do \ + echo "SUITE: $$i"; \ + clearmake -V $$i > $$i.log; \ + done + +mall: make + @echo "make sure epmd is new" + @epmd -kill > /dev/null + @echo "Running all misc sub-suites separatelly" + @for i in $(MISC_CASES); do \ + echo "SUITE: $$i"; \ + clearmake -V $$i > $$i.log; \ + done + +oall: make + @echo "make sure epmd is new" + @epmd -kill > /dev/null + @echo "Running all operation sub-suites separatelly" + @for i in $(OP_CASES); do \ + echo "SUITE: $$i"; \ + clearmake -V $$i > $$i.log; \ + done + +all: make + @echo "make sure epmd is new" + @epmd -kill > /dev/null + @echo "Running all sub-suites separatelly" + @for i in $(ALL_CASES); do \ + echo "SUITE: $$i"; \ + clearmake -V $$i > $$i.log; \ + done + +make: targets + +targets: $(TARGET_FILES) + +test: make + $(MERL) $(ARGS) -sname megaco_test $(ERL_PATH) \ + -s megaco_test_lib t $(SUITE) \ + $(MAYBE_ESTOP) + +utest: make + $(MERL) $(ARGS) -sname megaco_utest $(ERL_PATH) \ + $(MAYBE_ETVIEW) \ + -s megaco_test_lib t $(SUITE) \ + $(ESTOP) + +ftest: make + $(MERL) $(ARGS) -sname megaco_ftest $(ERL_PATH) \ + -s megaco_filter \ + -s megaco_test_lib t $(SUITE) \ + $(ESTOP) + +decode_compact_prof1: make + $(MERL) $(ARGS) -sname megaco_profile_decode_compact $(ERL_PATH) \ + -s megaco_codec_v1_test profile_decode_compact_text_messages \ + $(ESTOP) + +decode_compact_flex_prof1: make + $(MERL) $(ARGS) -sname megaco_profile_decode_compact_flex $(ERL_PATH) \ + -s megaco_codec_v1_test profile_decode_compact_flex_text_messages \ + $(ESTOP) + +decode_compact_prof2: make + $(MERL) $(ARGS) -sname megaco_profile_decode_compact $(ERL_PATH) \ + -s megaco_codec_v2_test profile_decode_compact_text_messages \ + $(ESTOP) + +decode_compact_flex_prof2: make + $(MERL) $(ARGS) -sname megaco_profile_decode_compact_flex $(ERL_PATH) \ + -s megaco_codec_v2_test profile_decode_compact_flex_text_messages \ + $(ESTOP) + +decode_pretty_prof1: make + $(MERL) $(ARGS) -sname megaco_profile_decode_pretty $(ERL_PATH) \ + -s megaco_codec_v1_test profile_decode_pretty_text_messages \ + $(ESTOP) + +decode_pretty_flex_prof1: make + $(MERL) $(ARGS) -sname megaco_profile_decode_pretty_flex $(ERL_PATH) \ + -s megaco_codec_v1_test profile_decode_pretty_flex_text_messages \ + $(ESTOP) + +decode_pretty_prof2: make + $(MERL) $(ARGS) -sname megaco_profile_decode_pretty $(ERL_PATH) \ + -s megaco_codec_v2_test profile_decode_pretty_text_messages \ + $(ESTOP) + +decode_pretty_flex_prof2: make + $(MERL) $(ARGS) -sname megaco_profile_decode_pretty_flex $(ERL_PATH) \ + -s megaco_codec_v2_test profile_decode_pretty_flex_text_messages \ + $(ESTOP) + +encode_compact_prof1: make + $(MERL) $(ARGS) -sname megaco_profile_encode_compact $(ERL_PATH) \ + -s megaco_codec_v1_test profile_encode_compact_text_messages \ + $(ESTOP) + +encode_compact_prof2: make + $(MERL) $(ARGS) -sname megaco_profile_encode_compact $(ERL_PATH) \ + -s megaco_codec_v2_test profile_encode_compact_text_messages \ + $(ESTOP) + +encode_pretty_prof1: make + $(MERL) $(ARGS) -sname megaco_profile_encode_pretty $(ERL_PATH) \ + -s megaco_codec_v1_test profile_encode_pretty_text_messages \ + $(ESTOP) + +encode_pretty_prof2: make + $(MERL) $(ARGS) -sname megaco_profile_encode_pretty $(ERL_PATH) \ + -s megaco_codec_v2_test profile_encode_pretty_text_messages \ + $(ESTOP) + + +########################## + +tickets: make + $(MERL) $(ARGS) -sname megaco_tickets $(ERL_PATH) \ + -s megaco_test_lib tickets $(SUITE) \ + $(ESTOP) + +app: make + $(MERL) $(ARGS) -sname megaco_app $(ERL_PATH) \ + -s megaco_test_lib t megaco_app_test \ + $(ESTOP) + +appup: make + $(MERL) $(ARGS) -sname megaco_appup $(ERL_PATH) \ + -s megaco_test_lib t megaco_appup_test \ + $(ESTOP) + +conf: make + $(MERL) $(ARGS) -sname megaco_config $(ERL_PATH) \ + -s megaco_test_lib t megaco_config_test \ + $(ESTOP) + + +########################## + +codec: make + $(MERL) $(ARGS) -sname megaco_codec $(ERL_PATH) \ + -s megaco_test_lib t megaco_codec_test \ + $(MAYBE_ESTOP) + +codec1: make + $(MERL) $(ARGS) -sname megaco_codec1 $(ERL_PATH) \ + -s megaco_test_lib t megaco_codec_v1_test \ + $(MAYBE_ESTOP) + +codec1_tickets: make + $(MERL) $(ARGS) -sname megaco_codec1_tickets $(ERL_PATH) \ + -s megaco_codec_v1_test tickets \ + $(ESTOP) + +codec2: make + $(MERL) $(ARGS) -sname megaco_codec2 $(ERL_PATH) \ + -s megaco_test_lib t megaco_codec_v2_test \ + $(MAYBE_ESTOP) + +codec2_tickets: make + $(MERL) $(ARGS) -sname megaco_codec2_tickets $(ERL_PATH) \ + -s megaco_codec_v2_test tickets \ + $(ESTOP) + +codec3a: make + $(MERL) $(ARGS) -sname megaco_codec3a $(ERL_PATH) \ + -s megaco_test_lib t megaco_codec_prev3a_test \ + $(MAYBE_ESTOP) + +codec3a_tickets: make + $(MERL) $(ARGS) -sname megaco_codec3a_tickets $(ERL_PATH) \ + -s megaco_codec_prev3a_test tickets \ + $(ESTOP) + +codec3b: make + $(MERL) $(ARGS) -sname megaco_codec3b $(ERL_PATH) \ + -s megaco_test_lib t megaco_codec_prev3b_test \ + $(MAYBE_ESTOP) + +codec3b_tickets: make + $(MERL) $(ARGS) -sname megaco_codec3b_tickets $(ERL_PATH) \ + -s megaco_codec_prev3b_test tickets \ + $(ESTOP) + +codec3c: make + $(MERL) $(ARGS) -sname megaco_codec3c $(ERL_PATH) \ + -s megaco_test_lib t megaco_codec_prev3c_test \ + $(MAYBE_ESTOP) + +codec3c_tickets: make + $(MERL) $(ARGS) -sname megaco_codec3c_tickets $(ERL_PATH) \ + -s megaco_codec_prev3c_test tickets \ + $(ESTOP) + +codec3: make + $(MERL) $(ARGS) -sname megaco_codec3 $(ERL_PATH) \ + -s megaco_test_lib t megaco_codec_v3_test \ + $(MAYBE_ESTOP) + +codec3_tickets: make + $(MERL) $(ARGS) -sname megaco_codec3_tickets $(ERL_PATH) \ + -s megaco_codec_v3_test tickets \ + $(ESTOP) + +codecm: make + $(MERL) $(ARGS) -sname megaco_codec1 $(ERL_PATH) \ + -s megaco_test_lib t megaco_codec_mini_test \ + $(MAYBE_ESTOP) + + +########################## + +time1: make + $(MERL) $(ARGS) -sname megaco_time1 $(ERL_PATH) \ + -run megaco_codec_v1_test tt $(TT_DIR) \ + $(ESTOP) + +time2: make + $(MERL) $(ARGS) -sname megaco_time2 $(ERL_PATH) \ + -run megaco_codec_v2_test tt $(TT_DIR) \ + $(ESTOP) + +timeo1: make + $(MERL) $(ARGS) -sname megaco_timeo1 $(ERL_PATH) \ + -run megaco_codec_v1_test tt_official $(TT_DIR) \ + $(ESTOP) + +timeo2: make + $(MERL) $(ARGS) -sname megaco_timeo2 $(ERL_PATH) \ + -run megaco_codec_v2_test tt_official $(TT_DIR) \ + $(ESTOP) + +timeo3: make + $(MERL) $(ARGS) -sname megaco_timeo3 $(ERL_PATH) \ + -run megaco_codec_v3_test tt_official $(TT_DIR) \ + $(ESTOP) + +timet1: make + $(MERL) $(ARGS) -sname megaco_timet1 $(ERL_PATH) \ + -run megaco_codec_v1_test tt_texts $(TT_DIR) \ + $(ESTOP) + +timet2: make + $(MERL) $(ARGS) -sname megaco_timet2 $(ERL_PATH) \ + -run megaco_codec_v2_test tt_texts $(TT_DIR) \ + $(ESTOP) + +timet3: make + $(MERL) $(ARGS) -sname megaco_timet3 $(ERL_PATH) \ + -run megaco_codec_v3_test tt_texts $(TT_DIR) \ + $(ESTOP) + +timeb1: make + $(MERL) $(ARGS) -sname megaco_timeb1 $(ERL_PATH) \ + -run megaco_codec_v1_test tt_bins $(TT_DIR) \ + $(ESTOP) + +timeb2: make + $(MERL) $(ARGS) -sname megaco_timeb2 $(ERL_PATH) \ + -run megaco_codec_v2_test tt_bins $(TT_DIR) \ + $(ESTOP) + +timeb3: make + $(MERL) $(ARGS) -sname megaco_timeb3 $(ERL_PATH) \ + -run megaco_codec_v3_test tt_bins $(TT_DIR) \ + $(ESTOP) + + +########################## + +flex: make + $(MERL) $(ARGS) -sname megaco_flex $(ERL_PATH) \ + -s megaco_test_lib t megaco_flex_test \ + $(ESTOP) + +dm: make + $(MERL) $(ARGS) -sname megaco_dm $(ERL_PATH) \ + -s megaco_test_lib t megaco_digit_map_test \ + $(ESTOP) + +tid: make + $(MERL) $(ARGS) -sname megaco_tid $(ERL_PATH) \ + -s megaco_test_lib t megaco_binary_term_id_test \ + $(ESTOP) + +sdp: make + $(MERL) $(ARGS) -sname megaco_sdp $(ERL_PATH) \ + -s megaco_test_lib t megaco_sdp_test \ + $(MAYBE_ESTOP) + +actions: make + $(MERL) $(ARGS) -sname megaco_actions $(ERL_PATH) \ + -s megaco_test_lib t megaco_actions_test \ + $(MAYBE_ESTOP) + +mess: make + $(MERL) $(ARGS) -sname megaco_mess $(ERL_PATH) \ + $(MAYBE_ETVIEW) \ + -s megaco_test_lib t megaco_mess_test \ + $(ESTOP) + +trans: make + $(MERL) $(ARGS) -sname megaco_trans $(ERL_PATH) \ + -s megaco_test_lib t megaco_trans_test \ + $(MAYBE_ESTOP) + +mib: make + $(MERL) $(ARGS) -sname megaco_mib $(ERL_PATH) \ + -s megaco_test_lib t megaco_mib_test \ + $(MAYBE_ESTOP) + +mreq: make + $(MERL) $(ARGS) -sname megaco_mreq $(ERL_PATH) \ + -s megaco_test_lib t megaco_mreq_test \ + $(MAYBE_ESTOP) + +pending: make + $(MERL) $(ARGS) -sname megaco_pending $(ERL_PATH) \ + -s megaco_test_lib t megaco_pending_limit_test \ + $(MAYBE_ESTOP) + +pl: make + $(MERL) $(ARGS) -sname megaco_pl $(ERL_PATH) \ + -s megaco_test_lib t megaco_pending_limit_test \ + $(MAYBE_ESTOP) + +udp: make + $(MERL) $(ARGS) -sname megaco_pl $(ERL_PATH) \ + -s megaco_test_lib t megaco_udp_test \ + $(MAYBE_ESTOP) + +tcp: make + $(MERL) $(ARGS) -sname megaco_pl $(ERL_PATH) \ + -s megaco_test_lib t megaco_tcp_test \ + $(MAYBE_ESTOP) + +load: make + $(MERL) $(ARGS) -sname megaco_load $(ERL_PATH) \ + -s megaco_test_lib t megaco_load_test \ + $(MAYBE_ESTOP) + +ex: make + $(MERL) $(ARGS) -sname megaco_ex $(ERL_PATH) \ + -s megaco_test_lib t megaco_examples_test \ + $(MAYBE_ESTOP) + +segment: make + $(MERL) $(ARGS) -sname megaco_segment $(ERL_PATH) \ + -s megaco_test_lib t megaco_segment_test \ + $(ESTOP) + +timer: make + $(MERL) $(ARGS) -sname megaco_timer $(ERL_PATH) \ + -s megaco_test_lib t megaco_timer_test \ + $(ESTOP) + + +################### + +gnuplot_gif: make + $(MERL) $(ARGS) -sname megaco_gnuplot_gif $(ERL_PATH) \ + -s megaco_call_flow_test gnuplot_gif \ + $(ESTOP) + +display_v1: make + $(MERL) $(ARGS) -sname megaco_display_text_msgs_v1 $(ERL_PATH) \ + -s megaco_codec_v1_test display_text_messages \ + $(ESTOP) + +generate_v1: make + $(MERL) $(ARGS) -sname megaco_generate_text_msgs_v1 $(ERL_PATH) \ + -s megaco_codec_v1_test generate_text_messages \ + $(ESTOP) + +display_v2: make + $(MERL) $(ARGS) -sname megaco_display_text_msgs_v2 $(ERL_PATH) \ + -s megaco_codec_v2_test display_text_messages \ + $(ESTOP) + +generate_v2: make + $(MERL) $(ARGS) -sname megaco_generate_text_msgs_v2 $(ERL_PATH) \ + -s megaco_codec_v2_test generate_text_messages \ + $(ESTOP) + +display_prev3a: make + $(MERL) $(ARGS) -sname megaco_display_text_msgs_prev3a $(ERL_PATH) \ + -s megaco_codec_prev3a_test display_text_messages \ + $(ESTOP) + +display_prev3b: make + $(MERL) $(ARGS) -sname megaco_display_text_msgs_prev3b $(ERL_PATH) \ + -s megaco_codec_prev3b_test display_text_messages \ + $(ESTOP) + +generate_prev3b: make + $(MERL) $(ARGS) -sname megaco_generate_text_msgs_prev3b $(ERL_PATH) \ + -s megaco_codec_prev3b_test generate_text_messages \ + $(ESTOP) + +display_prev3c: make + $(MERL) $(ARGS) -sname megaco_display_text_msgs_prev3c $(ERL_PATH) \ + -s megaco_codec_prev3c_test display_text_messages \ + $(ESTOP) + +generate_prev3c: make + $(MERL) $(ARGS) -sname megaco_generate_text_msgs_prev3c $(ERL_PATH) \ + -s megaco_codec_prev3c_test generate_text_messages \ + $(ESTOP) + +display_v3: make + $(MERL) $(ARGS) -sname megaco_display_text_msgs_v3 $(ERL_PATH) \ + -s megaco_codec_v3_test display_text_messages \ + $(ESTOP) + +generate_v3: make + $(MERL) $(ARGS) -sname megaco_generate_text_msgs_v3 $(ERL_PATH) \ + -s megaco_codec_v3_test generate_text_messages \ + $(ESTOP) + +generate: make + $(MERL) $(ARGS) -sname megaco_generate_text_msgs $(ERL_PATH) \ + -s megaco_codec_v1_test generate_text_messages \ + -s megaco_codec_v2_test generate_text_messages \ + -s megaco_codec_v3_test generate_text_messages \ + $(ESTOP) + +node: + $(MERL) -sname megaco $(ERL_PATH) + + +# ---------------------------------------------------- +# Release Targets +# ---------------------------------------------------- + +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: + +release_docs_spec: + +release_tests_spec: tests + $(INSTALL_DIR) $(RELSYSDIR) + $(INSTALL_DATA) $(TEST_SPEC_FILE) $(COVER_SPEC_FILE) \ + $(HRL_FILES) $(ERL_FILES) \ + $(RELSYSDIR) + $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR) + chmod -f -R u+w $(RELSYSDIR) + diff --git a/lib/megaco/test/megaco.cover b/lib/megaco/test/megaco.cover new file mode 100644 index 0000000000..e7764017d4 --- /dev/null +++ b/lib/megaco/test/megaco.cover @@ -0,0 +1,70 @@ +%% -*- erlang -*- +{exclude, + [megaco_encoder, + megaco_edist_compress, + megaco_filter, + megaco_transport, + megaco_erl_dist_encoder, + megaco_erl_dist_encoder_mc, + megaco_compact_text_encoder, + megaco_compact_text_encoder_v1, + megaco_compact_text_encoder_v2, + megaco_compact_text_encoder_prev3a, + megaco_compact_text_encoder_prev3b, + megaco_compact_text_encoder_prev3c, + megaco_compact_text_encoder_v3, + megaco_pretty_text_encoder, + megaco_pretty_text_encoder_v1, + megaco_pretty_text_encoder_v2, + megaco_pretty_text_encoder_prev3a, + megaco_pretty_text_encoder_prev3b, + megaco_pretty_text_encoder_prev3c, + megaco_pretty_text_encoder_v3, + megaco_text_mini_decoder, + megaco_text_mini_parser, + megaco_text_parser_v1, + megaco_text_parser_v2, + megaco_text_parser_prev3a, + megaco_text_parser_prev3b, + megaco_text_parser_prev3c, + megaco_text_parser_v3, + megaco_ber_bin_drv_media_gateway_control_v1, + megaco_ber_bin_drv_media_gateway_control_v2, + megaco_ber_bin_drv_media_gateway_control_prev3a, + megaco_ber_bin_drv_media_gateway_control_prev3b, + megaco_ber_bin_drv_media_gateway_control_prev3c, + megaco_ber_bin_drv_media_gateway_control_v3, + megaco_ber_bin_media_gateway_control_v1, + megaco_ber_bin_media_gateway_control_v2, + megaco_ber_bin_media_gateway_control_prev3a, + megaco_ber_bin_media_gateway_control_prev3b, + megaco_ber_bin_media_gateway_control_prev3c, + megaco_ber_bin_media_gateway_control_v3, + megaco_ber_media_gateway_control_v1, + megaco_ber_media_gateway_control_v2, + megaco_ber_media_gateway_control_prev3a, + megaco_ber_media_gateway_control_prev3b, + megaco_ber_media_gateway_control_prev3c, + megaco_ber_media_gateway_control_v3, + megaco_per_bin_drv_media_gateway_control_v1, + megaco_per_bin_drv_media_gateway_control_v2, + megaco_per_bin_drv_media_gateway_control_prev3a, + megaco_per_bin_drv_media_gateway_control_prev3b, + megaco_per_bin_drv_media_gateway_control_prev3c, + megaco_per_bin_drv_media_gateway_control_v3, + megaco_per_bin_media_gateway_control_v1, + megaco_per_bin_media_gateway_control_v2, + megaco_per_bin_media_gateway_control_prev3a, + megaco_per_bin_media_gateway_control_prev3b, + megaco_per_bin_media_gateway_control_prev3c, + megaco_per_bin_media_gateway_control_v3, + megaco_per_media_gateway_control_v1, + megaco_per_media_gateway_control_v2, + megaco_per_media_gateway_control_prev3a, + megaco_per_media_gateway_control_prev3b, + megaco_per_media_gateway_control_prev3c, + megaco_per_media_gateway_control_v3, + megaco_user_default + ] +}. + diff --git a/lib/megaco/test/megaco.spec b/lib/megaco/test/megaco.spec new file mode 100644 index 0000000000..7493bd5df8 --- /dev/null +++ b/lib/megaco/test/megaco.spec @@ -0,0 +1,5 @@ +{topcase, {dir, "../megaco_test"}}. +{require_nodenames, 1}. +%{skip, {megaco_digit_map_test, all, "Not yet implemented"}}. +{skip, {megaco_measure_test, all, "Not yet implemented"}}. +%{skip, {M, F, "Not yet implemented"}}. diff --git a/lib/megaco/test/megaco.spec.vxworks b/lib/megaco/test/megaco.spec.vxworks new file mode 100644 index 0000000000..2ac250e443 --- /dev/null +++ b/lib/megaco/test/megaco.spec.vxworks @@ -0,0 +1,5 @@ +{topcase, {dir, "../megaco_test"}}. +{require_nodenames, 1}. +{skip, {megaco_digit_map_test, all, "Not yet implemented"}}. +{skip, {megaco_measure_test, all, "Not yet implemented"}}. +%{skip, {M, F, "Not yet implemented"}}. diff --git a/lib/megaco/test/megaco_SUITE.erl b/lib/megaco/test/megaco_SUITE.erl new file mode 100644 index 0000000000..1bb3a570a4 --- /dev/null +++ b/lib/megaco/test/megaco_SUITE.erl @@ -0,0 +1,142 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test application config +%%---------------------------------------------------------------------- + +-module(megaco_SUITE). + +-compile(export_all). + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + +%% Test server callbacks +init_per_testcase(Case, Config) -> + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + megaco_test_lib:fin_per_testcase(Case, Config). + +init() -> + process_flag(trap_exit, true), + megaco_test_lib:flush(). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top test case + +all(suite) -> + [ + app_test, + appup_test, + config, + flex, + udp, + tcp, + examples, + %% call_flow, + digit_map, + mess, + measure, + binary_term_id, + codec, + sdp, + mib, + trans, + actions, + load, + pending_limit, + segmented, + timer + ]. + +tickets(suite) -> + [ + mess, + codec + ]. + +app_test(suite) -> + [{megaco_app_test, all}]. + +appup_test(suite) -> + [{megaco_appup_test, all}]. + +config(suite) -> + [{megaco_config_test, all}]. + +call_flow(suite) -> + [{megaco_call_flow_test, all}]. + +digit_map(suite) -> + [{megaco_digit_map_test, all}]. + +mess(suite) -> + [{megaco_mess_test, all}]. + +udp(suite) -> + [{megaco_udp_test, all}]. + +tcp(suite) -> + [{megaco_tcp_test, all}]. + +examples(suite) -> + [{megaco_examples_test, all}]. + +measure(suite) -> + [{megaco_measure_test, all}]. + +binary_term_id(suite) -> + [{megaco_binary_term_id_test, all}]. + +codec(suite) -> + [{megaco_codec_test, all}]. + +sdp(suite) -> + [{megaco_sdp_test, all}]. + +mib(suite) -> + [{megaco_mib_test, all}]. + +trans(suite) -> + [{megaco_trans_test, all}]. + +actions(suite) -> + [{megaco_actions_test, all}]. + +load(suite) -> + [{megaco_load_test, all}]. + +pending_limit(suite) -> + [{megaco_pending_limit_test, all}]. + +segmented(suite) -> + [{megaco_segment_test, all}]. + +timer(suite) -> + [{megaco_timer_test, all}]. + +flex(suite) -> + [{megaco_flex_test, all}]. + diff --git a/lib/megaco/test/megaco_actions_test.erl b/lib/megaco/test/megaco_actions_test.erl new file mode 100644 index 0000000000..d493022ca1 --- /dev/null +++ b/lib/megaco/test/megaco_actions_test.erl @@ -0,0 +1,446 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Verify that it is possible to separatelly encode +%% the action requests list. Do this with all codec's +%% that supports partial encode. +%%---------------------------------------------------------------------- +-module(megaco_actions_test). + +-compile(export_all). + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). + +-define(TEST_VERBOSITY, debug). +-define(MGC_VERBOSITY, debug). +-define(MG_VERBOSITY, debug). + +-define(LOAD_COUNTER_START, 10). +-define(A4444, ["11111111", "00000000", "00000000"]). +-define(A4445, ["11111111", "00000000", "11111111"]). +-define(A5555, ["11111111", "11111111", "00000000"]). +-define(A5556, ["11111111", "11111111", "11111111"]). + +-define(MGC_START(Pid, Mid, ET, Verb), + megaco_test_mgc:start(Pid, Mid, ET, Verb)). +-define(MGC_STOP(Pid), megaco_test_mgc:stop(Pid)). +-define(MGC_GET_STATS(Pid, No), megaco_test_mgc:get_stats(Pid, No)). +-define(MGC_RESET_STATS(Pid), megaco_test_mgc:reset_stats(Pid)). +-define(MGC_REQ_DISC(Pid,To), megaco_test_mgc:request_discard(Pid,To)). +-define(MGC_REQ_PEND(Pid,To), megaco_test_mgc:request_pending(Pid,To)). +-define(MGC_REQ_HAND(Pid), megaco_test_mgc:request_handle(Pid)). + +-define(MG_START(Pid, Mid, Codec, EC, Transp, Verb), + megaco_test_mg:start(Pid, Mid, {Codec, EC}, Transp, Verb)). +-define(MG_STOP(Pid), megaco_test_mg:stop(Pid)). +-define(MG_GET_STATS(Pid), megaco_test_mg:get_stats(Pid)). +-define(MG_RESET_STATS(Pid), megaco_test_mg:reset_stats(Pid)). +-define(MG_SERV_CHANGE(Pid), megaco_test_mg:service_change(Pid)). +-define(MG_NOTIF_RAR(Pid), megaco_test_mg:notify_request_and_reply(Pid)). +-define(MG_NOTIF_REQ(Pid), megaco_test_mg:notify_request(Pid)). +-define(MG_NOTIF_AR(Pid), megaco_test_mg:await_notify_reply(Pid)). +-define(MG_CANCEL(Pid,R), megaco_test_mg:cancel_request(Pid,R)). +-define(MG_APPLY_LOAD(Pid,CntStart), megaco_test_mg:apply_load(Pid,CntStart)). +-define(MG_EAR(Pid, Val), megaco_test_mg:encode_ar_first(Pid, Val)). + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + + +%% Test server callbacks +init_per_testcase(Case, Config) -> + process_flag(trap_exit, true), + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + process_flag(trap_exit, false), + megaco_test_lib:fin_per_testcase(Case, Config). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all(suite) -> + Cases = + [ + pretty_text, + flex_pretty_text, + compact_text, + flex_compact_text, + erl_dist, + erl_dist_mc, + ber_bin, + ber_bin_drv, + ber_bin_native, + ber_bin_drv_native + ], + Cases. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +pretty_text(suite) -> + []; +pretty_text(doc) -> + []; +pretty_text(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + i("pretty_text -> starting"), + + Codec = pretty_text, + Version = 1, + EncodingConfig = [], + req_and_rep(Config, Codec, Version, EncodingConfig). + + +flex_pretty_text(suite) -> + []; +flex_pretty_text(doc) -> + []; +flex_pretty_text(Config) when is_list(Config) -> + ?SKIP(not_implemented_yet). + + +compact_text(suite) -> + []; +compact_text(doc) -> + []; +compact_text(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + i("compact_text -> starting"), + + Codec = compact_text, + Version = 1, + EncodingConfig = [], + req_and_rep(Config, Codec, Version, EncodingConfig). + + +flex_compact_text(suite) -> + []; +flex_compact_text(doc) -> + []; +flex_compact_text(Config) when is_list(Config) -> + ?SKIP(not_implemented_yet). + + +erl_dist(suite) -> + []; +erl_dist(doc) -> + []; +erl_dist(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + i("erl_dist -> starting"), + + Codec = erl_dist, + Version = 1, + EncodingConfig = [], + req_and_rep(Config, Codec, Version, EncodingConfig). + + +erl_dist_mc(suite) -> + []; +erl_dist_mc(doc) -> + []; +erl_dist_mc(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + i("erl_dist_mc -> starting"), + + Codec = erl_dist, + Version = 1, + EncodingConfig = [megaco_compressed], + req_and_rep(Config, Codec, Version, EncodingConfig). + + +ber_bin(suite) -> + []; +ber_bin(doc) -> + []; +ber_bin(Config) when is_list(Config) -> + ?SKIP(currently_not_supported_by_asn1). + + +ber_bin_drv(suite) -> + []; +ber_bin_drv(doc) -> + []; +ber_bin_drv(Config) when is_list(Config) -> + ?SKIP(currently_not_supported_by_asn1). + + +ber_bin_native(suite) -> + []; +ber_bin_native(doc) -> + []; +ber_bin_native(Config) when is_list(Config) -> + ?SKIP(currently_not_supported_by_asn1). + + +ber_bin_drv_native(suite) -> + []; +ber_bin_drv_native(doc) -> + []; +ber_bin_drv_native(Config) when is_list(Config) -> + ?SKIP(currently_not_supported_by_asn1). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +req_and_rep(Config, Codec, _Version, EC) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + i("req_and_rep -> starting"), + MgcNode = make_node_name(mgc), + Mg1Node = make_node_name(mg1), + Mg2Node = make_node_name(mg2), + d("req_and_rep -> Nodes: " + "~n MgcNode: ~p" + "~n Mg1Node: ~p" + "~n Mg2Node: ~p", + [MgcNode, Mg1Node, Mg2Node]), + ok = megaco_test_lib:start_nodes([MgcNode, Mg1Node, Mg2Node], + ?FILE, ?LINE), + + %% Start the MGC and MGs + i("req_and_rep -> start the MGC"), + ET = [{Codec, EC, tcp}, {Codec, EC, udp}], + {ok, Mgc} = + ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY), + + i("req_and_rep -> start and connect the MGs"), + MgConf0 = [{Mg1Node, "mg1", Codec, EC, tcp, ?MG_VERBOSITY}, + {Mg2Node, "mg2", Codec, EC, udp, ?MG_VERBOSITY}], + MgConf = connect_mg(MgConf0, []), + + %% Collect the (initial) MGs statistics + Stats1 = get_mg_stats(MgConf, []), + d("req_and_rep -> stats for the MGs: ~n~p", [Stats1]), + + %% Collect and check the MGC statistics + i("req_and_rep -> collect and check the MGC stats"), + {ok, MgcStats1} = ?MGC_GET_STATS(Mgc, 1), + d("req_and_rep -> stats (1) for Mgc: ~n~p~n", [MgcStats1]), + + + sleep(1000), + + + %% And apply some load + i("req_and_rep -> apply traffic load"), + ok = apply_load(MgConf), + + %% Await completion of load part and the collect traffic + i("req_and_rep -> await load completion"), + ok = await_load_complete(MgConf), + + + sleep(1000), + + + i("req_and_rep -> collect the MGs statistics"), + Stats2 = get_mg_stats(MgConf, []), + d("req_and_rep -> stats for MGs: ~n~p", [Stats2]), + + i("req_and_rep -> collect the MGC statistics"), + {ok, MgcStats2} = ?MGC_GET_STATS(Mgc, 1), + d("req_and_rep -> stats (1) for Mgc: ~n~p~n", [MgcStats2]), + + + sleep(1000), + + + %% Reset counters + i("req_and_rep -> reset the MGs statistics"), + reset_mg_stats(MgConf), + Stats3 = get_mg_stats(MgConf, []), + d("req_and_rep -> stats for the MGs: ~n~p", [Stats3]), + + i("req_and_rep -> reset the MGC statistics"), + reset_mgc_stats(Mgc), + {ok, MgcStats3} = ?MGC_GET_STATS(Mgc, 1), + d("req_and_rep -> stats (1) for Mgc: ~n~p~n", [MgcStats3]), + + + sleep(1000), + + + %% Tell MGs to stop + i("req_and_rep -> stop the MGs"), + stop_mg(MgConf), + + + sleep(1000), + + + %% Collect the statistics + i("req_and_rep -> collect the MGC statistics"), + {ok, MgcStats4} = ?MGC_GET_STATS(Mgc, 1), + d("req_and_rep -> stats (1) for Mgc: ~n~p~n", [MgcStats4]), + {ok, MgcStats5} = ?MGC_GET_STATS(Mgc, 2), + d("req_and_rep -> stats (2) for Mgc: ~n~p~n", [MgcStats5]), + + %% Tell Mgc to stop + i("req_and_rep -> stop the MGC"), + ?MGC_STOP(Mgc), + + i("req_and_rep -> done", []), + ok. + + +connect_mg([], Acc) -> + lists:reverse(Acc); +connect_mg([{Node, Name, Codec, EC, Trans, Verb}|Mg], Acc) -> + Pid = connect_mg(Node, Name, Codec, EC, Trans, Verb), + connect_mg(Mg, [{Name, Pid}|Acc]). + +connect_mg(Node, Name, Codec, EC, Trans, Verb) -> + Mid = {deviceName, Name}, + {ok, Pid} = ?MG_START(Node, Mid, Codec, EC, Trans, Verb), + + {ok, _} = ?MG_EAR(Pid, true), + + %% Ask the MGs to do a service change + Res = ?MG_SERV_CHANGE(Pid), + d("connect_mg -> (~s) service change result: ~p", [Name,Res]), + + Pid. + + +stop_mg(MGs) -> + [?MG_STOP(Pid) || {_Name, Pid} <- MGs]. + + +get_mg_stats([], Acc) -> + lists:reverse(Acc); +get_mg_stats([{Name, Pid}|Mgs], Acc) -> + {ok, Stats} = ?MG_GET_STATS(Pid), + d("get_mg_stats -> stats for ~s: ~n~p~n", [Name, Stats]), + get_mg_stats(Mgs, [{Name, Stats}|Acc]). + + +apply_load([]) -> + ok; +apply_load([{_, MG}|MGs]) -> + d("apply_load -> apply load to ~p", [MG]), + ?MG_APPLY_LOAD(MG,?LOAD_COUNTER_START), + apply_load(MGs). + + +reset_mg_stats([]) -> + ok; +reset_mg_stats([{Name, Pid}|MGs]) -> + d("reset_mg_stats -> resetting ~s", [Name]), + ?MG_RESET_STATS(Pid), + reset_mg_stats(MGs). + +reset_mgc_stats(Mgc) -> + d("reset_mgc_stats -> resetting ~p", [Mgc]), + ?MGC_RESET_STATS(Mgc). + + +await_load_complete([]) -> + ok; +await_load_complete(MGs0) -> + receive + {load_complete, Pid} -> + d("received load_complete from ~p", [Pid]), + MGs1 = lists:keydelete(Pid, 2, MGs0), + await_load_complete(lists:delete(Pid, MGs1)); + {'EXIT', Pid, Reason} -> + i("exit signal from ~p: ~p", [Pid, Reason]), + case lists:keymember(Pid, 2, MGs0) of + true -> + exit({mg_exit, Pid, Reason}); + false -> + MGs1 = lists:keydelete(Pid, 2, MGs0), + await_load_complete(lists:delete(Pid, MGs1)) + end; + Other -> + d("received unexpected message: ~n~p", [Other]), + await_load_complete(MGs0) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +make_node_name(Name) -> + case string:tokens(atom_to_list(node()), [$@]) of + [_,Host] -> + list_to_atom(lists:concat([atom_to_list(Name) ++ "@" ++ Host])); + _ -> + exit("Test node must be started with '-sname'") + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +sleep(X) -> + receive after X -> ok end. + + +error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +i(F) -> + i(F, []). + +i(F, A) -> + print(info, get(verbosity), "", F, A). + + +d(F) -> + d(F, []). + +d(F, A) -> + print(debug, get(verbosity), "DBG: ", F, A). + + +printable(_, debug) -> true; +printable(info, info) -> true; +printable(_,_) -> false. + +print(Severity, Verbosity, P, F, A) -> + print(printable(Severity,Verbosity), P, F, A). + +print(true, P, F, A) -> + io:format("~s~p:~s: " ++ F ++ "~n", [P, self(), get(sname) | A]); +print(_, _, _, _) -> + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +random_init() -> + {A,B,C} = now(), + random:seed(A,B,C). + +random() -> + 10 * random:uniform(50). + +apply_load_timer() -> + erlang:send_after(random(), self(), apply_load_timeout). + diff --git a/lib/megaco/test/megaco_app_test.erl b/lib/megaco/test/megaco_app_test.erl new file mode 100644 index 0000000000..8e2148c236 --- /dev/null +++ b/lib/megaco/test/megaco_app_test.erl @@ -0,0 +1,308 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Verify the application specifics of the Megaco application +%%---------------------------------------------------------------------- +-module(megaco_app_test). + +-compile(export_all). + +-include("megaco_test_lib.hrl"). + + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + + +%% Test server callbacks +init_per_testcase(undef_funcs = Case, Config) -> + NewConfig = [{tc_timeout, ?MINUTES(10)} | Config], + megaco_test_lib:init_per_testcase(Case, NewConfig); +init_per_testcase(Case, Config) -> + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + megaco_test_lib:fin_per_testcase(Case, Config). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all(suite) -> + Cases = + [ + fields, + modules, + exportall, + app_depend, + undef_funcs + ], + {req, [], {conf, app_init, Cases, app_fin}}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +app_init(suite) -> []; +app_init(doc) -> []; +app_init(Config) when is_list(Config) -> + case is_app(megaco) of + {ok, AppFile} -> + io:format("AppFile: ~n~p~n", [AppFile]), + case megaco_flex_scanner:is_enabled() of + true -> + case megaco_flex_scanner:is_reentrant_enabled() of + true -> + io:format("~nMegaco reentrant flex scanner enabled~n~n", []); + false -> + io:format("~nMegaco non-reentrant flex scanner enabled~n~n", []) + end; + false -> + io:format("~nMegaco flex scanner disabled~n~n", []) + end, + megaco:print_version_info(), + [{app_file, AppFile}|Config]; + {error, Reason} -> + fail(Reason) + end. + +is_app(App) -> + LibDir = code:lib_dir(App), + File = filename:join([LibDir, "ebin", atom_to_list(App) ++ ".app"]), + case file:consult(File) of + {ok, [{application, App, AppFile}]} -> + {ok, AppFile}; + Error -> + {error, {invalid_format, Error}} + end. + + +app_fin(suite) -> []; +app_fin(doc) -> []; +app_fin(Config) when is_list(Config) -> + Config. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +fields(suite) -> + []; +fields(doc) -> + []; +fields(Config) when is_list(Config) -> + AppFile = key1search(app_file, Config), + Fields = [vsn, description, modules, registered, applications], + case check_fields(Fields, AppFile, []) of + [] -> + ok; + Missing -> + fail({missing_fields, Missing}) + end. + +check_fields([], _AppFile, Missing) -> + Missing; +check_fields([Field|Fields], AppFile, Missing) -> + check_fields(Fields, AppFile, check_field(Field, AppFile, Missing)). + +check_field(Name, AppFile, Missing) -> + io:format("checking field: ~p~n", [Name]), + case lists:keymember(Name, 1, AppFile) of + true -> + Missing; + false -> + [Name|Missing] + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +modules(suite) -> + []; +modules(doc) -> + []; +modules(Config) when is_list(Config) -> + AppFile = key1search(app_file, Config), + Mods = key1search(modules, AppFile), + EbinList = get_ebin_mods(megaco), + case missing_modules(Mods, EbinList, []) of + [] -> + ok; + Missing -> + throw({error, {missing_modules, Missing}}) + end, + case extra_modules(Mods, EbinList, []) of + [] -> + ok; + Extra -> + throw({error, {extra_modules, Extra}}) + end, + {ok, Mods}. + +get_ebin_mods(App) -> + LibDir = code:lib_dir(App), + EbinDir = filename:join([LibDir,"ebin"]), + {ok, Files0} = file:list_dir(EbinDir), + Files1 = [lists:reverse(File) || File <- Files0], + [list_to_atom(lists:reverse(Name)) || [$m,$a,$e,$b,$.|Name] <- Files1]. + + +missing_modules([], _Ebins, Missing) -> + Missing; +missing_modules([Mod|Mods], Ebins, Missing) -> + case lists:member(Mod, Ebins) of + true -> + missing_modules(Mods, Ebins, Missing); + false -> + io:format("missing module: ~p~n", [Mod]), + missing_modules(Mods, Ebins, [Mod|Missing]) + end. + + +extra_modules(_Mods, [], Extra) -> + Extra; +extra_modules(Mods, [Mod|Ebins], Extra) -> + case lists:member(Mod, Mods) of + true -> + extra_modules(Mods, Ebins, Extra); + false -> + io:format("supefluous module: ~p~n", [Mod]), + extra_modules(Mods, Ebins, [Mod|Extra]) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +exportall(suite) -> + []; +exportall(doc) -> + []; +exportall(Config) when is_list(Config) -> + AppFile = key1search(app_file, Config), + Mods = key1search(modules, AppFile), + check_export_all(Mods). + + +check_export_all([]) -> + ok; +check_export_all([Mod|Mods]) -> + case (catch apply(Mod, module_info, [compile])) of + {'EXIT', {undef, _}} -> + check_export_all(Mods); + O -> + case lists:keysearch(options, 1, O) of + false -> + check_export_all(Mods); + {value, {options, List}} -> + case lists:member(export_all, List) of + true -> + throw({error, {export_all, Mod}}); + false -> + check_export_all(Mods) + end + end + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +app_depend(suite) -> + []; +app_depend(doc) -> + []; +app_depend(Config) when is_list(Config) -> + AppFile = key1search(app_file, Config), + Apps = key1search(applications, AppFile), + check_apps(Apps). + + +check_apps([]) -> + ok; +check_apps([App|Apps]) -> + case is_app(App) of + {ok, _} -> + check_apps(Apps); + Error -> + throw({error, {missing_app, {App, Error}}}) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +undef_funcs(suite) -> + []; +undef_funcs(doc) -> + []; +undef_funcs(Config) when is_list(Config) -> + App = megaco, + AppFile = key1search(app_file, Config), + Mods = key1search(modules, AppFile), + Root = code:root_dir(), + LibDir = code:lib_dir(App), + EbinDir = filename:join([LibDir,"ebin"]), + XRefTestName = undef_funcs_make_name(App, xref_test_name), + {ok, XRef} = xref:start(XRefTestName), + ok = xref:set_default(XRef, + [{verbose,false},{warnings,false}]), + XRefName = undef_funcs_make_name(App, xref_name), + {ok, XRefName} = xref:add_release(XRef, Root, {name,XRefName}), + {ok, App} = xref:replace_application(XRef, App, EbinDir), + {ok, Undefs} = xref:analyze(XRef, undefined_function_calls), + xref:stop(XRef), + analyze_undefined_function_calls(Undefs, Mods, []). + +analyze_undefined_function_calls([], _, []) -> + ok; +analyze_undefined_function_calls([], _, AppUndefs) -> + exit({suite_failed, {undefined_function_calls, AppUndefs}}); +analyze_undefined_function_calls([{{Mod, _F, _A}, _C} = AppUndef|Undefs], + AppModules, AppUndefs) -> + %% Check that this module is our's + case lists:member(Mod,AppModules) of + true -> + {Calling,Called} = AppUndef, + {Mod1,Func1,Ar1} = Calling, + {Mod2,Func2,Ar2} = Called, + io:format("undefined function call: " + "~n ~w:~w/~w calls ~w:~w/~w~n", + [Mod1,Func1,Ar1,Mod2,Func2,Ar2]), + analyze_undefined_function_calls(Undefs, AppModules, + [AppUndef|AppUndefs]); + false -> + io:format("dropping ~p~n", [Mod]), + analyze_undefined_function_calls(Undefs, AppModules, AppUndefs) + end. + +%% This function is used simply to avoid cut-and-paste errors later... +undef_funcs_make_name(App, PostFix) -> + list_to_atom(atom_to_list(App) ++ "_" ++ atom_to_list(PostFix)). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +fail(Reason) -> + exit({suite_failed, Reason}). + +key1search(Key, L) -> + case lists:keysearch(Key, 1, L) of + undefined -> + fail({not_found, Key, L}); + {value, {Key, Value}} -> + Value + end. diff --git a/lib/megaco/test/megaco_appup_mg.erl b/lib/megaco/test/megaco_appup_mg.erl new file mode 100644 index 0000000000..f6060e406b --- /dev/null +++ b/lib/megaco/test/megaco_appup_mg.erl @@ -0,0 +1,198 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Used when performing testing appup tests +%% +%% {ok, P} = megaco_appup_mg:start(). +%% megaco_appup_mg:stop(P). +%% megaco_appup_mg:verbosity(P,silence). +%% megaco_appup_mg:verbosity(P,debug). +%% megaco_appup_mg:timeout(P,100). +%% megaco_appup_mg:aam(P,10). +%% megaco_appup_mg:aam(P,15). +%% megaco_appup_mg:aat(P,2000). +%% megaco_appup_mg:aat(P,10000). +%% +%%---------------------------------------------------------------------- + +-module(megaco_appup_mg). + +%% API +-export([start1/0, start2/0, start3/0, start4/0]). +-export([start/0, start/1, start/2]). +-export([verbosity/2, timeout/2]). +-export([aat/2, aam/2]). + +%% Internal +-export([main/4]). + +%% Constants: +-define(TIMEOUT,1000). +-define(MAXCOUNT,1). + +%% Wrapper macros +-define(START(Mid, Enc, Transp, Conf, Verb), + megaco_test_mg:start(node(), Mid, Enc, Transp, Conf, Verb)). +-define(STOP(Pid), megaco_test_mg:stop(Pid)). +-define(SERV_CHANGE(Pid), megaco_test_mg:service_change(Pid)). +-define(NOTIF_RAR(Pid), megaco_test_mg:notify_request_and_reply(Pid)). +-define(GRP_REQ(Pid,N), megaco_test_mg:group_requests(Pid,N)). +-define(VERBOSITY(Pid,V), megaco_test_mg:verbosity(Pid,V)). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start1() -> start(text, tcp). +start2() -> start(text, udp). +start3() -> start(binary, tcp). +start4() -> start(binary, udp). + +start() -> + start(text, tcp). + +start(tcp) -> + start(text, tcp); +start(udp) -> + start(text, udp). + +start(Encoding, Transport) -> + proc_lib:start_link(?MODULE, main, [self(), Encoding, Transport, 1]). + +stop(Pid) -> + Pid ! stop. + +verbosity(Pid, V) -> + Pid ! {verbosity, V}. + +timeout(Pid, T) -> + Pid ! {timeout, T}. + +aat(Pid, Val) -> + uci(Pid, accu_ack_timer, Val). + +aam(Pid, Val) -> + uci(Pid, accu_ack_maxcount, Val). + +uci(Pid, Item, Val) -> + Pid ! {update_conn_info, Item, Val}. + + +%% ------------------------------------------------------------------------- + +%% - start function - +main(Parent, Encoding, Transport, MaxCount) -> + Mg = init(Encoding, Transport, MaxCount), + proc_lib:init_ack(Parent, {ok, self()}), + loop(Mg, ?TIMEOUT, ?TIMEOUT). + +%% - init - +init(Encoding, Transport, MaxCount) -> + verify_encoding(Encoding), + verify_transport(Transport), + + Mid = {deviceName, "mg"}, + Config = [{auto_ack, true} %, + %{trans_timer, 2000}, + %{trans_ack_maxcount, MaxCount} + ], + + d("start MG"), + {ok, Mg} = ?START(Mid, Encoding, Transport, Config, debug), + + d("service change"), + ok = ?SERV_CHANGE(Mg), + + ?GRP_REQ(Mg, MaxCount), + + Mg. + +%% - main loop - +loop(Mg, Timeout, To) when To =< 0 -> + ?NOTIF_RAR(Mg), + loop(Mg, Timeout, Timeout); +loop(Mg, Timeout, To) -> + Start = t(), + receive + stop -> + d("stop"), + megaco_test_mg:stop(Mg), + exit(normal); + + {update_conn_info, Item, Val} -> + d("update_conn_info -> ~p:~p", [Item, Val]), + megaco_test_mg:update_conn_info(Mg, Item, Val), + loop(Mg, Timeout, To - (t() - Start)); + + {request_group_size, Size} when Size > 1 -> + d("request_group_size -> ~p", [Size]), + ?GRP_REQ(Mg, Size), + loop(Mg, Timeout, To - (t() - Start)); + + {verbosity, V} -> + d("verbosity: ~p", [V]), + ?VERBOSITY(Mg, V), + loop(Mg, Timeout, To - (t() - Start)); + + {timeout, T} -> + d("timeout: ~p", [T]), + T1 = T - Timeout, + loop(Mg, T, To - (t() - Start) + T1); + + Any -> + error("received unknown request: ~n~p", [Any]), + loop(Mg, Timeout, To - (t() - Start)) + + after To -> + ?NOTIF_RAR(Mg), + loop(Mg, Timeout, Timeout) + end. + + + +%% ------------------------------------------------------------------------- + +verify_encoding(text) -> ok; +verify_encoding(binary) -> ok; +verify_encoding(Encoding) -> exit({invalid_encoding, Encoding}). + +verify_transport(tcp) -> ok; +verify_transport(udp) -> ok; +verify_transport(Transport) -> exit({invalid_transport, Transport}). + +%% - + +sleep(X) -> receive after X -> ok end. + +t() -> + {A,B,C} = erlang:now(), + A*1000000000+B*1000+(C div 1000). + + +%% - + +error(F, A) -> + d("ERROR: " ++ F, A). + +d(F) -> + d(F, []). + +d(F, A) -> + io:format("~pAMG-" ++ F ++ "~n", [self()|A]). diff --git a/lib/megaco/test/megaco_appup_mgc.erl b/lib/megaco/test/megaco_appup_mgc.erl new file mode 100644 index 0000000000..b6e53655f8 --- /dev/null +++ b/lib/megaco/test/megaco_appup_mgc.erl @@ -0,0 +1,107 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Used when performing testing appup tests +%% +%% {ok, P} = megaco_appup_mgc:start(). +%% megaco_appup_mgc:stop(P). +%% megaco_appup_mgc:verbosity(P,silence). +%% megaco_appup_mgc:verbosity(P,debug). +%% +%%---------------------------------------------------------------------- + +-module(megaco_appup_mgc). + +-export([start/0, start/1, stop/1]). +-export([verbosity/2]). + +-export([main/2]). + +-define(START(Mid, ET, Verb), + megaco_test_mgc:start(node(), Mid, ET, Verb)). +-define(STOP(Pid), megaco_test_mgc:stop(Pid)). +-define(REQ_HANDS(Pid), megaco_test_mgc:request_handle_sloppy(Pid)). +-define(VERBOSITY(Pid,V), megaco_test_mgc:verbosity(Pid,V)). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start() -> + start(silence). +start(V) -> + proc_lib:start_link(?MODULE, main, [self(), V]). + +stop(Pid) -> + Pid ! stop. + +verbosity(Pid, V) -> + Pid ! {verbosity, V}. + + +%% ------------------------------------------------------------------------ + +main(Parent, V) -> + d("starting"), + Mgc = init(V), + proc_lib:init_ack(Parent, {ok, self()}), + d("started"), + loop(Mgc). + +init(V) -> + Mid = {deviceName, "mgc"}, + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + + d("start MGC"), + {ok, Mgc} = ?START(Mid, ET, debug), + + ?VERBOSITY(Mgc, V), + + Mgc. + +loop(Mgc) -> + d("awaiting request..."), + receive + + stop -> + d("stopping"), + ?STOP(Mgc), + exit(normal); + + {verbosity, V} -> + d("verbosity: ~p", [V]), + ?VERBOSITY(Mgc, V); + + Any -> + error("received unknown request: ~n~p", [Any]) + + end, + loop(Mgc). + +%% ------------------------------------------------------------------------ + +error(F, A) -> + io:format("AMGC-ERROR: " ++ F, A). + +d(F) -> + d(F, []). + +d(F, A) -> + io:format("AMGC: " ++ F ++ "~n", A). diff --git a/lib/megaco/test/megaco_appup_test.erl b/lib/megaco/test/megaco_appup_test.erl new file mode 100644 index 0000000000..09732c6a4d --- /dev/null +++ b/lib/megaco/test/megaco_appup_test.erl @@ -0,0 +1,516 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Verify the application specifics of the Megaco application +%%---------------------------------------------------------------------- +-module(megaco_appup_test). + +-compile(export_all). + +-include("megaco_test_lib.hrl"). + +-define(APPLICATION, megaco). + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + + +%% Test server callbacks +init_per_testcase(Case, Config) -> + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all(suite) -> + Cases = + [ + appup + ], + {req, [], {conf, appup_init, Cases, appup_fin}}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +appup_init(suite) -> []; +appup_init(doc) -> []; +appup_init(Config) when is_list(Config) -> + AppFile = file_name(?APPLICATION, ".app"), + AppupFile = file_name(?APPLICATION, ".appup"), + [{app_file, AppFile}, {appup_file, AppupFile}|Config]. + + +file_name(App, Ext) -> + LibDir = code:lib_dir(App), + filename:join([LibDir, "ebin", atom_to_list(App) ++ Ext]). + + +appup_fin(suite) -> []; +appup_fin(doc) -> []; +appup_fin(Config) when is_list(Config) -> + Config. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +appup(suite) -> + []; +appup(doc) -> + "perform a simple check of the appup file"; +appup(Config) when is_list(Config) -> + AppupFile = key1search(appup_file, Config), + AppFile = key1search(app_file, Config), + Modules = modules(AppFile), + check_appup(AppupFile, Modules). + +modules(File) -> + case file:consult(File) of + {ok, [{application,megaco,Info}]} -> + case lists:keysearch(modules,1,Info) of + {value, {modules, Modules}} -> + Modules; + false -> + fail({bad_appinfo, Info}) + end; + Error -> + fail({bad_appfile, Error}) + end. + + +check_appup(AppupFile, Modules) -> + case file:consult(AppupFile) of + {ok, [{V, UpFrom, DownTo}]} -> + check_appup(V, UpFrom, DownTo, Modules); + Else -> + fail({bad_appupfile, Else}) + end. + + +check_appup(V, UpFrom, DownTo, Modules) -> + check_version(V), + check_depends(up, UpFrom, Modules), + check_depends(down, DownTo, Modules), + check_module_subset(UpFrom), + check_module_subset(DownTo), + ok. + + +check_depends(_, [], _) -> + ok; +check_depends(UpDown, [Dep|Deps], Modules) -> + check_depend(UpDown, Dep, Modules), + check_depends(UpDown, Deps, Modules). + + +check_depend(up = UpDown, {add_application, ?APPLICATION} = Instr, Modules) -> + d("check_instructions(~w) -> entry with" + "~n Instruction: ~p" + "~n Modules: ~p", [UpDown, Instr, Modules]), + ok; +check_depend(down = UpDown, {remove_application, ?APPLICATION} = Instr, + Modules) -> + d("check_instructions(~w) -> entry with" + "~n Instruction: ~p" + "~n Modules: ~p", [UpDown, Instr, Modules]), + ok; +check_depend(UpDown, {V, Instructions}, Modules) -> + d("check_instructions(~w) -> entry with" + "~n V: ~p" + "~n Modules: ~p", [UpDown, V, Modules]), + check_version(V), + case check_instructions(UpDown, + Instructions, Instructions, [], [], Modules) of + {_Good, []} -> + ok; + {_, Bad} -> + fail({bad_instructions, Bad, UpDown}) + end. + + +check_instructions(_, [], _, Good, Bad, _) -> + {lists:reverse(Good), lists:reverse(Bad)}; +check_instructions(UpDown, [Instr|Instrs], AllInstr, Good, Bad, Modules) -> + d("check_instructions(~w) -> entry with" + "~n Instr: ~p", [UpDown,Instr]), + case (catch check_instruction(UpDown, Instr, AllInstr, Modules)) of + ok -> + check_instructions(UpDown, Instrs, AllInstr, + [Instr|Good], Bad, Modules); + {error, Reason} -> + d("check_instructions(~w) -> bad instruction: " + "~n Reason: ~p", [UpDown,Reason]), + check_instructions(UpDown, Instrs, AllInstr, Good, + [{Instr, Reason}|Bad], Modules) + end. + +%% A new module is added +check_instruction(up, {add_module, Module}, _, Modules) + when is_atom(Module) -> + d("check_instruction -> entry when up-add_module instruction with" + "~n Module: ~p", [Module]), + check_module(Module, Modules); + +%% An old module is re-added +check_instruction(down, {add_module, Module}, _, Modules) + when is_atom(Module) -> + d("check_instruction -> entry when down-add_module instruction with" + "~n Module: ~p", [Module]), + case (catch check_module(Module, Modules)) of + {error, {unknown_module, Module, Modules}} -> + ok; + ok -> + error({existing_readded_module, Module}) + end; + +%% Removing a module on upgrade: +%% - the module has been removed from the app-file. +%% - check that no module depends on this (removed) module +check_instruction(up, {remove, {Module, Pre, Post}}, _, Modules) + when is_atom(Module) andalso is_atom(Pre) andalso is_atom(Post) -> + d("check_instruction -> entry when up-remove instruction with" + "~n Module: ~p" + "~n Pre: ~p" + "~n Post: ~p", [Module, Pre, Post]), + case (catch check_module(Module, Modules)) of + {error, {unknown_module, Module, Modules}} -> + check_purge(Pre), + check_purge(Post); + ok -> + error({existing_removed_module, Module}) + end; + +%% Removing a module on downgrade: the module exist +%% in the app-file. +check_instruction(down, {remove, {Module, Pre, Post}}, AllInstr, Modules) + when is_atom(Module) andalso is_atom(Pre) andalso is_atom(Post) -> + d("check_instruction -> entry when down-remove instruction with" + "~n Module: ~p" + "~n Pre: ~p" + "~n Post: ~p", [Module, Pre, Post]), + case (catch check_module(Module, Modules)) of + ok -> + check_purge(Pre), + check_purge(Post), + check_no_remove_depends(Module, AllInstr); + {error, {unknown_module, Module, Modules}} -> + error({nonexisting_removed_module, Module}) + end; + +check_instruction(_, {load_module, Module, Pre, Post, Depend}, + AllInstr, Modules) + when is_atom(Module) andalso is_atom(Pre) andalso is_atom(Post) andalso is_list(Depend) -> + d("check_instruction -> entry when load_module instruction with" + "~n Module: ~p" + "~n Pre: ~p" + "~n Post: ~p" + "~n Depend: ~p", [Module, Pre, Post, Depend]), + check_module(Module, Modules), + check_module_depend(Module, Depend, Modules), + check_module_depend(Module, Depend, updated_modules(AllInstr, [])), + check_purge(Pre), + check_purge(Post); + +check_instruction(_, {update, Module, Change, Pre, Post, Depend}, + AllInstr, Modules) + when is_atom(Module) andalso is_atom(Pre) andalso is_atom(Post) andalso is_list(Depend) -> + d("check_instruction -> entry when update instruction with" + "~n Module: ~p" + "~n Change: ~p" + "~n Pre: ~p" + "~n Post: ~p" + "~n Depend: ~p", [Module, Change, Pre, Post, Depend]), + check_module(Module, Modules), + check_module_depend(Module, Depend, Modules), + check_module_depend(Module, Depend, updated_modules(AllInstr, [])), + check_change(Change), + check_purge(Pre), + check_purge(Post); + +check_instruction(_, {update, Module, supervisor}, _, Modules) + when is_atom(Module) -> + check_module(Module, Modules); + +check_instruction(_, {apply, {Module, Function, Args}}, _, Modules) + when is_atom(Module) andalso is_atom(Function) andalso is_list(Args) -> + d("check_instruction -> entry when down-apply instruction with" + "~n Module: ~p" + "~n Function: ~p" + "~n Args: ~p", [Module, Function, Args]), + check_module(Module, Modules), + check_apply(Module, Function, Args); + +check_instruction(_, {restart_application, ?APPLICATION}, _AllInstr, _Modules) -> + ok; + +check_instruction(_, Instr, _AllInstr, _Modules) -> + d("check_instruction -> entry when unknown instruction with" + "~n Instr: ~p", [Instr]), + error({error, {unknown_instruction, Instr}}). + + +%% If Module X depends on Module Y, then module Y must have an update +%% instruction of some sort (otherwise the depend is faulty). +updated_modules([], Modules) -> + d("update_modules -> entry when done with" + "~n Modules: ~p", [Modules]), + Modules; +updated_modules([Instr|Instrs], Modules) -> + d("update_modules -> entry with" + "~n Instr: ~p" + "~n Modules: ~p", [Instr,Modules]), + Module = instruction_module(Instr), + d("update_modules -> Module: ~p", [Module]), + updated_modules(Instrs, [Module|Modules]). + +instruction_module({add_module, Module}) -> + Module; +instruction_module({remove, {Module, _, _}}) -> + Module; +instruction_module({load_module, Module, _, _, _}) -> + Module; +instruction_module({update, Module, _, _, _, _}) -> + Module; +instruction_module({apply, {Module, _, _}}) -> + Module; +instruction_module(Instr) -> + d("instruction_module -> entry when unknown instruction with" + "~n Instr: ~p", [Instr]), + error({error, {unknown_instruction, Instr}}). + + +%% Check that the modules handled in an instruction set for version X +%% is a subset of the instruction set for version X-1. +check_module_subset(Instructions) -> + do_check_module_subset(modules_of(Instructions)). + +do_check_module_subset([]) -> + ok; +do_check_module_subset([_]) -> + ok; +do_check_module_subset([{_V1, Mods1}|T]) -> + {V2, Mods2} = hd(T), + %% Check that the modules in V1 is a subset of V2 + case do_check_module_subset2(Mods1, Mods2) of + ok -> + do_check_module_subset(T); + {error, Modules} -> + fail({subset_missing_instructions, V2, Modules}) + end. + +do_check_module_subset2(Mods1, Mods2) -> + do_check_module_subset2(Mods1, Mods2, []). + +do_check_module_subset2([], _, []) -> + ok; +do_check_module_subset2([], _, Acc) -> + {error, lists:reverse(Acc)}; +do_check_module_subset2([Mod|Mods], Mods2, Acc) -> + case lists:member(Mod, Mods2) of + true -> + do_check_module_subset2(Mods, Mods2, Acc); + false -> + do_check_module_subset2(Mods, Mods2, [Mod|Acc]) + end. + + +modules_of(Instructions) -> + modules_of(Instructions, []). + +modules_of([], Acc) -> + lists:reverse(Acc); +modules_of([{V,Instructions}|T], Acc) -> + Mods = modules_of2(Instructions, []), + modules_of(T, [{V, Mods}|Acc]). + +modules_of2([], Acc) -> + lists:reverse(Acc); +modules_of2([Instr|Instructions], Acc) -> + case module_of(Instr) of + {value, Mod} -> + modules_of2(Instructions, [Mod|Acc]); + false -> + modules_of2(Instructions, Acc) + end. + +module_of({add_module, Module}) -> + {value, Module}; +module_of({remove, {Module, _Pre, _Post}}) -> + {value, Module}; +module_of({load_module, Module, _Pre, _Post, _Depend}) -> + {value, Module}; +module_of({update, Module, _Change, _Pre, _Post, _Depend}) -> + {value, Module}; +module_of(_) -> + false. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% The version is a string consting of numbers separated by dots: "." +%% Example: "3.3.3" +%% +check_version(V) when is_list(V) -> + case do_check_version(string:tokens(V, [$.])) of + ok -> + ok; + {error, BadVersionPart} -> + throw({error, {bad_version, V, BadVersionPart}}) + end; +check_version(V) -> + error({bad_version, V}). + +do_check_version([]) -> + ok; +do_check_version([H|T]) -> + case (catch list_to_integer(H)) of + I when is_integer(I) -> + do_check_version(T); + _ -> + {error, H} + end. + +check_module(M, Modules) when is_atom(M) -> + case lists:member(M,Modules) of + true -> + ok; + false -> + error({unknown_module, M, Modules}) + end; +check_module(M, _) -> + error({bad_module, M}). + + +check_module_depend(M, [], _) when is_atom(M) -> + d("check_module_depend -> entry with" + "~n M: ~p", [M]), + ok; +check_module_depend(M, Deps, Modules) when is_atom(M) andalso is_list(Deps) -> + d("check_module_depend -> entry with" + "~n M: ~p" + "~n Deps: ~p" + "~n Modules: ~p", [M, Deps, Modules]), + case [Dep || Dep <- Deps, lists:member(Dep, Modules) == false] of + [] -> + ok; + Unknown -> + error({unknown_depend_modules, Unknown}) + end; +check_module_depend(_M, D, _Modules) -> + d("check_module_depend -> entry when bad depend with" + "~n D: ~p", [D]), + error({bad_depend, D}). + + +check_no_remove_depends(_Module, []) -> + ok; +check_no_remove_depends(Module, [Instr|Instrs]) -> + check_no_remove_depend(Module, Instr), + check_no_remove_depends(Module, Instrs). + +check_no_remove_depend(Module, {load_module, Mod, _Pre, _Post, Depend}) -> + case lists:member(Module, Depend) of + true -> + error({removed_module_in_depend, load_module, Mod, Module}); + false -> + ok + end; +check_no_remove_depend(Module, {update, Mod, _Change, _Pre, _Post, Depend}) -> + case lists:member(Module, Depend) of + true -> + error({removed_module_in_depend, update, Mod, Module}); + false -> + ok + end; +check_no_remove_depend(_, _) -> + ok. + + +check_change(soft) -> + ok; +check_change({advanced, _Something}) -> + ok; +check_change(Change) -> + error({bad_change, Change}). + + +check_purge(soft_purge) -> + ok; +check_purge(brutal_purge) -> + ok; +check_purge(Purge) -> + error({bad_purge, Purge}). + + +check_apply(Module, Function, Args) -> + case (catch Module:module_info()) of + Info when is_list(Info) -> + check_exported(Function, Args, Info); + {'EXIT', {undef, _}} -> + error({not_existing_module, Module}) + end. + +check_exported(Function, Args, Info) -> + case lists:keysearch(exports, 1, Info) of + {value, {exports, FuncList}} -> + Arity = length(Args), + Arities = [A || {F, A} <- FuncList, F == Function], + case lists:member(Arity, Arities) of + true -> + ok; + false -> + error({not_exported_function, Function, Arity}) + end; + _ -> + error({bad_export, Info}) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +error(Reason) -> + throw({error, Reason}). + +fail(Reason) -> + exit({suite_failed, Reason}). + +key1search(Key, L) -> + case lists:keysearch(Key, 1, L) of + undefined -> + fail({not_found, Key, L}); + {value, {Key, Value}} -> + Value + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +d(F, A) -> + d(false, F, A). + +d(true, F, A) -> + io:format(F ++ "~n", A); +d(_, _, _) -> + ok. + + diff --git a/lib/megaco/test/megaco_binary_term_id_test.erl b/lib/megaco/test/megaco_binary_term_id_test.erl new file mode 100644 index 0000000000..da4e69c617 --- /dev/null +++ b/lib/megaco/test/megaco_binary_term_id_test.erl @@ -0,0 +1,1012 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: +%%---------------------------------------------------------------------- + +-module(megaco_binary_term_id_test). + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/src/engine/megaco_message_internal.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([t/0]). + +%% Test suite exports +-export([all/1, encode_first/1, decode_first/1, + init_per_testcase/2, fin_per_testcase/2]). + + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- +-export([te01/1,te02/1,te03/1,te04/1,te05/1, + te06/1,te07/1,te08/1,te09/1,te10/1, + te11/1,te12/1,te13/1,te14/1,te15/1, + te16/1,te17/1,te18/1,te19/1]). +-export([td01/1,td02/1,td03/1,td04/1,td05/1,td06/1]). + + +%% --------------------------------------------------------------------- + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top test case + +all(suite) -> + [ + encode_first, + decode_first + ]. + +encode_first(suite) -> + encode_first_cases(). + +decode_first(suite) -> + decode_first_cases(). + + +%% Test server callbacks +init_per_testcase(Case, Config) -> + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%====================================================================== +%% External functions +%%====================================================================== + +t() -> + display([do(Case) || Case <- cases()]), + ok. + + +cases() -> encode_first_cases() ++ decode_first_cases(). + +encode_first_cases() -> [te01,te02,te03,te04,te05, + te06,te07,te08,te09,te10, + te11,te12,te13,te14,te15, + te16,te17,te18,te19]. +decode_first_cases() -> [td01,td02,td03,td04,td05,td06]. + +do(Case) -> + case doc(Case) of + {'EXIT',_} -> + {Case,error}; + Description -> + io:format("test case ~p~n",[Case]), + case suite(Case) of + {'EXIT',Reason} -> + Res = check_result(Case,Description,ok,{error,Reason}), + {Case,Res}; + {Expected,Result} -> + Res = check_result(Case,Description,Expected,Result), + {Case,Res} + end + end. + +doc(Case) -> (catch apply(?MODULE,Case,[doc])). +suite(Case) -> (catch apply(?MODULE,Case,[])). + +display(R) -> + [display(Case,Result) || {Case,Result} <- R]. + +display(C,error) -> + io:format("Test case ~p failed~n",[C]); +display(C,warning) -> + io:format("Test case ~p conspicuous~n",[C]); +display(C,ok) -> + io:format("Test case ~p succeeded~n",[C]). + +check(D,ok,{ok,T1,T2,T3}) -> + Result = case check_ok_result(T1,T3) of + ok -> + ok; + {error,Reason} -> + io:format(" => inconsistent result" + "~n Start and end record differ" + "~n ~s" + "~n ~s" + "~n ~w" + "~n", + [D,Reason,T2]), + warning + end, + Result; +check(D,error,{ok,T1,T2,T3}) -> + io:format(" => failed" + "~n ~s" + "~n ~p" + "~n ~p" + "~n ~p" + "~n", + [D,T1,T2,T3]), + error; +check(_D,error,{error,_Reason}) -> + ok; +check(D,ok,{error,Reason}) -> + io:format(" => failed" + "~n ~s" + "~n Failed for reason" + "~n ~p" + "~n", + [D,Reason]), + error. + +check_result(_C,D,ok,{ok,T1,T2,T3}) -> + Result = case check_ok_result(T1,T3) of + ok -> + io:format(" => succeeded" + "~n ~s" + "~n ~p" + "~n ~w" + "~n ~p", + [D,T1,T2,T3]), + ok; + {error,Reason} -> + io:format(" => inconsistent result" + "~n Start and end record differ" + "~n ~s" + "~n ~s" + "~n ~w", + [D,Reason,T2]), + warning + end, + io:format("~n~n--------------------~n",[]), + Result; +check_result(_C,D,error,{ok,T1,T2,T3}) -> + io:format(" => failed" + "~n ~s" + "~n ~p" + "~n ~p" + "~n ~p" + "~n~n--------------------~n", + [D,T1,T2,T3]), + error; +check_result(_C,D,error,{error,Reason}) -> + io:format(" => succeeded" + "~n ~s" + "~n Operation failed (expectedly) for reason" + "~n ~p" + "~n~n--------------------~n", + [D,Reason]), + ok; +check_result(_C,D,ok,{error,Reason}) -> + io:format(" => failed" + "~n ~s" + "~n Failed for reason" + "~n ~p" + "~n~n--------------------~n", + [D,Reason]), + error. + +check_ok_result(R,R) when is_record(R,megaco_term_id) -> + ok; % Same record type and same record content +check_ok_result(S,E) when is_record(S,megaco_term_id) andalso + is_record(E,megaco_term_id) -> + Reason = check_megaco_term_id_record(S,E), + {error,Reason}; % Same record type but different record content +check_ok_result(R,R) when is_record(R,'TerminationID') -> + ok; +check_ok_result(S,E) when is_record(S,'TerminationID') andalso + is_record(E,'TerminationID') -> + Reason = check_TerminationID_record(S,E), + {error,Reason}; % Same record type but different record content +check_ok_result(_S,_E) -> + {error,"NOT THE SAME RECORD TYPES"}. % OOPS, Not even the same record type + +check_megaco_term_id_record(#megaco_term_id{contains_wildcards = Cw1, + id = Id1}, + #megaco_term_id{contains_wildcards = Cw2, + id = Id2}) -> + Result = case check_megaco_term_id_cw(Cw1,Cw2) of + ok -> + check_megaco_term_id_id(Id1,Id2); + {error,R1} -> + R2 = check_megaco_term_id_id(Id1,Id2), + io_lib:format("~s~s",[R1,R2]) + end, + lists:flatten(Result). + +check_megaco_term_id_cw(Cw,Cw) -> + ok; +check_megaco_term_id_cw(Cw1,Cw2) -> + R = io_lib:format("~n The 'contains_wildcard' property of the start" + "~n megaco_term_id record " + "~n has value ~w " + "~n but the end record " + "~n has value ~w", + [Cw1,Cw2]), + {error,R}. + +check_megaco_term_id_id(Id,Id) -> + ok; +check_megaco_term_id_id(Id1,Id2) -> + R = io_lib:format("~n The 'id' property of the start" + "~n megaco_term_id record " + "~n has value ~w " + "~n but the end record " + "~n has value ~w", + [Id1,Id2]), + {error,R}. + + +check_TerminationID_record(#'TerminationID'{wildcard = W1, id = Id1}, + #'TerminationID'{wildcard = W2, id = Id2}) -> + Result = case check_TerminationID_w(W1,W2) of + ok -> + check_TerminationID_id(Id1,Id2); + {error,R1} -> + R2 = check_TerminationID_id(Id1,Id2), + io_lib:format("~s~s",[R1,R2]) + end, + lists:flatten(Result). + +check_TerminationID_w(W,W) -> + ok; +check_TerminationID_w(W1,W2) -> + R = io_lib:format("~n The 'wildcard' property of the start" + "~n 'TerminationID' record " + "~n has value ~w " + "~n but the end record " + "~n has value ~w", + [W1,W2]), + {error,R}. + +check_TerminationID_id(Id,Id) -> + ok; +check_TerminationID_id(Id1,Id2) -> + R = io_lib:format("~n The 'id' property of the start" + "~n 'TerminationID' record " + "~n has value ~w " + "~n but the end record " + "~n has value ~w", + [Id1,Id2]), + {error,R}. + + +%% -------------------------------------------------------- +%% Start test cases +%% -------------------------------------------------------- + +%% basic_enc_dec01 +te01(doc) -> + "Basic encoding & then decoding test [1,1]\n (asn -> binary -> asn)"; + +te01(suite) -> + []; + +te01(Config) when is_list(Config) -> + {Exp,Res} = te01(), + ok = check(te01(doc),Exp,Res). + + +te01() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config1(),mtid01()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% basic_enc_dec02 +te02(doc) -> + "Basic encoding & then decoding test [1,2]"; + +te02(suite) -> + []; + +te02(Config) when is_list(Config) -> + {Exp,Res} = te02(), + ok = check(te02(doc),Exp,Res). + +te02() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config1(),mtid02()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% basic_enc_dec03 +te03(doc) -> + "Basic encoding & then decoding test [1,3]"; + +te03(suite) -> + []; + +te03(Config) when is_list(Config) -> + {Exp,Res} = te03(), + ok = check(te03(doc),Exp,Res). + +te03() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config1(),mtid03()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% basic_enc_dec04 +te04(doc) -> + "Basic encoding & then decoding test [1,4]\n (asn -> binary -> asn)"; + +te04(suite) -> + []; + +te04(Config) when is_list(Config) -> + {Exp,Res} = te04(), + ok = check(te04(doc),Exp,Res). + +te04() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config1(),mtid04()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% basic_enc_dec05 +te05(doc) -> + "Basic encoding & then decoding test [1,5]\n (asn -> binary -> asn)"; + +te05(suite) -> + []; + +te05(Config) when is_list(Config) -> + {Exp,Res} = te05(), + ok = check(te05(doc),Exp,Res). + +te05() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config1(),mtid05()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% no_wildcard_spec_but_fond_some_enc_dec +te06(doc) -> + "Specified NO wildcards, but found some just the same [1,6]\n (asn -> binary -> asn)"; + +te06(suite) -> + []; + +te06(Config) when is_list(Config) -> + {Exp,Res} = te06(), + ok = check(te06(doc),Exp,Res). + +te06() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config1(),mtid06()), + erase(encode_debug), + erase(decode_debug), + {error,Res}. + + +%% -------------------------------------------------------- + +%% invalid_char_enc_dec +te07(doc) -> + "Invalid character found (2) [1,7]\n (asn -> binary -> asn)"; + +te07(suite) -> + []; + +te07(Config) when is_list(Config) -> + {Exp,Res} = te07(), + ok = check(te07(doc),Exp,Res). + +te07() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config1(),mtid07()), + erase(encode_debug), + erase(decode_debug), + {error,Res}. + + +%% -------------------------------------------------------- + +%% erroneous_first_level_length_enc_dec01 +te08(doc) -> + "Erroneous length of first level (a character after wildcard) [1,8]\n (asn -> binary -> asn)"; + +te08(suite) -> + []; + +te08(Config) when is_list(Config) -> + {Exp,Res} = te08(), + ok = check(te08(doc),Exp,Res). + +te08() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config1(),mtid08()), + erase(encode_debug), + erase(decode_debug), + {error,Res}. + + +%% -------------------------------------------------------- + +%% erroneous_first_level_length_enc_dec02 +te09(doc) -> + "Erroneous length of first level (a character after last valid) [1,9]\n (asn -> binary -> asn)"; + +te09(suite) -> + []; + +te09(Config) when is_list(Config) -> + {Exp,Res} = te09(), + ok = check(te09(doc),Exp,Res). + +te09() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config1(),mtid09()), + erase(encode_debug), + erase(decode_debug), + {error,Res}. + + +%% -------------------------------------------------------- + +%% basic_enc_dec_with_one_rec_wildcard01 +te10(doc) -> + "Basic encode & decode with one recursive wildcard [1,10]\n (asn -> binary -> asn)\n (NOTE THAT THIS SHOULD LATER BE A LEVEL WILDCARD)"; + +te10(suite) -> + []; + +te10(Config) when is_list(Config) -> + {Exp,Res} = te10(), + ok = check(te10(doc),Exp,Res). + +te10() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config1(),mtid10()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% basic_enc_dec_with_one_rec_wildcard02 +te11(doc) -> + "Basic encode & decode with one recursive wildcard [1,11]\n (asn -> binary -> asn)"; + +te11(suite) -> + []; + +te11(Config) when is_list(Config) -> + {Exp,Res} = te11(), + ok = check(te11(doc),Exp,Res). + +te11() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config1(),mtid11()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% basic_enc_dec_with_one_rec_wildcard03 +te12(doc) -> + "Basic encode & decode with one recursive wildcard [1,12]\n (asn -> binary -> asn)"; + +te12(suite) -> + []; + +te12(Config) when is_list(Config) -> + {Exp,Res} = te12(), + ok = check(te12(doc),Exp,Res). + +te12() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config1(),mtid12()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% basic_enc_dec_with_one_rec_wildcard04 +te13(doc) -> + "Basic encode & decode with one recursive wildcard [1,13]\n (asn -> binary -> asn)"; + +te13(suite) -> + []; + +te13(Config) when is_list(Config) -> + {Exp,Res} = te13(), + ok = check(te13(doc),Exp,Res). + +te13() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config1(),mtid13()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% basic_enc_dec_with_one_rec_wildcard05 +te14(doc) -> + "Basic encode & decode with one recursive wildcard [2,13]\n (asn -> binary -> asn)"; + +te14(suite) -> + []; + +te14(Config) when is_list(Config) -> + {Exp,Res} = te14(), + ok = check(te14(doc),Exp,Res). + +te14() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config2(),mtid13()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% basic_enc_dec_with_one_wildcard_1level +te15(doc) -> + "Basic encode & decode with one wildcard in the first level\nand then one empty level [1,15]\n (asn -> binary -> asn)"; + +te15(suite) -> + []; + +te15(Config) when is_list(Config) -> + {Exp,Res} = te15(), + ok = check(te15(doc),Exp,Res). + +te15() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config1(),mtid15()), + erase(encode_debug), + erase(decode_debug), + {error,Res}. + + +%% -------------------------------------------------------- + +%% basic_enc_dec_with_one_rec_wildcard06 +te16(doc) -> + "Basic encode & decode with one recursive wildcard [2,15]\n (asn -> binary -> asn)"; + +te16(suite) -> + []; + +te16(Config) when is_list(Config) -> + {Exp,Res} = te16(), + ok = check(te16(doc),Exp,Res). + +te16() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config2(),mtid15()), + erase(encode_debug), + erase(decode_debug), + {error,Res}. + + +%% -------------------------------------------------------- + +%% basic_enc_dec_with_one_rec_wildcard07 +te17(doc) -> + "Basic encode & decode with one recursive wildcard [2,11]\n (asn -> binary -> asn)"; + +te17(suite) -> + []; + +te17(Config) when is_list(Config) -> + {Exp,Res} = te17(), + ok = check(te17(doc),Exp,Res). + +te17() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config2(),mtid11()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% basic_enc_dec_with_one_rec_wildcard08 +te18(doc) -> + "Basic encode & decode with one recursive wildcard [4,16]\n (asn -> binary -> asn)"; + +te18(suite) -> + []; + +te18(Config) when is_list(Config) -> + {Exp,Res} = te18(), + ok = check(te18(doc),Exp,Res). + +te18() -> + put(encode_debug,dbg), + put(decode_debug,dbg), + Res = encode_decode(config4(),mtid16()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% basic_enc_dec_with_one_rec_wildcard09 +te19(doc) -> + "Basic encode & decode with one recursive wildcard [4,17]\n (asn -> binary -> asn)"; + +te19(suite) -> + []; + +te19(Config) when is_list(Config) -> + {Exp,Res} = te19(), + ok = check(te19(doc),Exp,Res). + +te19() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = encode_decode(config4(),mtid17()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% root_term_dec_enc +td01(doc) -> + "Root termination decoding & then encoding test [1,1]\n (binary -> asn -> binary)"; + +td01(suite) -> + []; + +td01(Config) when is_list(Config) -> + {Exp,Res} = td01(), + ok = check(td01(doc),Exp,Res). + +td01() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = decode_encode(config1(),atid1()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% One byte to much (should be two bytes but is three) +%% basic_dec_enc01 +td02(doc) -> + "Basic decoding & then encoding test [1,2]\n (binary -> asn -> binary)"; + +td02(suite) -> + []; + +td02(Config) when is_list(Config) -> + {Exp,Res} = td02(), + ok = check(td02(doc),Exp,Res). + +td02() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = decode_encode(config1(),atid2()), + erase(encode_debug), + erase(decode_debug), + {error,Res}. + + +%% -------------------------------------------------------- + +%% basic_dec_enc02 +td03(doc) -> + "Basic decoding & then encoding test [2,2]\n (binary -> asn -> binary)"; + +td03(suite) -> + []; + +td03(Config) when is_list(Config) -> + {Exp,Res} = td03(), + ok = check(td03(doc),Exp,Res). + +td03() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = decode_encode(config2(),atid2()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% basic_dec_enc03 +td04(doc) -> + "Basic decoding & then encoding test [2,3]\n (binary -> asn -> binary)"; + +td04(suite) -> + []; + +td04(Config) when is_list(Config) -> + {Exp,Res} = td04(), + ok = check(td04(doc),Exp,Res). + +td04() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = decode_encode(config2(),atid3()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% basic_dec_enc04 +td05(doc) -> + "Basic decoding & then encoding test [2,4]\n (binary -> asn -> binary)"; + +td05(suite) -> + []; + +td05(Config) when is_list(Config) -> + {Exp,Res} = td05(), + ok = check(td05(doc),Exp,Res). + +td05() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = decode_encode(config2(),atid4()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- + +%% basic_dec_enc05 +td06(doc) -> + "Basic decoding & then encoding test [3,5]\n (binary -> asn -> binary)"; + +td06(suite) -> + []; + +td06(Config) when is_list(Config) -> + {Exp,Res} = td06(), + ok = check(td06(doc),Exp,Res). + +td06() -> + %% put(encode_debug,dbg), + %% put(decode_debug,dbg), + Res = decode_encode(config3(),atid5()), + erase(encode_debug), + erase(decode_debug), + {ok,Res}. + + +%% -------------------------------------------------------- +%% -------------------------------------------------------- + +encode_decode(C,T) -> + case encode(C,T) of + {ok,T1} -> + case decode(C,T1) of + {ok,T2} -> + {ok,T,T1,T2}; + {error,R2} -> + {error,{decode_error,T,T1,R2}}; + {exit,E2} -> + {error,{decode_exit,T,T1,E2}} + end; + {error,R1} -> + {error,{encode_error,T,R1}}; + {exit,E1} -> + {error,{encode_exit,T,E1}} + end. + +decode_encode(C,T) -> + case decode(C,T) of + {ok,T1} -> + case encode(C,T1) of + {ok,T2} -> + {ok,T,T1,T2}; + {error,R2} -> + {error,{encode_error,T,T1,R2}}; + {exit,E2} -> + {error,{encode_exit,T,T1,E2}} + end; + {error,R1} -> + {error,{decode_error,T,R1}}; + {exit,E1} -> + {error,{decode_exit,T,E1}} + end. + +%% ------------------ + +config1() -> [3,8,5]. +config2() -> [3,5,4,8,4]. +config3() -> [3,5,4,16,4]. +config4() -> [8,8,8]. % Default config + +mtid01() -> + #megaco_term_id{contains_wildcards = false, + id = [[$1,$0,$1], + [$1,$1,$0,$1,$0,$0,$0,$1], + [$1,$1,$0,$1,$1]]}. +mtid02() -> + #megaco_term_id{contains_wildcards = true, + id = [[$1,$0,$$],[$1,$1,$0,$1,$$],[$1,$1,$*]]}. +mtid03() -> + #megaco_term_id{contains_wildcards = true, + id = [[$1,$0,$1],[$1,$0,$1,$$],[$1,$1,$*]]}. +mtid04() -> + #megaco_term_id{contains_wildcards = true, + id = [[$1,$0,$$],[$1,$1,$0,$1,$$],[$1,$1,$1,$0,$0]]}. +mtid05() -> + #megaco_term_id{contains_wildcards = true, + id = [[$1,$0,$1],[$1,$1,$0,$1,$$],[$1,$1,$1,$0,$0]]}. +mtid06() -> + #megaco_term_id{contains_wildcards = false, + id = [[$1,$0,$$],[$1,$1,$0,$1,$$],[$1,$1,$*]]}. +mtid07() -> + #megaco_term_id{contains_wildcards = true, + id = [[$1,$0,$*],[$1,2,$0,$1,$$],[$1,$1,$1,$0,$0]]}. +mtid08() -> + #megaco_term_id{contains_wildcards = true, + id = [[$1,$0,$*,$1],[$1,$1,$0,$1,$$],[$1,$1,$1,$0,$0]]}. +mtid09() -> + #megaco_term_id{contains_wildcards = true, + id = [[$1,$0,$0,$1],[$1,$1,$0,$1,$$],[$1,$1,$1,$0,$0]]}. +mtid10() -> + #megaco_term_id{contains_wildcards = true, + id = [[$1,$0,$1],[$1,$0,$1,$$],[$$]]}. +mtid11() -> + #megaco_term_id{contains_wildcards = true, + id = [[$1,$0,$1],[$1,$0,$1,$$]]}. +mtid12() -> + #megaco_term_id{contains_wildcards = true, + id = [[$1,$0,$1],[$1,$0,$1,$0,$1,$1,$$]]}. +mtid13() -> + #megaco_term_id{contains_wildcards = true, + id = [[$1,$0,$*]]}. +%% Empty last level +%% mtid14() -> +%% #megaco_term_id{contains_wildcards = true, +%% id = [[$1,$0,$*],[$1,$0,$0,$$],[]]}. + +%% Empty second level and missing last level +mtid15() -> + #megaco_term_id{contains_wildcards = true, + id = [[$1,$0,$*],[]]}. +%% Megaco all wildcard termination id +mtid16() -> + #megaco_term_id{contains_wildcards = true, + id = [[?megaco_all]]}. +%% Megaco choose wildcard termination id +mtid17() -> + #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}. + +aroot() -> + #'TerminationID'{wildcard = [], + id = [16#FF, 16#FF, 16#FF, 16#FF, + 16#FF, 16#FF, 16#FF, 16#FF]}. +atid1() -> aroot(). +atid2() -> + #'TerminationID'{wildcard = [], + id = [2#00000001, 02#00011110, 2#0]}. +atid3() -> + #'TerminationID'{wildcard = [[2#00010111], [2#00000111]], + id = [2#0, 2#00011110, 2#0]}. +atid4() -> + #'TerminationID'{wildcard = [[2#01001111]], + id = [2#0000001, 2#0, 2#0]}. +%% +atid5() -> + #'TerminationID'{wildcard = [[2#01001111]], + id = [2#00000001, 2#00110011, + 2#00000000, 2#00000000]}. + +%%-- + + +%% ------------------ + +encode(C,T) -> + encode(get(encode_debug),C,T). + +encode(L,C,T) -> + put(dsev,L), + Res = encode1(C,T), + erase(dsev), + Res. + +encode1(C,T) -> + case (catch megaco_binary_term_id:encode(C,T)) of + {'EXIT',Reason} -> + {exit,Reason}; + Else -> + Else + end. + +decode(C,T) -> + decode(get(decode_debug),C,T). + +decode(L,C,T) -> + put(dsev,L), + Res = decode1(C,T), + erase(dsev), + Res. + +decode1(C,T) -> + case (catch megaco_binary_term_id:decode(C,T)) of + {'EXIT',Reason} -> + {exit,Reason}; + Else -> + Else + end. + + + + diff --git a/lib/megaco/test/megaco_call_flow_test.erl b/lib/megaco/test/megaco_call_flow_test.erl new file mode 100644 index 0000000000..a25a7924e8 --- /dev/null +++ b/lib/megaco/test/megaco_call_flow_test.erl @@ -0,0 +1,1767 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test encoding/decoding of the sample call flows Megaco/H.248 +%%---------------------------------------------------------------------- +%% megaco_call_flow_test:pretty_text(). +%% megaco_call_flow_test:compact_text(). +%% megaco_call_flow_test:bin(). +%% megaco_call_flow_test:asn1_ber(). +%% megaco_call_flow_test:asn1_ber_bin(). +%% megaco_call_flow_test:asn1_per(). +%% megaco_call_flow_test:erl_dist(). +%% megaco_call_flow_test:compressed_erl_dist(). +%% megaco_call_flow_test:gnuplot_gif(). +%% megaco_call_flow_test:gnuplot_size_gif(). +%% megaco_call_flow_test:gnuplot_enc_time_gif(). +%% megaco_call_flow_test:gnuplot_dec_time_gif(). +%% megaco_call_flow_test:gnuplot_code_time_gif(). +%%---------------------------------------------------------------------- + +-module(megaco_call_flow_test). + +-compile(export_all). +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). +-include("megaco_test_lib.hrl"). + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + +%% Test server callbacks +init_per_testcase(Case, Config) -> + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + megaco_test_lib:fin_per_testcase(Case, Config). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top test case + +all(suite) -> + [ + text, + binary + ]. + +text(suite) -> + [ + pretty, + compact + ]. + +flex(suite) -> + [ + pretty_flex, + compact_flex + ]. + +binary(suite) -> + [ + bin, + ber, + ber_bin, + per + ]. + +pretty(suite) -> + []; +pretty(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + pretty_text(). + +compact(suite) -> + []; +compact(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + compact_text(). + +pretty_flex(suite) -> + []; +pretty_flex(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + pretty_flex(). + +compact_flex(suite) -> + []; +compact_flex(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + compact_flex(). + +bin(suite) -> + []; +bin(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + bin(). + +ber(suite) -> + []; +ber(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + asn1_ber(). + +ber_bin(suite) -> + []; +ber_bin(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + asn1_ber_bin(). + +per(suite) -> + []; +per(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + asn1_per(). + +standard_erl(suite) -> + []; +standard_erl(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + standard_erl(). + +compressed_erl(suite) -> + []; +compressed_erl(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + compressed_erl(). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-define(PP(Name, Val), #'PropertyParm'{name = Name, value = [Val]}). +-define(SP(Name, Val), #'StatisticsParameter'{statName = Name, statValue = [Val]}) . + +names() -> + [ + msg1, msg2, msg3, msg4, msg5a, msg5b, msg6, msg7, msg9, msg10, + msg11, msg12, msg13, msg14, msg15, msg16, msg17a, msg17b, + msg18a, msg18b, msg18c, msg18d, msg19a, msg19b, msg20, msg21, + msg22a, msg22b, msg23a, msg23b + ]. + +%% In this example, MG1 has the IP address 124.124.124.222, MG2 is +%% 125.125.125.111, and the MGC is 123.123.123.4. The default Megaco port +%% is 55555 for all three. + +-define(DEFAULT_PORT, 55555). +-define(MG1_MID_NO_PORT, {ip4Address, + #'IP4Address'{address = [124, 124, 124, 222]}}). +-define(MG1_MID, {ip4Address, #'IP4Address'{address = [124, 124, 124, 222], + portNumber = ?DEFAULT_PORT}}). +-define(MG2_MID, {ip4Address, #'IP4Address'{address = [125, 125, 125, 111], + portNumber = ?DEFAULT_PORT}}). +-define(MGC_MID, {ip4Address, #'IP4Address'{address = [123, 123, 123, 4], + portNumber = ?DEFAULT_PORT}}). + +-define(A4444, ["11111111", "00000000", "00000000"]). +-define(A4445, ["11111111", "00000000", "11111111"]). +-define(A5555, ["11111111", "11111111", "00000000"]). +-define(A5556, ["11111111", "11111111", "11111111"]). + +%% -define(A4444, ["00000000"]). +%% -define(A4445, ["00001111"]). +%% -define(A5555, ["11110000"]). +%% -define(A5556, ["11111111"]). + +request(Mid, TransId, ContextId, CmdReq) when is_list(CmdReq) -> + Actions = [#'ActionRequest'{contextId = ContextId, + commandRequests = CmdReq}], + Req = {transactions, + [{transactionRequest, + #'TransactionRequest'{transactionId = TransId, + actions = Actions}}]}, + #'MegacoMessage'{mess = #'Message'{version = 1, + mId = Mid, + messageBody = Req}}. + +reply(Mid, TransId, ContextId, CmdReply) when is_list(CmdReply) -> + Actions = [#'ActionReply'{contextId = ContextId, + commandReply = CmdReply}], + Req = {transactions, + [{transactionReply, + #'TransactionReply'{transactionId = TransId, + transactionResult = {actionReplies, Actions}}}]}, + #'MegacoMessage'{mess = #'Message'{version = 1, + mId = Mid, + messageBody = Req}}. + +%%---------------------------------------------------------------------- +%% 1. An MG registers with an MGC using the ServiceChange command: +%% +%% MG1 to MGC: +%% "MEGACO/1 [124.124.124.222] +%% Transaction = 9998 { +%% Context = - { +%% ServiceChange = ROOT {Services { +%% Method=Restart, +%% ServiceChangeAddress=55555, Profile=ResGW/1} +%% } +%% } +%% } +%%---------------------------------------------------------------------- + +msg1() -> + msg1(?MG1_MID_NO_PORT). +msg1(Mid) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = #'ServiceChangeProfile'{profileName = "resgw", + version = 1}, + Parm = #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeAddress = Address, + serviceChangeReason = ["901 mg cold boot"], + %% BUGBUG: Mandatory reason missing in spec + serviceChangeProfile = Profile}, + Req = #'ServiceChangeRequest'{terminationID = [?megaco_root_termination_id], + serviceChangeParms = Parm}, + CmdReq = #'CommandRequest'{command = {serviceChangeReq, Req}}, + request(Mid, 9998, ?megaco_null_context_id, [CmdReq]). + +%%---------------------------------------------------------------------- +%% +%% 2. The MGC sends a reply: +%% +%% MGC to MG1: +%% MEGACO/1 [123.123.123.4]:55555 +%% Reply = 9998 { +%% Context = - {ServiceChange = ROOT { +%% Services {ServiceChangeAddress=55555, Profile=ResGW/1} } } +%% } +%%---------------------------------------------------------------------- + +msg2() -> + msg2(?MGC_MID). +msg2(Mid) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = #'ServiceChangeProfile'{profileName = "resgw", + version = 1}, + Parm = #'ServiceChangeResParm'{serviceChangeAddress = Address, + serviceChangeProfile = Profile}, + Reply = #'ServiceChangeReply'{terminationID = [?megaco_root_termination_id], + serviceChangeResult = {serviceChangeResParms, + Parm}}, + reply(Mid, 9998, ?megaco_null_context_id, [{serviceChangeReply, Reply}]). + +%%---------------------------------------------------------------------- +%% 3. The MGC programs a Termination in the NULL context. The +%% terminationId is A4444, the streamId is 1, the requestId in the +%% Events descriptor is 2222. The mId is the identifier of the sender +%% of this message, in this case, it is the IP address and port +%% [123.123.123.4]:55555. Mode for this stream is set to +%% SendReceive. "al" is the analog line supervision package. +%% +%% MGC to MG1: +%% MEGACO/1 [123.123.123.4]:55555 +%% Transaction = 9999 { +%% Context = - { +%% Modify = A4444 { +%% Media { Stream = 1 { +%% LocalControl { +%% Mode = SendReceive, +%% tdmc/gain=2, ; in dB, +%% tdmc/ec=G165 +%% }, +%% Local { +%% v=0 +%% c=IN IP4 $ +%% m=audio $ RTP/AVP 0 +%% a=fmtp:PCMU VAD=X-NNVAD ; special voice activity +%% ; detection algorithm +%% } +%% } +%% }, +%% Events = 2222 {al/of} +%% } +%% } +%% } +%%---------------------------------------------------------------------- + +msg3() -> + msg3(?MGC_MID). +msg3(Mid) -> + msg3(Mid, ?A4444). +msg3(Mid, Tid) -> + Gain = ?PP("tdmc/gain", "2"), + %% Ec = ?PP("tdmc/ec", "G165"), + Ec = ?PP("tdmc/ec", "g165"), %% BUGBUG: should be case insensitive + LCD = #'LocalControlDescriptor'{streamMode = sendRecv, + propertyParms = [Gain, Ec]}, + V = ?PP("v", "0"), + C = ?PP("c", "IN IP4 $ "), + M = ?PP("m", "audio $ RTP/AVP 0"), + A = ?PP("a", "fmtp:PCMU VAD=X-NNVAD"), + LD = #'LocalRemoteDescriptor'{propGrps = [[V, C, M, A]]}, + Parms = #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD}, + StreamDesc = #'StreamDescriptor'{streamID = 1, + streamParms = Parms}, + MediaDesc = #'MediaDescriptor'{streams = {multiStream, [StreamDesc]}}, + ReqEvent = #'RequestedEvent'{pkgdName = "al/of", + evParList = []}, + EventsDesc = #'EventsDescriptor'{requestID = 2222, + eventList = [ReqEvent]}, + AmmReq = #'AmmRequest'{terminationID = [#megaco_term_id{id = Tid}], + descriptors = [{mediaDescriptor, MediaDesc}, + {eventsDescriptor, EventsDesc}]}, + CmdReq = #'CommandRequest'{command = {modReq, AmmReq}}, + request(Mid, 9999, ?megaco_null_context_id, [CmdReq]). + +%%---------------------------------------------------------------------- +%% The dialplan script could have been loaded into the MG previously. +%% Its function would be to wait for the OffHook, turn on dialtone and +%% start collecting DTMF digits. However in this example, we use the +%% digit map, which is put into place after the offhook is detected (step +%% 5 below). +%% +%% +%% Note that the embedded EventsDescriptor could have been used to +%% combine steps 3 and 4 with steps 8 and 9, eliminating steps 6 and 7. +%% +%% +%% 4. The MG1 accepts the Modify with this reply: +%% +%% MG1 to MGC: +%% MEGACO/1 [124.124.124.222]:55555 +%% Reply = 9999 { +%% Context = - {Modify = A4444} +%% } +%%---------------------------------------------------------------------- + +msg4() -> + msg4(?MG1_MID). +msg4(Mid) -> + msg4(Mid, ?A4444). +msg4(Mid, Tid) -> + Reply = #'AmmsReply'{terminationID = [#megaco_term_id{id = Tid}]}, + reply(Mid, 9999, ?megaco_null_context_id, [{modReply, Reply}]). + +%%---------------------------------------------------------------------- +%% 5. A similar exchange happens between MG2 and the MGC, resulting in an +%% idle Termination called A5555. +%%---------------------------------------------------------------------- + +msg5a() -> + msg5a(?MGC_MID). +msg5a(Mid) -> + msg3(Mid, ?A4444). + +msg5b() -> + msg5b(?MG2_MID). +msg5b(Mid) -> + msg4(Mid, ?A5555). + +%%---------------------------------------------------------------------- +%% A.1.2 Collecting Originator Digits and Initiating Termination +%% +%% The following builds upon the previously shown conditions. It +%% illustrates the transactions from the Media Gateway Controller and +%% originating Media Gateway (MG1) to get the originating Termination +%% (A4444) through the stages of digit collection required to initiate a +%% connection to the terminating Media Gateway (MG2). +%% +%% 6. MG1 detects an offhook event from User 1 and reports it to the +%% Media Gateway Controller via the Notify Command. +%% +%% MG1 to MGC: +%% MEGACO/1 [124.124.124.222]:55555 +%% Transaction = 10000 { +%% Context = - { +%% Notify = A4444 {ObservedEvents =2222 { +%% 19990729T22000000:al/of}} +%% } +%% } +%%---------------------------------------------------------------------- + +msg6() -> + msg6(?MG1_MID). +msg6(Mid) -> + TimeStamp = #'TimeNotation'{date = "19990729", + time = "22000000"}, + Event = #'ObservedEvent'{eventName = "al/of", + timeNotation = TimeStamp, + eventParList = []}, + Desc = #'ObservedEventsDescriptor'{requestId = 2222, + observedEventLst = [Event]}, + NotifyReq = #'NotifyRequest'{terminationID = [#megaco_term_id{id = ?A4444}], + observedEventsDescriptor = Desc}, + CmdReq = #'CommandRequest'{command = {notifyReq, NotifyReq}}, + request(Mid, 10000, ?megaco_null_context_id, [CmdReq]). + +%%---------------------------------------------------------------------- +%% 7. And the Notify is acknowledged. +%% +%% MGC to MG1: +%% MEGACO/1 [123.123.123.4]:55555 +%% Reply = 10000 { +%% Context = - {Notify = A4444} +%% } +%%---------------------------------------------------------------------- + +msg7() -> + msg7(?MGC_MID). +msg7(Mid) -> + Reply = #'NotifyReply'{terminationID = [#megaco_term_id{id = ?A4444}]}, + reply(Mid, 10000, ?megaco_null_context_id, [{notifyReply, Reply}]). + +%%---------------------------------------------------------------------- +%% 8. The MGC Modifies the termination to play dial tone, and to look for +%% digits now. There is also an embedded event to stop dialtone upon +%% detection of the first digit. dd is the DTMF Detection package, and +%% ce is the completion event. +%%---------------------------------------------------------------------- + +%% BUGBUG: Example missing in spec + +%%---------------------------------------------------------------------- +%% 9. +%% +%% MGC to MG1: +%% MEGACO/1 [123.123.123.4]:55555 +%% Transaction = 10001 { +%% Context = - { +%% Modify = A4444 { +%% Events = 2223 { +%% al/on, dd/ce {DigitMap=Dialplan0} +%% }, +%% Signals {cg/dt}, +%% DigitMap= Dialplan0{ +%% (0S| 00S|[1-7]xLxx|8Lxxxxxxx|#xxxxxxx|*xx|9L1xxxxxxxxxx|9L011x.S)} +%% } +%% } +%% } +%%---------------------------------------------------------------------- + +msg9() -> + msg9(?MGC_MID). +msg9(Mid) -> + Name = "dialplan00", + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = #'DigitMapValue'{digitMapBody = Body}, + On = #'RequestedEvent'{pkgdName = "al/on", evParList = []}, + Action = #'RequestedActions'{eventDM = {digitMapName, Name}}, + Ce = #'RequestedEvent'{pkgdName = "dd/ce", + eventAction = Action, + evParList = []}, + EventsDesc = #'EventsDescriptor'{requestID = 2223, + eventList = [On, Ce]}, + Signal = #'Signal'{signalName = "cg/rt", sigParList = []}, + DigMapDesc = #'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value}, + AmmReq = #'AmmRequest'{terminationID = [#megaco_term_id{id = ?A4444}], + descriptors = [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, [{signal, Signal}]}, + {digitMapDescriptor, DigMapDesc}]}, + CmdReq = #'CommandRequest'{command = {modReq, AmmReq}}, + request(Mid, 10001, ?megaco_null_context_id, [CmdReq]). + +%%---------------------------------------------------------------------- +%% 10. And the Modify is acknowledged. +%% +%% MG1 to MGC: +%% MEGACO/1 [124.124.124.222]:55555 +%% Reply = 10001 { +%% Context = - {Modify = A4444} +%% } +%%---------------------------------------------------------------------- + +msg10() -> + msg10(?MG1_MID). +msg10(Mid) -> + Reply = #'AmmsReply'{terminationID = [#megaco_term_id{id = ?A4444}]}, + reply(Mid, 10001, ?megaco_null_context_id, [{modReply, Reply}]). + +%%---------------------------------------------------------------------- +%% 11. Next, digits are accumulated by MG1 as they are dialed by User 1. +%% Dialtone is stopped upon detection of the first digit, using the +%% embedded event in step 8. When an appropriate match is made of +%% collected digits against the currently programmed Dialplan for +%% A4444, another Notify is sent to the Media Gateway Controller. +%% +%% MG1 to MGC: +%% MEGACO/1 [124.124.124.222]:55555 +%% Transaction = 10002 { +%% Context = - { +%% Notify = A4444 {ObservedEvents =2223 { +%% 19990729T22010001:dd/ce{ds="916135551212"}}} +%% } +%% } +%%---------------------------------------------------------------------- + +msg11() -> + msg11(?MG1_MID). +msg11(Mid) -> + TimeStamp = #'TimeNotation'{date = "19990729", + time = "22010001"}, + Parm = #'EventParameter'{eventParameterName = "ds", + value = ["916135551212"]}, + %% BUGBUG: Quoted string or safe char? + Event = #'ObservedEvent'{eventName = "dd/ce", + timeNotation = TimeStamp, + eventParList = [Parm]}, + Desc = #'ObservedEventsDescriptor'{requestId = 2223, + observedEventLst = [Event]}, + NotifyReq = #'NotifyRequest'{terminationID = [#megaco_term_id{id = ?A4444}], + observedEventsDescriptor = Desc}, + CmdReq = #'CommandRequest'{command = {notifyReq, NotifyReq}}, + request(Mid, 10002, ?megaco_null_context_id, [CmdReq]). + +%%---------------------------------------------------------------------- +%% 12. And the Notify is acknowledged. +%% +%% MGC to MG1: +%% MEGACO/1 [123.123.123.4]:55555 +%% Reply = 10002 { +%% Context = - {Notify = A4444} +%% } +%%---------------------------------------------------------------------- + +msg12() -> + msg12(?MGC_MID). +msg12(Mid) -> + Reply = #'NotifyReply'{terminationID = [#megaco_term_id{id = ?A4444}]}, + reply(Mid, 10002, ?megaco_null_context_id, [{notifyReply, Reply}]). + +%%---------------------------------------------------------------------- +%% 13. The controller then analyses the digits and determines that a +%% connection needs to be made from MG1 to MG2. Both the TDM +%% termination A4444, and an RTP termination are added to a new +%% context in MG1. Mode is ReceiveOnly since Remote descriptor values +%% are not yet specified. Preferred codecs are in the MGC's preferred +%% order of choice. +%% +%% MGC to MG1: +%% MEGACO/1 [123.123.123.4]:55555 +%% Transaction = 10003 { +%% Context = $ { +%% Add = A4444, +%% Add = $ { +%% Media { +%% Stream = 1 { +%% LocalControl { +%% Mode = ReceiveOnly, +%% +%% nt/jit=40, ; in ms +%% }, +%% Local { +%% v=0 +%% c=IN IP4 $ +%% m=audio $ RTP/AVP 4 +%% a=ptime:30 +%% v=0 +%% c=IN IP4 $ +%% m=audio $ RTP/AVP 0 +%% } +%% } +%% } +%% } +%% } +%% } +%% +%% NOTE - The MGC states its prefrred parameter values as a series of +%% sdp blocks in Local. The MG fills in the Local Descriptor in the +%% Reply. +%%---------------------------------------------------------------------- + +msg13() -> + msg13(?MGC_MID). +msg13(Mid) -> + AmmReq = #'AmmRequest'{terminationID = [#megaco_term_id{id = ?A4444}], + descriptors = []}, + CmdReq = #'CommandRequest'{command = {addReq, AmmReq}}, + Jit = ?PP("nt/jit", "40"), + LCD = #'LocalControlDescriptor'{streamMode = recvOnly, + propertyParms = [Jit]}, + V = ?PP("v", "0"), + C = ?PP("c", "IN IP4 $ "), + M = ?PP("m", "audio $ RTP/AVP 4"), + A = ?PP("a", "ptime:30"), + V2 = ?PP("v", "0"), + C2 = ?PP("c", "IN IP4 $ "), + M2 = ?PP("m", "audio $ RTP/AVP 0"), + LD = #'LocalRemoteDescriptor'{propGrps = [[V, C, M, A], [V2, C2, M2]]}, + Parms = #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD}, + StreamDesc = #'StreamDescriptor'{streamID = 1, + streamParms = Parms}, + MediaDesc = #'MediaDescriptor'{streams = {multiStream, [StreamDesc]}}, + ChooseTid = #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}, + AmmReq2 = #'AmmRequest'{terminationID = [ChooseTid], + descriptors = [{mediaDescriptor, MediaDesc}]}, + CmdReq2 = #'CommandRequest'{command = {addReq, AmmReq2}}, + request(Mid, 10003, ?megaco_choose_context_id, [CmdReq, CmdReq2]). + +%%---------------------------------------------------------------------- +%% 14. MG1 acknowledges the new Termination and fills in the Local IP +%% address and UDP port. It also makes a choice for the codec based +%% on the MGC preferences in Local. MG1 sets the RTP port to 2222. +%% +%% MEGACO/1 [124.124.124.222]:55555 +%% Reply = 10003 { +%% Context = 2000 { +%% Add = A4444, +%% Add=A4445{ +%% Media { +%% Stream = 1 { +%% Local { +%% v=0 +%% c=IN IP4 124.124.124.222 +%% m=audio 2222 RTP/AVP 4 +%% a=ptime:30 +%% a=recvonly +%% } ; RTP profile for G.723 is 4 +%% } +%% } +%% } +%% } +%% } +%%---------------------------------------------------------------------- + +msg14() -> + msg14(?MG1_MID). +msg14(Mid) -> + V = ?PP("v", "0"), + C = ?PP("c", "IN IP4 124.124.124.222"), + M = ?PP("m", "audio 2222 RTP/AVP 4"), + A = ?PP("a", "a=ptime:30"), + A2= ?PP("a", "recvonly"), + LD = #'LocalRemoteDescriptor'{propGrps = [[V, C, M, A, A2]]}, + Parms = #'StreamParms'{localDescriptor = LD}, + StreamDesc = #'StreamDescriptor'{streamID = 1, + streamParms = Parms}, + MediaDesc = #'MediaDescriptor'{streams = {multiStream, [StreamDesc]}}, + Reply = #'AmmsReply'{terminationID = [#megaco_term_id{id = ?A4444}]}, + Reply2 = #'AmmsReply'{terminationID = [#megaco_term_id{id = ?A4445}], + terminationAudit = [{mediaDescriptor, MediaDesc}]}, + reply(Mid, 10003, 2000, [{addReply, Reply}, {addReply, Reply2}]). + +%%---------------------------------------------------------------------- +%% 15. The MGC will now associate A5555 with a new Context on MG2, and +%% establish an RTP Stream (i.e, A5556 will be assigned), SendReceive +%% connection through to the originating user, User 1. The MGC also +%% sets ring on A5555. +%% +%% MGC to MG2: +%% MEGACO/1 [123.123.123.4]:55555 +%% Transaction = 50003 { +%% Context = $ { +%% Add = A5555 { Media { +%% Stream = 1 { +%% LocalControl {Mode = SendReceive} }}, +%% Signals {al/ri} +%% }, +%% Add = $ {Media { +%% Stream = 1 { +%% LocalControl { +%% Mode = SendReceive, +%% nt/jit=40 ; in ms +%% }, +%% Local { +%% v=0 +%% c=IN IP4 $ +%% m=audio $ RTP/AVP 4 +%% a=ptime:30 +%% }, +%% Remote { +%% v=0 +%% c=IN IP4 124.124.124.222 +%% m=audio 2222 RTP/AVP 4 +%% a=ptime:30 +%% } ; RTP profile for G.723 is 4 +%% } +%% } +%% } +%% } +%% } +%%---------------------------------------------------------------------- + +msg15() -> + msg15(?MGC_MID). +msg15(Mid) -> + LCD = #'LocalControlDescriptor'{streamMode = sendRecv, + propertyParms = []}, + Parms = #'StreamParms'{localControlDescriptor = LCD}, + StreamDesc = #'StreamDescriptor'{streamID = 1, + streamParms = Parms}, + MediaDesc = #'MediaDescriptor'{streams = {multiStream, [StreamDesc]}}, + Signal = #'Signal'{signalName = "al/ri", + sigParList = []}, + AmmReq = #'AmmRequest'{terminationID = [#megaco_term_id{id = ?A5555}], + descriptors = [{mediaDescriptor, MediaDesc}, + {signalsDescriptor, [{signal, Signal}]}]}, + CmdReq = #'CommandRequest'{command = {addReq, AmmReq}}, + Jit = ?PP("nt/jit", "40"), + LCD2 = #'LocalControlDescriptor'{streamMode = sendRecv, + propertyParms = [Jit]}, + V = ?PP("v", "0"), + C = ?PP("c", "IN IP4 $ "), + M = ?PP("m", "audio $ RTP/AVP 4"), + A = ?PP("a", "ptime:30"), + LD2 = #'LocalRemoteDescriptor'{propGrps = [[V, C, M, A]]}, + V2 = ?PP("v", "0"), + C2 = ?PP("c", "IN IP4 124.124.124.222"), + M2 = ?PP("m", "audio 2222 RTP/AVP 4"), + RD2 = #'LocalRemoteDescriptor'{propGrps = [[V2, C2, M2]]}, + Parms2 = #'StreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2}, + StreamDesc2 = #'StreamDescriptor'{streamID = 1, + streamParms = Parms2}, + MediaDesc2 = #'MediaDescriptor'{streams = {multiStream, [StreamDesc2]}}, + ChooseTid = #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}, + AmmReq2 = #'AmmRequest'{terminationID = [ChooseTid], + descriptors = [{mediaDescriptor, MediaDesc2}]}, + CmdReq2 = #'CommandRequest'{command = {addReq, AmmReq2}}, + request(Mid, 50003, ?megaco_choose_context_id, [CmdReq, CmdReq2]). + +%%---------------------------------------------------------------------- +%% 16. This is acknowledged. The stream port number is different from the +%% control port number. In this case it is 1111 (in the SDP). +%% +%% MG2 to MGC: +%% MEGACO/1 [124.124.124.222]:55555 +%% Reply = 50003 { +%% Context = 5000 { +%% Add = A5556{ +%% Media { +%% Stream = 1 { +%% Local { +%% v=0 +%% c=IN IP4 125.125.125.111 +%% m=audio 1111 RTP/AVP 4 +%% } +%% } ; RTP profile for G723 is 4 +%% } +%% } +%% } +%% } +%%---------------------------------------------------------------------- + +msg16() -> + msg16(?MG2_MID). +msg16(Mid) -> + V = ?PP("v", "0"), + C = ?PP("c", "IN IP4 125.125.125.111"), + M = ?PP("m", "audio 1111 RTP/AVP 4"), + LD = #'LocalRemoteDescriptor'{propGrps = [[V, C, M]]}, + Parms = #'StreamParms'{localDescriptor = LD}, + StreamDesc = #'StreamDescriptor'{streamID = 1, + streamParms = Parms}, + MediaDesc = #'MediaDescriptor'{streams = {multiStream, [StreamDesc]}}, + Reply = #'AmmsReply'{terminationID = [#megaco_term_id{id = ?A5556}], + terminationAudit = [{mediaDescriptor, MediaDesc}]}, + reply(Mid, 50003, 5000, [{addReply, Reply}]). + +%%---------------------------------------------------------------------- +%% 17. The above IPAddr and UDPport need to be given to MG1 now. +%% +%% MGC to MG1: +%% MEGACO/1 [123.123.123.4]:55555 +%% Transaction = 10005 { +%% Context = 2000 { +%% Modify = A4444 { +%% Signals {cg/rt} +%% }, +%% Modify = A4445 { +%% Media { +%% Stream = 1 { +%% Remote { +%% v=0 +%% c=IN IP4 125.125.125.111 +%% m=audio 1111 RTP/AVP 4 +%% } +%% } ; RTP profile for G723 is 4 +%% } +%% } +%% } +%% } +%%---------------------------------------------------------------------- + +msg17a() -> + msg17a(?MGC_MID). +msg17a(Mid) -> + Signal = #'Signal'{signalName = "cg/rt", sigParList = []}, + AmmReq = #'AmmRequest'{terminationID = [#megaco_term_id{id = ?A4444}], + descriptors = [{signalsDescriptor, [{signal, Signal}]}]}, + CmdReq = #'CommandRequest'{command = {modReq, AmmReq}}, + + V = ?PP("v", "0"), + C = ?PP("c", "IN IP4 125.125.125.111"), + M = ?PP("m", "audio 1111 RTP/AVP 4"), + RD2 = #'LocalRemoteDescriptor'{propGrps = [[V, C, M]]}, + Parms2 = #'StreamParms'{remoteDescriptor = RD2}, + StreamDesc2 = #'StreamDescriptor'{streamID = 1, + streamParms = Parms2}, + MediaDesc2 = #'MediaDescriptor'{streams = {multiStream, [StreamDesc2]}}, + AmmReq2 = #'AmmRequest'{terminationID = [#megaco_term_id{id = ?A4445}], + descriptors = [{mediaDescriptor, MediaDesc2}]}, + CmdReq2 = #'CommandRequest'{command = {modReq, AmmReq2}}, + request(Mid, 10005, 2000, [CmdReq, CmdReq2]). + +%%---------------------------------------------------------------------- +%% MG1 to MGC: +%% MEGACO/1 [124.124.124.222]:55555 +%% Reply = 10005 { +%% Context = 2000 {Modify = A4444, Modify = A4445} +%% } +%%---------------------------------------------------------------------- + +msg17b() -> + msg17b(?MG1_MID). +msg17b(Mid) -> + Reply = #'AmmsReply'{terminationID = [#megaco_term_id{id = ?A4444}]}, + Reply2 = #'AmmsReply'{terminationID = [#megaco_term_id{id = ?A4445}]}, + reply(Mid, 10005, 2000, [{modReply, Reply}, {modReply, Reply2}]). + +%%---------------------------------------------------------------------- +%% 18. The two gateways are now connected and User 1 hears the +%% RingBack. The MG2 now waits until User2 picks up the receiver and +%% then the two-way call is established. +%% +%% MG2 to MGC: +%% MEGACO/1 [125.125.125.111]:55555 +%% Transaction = 50005 { +%% Context = 5000 { +%% Notify = A5555 {ObservedEvents =1234 { +%% 19990729T22020002:al/of}} +%% } +%% } +%%---------------------------------------------------------------------- + +msg18a() -> + msg18a(?MG2_MID). +msg18a(Mid) -> + TimeStamp = #'TimeNotation'{date = "19990729", + time = "22020002"}, + Event = #'ObservedEvent'{eventName = "al/of", + timeNotation = TimeStamp, + eventParList = []}, + Desc = #'ObservedEventsDescriptor'{requestId = 1234, + observedEventLst = [Event]}, + NotifyReq = #'NotifyRequest'{terminationID = [#megaco_term_id{id = ?A5555}], + observedEventsDescriptor = Desc}, + CmdReq = #'CommandRequest'{command = {notifyReq, NotifyReq}}, + request(Mid, 50005, 5000, [CmdReq]). + +%%---------------------------------------------------------------------- +%% MGC to MG2: +%% MEGACO/1 [123.123.123.4]:55555 +%% Reply = 50005 { +%% Context = - {Notify = A5555} +%% } +%%---------------------------------------------------------------------- + +msg18b() -> + msg18b(?MGC_MID). +msg18b(Mid) -> + Reply = #'NotifyReply'{terminationID = [#megaco_term_id{id = ?A5555}]}, + reply(Mid, 50005, ?megaco_null_context_id, [{notifyReply, Reply}]). + +%%---------------------------------------------------------------------- +%% MGC to MG2: +%% MEGACO/1 [123.123.123.4]:55555 +%% Transaction = 50006 { +%% Context = 5000 { +%% Modify = A5555 { +%% Events = 1235 {al/on}, +%% Signals { } ; to turn off ringing +%% } +%% } +%% } +%%---------------------------------------------------------------------- + +msg18c() -> + msg18c(?MGC_MID). +msg18c(Mid) -> + On = #'RequestedEvent'{pkgdName = "al/on", evParList = []}, + EventsDesc = #'EventsDescriptor'{requestID = 1235, + eventList = [On]}, + AmmReq = #'AmmRequest'{terminationID = [#megaco_term_id{id = ?A5555}], + descriptors = [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, []}]}, + CmdReq = #'CommandRequest'{command = {modReq, AmmReq}}, + request(Mid, 50006, 5000, [CmdReq]). + +%%---------------------------------------------------------------------- +%% MG2 to MGC: +%% MEGACO/1 [125.125.125.111]:55555 +%% Reply = 50006 { +%% Context = 5000 {Modify = A4445} +%% } +%%---------------------------------------------------------------------- + +msg18d() -> + msg18d(?MG2_MID). +msg18d(Mid) -> + Reply = #'AmmsReply'{terminationID = [#megaco_term_id{id = ?A4445}]}, + reply(Mid, 50006, 5000, [{modReply, Reply}]). + +%%---------------------------------------------------------------------- +%% 19. Change mode on MG1 to SendReceive, and stop the ringback. +%% +%% MGC to MG1: +%% MEGACO/1 [123.123.123.4]:55555 +%% Transaction = 10006 { +%% Context = 2000 { +%% Modify = A4445 { +%% Media { +%% Stream = 1 { +%% LocalControl { +%% Mode=SendReceive +%% } +%% } +%% } +%% }, +%% Modify = A4444 { +%% Signals { } +%% } +%% } +%% } +%%---------------------------------------------------------------------- + +msg19a() -> + msg19a(?MGC_MID). +msg19a(Mid) -> + LCD = #'LocalControlDescriptor'{streamMode = sendRecv, + propertyParms = []}, + Parms = #'StreamParms'{localControlDescriptor = LCD}, + StreamDesc = #'StreamDescriptor'{streamID = 1, + streamParms = Parms}, + MediaDesc = #'MediaDescriptor'{streams = {multiStream, [StreamDesc]}}, + AmmReq = #'AmmRequest'{terminationID = [#megaco_term_id{id = ?A4445}], + descriptors = [{mediaDescriptor, MediaDesc}]}, + CmdReq = #'CommandRequest'{command = {modReq, AmmReq}}, + AmmReq2 = #'AmmRequest'{terminationID = [#megaco_term_id{id = ?A4444}], + descriptors = [{signalsDescriptor, []}]}, + CmdReq2 = #'CommandRequest'{command = {modReq, AmmReq2}}, + request(Mid, 10006, 2000, [CmdReq, CmdReq2]). + +%%---------------------------------------------------------------------- +%% MG1 to MGC: +%% MEGACO/1 [124.124.124.222]:55555 +%% Reply = 10006 { +%% Context = 2000 {Modify = A4445, Modify = A4444}} +%%---------------------------------------------------------------------- + +msg19b() -> + msg19b(?MG1_MID). +msg19b(Mid) -> + Reply = #'AmmsReply'{terminationID = [#megaco_term_id{id = ?A4445}]}, + Reply2= #'AmmsReply'{terminationID = [#megaco_term_id{id = ?A4444}]}, + reply(Mid, 10006, 2000, [{modReply, Reply}, {modReply, Reply2}]). + +%%---------------------------------------------------------------------- +%% 20. The MGC decides to Audit the RTP termination on MG2. +%% +%% MEGACO/1 [123.123.123.4]:55555 +%% Transaction = 50007 { +%% Context = - {AuditValue = A5556{ +%% Audit{Media, DigitMap, Events, Signals, Packages, Statistics }} +%% } +%% } +%%---------------------------------------------------------------------- + +msg20() -> + msg20(?MGC_MID). +msg20(Mid) -> + Tokens = [mediaToken, eventsToken, signalsToken, + digitMapToken, statsToken, packagesToken], + AuditDesc = #'AuditDescriptor'{auditToken = Tokens}, + Req = #'AuditRequest'{terminationID = #megaco_term_id{id = ?A5556}, + auditDescriptor = AuditDesc}, + CmdReq = #'CommandRequest'{command = {auditValueRequest, Req}}, + request(Mid, 50007, ?megaco_null_context_id, [CmdReq]). + +%%---------------------------------------------------------------------- +%% 21. The MG2 replies. An RTP termination has no events nor signals, so +%% these are left out in the reply . +%% +%% MEGACO/1 [125.125.125.111]:55555 +%% Reply = 50007 { +%% Context = - { +%% AuditValue = A5556 { +%% Media { +%% Stream = 1 { +%% LocalControl { Mode = SendReceive, +%% nt/jit=40 }, +%% Local { +%% v=0 +%% c=IN IP4 125.125.125.111 +%% m=audio 1111 RTP/AVP 4 +%% a=ptime:30 +%% }, +%% Remote { +%% v=0 +%% c=IN IP4 124.124.124.222 +%% m=audio 2222 RTP/AVP 4 +%% a=ptime:30 +%% } } }, +%% Packages {nt-1, rtp-1}, +%% Statistics { rtp/ps=1200, ; packets sent +%% nt/os=62300, ; octets sent +%% rtp/pr=700, ; packets received +%% nt/or=45100, ; octets received +%% rtp/pl=0.2, ; % packet loss +%% rtp/jit=20, +%% rtp/delay=40 } ; avg latency +%% } +%% } +%% } +%%---------------------------------------------------------------------- + +msg21() -> + msg21(?MG2_MID). +msg21(Mid) -> + Jit = ?PP("nt/jit", "40"), + LCD = #'LocalControlDescriptor'{streamMode = sendRecv, + propertyParms = [Jit]}, + LDV = ?PP("v", "0"), + LDC = ?PP("c", "IN IP4 125.125.125.111"), + LDM = ?PP("m", "audio 1111 RTP/AVP 4"), + LDA = ?PP("a", "ptime:30"), + LD = #'LocalRemoteDescriptor'{propGrps = [[LDV, LDC, LDM, LDA]]}, + RDV = ?PP("v", "0"), + RDC = ?PP("c", "IN IP4 124.124.124.222"), + RDM = ?PP("m", "audio 2222 RTP/AVP 4"), + RDA = ?PP("a", "ptime:30"), + RD = #'LocalRemoteDescriptor'{propGrps = [[RDV, RDC, RDM, RDA]]}, + StreamParms = #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD}, + StreamDesc = #'StreamDescriptor'{streamID = 1, + streamParms = StreamParms}, + Media = #'MediaDescriptor'{streams = {multiStream, [StreamDesc]}}, + PackagesItem = #'PackagesItem'{packageName = "nt", + packageVersion = 1}, + PackagesItem2 = #'PackagesItem'{packageName = "rtp", + packageVersion = 1}, + Stat = ?SP("rtp/ps","1200"), + Stat2 = ?SP("nt/os","62300"), + Stat3 = ?SP("rtp/pr","700"), + Stat4 = ?SP("nt/or","45100"), + Stat5 = ?SP("rtp/pl","0.2"), + Stat6 = ?SP("rtp/jit","20"), + Stat7 = ?SP("rtp/delay","40"), + Statistics = [Stat, Stat2, Stat3, Stat4, Stat5, Stat6, Stat7], + Audits = [{mediaDescriptor, Media}, + {packagesDescriptor, [PackagesItem, PackagesItem2]}, + {statisticsDescriptor, Statistics}], + Reply = {auditResult, #'AuditResult'{terminationID = #megaco_term_id{id = ?A5556}, + terminationAuditResult = Audits}}, + reply(Mid, 50007, ?megaco_null_context_id, [{auditValueReply, Reply}]). + +%%---------------------------------------------------------------------- +%% 22. When the MGC receives an onhook signal from one of the MGs, it +%% brings down the call. In this example, the user at MG2 hangs up first. +%% +%% MG2 to MGC: +%% MEGACO/1 [125.125.125.111]:55555 +%% Transaction = 50008 { +%% Context = 5000 { +%% Notify = A5555 {ObservedEvents =1235 { +%% 19990729T24020002:al/on} +%% } +%% } +%% } +%%---------------------------------------------------------------------- + +msg22a() -> + msg22a(?MG2_MID). +msg22a(Mid) -> + TimeStamp = #'TimeNotation'{date = "19990729", + time = "24020002"}, + Event = #'ObservedEvent'{eventName = "al/on", + timeNotation = TimeStamp, + eventParList = []}, + Desc = #'ObservedEventsDescriptor'{requestId = 1235, + observedEventLst = [Event]}, + NotifyReq = #'NotifyRequest'{terminationID = [#megaco_term_id{id = ?A5555}], + observedEventsDescriptor = Desc}, + CmdReq = #'CommandRequest'{command = {notifyReq, NotifyReq}}, + request(Mid, 50008, 5000, [CmdReq]). + +%%---------------------------------------------------------------------- +%% MGC to MG2: +%% MEGACO/1 [123.123.123.4]:55555 +%% Reply = 50008 { +%% Context = - {Notify = A5555} +%% } +%%---------------------------------------------------------------------- + +msg22b() -> + msg22b(?MGC_MID). +msg22b(Mid) -> + Reply = #'NotifyReply'{terminationID = [#megaco_term_id{id = ?A5555}]}, + reply(Mid, 50008, ?megaco_null_context_id, [{notifyReply, Reply}]). + +%%---------------------------------------------------------------------- +%% 23. The MGC now sends both MGs a Subtract to take down the call. Only +%% the subtracts to MG2 are shown here. Each termination has its own +%% set of statistics that it gathers. An MGC may not need to request +%% both to be returned. A5555 is a physical termination, and A5556 is +%% an RTP termination. +%% +%% MGC to MG2: +%% +%% MEGACO/1 [123.123.123.4]:55555 +%% Transaction = 50009 { +%% Context = 5000 { +%% Subtract = A5555 {Audit{Statistics}}, +%% Subtract = A5556 {Audit{Statistics}} +%% } +%% } +%%---------------------------------------------------------------------- + +msg23a() -> + msg23a(?MGC_MID). +msg23a(Mid) -> + CommonAuditDesc = #'AuditDescriptor'{auditToken = [statsToken]}, + SubReq = #'SubtractRequest'{terminationID = [#megaco_term_id{id = ?A5555}], + auditDescriptor = CommonAuditDesc}, + SubReq2 = #'SubtractRequest'{terminationID = [#megaco_term_id{id = ?A5556}], + auditDescriptor = CommonAuditDesc}, + CmdReq = #'CommandRequest'{command = {subtractReq, SubReq}}, + CmdReq2 = #'CommandRequest'{command = {subtractReq, SubReq2}}, + request(Mid, 50009, 5000, [CmdReq, CmdReq2]). +%% +%%---------------------------------------------------------------------- +%% MG2 to MGC: +%% +%% MEGACO/1 [125.125.125.111]:55555 +%% Reply = 50009 { +%% Context = 5000 { +%% Subtract = A5555 { +%% Statistics { +%% nt/os=45123, ; Octets Sent +%% nt/dur=40 ; in seconds +%% } +%% }, +%% Subtract = A5556 { +%% Statistics { +%% rtp/ps=1245, ; packets sent +%% nt/os=62345, ; octets sent +%% rtp/pr=780, ; packets received +%% nt/or=45123, ; octets received +%% rtp/pl=10, ; % packets lost +%% rtp/jit=27, +%% rtp/delay=48 ; average latency +%% } +%% } +%% } +%% } +%%---------------------------------------------------------------------- + +msg23b() -> + msg23b(?MG2_MID). +msg23b(Mid) -> + Stat11 = ?SP("nt/os","45123"), + Stat12 = ?SP("nt/dur", "40"), + Stats1 = [Stat11, Stat12], + Reply1 = #'AmmsReply'{terminationID = [#megaco_term_id{id = ?A5555}], + terminationAudit = [{statisticsDescriptor, Stats1}]}, + Stat21 = ?SP("rtp/ps","1245"), + Stat22 = ?SP("nt/os", "62345"), + Stat23 = ?SP("rtp/pr", "780"), + Stat24 = ?SP("nt/or", "45123"), + Stat25 = ?SP("rtp/pl", "10"), + Stat26 = ?SP("rtp/jit", "27"), + Stat27 = ?SP("rtp/delay","48"), + Stats2 = [Stat21, Stat22, Stat23, Stat24, Stat25, Stat26, Stat27], + Reply2 = #'AmmsReply'{terminationID = [#megaco_term_id{id = ?A5556}], + terminationAudit = [{statisticsDescriptor, Stats2}]}, + reply(Mid, 50009, 5000, [{subtractReply, Reply1}, {subtractReply, Reply2}]). + +%%---------------------------------------------------------------------- +%% 24. The MGC now sets up both MG1 and MG2 to be ready to detect the +%% next off-hook event. See step 1. Note that this could be the +%% default state of a termination in the null context, and if this +%% were the case, no message need be sent from the MGC to the +%% MG. Once a termination returns to the null context, it goes back +%% to the default termination values for that termination. +%%---------------------------------------------------------------------- + +%% BUGBUG: Example missing in spec + +%%---------------------------------------------------------------------- +%% Testing +%%---------------------------------------------------------------------- + +messages() -> + [{Slogan, catch ?MODULE:Slogan()} || Slogan <- names()]. + +encoders() -> + [ + {megaco_pretty_text_encoder, [], []}, + {megaco_compact_text_encoder, [], []}, + {megaco_binary_encoder, [], [native]}, + %% {megaco_ber_encoder, [], [native]}, + %% {megaco_ber_bin_encoder, [], [native]}, + {megaco_per_encoder, [], [native]}, + {megaco_erl_dist_encoder, [], []}, + {megaco_erl_dist_encoder, [compressed], [compressed]} + ]. + + +pretty_mod({Mod, Opt, _Opt2}) -> + case Mod of + megaco_pretty_text_encoder when Opt == [flex] -> pretty_flex; + megaco_compact_text_encoder when Opt == [flex] -> compact_flex; + megaco_pretty_text_encoder -> pretty_text; + megaco_compact_text_encoder -> compact_text; + megaco_binary_encoder -> asn1_ber; + megaco_ber_encoder -> asn1_ber_old; + megaco_ber_bin_encoder -> asn1_ber_bin; + megaco_per_encoder -> asn1_per; + megaco_erl_dist_encoder when Opt == [] -> standard_erl; + megaco_erl_dist_encoder when Opt == [compressed] -> compressed_erl; + Ugly -> Ugly + end. + +%%---------------------------------------------------------------------- +%% Run specific encoder for all test cases +%%---------------------------------------------------------------------- + +pretty_text() -> + Default = [], + Encoder = {megaco_pretty_text_encoder, Default, Default}, + All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], + compute_res(All). + +compact_text() -> + Default = [], + Encoder = {megaco_compact_text_encoder, Default, Default}, + All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], + compute_res(All). + +pretty_flex() -> + Default = [flex], + Encoder = {megaco_pretty_text_encoder, Default, Default}, + All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], + compute_res(All). + +compact_flex() -> + Default = [flex], + Encoder = {megaco_compact_text_encoder, Default, Default}, + All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], + compute_res(All). + +bin() -> + Default = [], + Native = [native], + Encoder = {megaco_binary_encoder, Default, Native}, + All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], + compute_res(All). + +asn1_ber() -> + Default = [], + Native = [native], + Encoder = {megaco_ber_encoder, Default, Native}, + All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], + compute_res(All). + +asn1_ber_bin() -> + Default = [], + Native = [native], + Encoder = {megaco_ber_bin_encoder, Default, Native}, + All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], + compute_res(All). + +asn1_per() -> + Default = [], + Native = [native], + Encoder = {megaco_per_encoder, Default, Native}, + All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], + compute_res(All). + +standard_erl() -> + Config = [], + Encoder = {megaco_erl_dist_encoder, Config, Config}, + All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], + compute_res(All). + +compressed_erl() -> + Config = [compressed], + Encoder = {megaco_erl_dist_encoder, Config, Config}, + All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], + compute_res(All). + +encode(Slogan, DecodedMsg, {Mod, Opt, _Opt2} = _Encoder) -> + Main = "==================================================", + Sub = "--------------------------------------------------", + case catch Mod:encode_message(Opt, DecodedMsg) of + {ok, EncodedMsg} when is_binary(EncodedMsg) -> + Sz = size(EncodedMsg), + ok = io:format("~w ~s ~w bytes~n", + [Slogan, Main, Sz]), + catch io:format("~n~s~n", [(catch binary_to_list(EncodedMsg))]), + case catch Mod:decode_message(Opt, EncodedMsg) of + {ok, ReDecodedMsg} -> + fmt(Slogan, DecodedMsg, ReDecodedMsg); + {error, {Line, _, Reason}} when is_integer(Line)-> + ?ERROR([{Slogan, Line, decode_failed}, {error, Reason}, {encoded, EncodedMsg}, DecodedMsg]), + io:format("~n~w <ERROR> #~w: ~w~n", + [Slogan, Line, Reason]); + Other -> + ?ERROR([{Slogan, 0, decode_failed}, Other, {encoded, EncodedMsg}, DecodedMsg]), + io:format("~n~w <ERROR> ~w~n", [Slogan, Other]) + end, + Sz; + Other -> + ?ERROR([{Slogan, encode_failed}, Other, DecodedMsg]), + ok = io:format("~w ~s~n~p~n<ERROR> ~s~n~p~n", + [Slogan, Main, DecodedMsg, Sub, Other]), + {Slogan, {encode_message, Other}} + end. + +fmt(_Slogan, Msg, Msg) -> + ok; +fmt(Slogan, {'MegacoMessage', A, {'Message', V, MID, {transactions, [{T, Old}]}}}, + {'MegacoMessage', A, {'Message', V, MID, {transactions, [{T, New}]}}}) -> + fmt(Slogan, Old, New); +fmt(Slogan, Old, New) -> + PrettyOld = lists:flatten(io_lib:format("~p", [Old])), + PrettyNew = lists:flatten(io_lib:format("~p", [New])), + fmt_diff(Slogan, Old, New, PrettyOld, PrettyNew, []). + +fmt_diff(Slogan, Old, New, [H | OldRest], [H | NewRest], Common) -> + fmt_diff(Slogan, Old, New, OldRest, NewRest, [H | Common]); +fmt_diff(Slogan, Old, New, OldRest, NewRest, Common) -> + RevCommon = lists:reverse(Common), + ?ERROR([{Slogan, decode_mismatch}, {old, Old}, {new, New}]), + Sub = "--------------------------------------------------", + io:format("~n~w COMMON ~s~n~s~n", [Slogan, Sub, RevCommon]), + io:format("~n~w OLD ~s~n~s~n", [Slogan, Sub, OldRest]), + io:format("~n~w NEW ~s~n~s~n", [Slogan, Sub, NewRest]). + +compute_res(All) -> + compute_res(All, [], 0). + +compute_res([H | T], Bad, Sum) when is_integer(H) -> + compute_res(T, Bad, Sum + H); +compute_res([H | T], Bad, Sum) -> + compute_res(T, [H | Bad], Sum); +compute_res([], Bad, Sum) -> + ok = io:format("#bytes: ~w; errors: ~p~n", [Sum, Bad]). + +%%---------------------------------------------------------------------- +%% Compute sizes of encoded messages +%%---------------------------------------------------------------------- + +msg_sizes() -> + Encoders = encoders(), + msg_sizes(Encoders). + +%% Returns a list of {MessageSlogan, MessageSizes} where +%% MessageSizes is the result from msg_sizes/2 +msg_sizes(Encoders) -> + [{S, msg_sizes(Msg, Encoders)} || {S, Msg} <- messages()]. + +%% Returns a list of {Encoder, Res} tuples +%% where Res either is the message size (integer) +%% or an error atom +msg_sizes(DecodedMsg, Encoders) -> + [abs_msg_size(DecodedMsg, E) || E <- Encoders]. + +abs_msg_size(DecodedMsg, {Mod, Opt, _Opt2} = Encoder) -> + case catch Mod:encode_message(Opt, DecodedMsg) of + {ok, EncodedMsg} when is_binary(EncodedMsg) -> + {Encoder, size(EncodedMsg)}; + Error -> + {Encoder, {bad_encoder, Error}} + end. + +%%---------------------------------------------------------------------- +%% Compute time for encoding messages +%%---------------------------------------------------------------------- + +encoding_times() -> + Encoders = encoders(), + encoding_times(Encoders). + +%% Returns a list of {MessageSlogan, EncodingTimes} where +%% EncodingTimes is the result from encoding_times/2 +encoding_times(Encoders) -> + [{Slogan, encoding_times(Msg, Encoders)} || {Slogan, Msg} <- messages()]. + +%% Returns a list of {Encoder, Res} tuples +%% where Res either is the encoding time (integer) +%% or an error atom +encoding_times(DecodedMsg, Encoders) -> + [{E, encoding_time(encoding_msg(DecodedMsg, E))} || E <- Encoders]. + +encoding_msg(DecodedMsg, {Mod, Opt, Opt2} = Encoder) -> + {ok, EncodedMsg} = Mod:encode_message(Opt, DecodedMsg), + {ok, DecodedMsg2} = Mod:decode_message(Opt2, EncodedMsg), + {Encoder, DecodedMsg2}. + +encoding_time({{Mod, _Opt, Opt2} = Encoder, DecodedMsg}) -> + meter(fun() -> {ok, _} = Mod:encode_message(Opt2, DecodedMsg) end, Encoder). + +%%---------------------------------------------------------------------- +%% Compute time for decoding messages +%%---------------------------------------------------------------------- + +decoding_times() -> + Decoders = encoders(), + decoding_times(Decoders). + +%% Returns a list of {MessageSlogan, DecodingTimes} where +%% DecodingTimes is the result from decoding_times/2 +decoding_times(Decoders) -> + [{Slogan, decoding_times(Msg, Decoders)} || {Slogan, Msg} <- messages()]. + +%% Returns a list of {Decoder, Res} tuples +%% where Res either is the decoding time (integer) +%% or an error atom +decoding_times(DecodedMsg, Encoders) -> + [{E, decoding_time(decoding_msg(DecodedMsg, E))} || E <- Encoders]. + +decoding_msg(DecodedMsg, {Mod, Opt, _Opt2} = Encoder) -> + {ok, EncodedMsg} = Mod:encode_message(Opt, DecodedMsg), + {Encoder, EncodedMsg}. + +decoding_time({{Mod, _Opt, Opt2} = Encoder, EncodedMsg}) -> + meter(fun() -> {ok, _} = Mod:decode_message(Opt2, EncodedMsg) end, Encoder). + +%%---------------------------------------------------------------------- +%%---------------------------------------------------------------------- + +coding_times() -> + Coders = encoders(), + coding_times(Coders). + +%% Returns a list of {MessageSlogan, DecodingTimes} where +%% DecodingTimes is the result from decoding_times/2 +coding_times(Coders) -> + [{Slogan, coding_times(Msg, Coders)} || {Slogan, Msg} <- messages()]. + +%% Returns a list of {Decoder, Res} tuples +%% where Res either is the decoding time (integer) +%% or an error atom +coding_times(DecodedMsg, Coders) -> + [{E, coding_time(coding_msg(DecodedMsg, E))} || E <- Coders]. + +coding_msg(DecodedMsg, {Mod, Opt, _Opt2} = Encoder) -> + {ok, EncodedMsg} = Mod:encode_message(Opt, DecodedMsg), + {Encoder, EncodedMsg}. + +coding_time({{Mod, _Opt, Opt2} = Encoder, EncodedMsg}) -> + Fun = fun() -> + {ok, DecodedMsg} = Mod:decode_message(Opt2, EncodedMsg), + {ok, _} = Mod:encode_message(Opt2, DecodedMsg) + end, + meter(Fun, Encoder). + +%%---------------------------------------------------------------------- +%% Return size statistics as term +%%---------------------------------------------------------------------- + +size_stat() -> + Encoders = encoders(), + MsgSizes = msg_sizes(Encoders), + stat(Encoders, MsgSizes). + +%%---------------------------------------------------------------------- +%%---------------------------------------------------------------------- + +gnuplot_gif() -> + [ + {size, gnuplot_size_gif()}, + {encoding, gnuplot_enc_time_gif()}, + {decoding, gnuplot_dec_time_gif()}, + {coding, gnuplot_code_time_gif()} + ]. + +%%---------------------------------------------------------------------- +%% Generate GIF picture from size statistics with gnuplot +%%---------------------------------------------------------------------- + +gnuplot_size_gif() -> + {ok, _Cwd} = file:get_cwd(), + TmpDir = "megaco_encoded_size.tmp", + GifFile = "megaco_encoded_size.gif", + Header = + ["set title \"Size comparison of Megaco/H.248 encoding formats\"\n", + "set timestamp top\n", + "set terminal gif\n", + "set xlabel \"Test cases from Appendix A\"\n", + "set ylabel \"Message size in bytes\"\n", + "set rmargin 10\n", + "set key left top Left\n", + "set output \"", GifFile, "\"\n\n"], + Encoders = encoders(), + Stat = msg_sizes(Encoders), + BatchFile = gnuplot_dir(TmpDir, Header, Encoders, Stat), + Cmd = "cd " ++ TmpDir ++ "; gnuplot " ++ BatchFile, + os:cmd(Cmd), + ok = io:format("~n~s~nxv ~s~n", [Cmd, filename:join([TmpDir, GifFile])]), + stat(Encoders, Stat). + +%%---------------------------------------------------------------------- +%% Return encoding time statistics as term +%%---------------------------------------------------------------------- + +encoding_times_stat() -> + Encoders = encoders(), + EncodingTimes = encoding_times(Encoders), + stat(Encoders, EncodingTimes). + +%%---------------------------------------------------------------------- +%% Return encoding time statistics as term +%%---------------------------------------------------------------------- + +decoding_times_stat() -> + Encoders = encoders(), + DecodingTimes = decoding_times(Encoders), + stat(Encoders, DecodingTimes). + +%%---------------------------------------------------------------------- +%% Return encoding time statistics as term +%%---------------------------------------------------------------------- + +coding_times_stat() -> + Encoders = encoders(), + CodingTimes = coding_times(Encoders), + stat(Encoders, CodingTimes). + +%%---------------------------------------------------------------------- +%% Generate GIF picture from encoding time statistics with gnuplot +%%---------------------------------------------------------------------- + +gnuplot_enc_time_gif() -> + {ok, _Cwd} = file:get_cwd(), + TmpDir = "megaco_encoding_time.tmp", + GifFile = "megaco_encoding_time.gif", + Header = + ["set title \"Encoding time comparison of Megaco/H.248 encoding formats\"\n", + "set timestamp top\n", + "set terminal gif\n", + "set xlabel \"Test cases from Appendix A\"\n", + "set ylabel \"Time for encoding in micro seconds\"\n", + "set rmargin 10\n", + "set key left top Left\n", + "set output \"", GifFile, "\"\n\n"], + Encoders = encoders(), + Stat = encoding_times(Encoders), + BatchFile = gnuplot_dir(TmpDir, Header, Encoders, Stat), + Cmd = "cd " ++ TmpDir ++ "; gnuplot " ++ BatchFile, + os:cmd(Cmd), + ok = io:format("~n~s~nxv ~s~n", [Cmd, filename:join([TmpDir, GifFile])]), + stat(Encoders, Stat). + +%%---------------------------------------------------------------------- +%% Generate GIF picture from decoding time statistics with gnuplot +%%---------------------------------------------------------------------- + +gnuplot_dec_time_gif() -> + {ok, _Cwd} = file:get_cwd(), + TmpDir = "megaco_decoding_time.tmp", + GifFile = "megaco_decoding_time.gif", + Header = + ["set title \"Decoding time comparison of Megaco/H.248 encoding formats\"\n", + "set timestamp top\n", + "set terminal gif\n", + "set xlabel \"Test cases from Appendix A\"\n", + "set ylabel \"Time for decoding in micro seconds\"\n", + "set rmargin 10\n", + "set key left top Left\n", + "set output \"", GifFile, "\"\n\n"], + Encoders = encoders(), + Stat = decoding_times(Encoders), + BatchFile = gnuplot_dir(TmpDir, Header, Encoders, Stat), + Cmd = "cd " ++ TmpDir ++ "; gnuplot " ++ BatchFile, + os:cmd(Cmd), + ok = io:format("~n~s~nxv ~s~n", [Cmd, filename:join([TmpDir, GifFile])]), + stat(Encoders, Stat). + +%%---------------------------------------------------------------------- +%% Generate GIF picture from decoding time statistics with gnuplot +%%---------------------------------------------------------------------- + +gnuplot_code_time_gif() -> + {ok, _Cwd} = file:get_cwd(), + TmpDir = "megaco_coding_time.tmp", + GifFile = "megaco_coding_time.gif", + Header = + ["set title \"Encoding + decoding time comparison of Megaco/H.248 encoding formats\"\n", + "set timestamp top\n", + "set terminal gif\n", + "set xlabel \"Test cases from Appendix A\"\n", + "set ylabel \"Time for encoding+decoding in micro seconds\"\n", + "set rmargin 10\n", + "set key left top Left\n", + "set output \"", GifFile, "\"\n\n"], + Encoders = encoders(), + Stat = coding_times(Encoders), + BatchFile = gnuplot_dir(TmpDir, Header, Encoders, Stat), + Cmd = "cd " ++ TmpDir ++ "; gnuplot " ++ BatchFile, + os:cmd(Cmd), + ok = io:format("~n~s~nxv ~s~n", [Cmd, filename:join([TmpDir, GifFile])]), + stat(Encoders, Stat). + +%%---------------------------------------------------------------------- +%% Encode asn.1 messages +%%---------------------------------------------------------------------- + +gen_byte_msg(Msg, {Mod, Opt, _Opt2} = _Encoder) -> + {ok, EncodedMsg} = Mod:encode_message(Opt, Msg), + EncodedMsg. + +%%---------------------------------------------------------------------- +%% Gen the C header file content as a binary +%%---------------------------------------------------------------------- + +gen_header_file_binary([]) -> + ok; +gen_header_file_binary([{S, B}| Rest]) -> + file:write_file(atom_to_list(S), B), + gen_header_file_binary(Rest). + +%%---------------------------------------------------------------------- +%% Generate headerfile for asn.1 BER test in C +%%---------------------------------------------------------------------- + +gen_ber_header() -> + Encoder = {megaco_ber_encoder, [], []}, + L = [{S, gen_byte_msg(Msg, Encoder)} || {S, Msg} <- messages()], + gen_header_file_binary(L). + +%%---------------------------------------------------------------------- +%% Generate headerfile for asn.1 BER test in C +%%---------------------------------------------------------------------- +gen_ber_bin_header() -> + Encoder = {megaco_ber_bin_encoder, [], []}, + L = [{S, gen_byte_msg(Msg, Encoder)} || {S, Msg} <- messages()], + gen_header_file_binary(L). + +%%---------------------------------------------------------------------- +%% Generate headerfile for asn.1 PER test in C +%%---------------------------------------------------------------------- +gen_per_header() -> + Encoder = {megaco_per_encoder, [], []}, + L = [{S, gen_byte_msg(Msg, Encoder)} || {S, Msg} <- messages()], + gen_header_file_binary(L). + +%%---------------------------------------------------------------------- +%% Execute a fun a number of times and return avg in millis +%%---------------------------------------------------------------------- + +meter(Fun, Encoder) -> + MaxTime = timer:seconds(5), + Rep = 2, + M = pretty_mod(Encoder), + io:format("~p:\t", [M]), + Times = [single_meter(Fun, MaxTime, {M, N}) || N <- lists:seq(1, Rep)], + Min = lists:min(Times), + Max = lists:max(Times), + Median = lists:nth((Rep + 1) div 2, lists:sort(Times)), + io:format("(median=~p, diff=~p)~n", [Median, Max - Min]), + Median. + +single_meter(Fun, MaxTime, Tag) -> + Pid = spawn_link(?MODULE, single_meter, [self(), Fun, MaxTime, Tag]), + receive + {meter, Pid, Time} -> + io:format("~p \t", [Time]), + Time; + {'EXIT', Pid, Reason} -> + {bad_result, Reason} + end. + +single_meter(Parent, Fun, Expected, _Tag) -> + erlang:statistics(runtime), + erlang:send_after(Expected, self(), return_count), + Count = count(Fun, 1), + {_, Actual} = erlang:statistics(runtime), + %% Diff = Actual - Expected, + Micros = trunc((Actual / Count) * 1000), + Parent ! {meter, self(), Micros}, + unlink(Parent), + exit(normal). + +count(Fun, N) -> + Fun(), + receive + return_count -> + N + after 0 -> + count(Fun, N + 1) + end. + +stat(Encoders, Stat) -> + Fun = + fun({_Mod, _Opt, _Opt2} = E) -> + List = lists:flatten([[Val || {E2, Val} <- Info, E2 == E] || + {_Slogan, Info} <- Stat]), + Max = lists:max(List), + Min = lists:min(List), + case catch lists:sum(List) of + {'EXIT', _} -> + {E, bad, List}; + Sum when is_integer(Sum) -> + N = length(List), + {E, [{min, Min}, {avg, Sum div N}, {max, Max}]} + end + end, + lists:map(Fun, Encoders). + +gnuplot_dir(Dir, Header, Encoders, Stat) -> + file:make_dir(Dir), + {Names, Arrows} = gnuplot_data(Encoders, Dir, Stat, 1, [], []), + [H | T] = [lists:concat(["\"", N, "\" with linespoints"]) || N <- Names], + Plots = [[", ", Plot] || Plot <- T], + IoList = [Header, Arrows, "\nplot ", H, Plots, "\n\nshow output\n"], + Bin = list_to_binary(IoList), + BatchFile = "gnuplot.batch", + file:write_file(filename:join(Dir, BatchFile), Bin), + BatchFile. + +gnuplot_data([], _Dir, _Stat, _Pos, Names, Arrows) -> + {lists:reverse(Names), lists:reverse(Arrows)}; +gnuplot_data([{Mod, _Opt, _Opt2} = E | Encoders], Dir, Stat, Pos, Names, Arrows) -> + Plot = fun({Msg, List}, {N, AccSz}) -> + {value, {_, Sz}} = lists:keysearch(E, 1, List), + ActualSz = + if + is_integer(Sz) -> + Sz; + true -> + ok = io:format("<ERROR> ~p(~p) -> ~p~n", + [Mod, Msg, Sz]), + 0 + end, + Acc = {N + 1, [ActualSz | AccSz]}, + {lists:concat([N + 1, " ", ActualSz, "\n"]), Acc} + end, + {Data, {N, Sizes}} = lists:mapfoldl(Plot, {0, []}, Stat), + Min = lists:min(Sizes), + Max = lists:max(Sizes), + Sum = lists:sum(Sizes), + Avg = Sum div N, + Len = length(Stat), + Pretty = pretty_mod(E), + Name = lists:concat([Pretty, " (", Min, ",", Avg, ",", Max, ")"]), + file:write_file(filename:join(Dir, Name), list_to_binary(Data)), + %%"plot \"-\" title \"", E, "\" with linespoints\n", Data, "e\n", + Arrow = + lists:concat(["set arrow from 1,", Avg, + " to ", Len, ", ", Avg, + " nohead lt ", Pos, "\n", + "set label \" ", Avg, " (avg)\" at ", Len, ",", Avg + 10, "\n"]), + gnuplot_data(Encoders, Dir, Stat, Pos + 1, [Name | Names], [Arrow | Arrows]). diff --git a/lib/megaco/test/megaco_codec_flex_lib.erl b/lib/megaco/test/megaco_codec_flex_lib.erl new file mode 100644 index 0000000000..de76956711 --- /dev/null +++ b/lib/megaco/test/megaco_codec_flex_lib.erl @@ -0,0 +1,174 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Utility module used by the codec suites when testing flex +%% configured text codec(s). +%%---------------------------------------------------------------------- + +-module(megaco_codec_flex_lib). + +%% ---- + +-include("megaco_test_lib.hrl"). + +%% ---- + +-export([ + init/1, + finish/1, + scanner_conf/1, + start/0, + stop/1 + ]). + +-export([ + handler/1 + ]). + + +%% ---- + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +init(Config) when is_list(Config) -> + Flag = process_flag(trap_exit, true), + Res = (catch start()), + process_flag(trap_exit, Flag), + case Res of + {error, Reason} -> + skip(Reason); + {ok, FlexConfig} -> + [{flex_scanner, FlexConfig} | Config] + end. + + +finish(Config) when is_list(Config) -> + case lists:keysearch(flex_scanner, 1, Config) of + {value, {flex_scanner, {Pid, _Conf}}} -> + stop(Pid), + lists:keydelete(flex_scanner, 1, Config); + false -> + Config + end. + + +start() -> + Pid = proc_lib:spawn(?MODULE, handler, [self()]), + receive + {flex_scanner_started, Pid, Conf} -> + {ok, {Pid, Conf}}; + {flex_scanner_error, {failed_loading_flex_scanner_driver, Reason}} -> + ?LOG("start_flex_scanner -> failed loading flex scanner driver: " + "~n Reason: ~p~n", [Reason]), + {error, {failed_loading_flex_scanner_driver, Reason}}; + {flex_scanner_error, Reason} -> + ?LOG("start_flex_scanner -> error: " + "~n Reason: ~p~n", [Reason]), + {error, {failed_loading_flex_scanner_driver, Reason}} + after 10000 -> + exit(Pid, kill), + {error, {failed_starting_flex_scanner, timeout}} + end. + + +scanner_conf(Config) when is_list(Config) -> + case lists:keysearch(flex_scanner, 1, Config) of + {value, {flex_scanner, {Pid, Conf}}} -> + case ping_flex_scanner(Pid) of + ok -> + Conf; + Else -> + skip({no_response_from_flex_scanner_handler, Else}) + end; + false -> + skip("Flex scanner driver not loaded") + end. + + +ping_flex_scanner(Pid) -> + Pid ! {ping, self()}, + receive + {pong, Pid} -> + ok + after 5000 -> + timeout + end. + + +stop(Pid) -> + Pid ! stop. + + +handler(Pid) -> + SMP = erlang:system_info(smp_support), + case (catch megaco_flex_scanner:start(SMP)) of + {ok, PortOrPorts} -> + Pid ! {flex_scanner_started, self(), {flex, PortOrPorts}}, + handler(Pid, PortOrPorts); + {error, {load_driver, {open_error, Reason}}} -> + Error = {failed_loading_flex_scanner_driver, Reason}, + Pid ! {flex_scanner_error, Error}, + exit(Error); + {error, {load_driver, Reason}} -> + Error = {failed_loading_flex_scanner_driver, Reason}, + Pid ! {flex_scanner_error, Error}, + exit(Error); + Else -> + Error = {unknown_result_from_start_flex_scanner, Else}, + Pid ! {flex_scanner_error, Error}, + exit(Error) + end. + +handler(Pid, PortOrPorts) -> + receive + {ping, Pinger} -> + Pinger ! {pong, self()}, + handler(Pid, PortOrPorts); + {'EXIT', Port, Reason} when (PortOrPorts =:= Port) -> + Pid ! {flex_scanner_exit, Reason}, + exit({flex_scanner_exit, Reason}); + {'EXIT', Port, Reason} when is_port(Port) -> + case megaco_flex_scanner:is_scanner_port(Port, PortOrPorts) of + true -> + Pid ! {flex_scanner_exit, Reason}, + exit({flex_scanner_exit, Reason}); + false -> + io:format("flex scanner handler got port exit " + "from unknown:" + "~n ~p: ~p", [Port, Reason]), + ok + end, + handler(Pid, PortOrPorts); + stop -> + megaco_flex_scanner:stop(PortOrPorts), + exit(normal); + Other -> + io:format("flex scanner handler got something:~n" + "~p", [Other]), + handler(Pid, PortOrPorts) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +skip(Reason) -> + megaco_codec_test_lib:skip(Reason). + diff --git a/lib/megaco/test/megaco_codec_mini_test.erl b/lib/megaco/test/megaco_codec_mini_test.erl new file mode 100644 index 0000000000..e509739bb1 --- /dev/null +++ b/lib/megaco/test/megaco_codec_mini_test.erl @@ -0,0 +1,220 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test mini encoding/decoding (codec) module of Megaco/H.248 +%%---------------------------------------------------------------------- + +-module(megaco_codec_mini_test). + +%% ---- + +-include_lib("megaco/include/megaco.hrl"). +%% -include_lib("megaco/include/megaco_message_v3.hrl"). +-include("megaco_test_lib.hrl"). + +%% ---- + +-export([t/0, t/1]). + +-export([all/1, + + tickets/0, + tickets/1, + otp7672_msg01/1, + otp7672_msg02/1, + + init_per_testcase/2, fin_per_testcase/2]). + + +%% ---- + +-define(SET_DBG(S,D), begin put(severity, S), put(dbg, D) end). +-define(RESET_DBG(), begin erase(severity), erase(dbg) end). + + +%% ---- + +tickets() -> + Flag = process_flag(trap_exit, true), + Cases = expand(tickets), + Fun = fun(Case) -> + C = init_per_testcase(Case, [{tc_timeout, + timer:minutes(10)}]), + io:format("Eval ~w~n", [Case]), + Result = + case (catch apply(?MODULE, Case, [C])) of + {'EXIT', Reason} -> + io:format("~n~p exited:~n ~p~n", + [Case, Reason]), + {error, {Case, Reason}}; + Res -> + Res + end, + fin_per_testcase(Case, C), + Result + end, + process_flag(trap_exit, Flag), + lists:map(Fun, Cases). + +expand(RootCase) -> + expand([RootCase], []). + +expand([], Acc) -> + lists:flatten(lists:reverse(Acc)); +expand([Case|Cases], Acc) -> + case (catch apply(?MODULE,Case,[suite])) of + [] -> + expand(Cases, [Case|Acc]); + C when is_list(C) -> + expand(Cases, [expand(C, [])|Acc]); + _ -> + expand(Cases, [Case|Acc]) + end. + + +%% ---- + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + +init_per_testcase(Case, Config) -> + C = + case lists:suffix("time_test", atom_to_list(Case)) of + true -> + [{tc_timeout, timer:minutes(10)}|Config]; + false -> + put(verbosity,trc), + Config + end, + megaco_test_lib:init_per_testcase(Case, C). + +fin_per_testcase(Case, Config) -> + erase(verbosity), + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top test case + +all(suite) -> + [ + tickets + ]. + +tickets(suite) -> + [ + otp7672_msg01, + otp7672_msg02 + ]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +%% Ticket test cases: + + +%% -------------------------------------------------------------- +%% + +otp7672_msg01(suite) -> + []; +otp7672_msg01(Config) when is_list(Config) -> + %% ?SET_DBG(trc, true), + d("otp7672_msg01 -> entry", []), + ok = otp7672( otp7672_msg01() ), + %% ?RESET_DBG(), + ok. + +otp7672_msg02(suite) -> + []; +otp7672_msg02(Config) when is_list(Config) -> + %% ?SET_DBG(trc, true), + d("otp7672_msg02 -> entry", []), + ok = otp7672( otp7672_msg02() ), + %% ?RESET_DBG(), + ok. + + +otp7672_msg01() -> + <<"!/1 <TEST> ">>. + +otp7672_msg02() -> + <<"!/1 <TE> ">>. + +otp7672(Msg) -> + case megaco_text_mini_decoder:decode_message([], Msg) of + {ok, M} -> + t("mini decode successfull: ~n~p", [M]), + ok; + Error -> + e("mini decode failed: ~n~p", [Error]), + {error, Error} + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +t(F,A) -> + p(printable(get(severity),trc),trc,F,A). + +d(F,A) -> + p(printable(get(severity),dbg),dbg,F,A). + +%% l(F,A) -> +%% p(printable(get(severity),log),log,F,A). + +e(F,A) -> + p(printable(get(severity),err),err,F,A). + + +printable(trc,_) -> + true; +printable(dbg,trc) -> + false; +printable(dbg,_) -> + true; +printable(log,log) -> + true; +printable(log,err) -> + true; +printable(err,err) -> + true; +printable(_,_) -> + false. + + +p(true,L,F,A) -> + io:format("~s:" ++ F ++ "~n", [image_of(L)|A]); +p(_,_,_,_) -> + ok. + +image_of(trc) -> + "TRC"; +image_of(dbg) -> + "DBG"; +image_of(log) -> + "LOG"; +image_of(err) -> + "ERR"; +image_of(L) -> + io_lib:format("~p",[L]). + diff --git a/lib/megaco/test/megaco_codec_prev3a_test.erl b/lib/megaco/test/megaco_codec_prev3a_test.erl new file mode 100644 index 0000000000..696a72343c --- /dev/null +++ b/lib/megaco/test/megaco_codec_prev3a_test.erl @@ -0,0 +1,7350 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test encoding/decoding (codec) module of Megaco/H.248 +%%---------------------------------------------------------------------- +-module(megaco_codec_prev3a_test). + +%% ---- + +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_prev3a.hrl"). +-include("megaco_test_lib.hrl"). + +%% ---- + +-export([msgs/0]). +-export([rfc3525_msgs_display/0, rfc3525_msgs_test/0]). + +-export([t/0, t/1]). + +-export([all/1, + + text/1, + + pretty/1, + pretty_test_msgs/1, + + compact/1, + compact_test_msgs/1, + + flex_pretty/1, + flex_pretty_init/1, + flex_pretty_finish/1, + flex_pretty_test_msgs/1, + + flex_compact/1, + flex_compact_init/1, + flex_compact_finish/1, + flex_compact_test_msgs/1, + + flex_compact_dm_timers1/1, + flex_compact_dm_timers2/1, + flex_compact_dm_timers3/1, + flex_compact_dm_timers4/1, + flex_compact_dm_timers5/1, + flex_compact_dm_timers6/1, + flex_compact_dm_timers7/1, + flex_compact_dm_timers8/1, + + binary/1, + + bin/1, + bin_test_msgs/1, + + ber/1, + ber_test_msgs/1, + + ber_bin/1, + ber_bin_test_msgs/1, + + per/1, + per_test_msgs/1, + + per_bin/1, + per_bin_test_msgs/1, + + erl_dist/1, + erl_dist_m/1, + erl_dist_m_test_msgs/1, + + tickets/0, + tickets/1, + + compact_tickets/1, + compact_otp4011_msg1/1, + compact_otp4011_msg2/1, + compact_otp4011_msg3/1, + compact_otp4013_msg1/1, + compact_otp4085_msg1/1, + compact_otp4085_msg2/1, + compact_otp4280_msg1/1, + compact_otp4299_msg1/1, + compact_otp4299_msg2/1, + compact_otp4359_msg1/1, + compact_otp4920_msg0/1, + compact_otp4920_msg1/1, + compact_otp4920_msg2/1, + compact_otp4920_msg3/1, + compact_otp4920_msg4/1, + compact_otp4920_msg5/1, + compact_otp4920_msg6/1, + compact_otp4920_msg7/1, + compact_otp4920_msg8/1, + compact_otp4920_msg9/1, + compact_otp4920_msg10/1, + compact_otp4920_msg11/1, + compact_otp4920_msg12/1, + compact_otp4920_msg20/1, + compact_otp4920_msg21/1, + compact_otp4920_msg22/1, + compact_otp4920_msg23/1, + compact_otp4920_msg24/1, + compact_otp4920_msg25/1, + compact_otp5186_msg01/1, + compact_otp5186_msg02/1, + compact_otp5186_msg03/1, + compact_otp5186_msg04/1, + compact_otp5186_msg05/1, + compact_otp5186_msg06/1, + compact_otp5793_msg01/1, + compact_otp5993_msg01/1, + compact_otp5993_msg02/1, + compact_otp5993_msg03/1, + compact_otp6017_msg01/1, + compact_otp6017_msg02/1, + compact_otp6017_msg03/1, + + flex_compact_tickets/1, + flex_compact_otp7431_msg01/1, + flex_compact_otp7431_msg02/1, + flex_compact_otp7431_msg03/1, + flex_compact_otp7431_msg04/1, + flex_compact_otp7431_msg05/1, + flex_compact_otp7431_msg06/1, + flex_compact_otp7431_msg07/1, + + pretty_tickets/1, + pretty_otp4632_msg1/1, + pretty_otp4632_msg2/1, + pretty_otp4632_msg3/1, + pretty_otp4632_msg4/1, + pretty_otp4710_msg1/1, + pretty_otp4710_msg2/1, + pretty_otp4945_msg1/1, + pretty_otp4945_msg2/1, + pretty_otp4945_msg3/1, + pretty_otp4945_msg4/1, + pretty_otp4945_msg5/1, + pretty_otp4945_msg6/1, + pretty_otp4949_msg1/1, + pretty_otp4949_msg2/1, + pretty_otp4949_msg3/1, + pretty_otp5042_msg1/1, + pretty_otp5068_msg1/1, + pretty_otp5085_msg1/1, + pretty_otp5085_msg2/1, + pretty_otp5085_msg3/1, + pretty_otp5085_msg4/1, + pretty_otp5085_msg5/1, + pretty_otp5085_msg6/1, + pretty_otp5085_msg7/1, + pretty_otp5085_msg8/1, + pretty_otp5600_msg1/1, + pretty_otp5600_msg2/1, + pretty_otp5601_msg1/1, + pretty_otp5793_msg01/1, + pretty_otp5882_msg01/1, + pretty_otp6490_msg01/1, + pretty_otp6490_msg02/1, + pretty_otp6490_msg03/1, + pretty_otp6490_msg04/1, + pretty_otp6490_msg05/1, + pretty_otp6490_msg06/1, + pretty_otp7671_msg01/1, + pretty_otp7671_msg02/1, + pretty_otp7671_msg03/1, + pretty_otp7671_msg04/1, + pretty_otp7671_msg05/1, + pretty_otp8114_msg01/1, + + flex_pretty_tickets/1, + flex_pretty_otp5042_msg1/1, + flex_pretty_otp5085_msg1/1, + flex_pretty_otp5085_msg2/1, + flex_pretty_otp5085_msg3/1, + flex_pretty_otp5085_msg4/1, + flex_pretty_otp5085_msg5/1, + flex_pretty_otp5085_msg6/1, + flex_pretty_otp5085_msg7/1, + flex_pretty_otp5085_msg8/1, + flex_pretty_otp5600_msg1/1, + flex_pretty_otp5600_msg2/1, + flex_pretty_otp5601_msg1/1, + flex_pretty_otp5793_msg01/1, + flex_pretty_otp7431_msg01/1, + flex_pretty_otp7431_msg02/1, + flex_pretty_otp7431_msg03/1, + flex_pretty_otp7431_msg04/1, + flex_pretty_otp7431_msg05/1, + flex_pretty_otp7431_msg06/1, + flex_pretty_otp7431_msg07/1, + + init_per_testcase/2, fin_per_testcase/2]). + +-export([display_text_messages/0]). + + +%% ---- + +-define(EC_V3, {version3,prev3a}). +-define(EC, [?EC_V3]). + +-define(VERSION, 3). +-define(VERSION_STR, "3"). +-define(MSG_LIB, megaco_test_msg_prev3a_lib). +-define(DEFAULT_PORT, 55555). +-define(MG1_MID_NO_PORT, {ip4Address, + #'IP4Address'{address = [124, 124, 124, 222]}}). +-define(MG1_MID, {ip4Address, #'IP4Address'{address = [124, 124, 124, 222], + portNumber = ?DEFAULT_PORT}}). +-define(MG2_MID, {ip4Address, #'IP4Address'{address = [125, 125, 125, 111], + portNumber = ?DEFAULT_PORT}}). +-define(MGC_MID, {ip4Address, #'IP4Address'{address = [123, 123, 123, 4], + portNumber = ?DEFAULT_PORT}}). + +-define(A4444, ["11111111", "00000000", "00000000"]). +-define(A4445, ["11111111", "00000000", "11111111"]). +-define(A5555, ["11111111", "11111111", "00000000"]). +-define(A5556, ["11111111", "11111111", "11111111"]). + + +%% ---- + +display_text_messages() -> + Msgs = msgs1(text) ++ msgs4(text) ++ msgs5(text) ++ msgs6(text), + %% Msgs = msgs5(text) ++ msgs6(text), + megaco_codec_test_lib:display_text_messages(?VERSION, ?EC, Msgs). + + +%% ---- + + +expand(RootCase) -> + expand([RootCase], []). + +expand([], Acc) -> + lists:flatten(lists:reverse(Acc)); +expand([Case|Cases], Acc) -> + case (catch apply(?MODULE,Case,[suite])) of + [] -> + expand(Cases, [Case|Acc]); + C when is_list(C) -> + expand(Cases, [expand(C, [])|Acc]); + _ -> + expand(Cases, [Case|Acc]) + end. + + +%% ---- + +tickets() -> + Flag = process_flag(trap_exit, true), + Cases = expand(tickets), + Fun = fun(Case) -> + C = init_per_testcase(Case, [{tc_timeout, + timer:minutes(10)}]), + io:format("Eval ~w~n", [Case]), + Result = + case (catch apply(?MODULE, Case, [C])) of + {'EXIT', Reason} -> + io:format("~n~p exited:~n ~p~n", + [Case, Reason]), + {error, {Case, Reason}}; + Res -> + Res + end, + fin_per_testcase(Case, C), + Result + end, + process_flag(trap_exit, Flag), + lists:map(Fun, Cases). + + +%% ---- + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + +init_per_testcase(Case, Config) -> + %% CaseString = io_lib:format("~p", [Case]), + C = + case lists:suffix("time_test", atom_to_list(Case)) of + true -> + [{tc_timeout, timer:minutes(10)}|Config]; + false -> + put(verbosity,trc), + Config + end, + megaco_test_lib:init_per_testcase(Case, C). + +fin_per_testcase(Case, Config) -> + erase(verbosity), + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top test case + +all(suite) -> + [ + text, + binary, + erl_dist, + tickets + ]. + +text(suite) -> + [ + pretty, + flex_pretty, + compact, + flex_compact + ]. + +binary(suite) -> + [ + bin, + ber, + ber_bin, + per, + per_bin + ]. + +erl_dist(suite) -> + [ + erl_dist_m + ]. + +pretty(suite) -> + [ + pretty_test_msgs + ]. + + +compact(suite) -> + [ + compact_test_msgs + ]. + + +flex_pretty(suite) -> + {req, [], + {conf, flex_pretty_init, flex_pretty_cases(), flex_pretty_finish}}. + +flex_pretty_cases() -> + [ + flex_pretty_test_msgs + ]. + +flex_compact(suite) -> + {req, [], + {conf, flex_compact_init, flex_compact_cases(), flex_compact_finish}}. + +flex_compact_cases() -> + [ + flex_compact_test_msgs, + flex_compact_dm_timers1, + flex_compact_dm_timers2, + flex_compact_dm_timers3, + flex_compact_dm_timers4, + flex_compact_dm_timers5, + flex_compact_dm_timers6, + flex_compact_dm_timers7, + flex_compact_dm_timers8 + ]. + + +bin(suite) -> + [ + bin_test_msgs + ]. + + +ber(suite) -> + [ + ber_test_msgs + ]. + + +ber_bin(suite) -> + [ + ber_bin_test_msgs + ]. + + +per(suite) -> + [ + per_test_msgs + ]. + + +%% Support for per_bin was added to ASN.1 as of version +%% 1.3.2 (R8). And later merged into 1.3.1.3 (R7). These +%% releases are identical (as far as I know). +%% +per_bin(suite) -> + [ + per_bin_test_msgs + ]. + + +erl_dist_m(suite) -> + [ + erl_dist_m_test_msgs + ]. + +tickets(suite) -> + [ + compact_tickets, + flex_compact_tickets, + pretty_tickets, + flex_pretty_tickets + ]. + + +compact_tickets(suite) -> + [ + compact_otp4011_msg1, + compact_otp4011_msg2, + compact_otp4011_msg3, + compact_otp4013_msg1, + compact_otp4085_msg1, + compact_otp4085_msg2, + compact_otp4280_msg1, + compact_otp4299_msg1, + compact_otp4299_msg2, + compact_otp4359_msg1, + compact_otp4920_msg0, + compact_otp4920_msg1, + compact_otp4920_msg2, + compact_otp4920_msg3, + compact_otp4920_msg4, + compact_otp4920_msg5, + compact_otp4920_msg6, + compact_otp4920_msg7, + compact_otp4920_msg8, + compact_otp4920_msg9, + compact_otp4920_msg10, + compact_otp4920_msg11, + compact_otp4920_msg12, + compact_otp4920_msg20, + compact_otp4920_msg21, + compact_otp4920_msg22, + compact_otp4920_msg23, + compact_otp4920_msg24, + compact_otp4920_msg25, + compact_otp5186_msg01, + compact_otp5186_msg02, + compact_otp5186_msg03, + compact_otp5186_msg04, + compact_otp5186_msg05, + compact_otp5186_msg06, + compact_otp5793_msg01, + compact_otp5993_msg01, + compact_otp5993_msg02, + compact_otp5993_msg03, + compact_otp6017_msg01, + compact_otp6017_msg02, + compact_otp6017_msg03 + ]. + +flex_compact_tickets(suite) -> + {req, [], + {conf, flex_compact_init, flex_compact_tickets_cases(), + flex_compact_finish}}. + +flex_compact_tickets_cases() -> + [ + flex_compact_otp7431_msg01, + flex_compact_otp7431_msg02, + flex_compact_otp7431_msg03, + flex_compact_otp7431_msg04, + flex_compact_otp7431_msg05, + flex_compact_otp7431_msg06, + flex_compact_otp7431_msg07 + ]. + + +pretty_tickets(suite) -> + [ + pretty_otp4632_msg1, + pretty_otp4632_msg2, + pretty_otp4632_msg3, + pretty_otp4632_msg4, + pretty_otp4710_msg1, + pretty_otp4710_msg2, + pretty_otp4945_msg1, + pretty_otp4945_msg2, + pretty_otp4945_msg3, + pretty_otp4945_msg4, + pretty_otp4945_msg5, + pretty_otp4945_msg6, + pretty_otp4949_msg1, + pretty_otp4949_msg2, + pretty_otp4949_msg3, + pretty_otp5042_msg1, + pretty_otp5068_msg1, + pretty_otp5085_msg1, + pretty_otp5085_msg2, + pretty_otp5085_msg3, + pretty_otp5085_msg4, + pretty_otp5085_msg5, + pretty_otp5085_msg6, + pretty_otp5085_msg7, + pretty_otp5085_msg8, + pretty_otp5600_msg1, + pretty_otp5600_msg2, + pretty_otp5601_msg1, + pretty_otp5793_msg01, + pretty_otp5882_msg01, + pretty_otp6490_msg01, + pretty_otp6490_msg02, + pretty_otp6490_msg03, + pretty_otp6490_msg04, + pretty_otp6490_msg05, + pretty_otp6490_msg06, + pretty_otp7671_msg01, + pretty_otp7671_msg02, + pretty_otp7671_msg03, + pretty_otp7671_msg04, + pretty_otp7671_msg05, + pretty_otp8114_msg01 + ]. + +flex_pretty_tickets(suite) -> + {req, [], + {conf, flex_pretty_init, flex_pretty_tickets_cases(), + flex_pretty_finish}}. + +flex_pretty_tickets_cases() -> + [ + flex_pretty_otp5042_msg1, + flex_pretty_otp5085_msg1, + flex_pretty_otp5085_msg2, + flex_pretty_otp5085_msg3, + flex_pretty_otp5085_msg4, + flex_pretty_otp5085_msg5, + flex_pretty_otp5085_msg6, + flex_pretty_otp5085_msg7, + flex_pretty_otp5085_msg8, + flex_pretty_otp5600_msg1, + flex_pretty_otp5600_msg2, + flex_pretty_otp5601_msg1, + flex_pretty_otp5793_msg01, + flex_pretty_otp7431_msg01, + flex_pretty_otp7431_msg02, + flex_pretty_otp7431_msg03, + flex_pretty_otp7431_msg04, + flex_pretty_otp7431_msg05, + flex_pretty_otp7431_msg06, + flex_pretty_otp7431_msg07 + ]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +pretty_test_msgs(suite) -> + []; +pretty_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(text) ++ msgs2(text) ++ msgs3(text) ++ msgs4(text) ++ + msgs5(text) ++ msgs6(text), + %% Msgs = msgs5(text), + %% Msgs = msgs6(text), + DynamicDecode = false, + test_msgs(megaco_pretty_text_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_pretty_init(Config) -> + flex_init(Config). + +flex_pretty_finish(Config) -> + flex_finish(Config). + + +flex_pretty_test_msgs(suite) -> + []; +flex_pretty_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), +%% Msgs = msgs5(text), + Msgs = msgs1(text) ++ msgs2(text) ++ msgs3(text) ++ msgs4(text) ++ + msgs5(text) ++ msgs6(text), + Conf = flex_scanner_conf(Config), + DynamicDecode = false, + test_msgs(megaco_pretty_text_encoder, DynamicDecode, [?EC_V3,Conf], Msgs). + + +flex_pretty_otp5042_msg1(suite) -> + []; +flex_pretty_otp5042_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5042_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp5042_msg1(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {_, _Mod, {bad_timeStamp, TimeStamp}} -> + exit({bad_timeStamp, TimeStamp}); + _ -> + io:format("flex_pretty_otp5042_msg1 -> " + "~n Reason: ~w" + "~n", [Reason]), + exit({unexpected_decode_result, Reason}) + end; + {ok, M} -> + t("flex_pretty_otp5042_msg1 -> successfull decode:" + "~n~p", [M]), + ok + end. + + +flex_pretty_otp5085_msg1(suite) -> + []; +flex_pretty_otp5085_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg1(), [Conf]). + +flex_pretty_otp5085_msg2(suite) -> + []; +flex_pretty_otp5085_msg2(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(error, pretty_otp5085_msg2(), [Conf]). + +flex_pretty_otp5085_msg3(suite) -> + []; +flex_pretty_otp5085_msg3(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg3(), [Conf]). + +flex_pretty_otp5085_msg4(suite) -> + []; +flex_pretty_otp5085_msg4(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg4(), [Conf]). + +flex_pretty_otp5085_msg5(suite) -> + []; +flex_pretty_otp5085_msg5(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg5(), [Conf]). + +flex_pretty_otp5085_msg6(suite) -> + []; +flex_pretty_otp5085_msg6(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg6(), [Conf]). + +flex_pretty_otp5085_msg7(suite) -> + []; +flex_pretty_otp5085_msg7(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg7(), [Conf]). + +flex_pretty_otp5085_msg8(suite) -> + []; +flex_pretty_otp5085_msg8(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg8 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg8(), [Conf]). + +flex_pretty_otp5600_msg1(suite) -> + []; +flex_pretty_otp5600_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5600_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5600(ok, pretty_otp5600_msg1(), [Conf]). + +flex_pretty_otp5600_msg2(suite) -> + []; +flex_pretty_otp5600_msg2(Config) when is_list(Config) -> + d("flex_pretty_otp5600_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5600(ok, pretty_otp5600_msg2(), [Conf]). + +flex_pretty_otp5601_msg1(suite) -> + []; +flex_pretty_otp5601_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5601_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5601(ok, pretty_otp5601_msg1(), [Conf]). + +flex_pretty_otp5793_msg01(suite) -> + []; +flex_pretty_otp5793_msg01(Config) when is_list(Config) -> + d("flex_pretty_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5793(ok, pretty_otp5793_msg1(), [Conf]). + + +flex_pretty_otp7431_msg01(suite) -> + []; +flex_pretty_otp7431_msg01(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(ok, flex_pretty_otp7431_msg1(), [Conf]). + +flex_pretty_otp7431_msg02(suite) -> + []; +flex_pretty_otp7431_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp7431_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg2(), [Conf]). + +flex_pretty_otp7431_msg03(suite) -> + []; +flex_pretty_otp7431_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp7431_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg3(), [Conf]). + +flex_pretty_otp7431_msg04(suite) -> + []; +flex_pretty_otp7431_msg04(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg04 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg4(), [Conf]). + +flex_pretty_otp7431_msg05(suite) -> + []; +flex_pretty_otp7431_msg05(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg05 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg5(), [Conf]). + +flex_pretty_otp7431_msg06(suite) -> + []; +flex_pretty_otp7431_msg06(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg06 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg6(), [Conf]). + +flex_pretty_otp7431_msg07(suite) -> + []; +flex_pretty_otp7431_msg07(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg07 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg7(), [Conf]). + +flex_pretty_otp7431(Expected, Msg, Conf) -> + otp7431(Expected, megaco_pretty_text_encoder, Msg, Conf). + +otp7431(Expected, Codec, Msg0, Conf) -> + Bin0 = list_to_binary(Msg0), + case decode_message(Codec, false, Conf, Bin0) of + {ok, _Msg1} when Expected =:= ok -> + io:format(" decoded", []); + {error, {bad_property_parm, Reason}} when (Expected =:= error) andalso + is_list(Reason) -> + io:format("expected result: ~s", [Reason]), + ok; + Else -> + io:format("unexpected result", []), + exit({unexpected_decode_result, Else}) + end. + + +flex_pretty_otp7431_msg1() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a=recvonly + } ; RTP profile for G.723.1 is 4 + } + } + } + } + }". + +flex_pretty_otp7431_msg2() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a= } + } + } + } + } + }". + +flex_pretty_otp7431_msg3() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a } + } + } + } + } + }". + +flex_pretty_otp7431_msg4() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a} + } + } + } + } + }". + +flex_pretty_otp7431_msg5() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v= } + } + } + } + } + }". + +flex_pretty_otp7431_msg6() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v } + } + } + } + } + }". + +flex_pretty_otp7431_msg7() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v} + } + } + } + } + }". + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +compact_test_msgs(suite) -> + []; +compact_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(text) ++ msgs2(text) ++ msgs3(text) ++ msgs4(text) ++ + msgs5(text) ++ msgs6(text), + %% Msgs = msgs6(text), + DynamicDecode = false, + test_msgs(megaco_compact_text_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_compact_init(Config) -> + flex_init(Config). + +flex_compact_finish(Config) -> + flex_finish(Config). + + +flex_compact_test_msgs(suite) -> + []; +flex_compact_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(text) ++ msgs2(text) ++ msgs3(text) ++ msgs4(text) ++ + msgs5(text) ++ msgs6(text), + Conf = flex_scanner_conf(Config), + DynamicDecode = true, + test_msgs(megaco_compact_text_encoder, DynamicDecode, [?EC_V3,Conf], Msgs). + + +flex_compact_dm_timers1(suite) -> + []; +flex_compact_dm_timers1(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("1", "2", "3"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers1 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({1,2,3}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers2(suite) -> + []; +flex_compact_dm_timers2(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("02", "03", "04"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers2 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({2,3,4}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers3(suite) -> + []; +flex_compact_dm_timers3(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("1", "02", "31"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers3 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({1,2,31}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers4(suite) -> + []; +flex_compact_dm_timers4(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("10", "21", "99"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers4 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({10,21,99}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers5(suite) -> + []; +flex_compact_dm_timers5(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("99", "23", "11"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers5 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({99,23,11}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers6(suite) -> + []; +flex_compact_dm_timers6(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("77", "09", "1"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers6 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({77,9,1}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers7(suite) -> + []; +flex_compact_dm_timers7(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("77", "09", "1", "99"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers7 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({77,9,1,99}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers8(suite) -> + []; +flex_compact_dm_timers8(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("01", "09", "01", "02"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers8 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({1,9,1,2}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +build_dm_timers_message(T, S, L) -> + TMRs = lists:flatten(io_lib:format("T:~s,S:~s,L:~s", [T, S, L])), + build_dm_timers_message(TMRs). + +build_dm_timers_message(T, S, L, Z) -> + TMRs = lists:flatten(io_lib:format("T:~s,S:~s,L:~s,Z:~s", [T, S, L,Z])), + build_dm_timers_message(TMRs). + +build_dm_timers_message(TMRs) -> + M = io_lib:format("!/" ?VERSION_STR " [123.123.123.4]:55555\nT=10001{C=-{MF=11111111/00000000/00000000{E=2223{al/on,dd/ce{DM=dialplan00}},SG{cg/rt},DM=dialplan00{~s,(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)}}}}", [TMRs]), + lists:flatten(M). + + +verify_dm_timers(TMRs, #'MegacoMessage'{mess = Mess}) -> + #'Message'{messageBody = Body} = Mess, + case get_dm_timers(Body) of + TMRs -> + ok; + {error, Reason} -> + exit({invalid_timer, {TMRs, Reason}}); + TMRs1 -> + exit({invalid_timer_values, {TMRs, TMRs1}}) + end. + +get_dm_timers({transactions, T}) when is_list(T) -> + get_dm_timers1(T); +get_dm_timers(Other) -> + {error, {invalid_transactions, Other}}. + +get_dm_timers1([{transactionRequest,T}|Ts]) + when is_record(T,'TransactionRequest') -> + case get_dm_timers2(T) of + {ok, Timers} -> + Timers; + _ -> + get_dm_timers1(Ts) + end; +get_dm_timers1([_|Ts]) -> + get_dm_timers1(Ts); +get_dm_timers1([]) -> + {error, {no_timers, 'TransactionRequest'}}. + + +get_dm_timers2(#'TransactionRequest'{actions = Actions}) when is_list(Actions) -> + get_dm_timers3(Actions). + + +get_dm_timers3([#'ActionRequest'{commandRequests = Cmds}|Ars]) when is_list(Cmds) -> + case get_dm_timers4(Cmds) of + {ok, Timers} -> + {ok, Timers}; + _ -> + get_dm_timers3(Ars) + end; +get_dm_timers3([_|Ars]) -> + get_dm_timers3(Ars); +get_dm_timers3([]) -> + {error, {no_timers, 'ActionRequest'}}. + +get_dm_timers4([#'CommandRequest'{command = Cmd}|Cmds]) -> + case get_dm_timers5(Cmd) of + {ok, Timers} -> + {ok, Timers}; + _ -> + get_dm_timers4(Cmds) + end; +get_dm_timers4([_|Cmds]) -> + get_dm_timers4(Cmds); +get_dm_timers4([]) -> + {error, {no_timers, 'CommandRequest'}}. + + +get_dm_timers5({modReq, #'AmmRequest'{descriptors = Descriptors}}) -> + get_dm_timers6(Descriptors); +get_dm_timers5(R) -> + {error, {no_modReq, R}}. + + +get_dm_timers6([{digitMapDescriptor, #'DigitMapDescriptor'{digitMapValue = Val}}|_]) -> + case Val of + #'DigitMapValue'{startTimer = T, + shortTimer = S, + longTimer = L, + durationTimer = asn1_NOVALUE} -> + {ok, {T, S, L}}; + #'DigitMapValue'{startTimer = T, + shortTimer = S, + longTimer = L, + durationTimer = Z} -> + {ok, {T, S, L, Z}}; + _ -> + {error, no_value_in_dm} + end; +get_dm_timers6([_|Descs]) -> + get_dm_timers6(Descs); +get_dm_timers6([]) -> + {error, {no_timers, descriptors}}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bin_test_msgs(suite) -> + []; +bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(binary) ++ msgs4(binary) ++ msgs5(binary) ++ msgs6(binary), + %% Msgs = msgs5(binary), + DynamicDecode = false, + test_msgs(megaco_binary_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ber_test_msgs(suite) -> + []; +ber_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(binary) ++ msgs4(binary) ++ msgs5(binary) ++ msgs6(binary), + %% Msgs = msgs6(binary), + DynamicDecode = false, + test_msgs(megaco_ber_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ber_bin_test_msgs(suite) -> + []; +ber_bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(binary) ++ msgs4(binary) ++ msgs5(binary) ++ msgs6(binary), + DynamicDecode = true, + test_msgs(megaco_ber_bin_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +per_test_msgs(suite) -> + []; +per_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(binary) ++ msgs4(binary) ++ msgs5(binary) ++ msgs6(binary), + DynamicDecode = false, + test_msgs(megaco_per_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +per_bin_test_msgs(suite) -> + []; +per_bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(binary) ++ msgs4(binary) ++ msgs5(binary) ++ msgs6(binary), + DynamicDecode = false, + test_msgs(megaco_per_bin_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +erl_dist_m_test_msgs(suite) -> + []; +erl_dist_m_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(erlang) ++ + msgs2(erlang) ++ + msgs3(erlang) ++ + msgs4(erlang) ++ + msgs5(erlang) ++ + msgs6(erlang), + DynamicDecode = false, + Conf = [megaco_compressed], + test_msgs(megaco_erl_dist_encoder, DynamicDecode, Conf, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +%% Ticket test cases: + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg1(suite) -> + []; +compact_otp4011_msg1(Config) when is_list(Config) -> +% put(severity,trc), +% put(dbg,true), + d("compact_otp4011_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR " ML T=233350{C=${A=stedevice/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SR}}}}}", + ok = compact_otp4011(M), +% erase(severity), +% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg2(suite) -> + []; +compact_otp4011_msg2(Config) when is_list(Config) -> + d("compact_otp4011_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR " ML T=233350{C=${A=stedevice/01{M{O{MO=SO,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SR}}}}}", +% put(severity,trc), +% put(dbg,true), + ok = compact_otp4011(M). + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg3(suite) -> + []; +compact_otp4011_msg3(Config) when is_list(Config) -> + d("compact_otp4011_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR " ML T=233350{C=${A=stedevice/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SO}}}}}", +% put(severity,trc), +% put(dbg,true), + ok = compact_otp4011(M). + + +compact_otp4011(M) -> + d("compact_otp4011 -> entry with" + "~n M: '~s'", [M]), + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, _} -> + exit({decoded_erroneous_message,M}); + {error, Error} when is_list(Error) -> % Expected result + d("compact_otp4011 -> expected error result (so far)", []), + case lists:keysearch(reason,1,Error) of + {value, {reason,Reason}} -> + d("compact_otp4011 -> expected error: " + "~n Reason: ~p", [Reason]), + case Reason of + {0, megaco_text_parser_prev3a, + {do_merge_control_streamParms, [A,B]}} + when is_list(A) andalso is_record(B, 'LocalControlDescriptor') -> + case lists:keysearch(mode,1,A) of + {value, {mode, _Mode}} + when B#'LocalControlDescriptor'.streamMode =/= asn1_NOVALUE -> + d("compact_otp4011 -> expected error",[]), + ok; + Other -> + exit({unexpected_mode_reason, {A,B,Other}}) + end; + Other -> + exit({unexpected_reason, Other}) + end; + + false -> + d("compact_otp4011 -> OUPS, wrong kind of error", []), + exit({unexpected_result, Error}) + end; + Else -> + d("compact_otp4011 -> unexpected decode result: ~p", [Else]), + exit({unexpected_decode_result, Else}) + end. + + +%% -------------------------------------------------------------- +%% Note that this decode SHALL fail, because of the misspelled +%% MEGCAO instead of the correct MEGACO. +compact_otp4013_msg1(suite) -> + []; +compact_otp4013_msg1(Config) when is_list(Config) -> + d("compact_otp4013_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "MEGCAO/3 MG1 T=12345678{C=-{SC=root{SV{MT=RS,RE=901}}}}", + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, _} -> + exit({decoded_erroneous_message,M}); + {error, Reason} when is_list(Reason) -> + {value, {reason, no_version_found, _}} = + lists:keysearch(reason, 1, Reason), + {value, {token, [{'SafeChars',_,"megcao/3"}|_]}} = + lists:keysearch(token, 1, Reason), + ok; + Else -> + exit({unexpected_decode_result,Else}) + end. + + + +%% -------------------------------------------------------------- +%% +%% +compact_otp4085_msg1(suite) -> + []; +compact_otp4085_msg1(Config) when is_list(Config) -> + d("compact_otp4085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = compact_otp4085_erroneous_msg(), + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, M} -> + exit({decoded_erroneous_message,M}); + {error, Error} when is_list(Error) -> % Expected result + t("compact_otp4085_msg1 -> decode failed", []), + case lists:keysearch(reason, 1, Error) of + {value, {reason,{999999, Module, Crap}}} -> + t("compact_otp4085_msg1 -> THE ACTUAL ERROR: " + "~n LINE NUMBER: 999999" + "~n Module: ~p" + "~n Crap: ~p", [Module, Crap]), + %% ok; + exit({decode_failed_999999, Module, Crap}); + {value, {reason,{Line, Module, Crap}}} -> + t("compact_otp4085_msg1 -> Expected: " + "~n Line: ~p" + "~n Module: ~p" + "~n Crap: ~p", [Line, Module, Crap]), + ok; + false -> + exit({unexpected_result, Error}) + end; + Else -> + exit({unexpected_decode_result, Else}) + end. + + +%% -------------------------------------------------------------- +%% This test case is just to show that the message used in +%% compact_otp4085_msg1 is actually ok when you add '}' at the end. +compact_otp4085_msg2(suite) -> + []; +compact_otp4085_msg2(Config) when is_list(Config) -> + d("compact_otp4085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M1 = compact_otp4085_erroneous_msg() ++ "}", + Bin = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, M2} -> + l("compact_otp4085_msg1 -> successfull decode" + "~n M2: ~p", [M2]), + ok; + Else -> + e("compact_otp4085_msg1 -> decode error" + "~n Else: ~p", [Else]), + exit({unexpected_decode_result,Else}) + end. + + +%% This message lack the ending parentesis (}). +compact_otp4085_erroneous_msg() -> + M = "!/" + ?VERSION_STR + " ML T=11223342{C=${A=${M{O{MO=SR,RV=OFF,RG=OFF},L{v=0," + "c=ATM NSAP $ ," + "a=eecid:$ ," + "m=audio - AAL1/ATMF -," + "}}},A=stee1181/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=off}}}}", + M. + +%% -------------------------------------------------------------- +%% +%% +compact_otp4280_msg1(suite) -> + []; +compact_otp4280_msg1(Config) when is_list(Config) -> + d("compact_otp4280_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Bin = list_to_binary(compact_otp4280_msg()), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, _Msg} -> + ok; + {error, Error} when is_list(Error) -> + t("compact_otp4280_msg1 -> decode failed", []), + case lists:keysearch(reason, 1, Error) of + {value, {reason,{Line, Module, Reason} = R}} -> + t("compact_otp4280_msg1 -> " + "~n Line: ~w" + "~n Module: ~w" + "~n Reason: ~w", [Line, Module, Reason]), + exit({decode_failed, R}); + false -> + exit({unexpected_result, Error}) + end; + Else -> + exit({unexpected_decode_result, Else}) + end. + +compact_otp4280_msg() -> + M = "!/" + ?VERSION_STR + " mgw1 P=71853646{C=-{AV=root{M{TS{root/maxnumberofcontexts=49500," + "root/maxterminationspercontext=2,root/normalmgexecutiontime=200," + "root/normalmgcexecutiontime=150," + "root/provisionalresponsetimervalue=2000,BF=OFF,SI=IV}}}}}", + M. + + +%% -------------------------------------------------------------- +%% This ticket is about comments in a message +compact_otp4299_msg1(suite) -> + []; +compact_otp4299_msg1(Config) when is_list(Config) -> + d("compact_otp4299_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Bin = list_to_binary(compact_otp4299_msg()), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, _Msg} -> + ok; + + {error, Reason} -> + exit({decode_error, Reason}); + + Else -> + exit({unexpected_decode_result, Else}) + end. + + +%% Same message, but this time decoded using the flex scanner +compact_otp4299_msg2(suite) -> + []; +compact_otp4299_msg2(Config) when is_list(Config) -> + d("compact_otp4299_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + + {Pid, Conf} = compact_otp4299_msg2_init(), + + M1 = compact_otp4299_msg(), + d("compact_otp4299_msg2 -> M1: ~n~s", [M1]), + Bin = list_to_binary(M1), + Res = decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], Bin), + compact_otp4299_msg2_finish(Pid), + + case Res of + {ok, M2} -> + d("compact_otp4299_msg2 -> M2: ~n~p", [M2]), + ok; + + {error, Reason} -> + exit({decode_error, Reason}); + + Else -> + exit({unexpected_decode_result, Else}) + end. + + +compact_otp4299_msg2_init() -> + Flag = process_flag(trap_exit, true), + Res = (catch start_flex_scanner()), + process_flag(trap_exit, Flag), + case Res of + {error, Reason} -> + skip(Reason); + {ok, FlexConfig} -> + FlexConfig + end. + +compact_otp4299_msg2_finish(Pid) -> + stop_flex_scanner(Pid). + + +compact_otp4299_msg() -> + M = ";KALLE\n" + "!/" + ?VERSION_STR + " mg58_1 P=005197711{; YET ANOTHER COMMENT\n" + "C=035146207{A=mg58_1_1_4_1_23/19; BEFORE COMMA\n" + ",; AFTER COMMA\n" + "A=eph58_1/0xA4023371{M{L{\n" + "v=0\n" + "c=ATM NSAP 39.0102.0304.0506.0708.090a.0b58.0100.0000.0000.00\n" + "m=audio - AAL1/ATMF -\n" + "a=eecid:A4023371\n" + "}}; HOBBE\n}; KALLE \"HOBBE \n}}" + ";KALLE\n\n", + M. + + +%% -------------------------------------------------------------- +%% +%% +compact_otp4359_msg1(suite) -> + []; +compact_otp4359_msg1(Config) when is_list(Config) -> + d("compact_otp4359_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Bin = list_to_binary(compact_otp4359_msg()), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, #'MegacoMessage'{mess = Mess}} -> + {transactions, Trans} = Mess#'Message'.messageBody, + case Trans of + [{transactionRequest,#'TransactionRequest'{transactionId = asn1_NOVALUE}}] -> + ok; + _ -> + exit({unexpected_transactions, Trans}) + end; + Else -> + t("compact_otp4359_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +compact_otp4359_msg() -> + M = "!/" ?VERSION_STR " ml2 T={C=${A=${M{O {MO=SR,RG=OFF,RV=OFF}}}}}", + M. + + +%% -------------------------------------------------------------- +%% +%% +compact_otp4920_msg0(suite) -> + []; +compact_otp4920_msg0(Config) when is_list(Config) -> + d("compact_otp4920_msg0 -> entry", []), + ?ACQUIRE_NODES(1, Config), + % put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg0(), true). + +compact_otp4920_msg1(suite) -> + []; +compact_otp4920_msg1(Config) when is_list(Config) -> + d("compact_otp4920_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + % put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg1(), false). + +compact_otp4920_msg2(suite) -> + []; +compact_otp4920_msg2(Config) when is_list(Config) -> + d("compact_otp4920_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg2(), false). + +compact_otp4920_msg3(suite) -> + []; +compact_otp4920_msg3(Config) when is_list(Config) -> + d("compact_otp4920_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg3(), true). + +compact_otp4920_msg4(suite) -> + []; +compact_otp4920_msg4(Config) when is_list(Config) -> + d("compact_otp4920_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg4(), true). + +compact_otp4920_msg5(suite) -> + []; +compact_otp4920_msg5(Config) when is_list(Config) -> + d("compact_otp4920_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg5(), true). + +compact_otp4920_msg6(suite) -> + []; +compact_otp4920_msg6(Config) when is_list(Config) -> + d("compact_otp4920_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg6(), true). + +compact_otp4920_msg7(suite) -> + []; +compact_otp4920_msg7(Config) when is_list(Config) -> + d("compact_otp4920_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + % put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg7(), true). + +compact_otp4920_msg8(suite) -> + []; +compact_otp4920_msg8(Config) when is_list(Config) -> + d("compact_otp4920_msg8 -> entry", []), + ?ACQUIRE_NODES(1, Config), + % put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg8(), false). + +compact_otp4920_msg9(suite) -> + []; +compact_otp4920_msg9(Config) when is_list(Config) -> + d("compact_otp4920_msg9 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg9(), false). + +compact_otp4920_msg10(suite) -> + []; +compact_otp4920_msg10(Config) when is_list(Config) -> + d("compact_otp4920_msg10 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg10(), false). + +compact_otp4920_msg11(suite) -> + []; +compact_otp4920_msg11(Config) when is_list(Config) -> + d("compact_otp4920_msg11 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg11(), false). + +compact_otp4920_msg12(suite) -> + []; +compact_otp4920_msg12(Config) when is_list(Config) -> + d("compact_otp4920_msg12 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg12(), true). + +%% Duplicate padding +compact_otp4920_msg20(suite) -> + []; +compact_otp4920_msg20(Config) when is_list(Config) -> + d("compact_otp4920_msg20 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg20(), bad_mid_duplicate_padding). + +%% Length +compact_otp4920_msg21(suite) -> + []; +compact_otp4920_msg21(Config) when is_list(Config) -> + d("compact_otp4920_msg21 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg21(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg22(suite) -> + []; +compact_otp4920_msg22(Config) when is_list(Config) -> + d("compact_otp4920_msg22 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg22(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg23(suite) -> + []; +compact_otp4920_msg23(Config) when is_list(Config) -> + d("compact_otp4920_msg23 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg23(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg24(suite) -> + []; +compact_otp4920_msg24(Config) when is_list(Config) -> + d("compact_otp4920_msg24 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg24(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg25(suite) -> + []; +compact_otp4920_msg25(Config) when is_list(Config) -> + d("compact_otp4920_msg25 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg25(), bad_mid_ip6addr_length). + +compact_otp4920_msg_1(M1, CheckEqual) -> + Bin1 = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin1) of + {ok, Msg} -> + io:format(" decoded", []), + case encode_message(megaco_compact_text_encoder, ?EC, Msg) of + {ok, Bin1} -> + io:format(", encoded - equal:", []), + ok; + {ok, Bin2} when CheckEqual == true -> + M2 = binary_to_list(Bin2), + io:format(", encoded - not equal:", []), + exit({messages_not_equal, M1, M2}); + {ok, _} -> + io:format(", encoded:", []), + ok; + Else -> + io:format(", encode failed:", []), + exit({unexpected_encode_result, Else}) + end; + Else -> + io:format("decode failed:", []), + exit({unexpected_decode_result, Else}) + end. + +compact_otp4920_msg_2(M1, ExpectedReason) -> + Bin = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, Msg} -> + io:format("unexpected successfull decode", []), + exit({unexpected_encode_ok, Msg}); + {error, [{reason, {__Line, _Mod, Reason}}|_]} -> + case element(1, Reason) of + ExpectedReason -> + ok; + _ -> + exit({unexpected_decode_error_reason, + ExpectedReason, Reason}) + end; + {error, [{reason, {_Mod, Reason}}|_]} -> + case element(1, Reason) of + ExpectedReason -> + ok; + _ -> + exit({unexpected_decode_error_reason, + ExpectedReason, Reason}) + end; + Else -> + io:format("unexpected decode result", []), + exit({unexpected_decode_result, Else}) + + end. + +compact_otp4920_msg0() -> + M = "!/" ?VERSION_STR " [192.168.30.1]\nT=100{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg1() -> + M = "!/" ?VERSION_STR " [2031:0000:130F:0000:0000:09C0:876A:130B]\nT=101{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg2() -> + M = "!/" ?VERSION_STR " [2031:0:130F:0:0:9C0:876A:130B]\nT=102{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg3() -> + M = "!/" ?VERSION_STR " [2031:0:130F::9C0:876A:130B]\nT=103{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg4() -> + M = "!/" ?VERSION_STR " [::1]\nT=104{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg5() -> + M = "!/" ?VERSION_STR " [::]\nT=105{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg6() -> + M = "!/" ?VERSION_STR " [1::]\nT=106{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg7() -> + M = "!/" ?VERSION_STR " [FEDC:1::]\nT=107{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg8() -> + M = "!/" ?VERSION_STR " [2031:0:130F:0:0:9C0:135.106.19.11]\nT=108{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg9() -> + M = "!/" ?VERSION_STR " [2031:0:130F::9C0:135.106.19.11]\nT=109{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg10() -> + M = "!/" ?VERSION_STR " [::FFFF:192.168.30.1]\nT=110{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg11() -> + M = "!/" ?VERSION_STR " [::192.168.30.1]\nT=111{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg12() -> + M = "!/" ?VERSION_STR " [::C0A8:1E01]\nT=112{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: only one :: allowed +compact_otp4920_msg20() -> + M = "!/" ?VERSION_STR " [2031::130F::9C0]\nT=120{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg21() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:0000:0000:09C0:876A:130B]\nT=121{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg22() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0:130F:0:0:9C0:135.106.19.11]\nT=122{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg23() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:2132:4354::09C0:876A:130B]\nT=123{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg24() -> + M = "!/" ?VERSION_STR " [::2031:FFEE:0000:130F:2132:4354:09C0:876A:130B]\nT=124{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg25() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:2132:4354:09C0:876A:130B::]\nT=125{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + + +compact_otp5186_msg01(suite) -> + []; +compact_otp5186_msg01(Config) when is_list(Config) -> + d("compact_otp5186_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_1(compact_otp5186_msg01(), error, ignore). + +compact_otp5186_msg02(suite) -> + []; +compact_otp5186_msg02(Config) when is_list(Config) -> + d("compact_otp5186_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_1(compact_otp5186_msg02(), ok, ok). + +compact_otp5186_msg03(suite) -> + []; +compact_otp5186_msg03(Config) when is_list(Config) -> + d("compact_otp5186_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg03(), ok, ok). + +compact_otp5186_msg04(suite) -> + []; +compact_otp5186_msg04(Config) when is_list(Config) -> + d("compact_otp5186_msg04 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg04(), ok, ok). + +compact_otp5186_msg05(suite) -> + []; +compact_otp5186_msg05(Config) when is_list(Config) -> + d("compact_otp5186_msg05 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg05(), ok, ok). + +compact_otp5186_msg06(suite) -> + []; +compact_otp5186_msg06(Config) when is_list(Config) -> + d("compact_otp5186_msg06 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg06(), ok, ok). + +compact_otp5186_msg_1(M1, DecodeExpect, EncodeExpect) -> + Bin1 = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin1) of + {ok, Msg} when DecodeExpect == ok -> + io:format(" decoded", []), + case encode_message(megaco_compact_text_encoder, ?EC, Msg) of + {ok, Bin1} when EncodeExpect == ok -> + io:format(", encoded - equal:", []), + ok; + {ok, Bin2} when EncodeExpect == ok -> + M2 = binary_to_list(Bin2), + io:format(", encoded - not equal:", []), + exit({messages_not_equal, Msg, M1, M2}); + {ok, Bin3} when EncodeExpect == error -> + M3 = binary_to_list(Bin3), + io:format(", unexpected encode:", []), + exit({unexpected_encode_success, Msg, M1, M3}); + _Else when EncodeExpect == error -> + io:format(", encode failed ", []), + ok + end; + {ok, Msg} when DecodeExpect == error -> + io:format(" decoded", []), + exit({unexpected_decode_success, Msg}); + _Else when DecodeExpect == error -> + io:format(" decode failed ", []), + ok; + Else when DecodeExpect == ok -> + io:format(" decode failed ", []), + exit({unexpected_decode_result, Else}) + end. + +compact_otp5186_msg_2(Msg1, EncodeExpect, DecodeExpect) -> + case encode_message(megaco_compact_text_encoder, ?EC, Msg1) of + {ok, Bin} when EncodeExpect == ok -> + io:format(" encoded", []), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, Msg1} when DecodeExpect == ok -> + io:format(", decoded - equal:", []), + ok; + {ok, Msg2} when DecodeExpect == ok -> + M = binary_to_list(Bin), + case (catch compact_otp5186_check_megamsg(Msg1, Msg2)) of + ok -> + io:format(", decoded - not equal - ok:", []), + ok; + {'EXIT', Reason} -> + io:format(", decoded - not equal:", []), + exit({messages_not_equal, M, Reason, Msg1, Msg2}) + end; + {ok, Msg3} when DecodeExpect == error -> + M = binary_to_list(Bin), + io:format(", decoded:", []), + exit({unexpected_decode_success, M, Msg1, Msg3}); + Else when DecodeExpect == ok -> + M = binary_to_list(Bin), + io:format(", decode failed ", []), + exit({unexpected_decode_success, Msg1, M, Else}); + _Else when DecodeExpect == error -> + io:format(", decode failed ", []), + ok + end; + {ok, Bin} when EncodeExpect == error -> + M = binary_to_list(Bin), + io:format(" encoded", []), + exit({unexpected_encode_success, Msg1, M}); + _Else when EncodeExpect == error -> + io:format(" encode failed ", []), + ok; + Else when EncodeExpect == ok -> + io:format(" encode failed ", []), + exit({unexpected_encode_result, Else}) + end. + + +%% -- + +compact_otp5186_msg01() -> + "!/" ?VERSION_STR " <mg5>\nP=67111298{C=2699{AV=mg5_ipeph/0x0f0001{}}}". + +compact_otp5186_msg02() -> + "!/" ?VERSION_STR " <mg5>\nP=67111298{C=2699{AV=mg5_ipeph/0x0f0001}}". + +compact_otp5186_msg03() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]}, + [ + ] + } + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +compact_otp5186_msg04() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',?VERSION,{domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]}, + [ + {emptyDescriptors, + {'AuditDescriptor',asn1_NOVALUE,asn1_NOVALUE} + } + ] + } + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +compact_otp5186_msg05() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {addReply, + {'AmmsReply', + [ + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]} + ], + [ + ] + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +compact_otp5186_msg06() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',?VERSION,{domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {addReply, + {'AmmsReply', + [ + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]} + ], + [ + {emptyDescriptors, + {'AuditDescriptor',asn1_NOVALUE,asn1_NOVALUE} + } + ] + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +%% -- + +compact_otp5186_check_megamsg(M1, M1) -> + ok; +compact_otp5186_check_megamsg(#'MegacoMessage'{authHeader = AH, + mess = M1}, + #'MegacoMessage'{authHeader = AH, + mess = M2}) -> + compact_otp5186_check_mess(M1, M2); +compact_otp5186_check_megamsg(#'MegacoMessage'{authHeader = AH1}, + #'MegacoMessage'{authHeader = AH2}) -> + exit({not_equal, authHeader, AH1, AH2}). + +compact_otp5186_check_mess(M, M) -> + ok; +compact_otp5186_check_mess(#'Message'{version = V, + mId = MId, + messageBody = B1}, + #'Message'{version = V, + mId = MId, + messageBody = B2}) -> + compact_otp5186_check_body(B1, B2); +compact_otp5186_check_mess(#'Message'{version = V, + mId = MId1}, + #'Message'{version = V, + mId = MId2}) -> + exit({not_equal, mId, MId1, MId2}); +compact_otp5186_check_mess(#'Message'{version = V1, + mId = MId}, + #'Message'{version = V2, + mId = MId}) -> + exit({not_equal, version, V1, V2}). + +compact_otp5186_check_body(B, B) -> + ok; +compact_otp5186_check_body({transactions, T1}, {transactions, T2}) -> + compact_otp5186_check_trans(T1, T2); +compact_otp5186_check_body({messageError, E1}, {messageError, E2}) -> + compact_otp5186_check_merr(E1, E2); +compact_otp5186_check_body(B1, B2) -> + exit({not_equal, messageBody, B1, B2}). + +compact_otp5186_check_trans([], []) -> + ok; +compact_otp5186_check_trans([], T2) -> + exit({not_equal, transactions, [], T2}); +compact_otp5186_check_trans(T1, []) -> + exit({not_equal, transactions, T1, []}); +compact_otp5186_check_trans([Tran1|Trans1], [Tran2|Trans2]) -> + compact_otp5186_check_trans(Trans1, Trans2), + compact_otp5186_check_transaction(Tran1, Tran2). + +compact_otp5186_check_merr(ME, ME) -> + ok; +compact_otp5186_check_merr(#'ErrorDescriptor'{errorCode = EC, + errorText = ET1}, + #'ErrorDescriptor'{errorCode = EC, + errorText = ET2}) -> + exit({not_equal, errorText, ET1, ET2}); +compact_otp5186_check_merr(#'ErrorDescriptor'{errorCode = EC1, + errorText = ET}, + #'ErrorDescriptor'{errorCode = EC2, + errorText = ET}) -> + exit({not_equal, errorCode, EC1, EC2}). + +compact_otp5186_check_transaction(T, T) -> + ok; +compact_otp5186_check_transaction({transactionReply, TR1}, + {transactionReply, TR2}) -> + compact_otp5186_check_transRep(TR1, TR2); +compact_otp5186_check_transaction(T1, T2) -> + exit({unexpected_transactions, T1, T2}). + +compact_otp5186_check_transRep(T, T) -> + ok; +compact_otp5186_check_transRep(#'TransactionReply'{transactionId = TId, + immAckRequired = IAR, + transactionResult = TR1}, + #'TransactionReply'{transactionId = TId, + immAckRequired = IAR, + transactionResult = TR2}) -> + compact_otp5186_check_transRes(TR1, TR2); +compact_otp5186_check_transRep(T1, T2) -> + exit({unexpected_transaction_reply, T1, T2}). + +compact_otp5186_check_transRes(TR, TR) -> + ok; +compact_otp5186_check_transRes({actionReplies, AR1}, + {actionReplies, AR2}) -> + compact_otp5186_check_actReps(AR1, AR2); +compact_otp5186_check_transRes(TR1, TR2) -> + exit({unexpected_transaction_result, TR1, TR2}). + +compact_otp5186_check_actReps([], []) -> + ok; +compact_otp5186_check_actReps(AR1, []) -> + exit({not_equal, actionReplies, AR1, []}); +compact_otp5186_check_actReps([], AR2) -> + exit({not_equal, actionReplies, [], AR2}); +compact_otp5186_check_actReps([AR1|ARs1], [AR2|ARs2]) -> + compact_otp5186_check_actRep(AR1, AR2), + compact_otp5186_check_actReps(ARs1, ARs2). + +compact_otp5186_check_actRep(AR, AR) -> + ok; +compact_otp5186_check_actRep(#'ActionReply'{contextId = ID, + errorDescriptor = ED, + contextReply = CtxRep, + commandReply = CmdRep1}, + #'ActionReply'{contextId = ID, + errorDescriptor = ED, + contextReply = CtxRep, + commandReply = CmdRep2}) -> + compact_otp5186_check_cmdReps(CmdRep1, CmdRep2); +compact_otp5186_check_actRep(AR1, AR2) -> + exit({unexpected_actionReply, AR1, AR2}). + +compact_otp5186_check_cmdReps([], []) -> + ok; +compact_otp5186_check_cmdReps(CR1, []) -> + exit({not_equal, commandReplies, CR1, []}); +compact_otp5186_check_cmdReps([], CR2) -> + exit({not_equal, commandReplies, [], CR2}); +compact_otp5186_check_cmdReps([CR1|CRs1], [CR2|CRs2]) -> + compact_otp5186_check_cmdRep(CR1, CR2), + compact_otp5186_check_cmdReps(CRs1, CRs2). + +compact_otp5186_check_cmdRep(CR, CR) -> + ok; +compact_otp5186_check_cmdRep({auditValueReply, AVR1}, + {auditValueReply, AVR2}) -> + compact_otp5186_check_auditReply(AVR1, AVR2); +compact_otp5186_check_cmdRep({addReply, AVR1}, + {addReply, AVR2}) -> + compact_otp5186_check_ammsReply(AVR1, AVR2); +compact_otp5186_check_cmdRep(CR1, CR2) -> + exit({unexpected_commandReply, CR1, CR2}). + +compact_otp5186_check_auditReply(AR, AR) -> + ok; +compact_otp5186_check_auditReply({auditResult, AR1}, + {auditResult, AR2}) -> + compact_otp5186_check_auditRes(AR1, AR2); +compact_otp5186_check_auditReply(AR1, AR2) -> + exit({unexpected_auditReply, AR1, AR2}). + +compact_otp5186_check_ammsReply(AR, AR) -> + ok; +compact_otp5186_check_ammsReply(#'AmmsReply'{terminationID = ID, + terminationAudit = TA1}, + #'AmmsReply'{terminationID = ID, + terminationAudit = TA2}) -> + %% This is just to simplify the test + F = fun(asn1_NOVALUE) -> []; + (E) -> E + end, + compact_otp5186_check_termAudit(F(TA1), F(TA2)); +compact_otp5186_check_ammsReply(AR1, AR2) -> + exit({unexpected_ammsReply, AR1, AR2}). + +compact_otp5186_check_auditRes(AR, AR) -> + ok; +compact_otp5186_check_auditRes(#'AuditResult'{terminationID = ID, + terminationAuditResult = TAR1}, + #'AuditResult'{terminationID = ID, + terminationAuditResult = TAR2}) -> + compact_otp5186_check_termAuditRes(TAR1, TAR2); +compact_otp5186_check_auditRes(AR1, AR2) -> + exit({unexpected_auditResult, AR1, AR2}). + +compact_otp5186_check_termAuditRes([], []) -> + ok; +%% An empty empty descriptor is removed +compact_otp5186_check_termAuditRes([{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = asn1_NOVALUE}}|TAR1], []) -> + compact_otp5186_check_termAuditRes(TAR1, []); +compact_otp5186_check_termAuditRes(TAR1, []) -> + exit({not_equal, termAuditRes, TAR1, []}); +%% An empty empty descriptor is removed +compact_otp5186_check_termAuditRes([], [{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = asn1_NOVALUE}}|TAR2]) -> + compact_otp5186_check_termAuditRes([], TAR2); +compact_otp5186_check_termAuditRes([], TAR2) -> + exit({not_equal, termAuditRes, [], TAR2}); +compact_otp5186_check_termAuditRes([ARP1|TAR1], [ARP2|TAR2]) -> + compact_otp5186_check_auditRetParm(ARP1, ARP2), + compact_otp5186_check_termAuditRes(TAR1, TAR2). + +compact_otp5186_check_termAudit([], []) -> + ok; +%% An empty empty descriptor is removed +compact_otp5186_check_termAudit([{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = asn1_NOVALUE}}|TAR1], []) -> + compact_otp5186_check_termAudit(TAR1, []); +compact_otp5186_check_termAudit(TAR1, []) -> + exit({not_equal, termAudit, TAR1, []}); +%% An empty empty descriptor is removed +compact_otp5186_check_termAudit([], + [{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = asn1_NOVALUE}}|TAR2]) -> + compact_otp5186_check_termAudit([], TAR2); +compact_otp5186_check_termAudit([], TAR2) -> + exit({not_equal, termAudit, [], TAR2}); +compact_otp5186_check_termAudit([ARP1|TAR1], [ARP2|TAR2]) -> + compact_otp5186_check_auditRetParm(ARP1, ARP2), + compact_otp5186_check_termAudit(TAR1, TAR2). + +compact_otp5186_check_auditRetParm(ARP, ARP) -> + ok; +compact_otp5186_check_auditRetParm({emptyDescriptors, AD1}, + {emptyDescriptors, AD2}) -> + compact_otp5186_check_auditDesc(AD1, AD2); +compact_otp5186_check_auditRetParm(ARP1, ARP2) -> + exit({unexpected_auditRetParm, ARP1, ARP2}). + +compact_otp5186_check_auditDesc(AD, AD) -> + ok; +compact_otp5186_check_auditDesc(#'AuditDescriptor'{auditToken = L1, + auditPropertyToken = asn1_NOVALUE}, + #'AuditDescriptor'{auditToken = L2, + auditPropertyToken = asn1_NOVALUE}) -> + compact_otp5186_check_auditDesc_auditItems(L1, L2); +compact_otp5186_check_auditDesc(#'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = APT1}, + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = APT2}) -> + compact_otp5186_check_auditDesc_apt(APT1, APT2); +compact_otp5186_check_auditDesc(AD1, AD2) -> + exit({unexpected_auditDesc, AD1, AD2}). + +compact_otp5186_check_auditDesc_auditItems([], []) -> + ok; +compact_otp5186_check_auditDesc_auditItems(AI1, []) -> + exit({not_equal, auditItems, AI1, []}); +compact_otp5186_check_auditDesc_auditItems([], AI2) -> + exit({not_equal, auditItems, [], AI2}); +compact_otp5186_check_auditDesc_auditItems([AI1|AIs1], [AI2|AIs2]) -> + compact_otp5186_check_auditDesc_auditItem(AI1, AI2), + compact_otp5186_check_auditDesc_auditItems(AIs1, AIs2). + +compact_otp5186_check_auditDesc_auditItem(AI, AI) -> + ok; +compact_otp5186_check_auditDesc_auditItem(AI1, AI2) -> + exit({not_equal, auditItem, AI1, AI2}). + +compact_otp5186_check_auditDesc_apt(APT, APT) -> + ok; +compact_otp5186_check_auditDesc_apt(APT1, APT2) -> + exit({not_equal, auditPropertyToken, APT1, APT2}). + +compact_otp5793_msg01(suite) -> + []; +compact_otp5793_msg01(Config) when is_list(Config) -> + d("compact_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5793(ok, pretty_otp5793_msg1()). + +compact_otp5793(Expected, Msg) -> + expect_codec(Expected, megaco_compact_text_encoder, Msg, []). + + +%% -------------------------------------------------------------- + +compact_otp5993_msg01(suite) -> + []; +compact_otp5993_msg01(Config) when is_list(Config) -> + d("compact_otp5993_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5993(ok, compact_otp5993_msg01()). + +compact_otp5993_msg02(suite) -> + []; +compact_otp5993_msg02(Config) when is_list(Config) -> + d("compact_otp5993_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5993(ok, compact_otp5993_msg02()). + +compact_otp5993_msg03(suite) -> + []; +compact_otp5993_msg03(Config) when is_list(Config) -> + d("compact_otp5993_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5993(ok, compact_otp5993_msg03()). + +compact_otp5993(Expected, Msg) -> + expect_codec(Expected, megaco_compact_text_encoder, Msg, []). + +compact_otp5993_msg01() -> + MT = h221, + T = #megaco_term_id{id = ?A4444}, + TL = [T], + MD = #'MuxDescriptor'{muxType = MT, + termList = TL}, + compact_otp5993_msg(MD). + +compact_otp5993_msg02() -> + MT = h223, + T1 = #megaco_term_id{id = ?A4445}, + T2 = #megaco_term_id{id = ?A5556}, + TL = [T1, T2], + MD = #'MuxDescriptor'{muxType = MT, + termList = TL}, + compact_otp5993_msg(MD). + +compact_otp5993_msg(MD) when is_record(MD, 'MuxDescriptor') -> + AmmDesc = {muxDescriptor, MD}, + AmmReq = #'AmmRequest'{terminationID = [hd(MD#'MuxDescriptor'.termList)], + descriptors = [AmmDesc]}, + Cmd = {addReq, AmmReq}, + CmdReq = #'CommandRequest'{command = Cmd}, + ActReq = #'ActionRequest'{contextId = 5993, + commandRequests = [CmdReq]}, + TransReq = #'TransactionRequest'{transactionId = 3995, + actions = [ActReq]}, + Trans = {transactionRequest, TransReq}, + Body = {transactions, [Trans]}, + Msg = #'Message'{version = ?VERSION, + mId = ?MG1_MID, + messageBody = Body}, + #'MegacoMessage'{mess = Msg}. + +compact_otp5993_msg03() -> + T1 = #megaco_term_id{id = ?A4445}, + T2 = #megaco_term_id{id = ?A5556}, + TIDs = [T1, T2], + AudRep = {contextAuditResult, TIDs}, + CmdRep = {auditValueReply, AudRep}, + ActRep = #'ActionReply'{contextId = 5993, + commandReply = [CmdRep]}, + TransRes = {actionReplies, [ActRep]}, + TransRep = #'TransactionReply'{transactionId = 3995, + transactionResult = TransRes}, + Trans = {transactionReply, TransRep}, + Body = {transactions, [Trans]}, + Msg = #'Message'{version = ?VERSION, + mId = ?MG1_MID, + messageBody = Body}, + #'MegacoMessage'{mess = Msg}. + + +%% -------------------------------------------------------------- + +compact_otp6017_msg01(suite) -> + []; +compact_otp6017_msg01(Config) when is_list(Config) -> + d("compact_otp6017_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(0), + ok. + +compact_otp6017_msg02(suite) -> + []; +compact_otp6017_msg02(Config) when is_list(Config) -> + d("compact_otp6017_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(16#FFFFFFFE), + ok. + +compact_otp6017_msg03(suite) -> + []; +compact_otp6017_msg03(Config) when is_list(Config) -> + d("compact_otp6017_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(16#FFFFFFFF), + ok. + +compact_otp6017(BadCID) -> + Conf = ?EC, + M = compact_otp6017_msg(BadCID), + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, Conf, Bin) of + {ok, Msg} -> + exit({unexpected_decode_success, {Msg, M}}); + {error, Reason} when is_list(Reason) -> % Expected result + case lists:keysearch(reason, 1, Reason) of + {value, {reason, {_Line, _Mod, {bad_ContextID, BadCID}}}} -> + io:format(" ~w", [BadCID]), + ok; + {value, {reason, ActualReason}} -> + exit({unexpected_reason, ActualReason}); + false -> + exit({reason_not_found, Reason}) + end; + Crap -> + exit({unexpected_decode_result, Crap}) + end. + +compact_otp6017_msg(CID) when is_integer(CID) -> + "MEGACO/" ?VERSION_STR " MG1 T=12345678{C=" ++ + integer_to_list(CID) ++ + "{SC=root{SV{MT=RS,RE=901}}}}". + + +%% ============================================================== +%% +%% F l e x C o m p a c t T e s t c a s e s +%% + + +flex_compact_otp7431_msg01(suite) -> + []; +flex_compact_otp7431_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg01 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(ok, flex_compact_otp7431_msg1(), [Conf]). + +flex_compact_otp7431_msg02(suite) -> + []; +flex_compact_otp7431_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg02 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg2(), [Conf]). + +flex_compact_otp7431_msg03(suite) -> + []; +flex_compact_otp7431_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg03 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg3(), [Conf]). + +flex_compact_otp7431_msg04(suite) -> + []; +flex_compact_otp7431_msg04(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg04 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg4(), [Conf]). + +flex_compact_otp7431_msg05(suite) -> + []; +flex_compact_otp7431_msg05(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg05 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg5(), [Conf]). + +flex_compact_otp7431_msg06(suite) -> + []; +flex_compact_otp7431_msg06(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg06 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg6(), [Conf]). + +flex_compact_otp7431_msg07(suite) -> + []; +flex_compact_otp7431_msg07(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg07 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg7(), [Conf]). + + +flex_compact_otp7431(Expected, Msg, Conf) -> + otp7431(Expected, megaco_compact_text_encoder, Msg, Conf). + +flex_compact_otp7431_msg1() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a=recvonly +}}}}}}". + +flex_compact_otp7431_msg2() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +a= } +}}}}}". + + +flex_compact_otp7431_msg3() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a } +}}}}}". + + +flex_compact_otp7431_msg4() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a} +}}}}}". + + +flex_compact_otp7431_msg5() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v= } +}}}}}". + + +flex_compact_otp7431_msg6() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v } +}}}}}". + +flex_compact_otp7431_msg7() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v} +}}}}}". + + +%% ============================================================== +%% +%% P r e t t y T e s t c a s e s +%% + +pretty_otp4632_msg1(suite) -> + []; +pretty_otp4632_msg1(Config) when is_list(Config) -> + d("pretty_otp4632_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg1(), + case encode_message(megaco_pretty_text_encoder, ?EC, Msg0) of + {ok, BinMsg} when is_binary(BinMsg) -> + {ok, Msg1} = decode_message(megaco_pretty_text_encoder, false, + ?EC, BinMsg), + ok = chk_MegacoMessage(Msg0, Msg1); + Else -> + t("pretty_otp4632_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4632_msg1() -> + msg4(?MG1_MID_NO_PORT, "901 mg col boot"). + +pretty_otp4632_msg2(suite) -> + []; +pretty_otp4632_msg2(Config) when is_list(Config) -> + d("pretty_otp4632_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg2(), + case encode_message(megaco_pretty_text_encoder, ?EC, Msg0) of + {ok, BinMsg} when is_binary(BinMsg) -> + {ok, Msg1} = decode_message(megaco_pretty_text_encoder, false, + ?EC, BinMsg), + ok = chk_MegacoMessage(Msg0,Msg1); + Else -> + t("pretty_otp4632_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4632_msg2() -> + msg4(?MG1_MID_NO_PORT, "901"). + + +pretty_otp4632_msg3(suite) -> + []; +pretty_otp4632_msg3(Config) when is_list(Config) -> + d("pretty_otp4632_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg3(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, + false, ?EC, Bin0) of + {ok, Msg} when is_record(Msg, 'MegacoMessage') -> + {ok, Bin1} = encode_message(megaco_pretty_text_encoder, ?EC, Msg), + Msg1 = binary_to_list(Bin1), + %% io:format("Msg1:~n~s~n", [Msg1]), + Msg0 = Msg1, + ok; + Else -> + t("pretty_otp4632_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4632_msg3() -> + M = "MEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = \"901\"\n\t\t\t}\n\t\t}\n\t}\n}", + M. + + +pretty_otp4632_msg4(suite) -> + []; +pretty_otp4632_msg4(Config) when is_list(Config) -> + d("pretty_otp4632_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg4(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {ok, Msg} when is_record(Msg, 'MegacoMessage') -> + {ok, Bin1} = encode_message(megaco_pretty_text_encoder, ?EC, Msg), + Msg1 = binary_to_list(Bin1), + %% io:format("Msg1:~n~s~n", [Msg1]), + pretty_otp4632_msg4_chk(Msg0,Msg1); + Else -> + t("pretty_otp4632_msg4 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + + +pretty_otp4632_msg4() -> + M = "MEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = 901\n\t\t\t}\n\t\t}\n\t}\n}", + M. + + +pretty_otp4632_msg4_chk([], []) -> + exit(messages_not_eq); +pretty_otp4632_msg4_chk([], Rest1) -> + exit({messages_not_eq1, Rest1}); +pretty_otp4632_msg4_chk(Rest0, []) -> + exit({messages_not_eq0, Rest0}); +pretty_otp4632_msg4_chk([$R,$e,$a,$s,$o,$n,$ ,$=,$ ,$9,$0,$1|_Rest0], + [$R,$e,$a,$s,$o,$n,$ ,$=,$ ,$",$9,$0,$1,$"|_Rest1]) -> + ok; +pretty_otp4632_msg4_chk([_|Rest0], [_|Rest1]) -> + pretty_otp4632_msg4_chk(Rest0,Rest1). + + +pretty_otp4710_msg1(suite) -> + []; +pretty_otp4710_msg1(Config) when is_list(Config) -> + d("pretty_otp4710_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4710_msg1(), + case encode_message(megaco_pretty_text_encoder, ?EC, Msg0) of + {ok, Bin} when is_binary(Bin) -> + {ok, Msg1} = decode_message(megaco_pretty_text_encoder, false, + ?EC, Bin), + ok = chk_MegacoMessage(Msg0,Msg1); + Else -> + t("pretty_otp4710_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4710_msg1() -> + msg40(). + + +pretty_otp4710_msg2(suite) -> + []; +pretty_otp4710_msg2(Config) when is_list(Config) -> + d("pretty_otp4710_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4710_msg2(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {ok, Msg} when is_record(Msg, 'MegacoMessage') -> + {ok, Bin1} = encode_message(megaco_pretty_text_encoder, ?EC, Msg), + Msg1 = binary_to_list(Bin1), + %% io:format("Msg1:~n~s~n", [Msg1]), + pretty_otp4710_msg2_chk(Msg0,Msg1); + Else -> + t("pretty_otp4710_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4710_msg2() -> + "Authentication = 0xEFCDAB89:0x12345678:0x1234567889ABCDEF76543210\nMEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = \"901 mg col boot\"\n\t\t\t}\n\t\t}\n\t}\n}". + +pretty_otp4710_msg2_chk(Msg,Msg) -> + ok; +pretty_otp4710_msg2_chk( + [$A,$u,$t,$h,$e,$n,$t,$i,$c,$a,$t,$i,$o,$n,$=,$ |Msg0], + [$A,$u,$t,$h,$e,$n,$t,$i,$c,$a,$t,$i,$o,$n,$=,$ |Msg1]) -> + {AH0, Rest0} = pretty_otp4710_msg2_chk_ah(Msg0, []), + {AH1, Rest1} = pretty_otp4710_msg2_chk_ah(Msg1, []), + case AH0 == AH1 of + true -> + exit({message_not_equal, Rest0, Rest1}); + false -> + exit({auth_header_not_equal, AH0, AH1}) + end. + +pretty_otp4710_msg2_chk_ah([], _Acc) -> + exit(no_auth_header_found); +pretty_otp4710_msg2_chk_ah([$M,$E,$G,$A,$C,$O,$/,_|Rest], Acc) -> + {lists:reverse(Acc), Rest}; +pretty_otp4710_msg2_chk_ah([C|R], Acc) -> + pretty_otp4710_msg2_chk_ah(R, [C|Acc]). + + +pretty_otp4945_msg1(suite) -> + []; +pretty_otp4945_msg1(Config) when is_list(Config) -> + d("pretty_otp4945_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg1(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {missing_required_serviceChangeParm, [serviceChangeReason]} -> + ok; + Else -> + t("pretty_otp4945_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + io:format("pretty_otp4945_msg1 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg2(suite) -> + []; +pretty_otp4945_msg2(Config) when is_list(Config) -> + d("pretty_otp4945_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg2(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {missing_required_serviceChangeParm, [serviceChangeMethod]} -> + ok; + Else -> + t("pretty_otp4945_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg2() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg3(suite) -> + []; +pretty_otp4945_msg3(Config) when is_list(Config) -> + d("pretty_otp4945_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg3(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {missing_required_serviceChangeParm, [serviceChangeReason, serviceChangeMethod]} -> + ok; + {missing_required_serviceChangeParm, [serviceChangeMethod, serviceChangeReason]} -> + ok; + Else -> + t("pretty_otp4945_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg3() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg4(suite) -> + []; +pretty_otp4945_msg4(Config) when is_list(Config) -> + d("pretty_otp4945_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg4(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {ok, _} -> + ok; + Else -> + t("pretty_otp4945_msg4 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg4() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg5(suite) -> + []; +pretty_otp4945_msg5(Config) when is_list(Config) -> + d("pretty_otp4945_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg5(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {at_most_once_serviceChangeParm, {profile, _Val1, _Val2}} -> + ok; + Else -> + io:format("pretty_otp4945_msg6 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg5 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg5() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + Profile = ResGW/1, + ServiceChangeAddress = 55555, + Profile = ResGW/2 + } + } + } +}". + + +pretty_otp4945_msg6(suite) -> + []; +pretty_otp4945_msg6(Config) when is_list(Config) -> + d("pretty_otp4945_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg6(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {not_both_address_mgcid_serviceChangeParm, _Val1, _Val2} -> + ok; + Else -> + io:format("pretty_otp4945_msg6 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg6 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg6() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + MgcIdToTry = kalle, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4949_msg1(suite) -> + []; +pretty_otp4949_msg1(Config) when is_list(Config) -> + d("pretty_otp4949_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4949_msg1(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {ok, _} -> + ok; + Else -> + t("pretty_otp4949_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4949_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4949_msg2(suite) -> + []; +pretty_otp4949_msg2(Config) when is_list(Config) -> + d("pretty_otp4949_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4949_msg2(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {at_most_once_servChgReplyParm, {profile, _Val1, _Val2}} -> + ok; + Else -> + io:format("pretty_otp4949_msg2 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4949_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4949_msg2() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Profile = ResGW/1, + ServiceChangeAddress = 55555, + Profile = ResGW/2 + } + } + } +}". + + +pretty_otp4949_msg3(suite) -> + []; +pretty_otp4949_msg3(Config) when is_list(Config) -> + d("pretty_otp4949_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4949_msg3(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {not_both_address_mgcid_servChgReplyParm, _Val1, _Val2} -> + ok; + Else -> + io:format("pretty_otp4949_msg3 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4949_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4949_msg3() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + MgcIdToTry = kalle, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp5042_msg1(suite) -> + []; +pretty_otp5042_msg1(Config) when is_list(Config) -> + d("pretty_otp5042_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp5042_msg1(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {_, _Mod, {bad_timeStamp, TimeStamp}} -> + exit({bad_timeStamp, TimeStamp}); + _ -> + io:format("pretty_otp5042_msg1 -> " + "~n Reason: ~w" + "~n", [Reason]), + exit({unexpected_decode_result, Reason}) + end; + {ok, M} -> + t("pretty_otp5042_msg1 -> successfull decode:" + "~n~p", [M]), + ok + end. + +pretty_otp5042_msg1() -> +"MEGACO/" ?VERSION_STR " <CATAPULT>:2944 +Transaction = 102 { +Context = 5 { Notify = MUX/1 { ObservedEvents = 1 { +h245bh/h245msgin { Stream = 1 +, h245enc = +0270020600088175000653401004100403E802E00180018001780680000034301160000700088175010101007A0100020001800001320000C0000219D005027F0070500100040100021080000319D005027F00504001008000041C001250000700088175010000400280010003000880000518AA027F400006850130008011020100000001030002000300040005000006 + } } + } } }". + + +pretty_otp5068_msg1(suite) -> + []; +pretty_otp5068_msg1(Config) when is_list(Config) -> + d("pretty_otp5068_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = pretty_otp5068_msg1(), + case encode_message(megaco_pretty_text_encoder, ?EC, Msg) of + {error, Reason} -> +% io:format("pretty_otp5068_msg1 -> " +% "~n Reason: ~w" +% "~n", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} -> +% io:format("pretty_otp5068_msg1 -> successfull encode:" +% "~n~s~n", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin) of + {ok, _} -> +% io:format("pretty_otp5068_msg1 -> ok~n", []), + ok; + Else -> +% io:format("pretty_otp5068_msg1 -> ~n~p~n", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + +pretty_otp5068_msg1() -> +{'MegacoMessage', + asn1_NOVALUE, + {'Message', + 2, + {deviceName,[109,103,51,51]}, + {transactions, + [{transactionReply, + {'TransactionReply', + 190, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', %% Comments: Detta upprepas m�nga g�nger + 0, + asn1_NOVALUE, + asn1_NOVALUE, + [{auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false, + [[99,101,100,101,118,49,47,52,47,49,47,49],[51,49]]}, + [{mediaDescriptor, + {'MediaDescriptor', + {'TerminationStateDescriptor', + [], + asn1_NOVALUE, + inSvc}, + asn1_NOVALUE} + } + ] + } + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } +}. + + + +pretty_otp5085_msg1(suite) -> + []; +pretty_otp5085_msg1(Config) when is_list(Config) -> + d("pretty_otp5085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg1()). + +pretty_otp5085_msg2(suite) -> + []; +pretty_otp5085_msg2(Config) when is_list(Config) -> + d("pretty_otp5085_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(error, pretty_otp5085_msg2()). + +pretty_otp5085_msg3(suite) -> + []; +pretty_otp5085_msg3(Config) when is_list(Config) -> + d("pretty_otp5085_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg3()). + +pretty_otp5085_msg4(suite) -> + []; +pretty_otp5085_msg4(Config) when is_list(Config) -> + d("pretty_otp5085_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg4()). + +pretty_otp5085_msg5(suite) -> + []; +pretty_otp5085_msg5(Config) when is_list(Config) -> + d("pretty_otp5085_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg5()). + +pretty_otp5085_msg6(suite) -> + []; +pretty_otp5085_msg6(Config) when is_list(Config) -> + d("pretty_otp5085_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg6()). + +pretty_otp5085_msg7(suite) -> + []; +pretty_otp5085_msg7(Config) when is_list(Config) -> + d("pretty_otp5085_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg7()). + +pretty_otp5085_msg8(suite) -> + []; +pretty_otp5085_msg8(Config) when is_list(Config) -> + d("pretty_otp5085_msg8 -> entry", []), + ?ACQUIRE_NODES(1, Config), +% put(dbg,true), +% put(severity, trc), + Res = (catch pretty_otp5085(ok, pretty_otp5085_msg8())), +% erase(dbg), +% erase(severity), + case Res of + ok -> + ok; + {'EXIT', Reason} -> + exit(Reason) + end. + +pretty_otp5085(Expected, Msg) -> + pretty_otp5085(Expected, Msg, []). + +pretty_otp5085(Expected, Msg, Conf) -> + t("pretty_otp5085 -> entry with" + "~n Expected: ~p" + "~n Msg: ~p", [Expected, Msg]), + case (catch encode_message(megaco_pretty_text_encoder, [?EC_V3|Conf], Msg)) of + {error, Reason} when Expected =:= error -> + d("pretty_otp5085 -> encode failed as expected" + "~n Reason: ~w", [Reason]), + ok; + {error, Reason} -> + e("pretty_otp5085 -> encode failed unexpectedly: " + "~n Reason: ~w", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} when Expected =:= error -> + e("pretty_otp5085 -> encode succeded unexpectedly: " + "~n ~w", [binary_to_list(Bin)]), + exit({unexpected_encode_result, binary_to_list(Bin)}); + {ok, Bin} -> + d("pretty_otp5085 -> successfull encode as expected:" + "~n~s", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, [?EC_V3|Conf], Bin) of + {ok, Msg} -> + d("pretty_otp5085 -> successfull decode~n", []), + ok; + {ok, Msg2} -> + e("pretty_otp5085 -> successfull decode" + " - but not equal", []), + exit({unexpected_decode_result, Msg, Msg2}); + Else -> + e("pretty_otp5085 -> decode failed:~n~p", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + +pretty_otp5085_msg1() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + asn1_NOVALUE, + [] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +pretty_otp5085_msg2() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + asn1_NOVALUE, + [] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +pretty_otp5085_msg3() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + #'ContextRequest'{priority = 3}, + [] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +pretty_otp5085_msg4() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + asn1_NOVALUE, + [{addReply, cre_AmmsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +pretty_otp5085_msg5() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + #'ContextRequest'{priority = 5}, + [{addReply, cre_AmmsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +pretty_otp5085_msg6() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 6}, + [{addReply, cre_AmmsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +pretty_otp5085_msg7() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 7}, + [{notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg8() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 8, + emergency = true, + topologyReq = + [#'TopologyRequest'{terminationFrom = From1, + terminationTo = To1, + topologyDirection = bothway}, + #'TopologyRequest'{terminationFrom = From2, + terminationTo = To2, + topologyDirection = oneway} + ], + iepsCallind = true, + contextProp = [cre_PropParm("tdmc/gain", "2")]}, + [{notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +pretty_otp5600_msg1(suite) -> + []; +pretty_otp5600_msg1(Config) when is_list(Config) -> + d("pretty_otp5600_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5600(ok, pretty_otp5600_msg1()). + +pretty_otp5600_msg2(suite) -> + []; +pretty_otp5600_msg2(Config) when is_list(Config) -> + d("pretty_otp5600_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5600(ok, pretty_otp5600_msg2()). + +pretty_otp5600(Expected, Msg) -> + pretty_otp5600(Expected, Msg, []). + +pretty_otp5600(Expected, Msg, Conf) -> + t("pretty_otp5600 -> entry with" + "~n Expected: ~p" + "~n Msg: ~p", [Expected, Msg]), + case (catch encode_message(megaco_pretty_text_encoder, [?EC_V3|Conf], Msg)) of + {error, Reason} when Expected =:= error -> + d("pretty_otp5600 -> encode failed as expected" + "~n Reason: ~w", [Reason]), + ok; + {error, Reason} -> + e("pretty_otp5600 -> encode failed unexpectedly: " + "~n Reason: ~w", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} when Expected =:= error -> + e("pretty_otp5600 -> encode succeded unexpectedly: " + "~n ~w", [binary_to_list(Bin)]), + exit({unexpected_encode_result, binary_to_list(Bin)}); + {ok, Bin} -> + d("pretty_otp5600 -> successfull encode as expected:" + "~n~s", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, [?EC_V3|Conf], Bin) of + {ok, Msg} -> + d("pretty_otp5600 -> successfull decode~n", []), + ok; + {ok, Msg2} -> + e("pretty_otp5600 -> successfull decode" + " - but not equal", []), + exit({unexpected_decode_result, Msg, Msg2}); + Else -> + e("pretty_otp5600 -> decode failed:~n~p", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + +pretty_otp5600_msg1() -> + SRE = #'SecondRequestedEvent'{ pkgdName = "al/on", + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE ] }, + + SIG = { signal, #'Signal'{ signalName = "cg/dt", + sigParList = [] } }, + + RA = #'RequestedActions'{ secondEvent = SED, + signalsDescriptor = [ SIG ] }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + +pretty_otp5600_msg2() -> + SIG = { signal, #'Signal'{ signalName = "cg/dt", + sigParList = [] } }, + + SRA = #'SecondRequestedActions'{ signalsDescriptor = [ SIG ] }, + + SRE = #'SecondRequestedEvent'{ pkgdName = "al/on", + eventAction = SRA, + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE ] }, + + RA = #'RequestedActions'{ secondEvent = SED }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + + +pretty_otp5601_msg1(suite) -> + []; +pretty_otp5601_msg1(Config) when is_list(Config) -> + d("pretty_otp5601_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5601(ok, pretty_otp5601_msg1()). + +pretty_otp5601(Expected, Msg) -> + pretty_otp5601(Expected, Msg, []). + +pretty_otp5601(Expected, Msg, Conf) -> + t("pretty_otp5601 -> entry with" + "~n Expected: ~p" + "~n Msg: ~p", [Expected, Msg]), + case (catch encode_message(megaco_pretty_text_encoder, [?EC_V3|Conf], Msg)) of + {error, Reason} when Expected =:= error -> + d("pretty_otp5601 -> encode failed as expected" + "~n Reason: ~w", [Reason]), + ok; + {error, Reason} -> + e("pretty_otp5601 -> encode failed unexpectedly: " + "~n Reason: ~w", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} when Expected =:= error -> + e("pretty_otp5601 -> encode succeded unexpectedly: " + "~n ~w", [binary_to_list(Bin)]), + exit({unexpected_encode_result, binary_to_list(Bin)}); + {ok, Bin} -> + d("pretty_otp5601 -> successfull encode as expected:" + "~n~s", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, [?EC_V3|Conf], Bin) of + {ok, Msg} -> + d("pretty_otp5601 -> successfull decode~n", []), + ok; + {ok, Msg2} -> + e("pretty_otp5601 -> successfull decode" + " - but not equal", []), + exit({unexpected_decode_result, Msg, Msg2}); + Else -> + e("pretty_otp5601 -> decode failed:~n~p", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + +pretty_otp5601_msg1() -> + SRE1 = #'SecondRequestedEvent'{ pkgdName = "al/on", + evParList = [] }, + + SRA = #'SecondRequestedActions'{ eventDM = { digitMapName, "dialllan0" }}, + + SRE2 = #'SecondRequestedEvent'{ pkgdName = "dd/ce", + eventAction = SRA, + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE1, SRE2 ] }, + + RA = #'RequestedActions'{ secondEvent = SED }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + + +pretty_otp5793_msg01(suite) -> + []; +pretty_otp5793_msg01(Config) when is_list(Config) -> + d("pretty_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5793(ok, pretty_otp5793_msg1()). + +pretty_otp5793(Expected, Msg) -> + expect_codec(Expected, megaco_pretty_text_encoder, Msg, []). + +pretty_otp5793(Expected, Msg, Conf) -> + expect_codec(Expected, megaco_pretty_text_encoder, Msg, Conf). + +pretty_otp5793_msg1() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',3, + {deviceName,"bs_sbg_4/99"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 370, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 3, + asn1_NOVALUE, + asn1_NOVALUE, + [{auditValueReply, + {contextAuditResult, + [{megaco_term_id, + false, + ["ip", + "104", + "1", + "18"]}]}}, + {auditValueReply, + {contextAuditResult, + [{megaco_term_id, + false, + ["ip", + "104", + "2", + "19"] + } + ] + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + + +pretty_otp5882_msg01(suite) -> + []; +pretty_otp5882_msg01(Config) when is_list(Config) -> + d("pretty_otp5882_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5882(). + +pretty_otp5882() -> + otp5882(megaco_pretty_text_encoder, []). + +otp5882(Codec, Conf) -> + Msg = pretty_otp5882_msg01(), + case (catch encode_message(Codec, [?EC_V3|Conf], Msg)) of + {error, {message_encode_failed, {error, {ActualReason, _}}, _}} -> + case ActualReason of + {invalid_LocalControlDescriptor, empty} -> + ok; + _ -> + exit({unexpected_error_actual_reason, ActualReason}) + end; + {error, Reason} -> + exit({unexpected_error_reason, Reason}); + {ok, Bin} -> + exit({unexpected_encode_sucess, binary_to_list(Bin)}) + end. + +pretty_otp5882_msg01() -> + LCD = #'LocalControlDescriptor'{}, % Create illegal LCD + Parms = cre_StreamParms(LCD), + StreamDesc = cre_StreamDesc(1, Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + CID = cre_CtxID(7301), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(7302), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + + +%% -------------------------------------------------------------- +%% +pretty_otp6490_msg01(suite) -> + []; +pretty_otp6490_msg01(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg01 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg01(), [] ), + %% erase(dbg), + %% erase(severity), + ok. + +pretty_otp6490_msg02(suite) -> + []; +pretty_otp6490_msg02(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg02 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg02(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg03(suite) -> + []; +pretty_otp6490_msg03(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg03 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg03(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg04(suite) -> + []; +pretty_otp6490_msg04(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg04 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg04(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg05(suite) -> + []; +pretty_otp6490_msg05(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg05 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg05(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg06(suite) -> + []; +pretty_otp6490_msg06(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg06 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg06(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490(Msg, Conf) -> + pretty_otp6490(Msg, Conf, ok). + +pretty_otp6490(Msg, Conf, ExpectedEncode) -> + pretty_otp6490(Msg, Conf, ExpectedEncode, ok). + +pretty_otp6490(Msg, Conf, ExpectedEncode, ExpectedDecode) -> + otp6490(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode). + +otp6490(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode) -> + case (catch encode_message(Codec, [?EC_V3|Conf], Msg)) of + {error, _Reason} when ExpectedEncode =:= error -> + ok; + {error, Reason} when ExpectedEncode =:= ok -> + exit({unexpected_encode_failure, Reason}); + {ok, Bin} when ExpectedEncode =:= error -> + exit({unexpected_encode_success, Msg, binary_to_list(Bin)}); + {ok, Bin} when ExpectedEncode =:= ok -> + case decode_message(Codec, false, [?EC_V3|Conf], Bin) of + {ok, Msg} when ExpectedDecode =:= ok -> + ok; + {ok, Msg} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg}); + {ok, Msg2} when ExpectedDecode =:= ok -> + exit({unexpected_decode_result, Msg, Msg2}); + {ok, Msg2} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg, Msg2}); + {error, _Reason} when ExpectedDecode =:= error -> + ok; + {error, Reason} when ExpectedDecode =:= ok -> + exit({unexpected_decode_failure, Msg, Reason}) + end + end. + + +pretty_otp6490_msg(EBD) -> + AmmDesc = ?MSG_LIB:cre_AmmDescriptor(EBD), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4445}], [AmmDesc]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + CID = cre_CtxID(64901), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(64902), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +pretty_otp6490_msg01() -> + EvSpecs = [], % This will result in an error + EBD = EvSpecs, % This is because the lib checks that the size is valid + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg02() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg03() -> + EvPar1 = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + EvPar2 = ?MSG_LIB:cre_EventParameter("kalle", ["anka"]), + EvPar3 = ?MSG_LIB:cre_EventParameter("flippa", ["ur"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar1,EvPar2,EvPar3]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg04() -> + EvPar1 = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + EvPar2 = ?MSG_LIB:cre_EventParameter("kalle", ["anka"]), + EvPar3 = ?MSG_LIB:cre_EventParameter("flippa", ["ur"]), + PkgdName1 = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName1 = ?MSG_LIB:cre_EventName(PkgdName1), + EvSpec1 = ?MSG_LIB:cre_EventSpec(EvName1, [EvPar1,EvPar2,EvPar3]), + EvPar4 = ?MSG_LIB:cre_EventParameter("hej", ["hopp"]), + PkgdName2 = ?MSG_LIB:cre_PkgdName("bar", "b"), + EvName2 = ?MSG_LIB:cre_EventName(PkgdName2), + EvSpec2 = ?MSG_LIB:cre_EventSpec(EvName2, [EvPar4]), + EvSpecs = [EvSpec1,EvSpec2], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg05() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", root), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg06() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName(root, root), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + + + +%% -------------------------------------------------------------- +%% + +pretty_otp7671_msg01(suite) -> + []; +pretty_otp7671_msg01(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg01 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg01(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg02(suite) -> + []; +pretty_otp7671_msg02(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg02 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg02(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg03(suite) -> + []; +pretty_otp7671_msg03(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg03 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg03(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg04(suite) -> + []; +pretty_otp7671_msg04(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg04 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg04(), [] , error, ignore), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg05(suite) -> + []; +pretty_otp7671_msg05(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg05 -> entry", []), + Check = fun(M1, M2) -> cmp_otp7671_msg05(M1, M2) end, + ok = pretty_otp7671( pretty_otp7671_msg05(), [] , ok, ok, Check), +%% erase(dbg), +%% erase(severity), + ok. + + +pretty_otp7671(Msg, Conf) -> + pretty_otp7671(Msg, Conf, ok). + +pretty_otp7671(Msg, Conf, ExpectedEncode) -> + pretty_otp7671(Msg, Conf, ExpectedEncode, ok). + +pretty_otp7671(Msg, Conf, ExpectedEncode, ExpectedDecode) -> + otp7671(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode). + +pretty_otp7671(Msg, Conf, ExpectedEncode, ExpectedDecode, Check) -> + otp7671(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode, Check). + +otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode) -> + Check = fun(M1, M2) -> + exit({unexpected_decode_result, M1, M2}) + end, + otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode, Check). + +otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode, Check) -> + case (catch encode_message(Codec, Conf, Msg)) of + {error, _Reason} when ExpectedEncode =:= error -> + ok; + {error, Reason} when ExpectedEncode =:= ok -> + exit({unexpected_encode_failure, Reason}); + {ok, Bin} when ExpectedEncode =:= error -> + exit({unexpected_encode_success, Msg, binary_to_list(Bin)}); + {ok, Bin} when ExpectedEncode =:= ok -> + case decode_message(Codec, false, Conf, Bin) of + {ok, Msg} when ExpectedDecode =:= ok -> + ok; + {ok, Msg2} when ExpectedDecode =:= ok -> + Check(Msg, Msg2); + {ok, Msg} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg}); + {ok, Msg2} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg, Msg2}); + {error, _Reason} when ExpectedDecode =:= error -> + ok; + {error, Reason} when ExpectedDecode == ok -> + exit({unexpected_decode_failure, Msg, Reason}) + end + end. + + +pretty_otp7671_msg(DigitMapDesc) -> + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{digitMapDescriptor, DigitMapDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(?MGC_MID, 10001, ?megaco_null_context_id, [CmdReq]). + +pretty_otp7671_msg01() -> + Name = "dialplan01", + DigitMapDesc = cre_DigitMapDesc(Name), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg02() -> + Name = "dialplan02", + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body), + DigitMapDesc = cre_DigitMapDesc(Name, Value), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg03() -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body), + DigitMapDesc = cre_DigitMapDesc(Value), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg04() -> + DigitMapDesc = cre_DigitMapDesc(), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg05() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',?VERSION, + {domainName,{'DomainName',"tgc",asn1_NOVALUE}}, + {transactions, + [{transactionRequest, + {'TransactionRequest',12582952, + [{'ActionRequest',0,asn1_NOVALUE,asn1_NOVALUE, + [{'CommandRequest', + {modReq, + {'AmmRequest', + [{megaco_term_id,false,["root"]}], + [{digitMapDescriptor, + {'DigitMapDescriptor',"dialplan1", + {'DigitMapValue',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,[], + asn1_NOVALUE}}}]}}, + asn1_NOVALUE,asn1_NOVALUE}]}]}}]}}}. + +cmp_otp7671_msg05(#'MegacoMessage'{authHeader = asn1_NOVALUE, + mess = M1}, + #'MegacoMessage'{authHeader = asn1_NOVALUE, + mess = M2}) -> + #'Message'{messageBody = Body1} = M1, + #'Message'{messageBody = Body2} = M2, + {transactions, Trans1} = Body1, + {transactions, Trans2} = Body2, + [{transactionRequest, TR1}] = Trans1, + [{transactionRequest, TR2}] = Trans2, + #'TransactionRequest'{actions = Acts1} = TR1, + #'TransactionRequest'{actions = Acts2} = TR2, + [#'ActionRequest'{commandRequests = CR1}] = Acts1, + [#'ActionRequest'{commandRequests = CR2}] = Acts2, + [#'CommandRequest'{command = Cmd1}] = CR1, + [#'CommandRequest'{command = Cmd2}] = CR2, + {modReq, #'AmmRequest'{descriptors = Descs1}} = Cmd1, + {modReq, #'AmmRequest'{descriptors = Descs2}} = Cmd2, + [{digitMapDescriptor, + #'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value1}}] = Descs1, + [{digitMapDescriptor, + #'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value2}}] = Descs2, + #'DigitMapValue'{startTimer = asn1_NOVALUE, + shortTimer = asn1_NOVALUE, + longTimer = asn1_NOVALUE, + digitMapBody = [], + durationTimer = asn1_NOVALUE} = Value1, + asn1_NOVALUE = Value2, + ok. + + +%% -------------------------------------------------------------- +%% + + +pretty_otp8114_msg01(suite) -> + []; +pretty_otp8114_msg01(Config) when is_list(Config) -> + put(severity, trc), + put(dbg, true), + d("pretty_otp8114_msg01 -> entry", []), + ok = otp8114( pretty_otp8114_msg01(), megaco_pretty_text_encoder, ?EC), + erase(dbg), + erase(severity), + ok. + +pretty_otp8114_msg01() -> + "MEGACO/" ?VERSION_STR " [10.10.10.10]:1234\nTransaction = 1 {\n\tContext =\n1 {\n\t\tModify = ip/1/1/1 {\n\t\t\tMedia {\n\t\t\t\tStream = 1\n{\n\t\t\t\t\t\tLocalControl {\n\t\t\t\t\t\tMode =\nSendReceive\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tEvents = 1\n{\n\t\t\t\tadid/ipstop\n{\n\t\t\t\t\tdt=30,\n\t\t\t\t\tdir=\"BOTH\"\n\t\t\t\t},\n\t\t\t\tg/cause\n\n\t\t\t}\n\t\t}\n\t}\n}". + + +otp8114(InitialMessage, Codec, Conf) -> + Decode = fun(M) -> Codec:decode_message(Conf, M) end, + Encode = fun(B) -> Codec:encode_message(Conf, B) end, + InitialData = InitialMessage, + Instructions = + [ + %% List to binary + megaco_codec_test_lib:expect_instruction( + "Convert (initial) message to a binary", + fun(Msg) when is_list(Msg) -> + %% io:format("~s~n", [Msg]), + {ok, list_to_binary(Msg)}; + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Bin}, _Msg) when is_binary(Bin) -> + {ok, Bin}; + (Bad, _Msg) -> + {error, {failed_to_binary, Bad}} + end), + + %% Initial decode + megaco_codec_test_lib:expect_instruction( + "Decode (initial) message", + fun(Bin) when is_binary(Bin) -> + (catch Decode(Bin)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Msg}, _Bin) when is_record(Msg, 'MegacoMessage') -> + %% io:format("~p~n", [Msg]), + {ok, Msg}; + (Bad, _) -> + {error, {initial_decode_failed, Bad}} + end), + + %% Encode + megaco_codec_test_lib:expect_instruction( + "Encode message", + fun(Msg) when is_record(Msg, 'MegacoMessage') -> + (catch Encode(Msg)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Bin}, _Msg) when is_binary(Bin) -> + %% io:format("~s~n", [binary_to_list(Bin)]), + {ok, Bin}; + (Bad, _) -> + {error, {encode_failed, Bad}} + end), + + %% Decode + megaco_codec_test_lib:expect_instruction( + "(final) Decode message", + fun(Bin) when is_binary(Bin) -> + (catch Decode(Bin)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Msg}, _Bin) when is_record(Msg, 'MegacoMessage') -> + %% io:format("~p~n", [Msg]), + {ok, Msg}; + (Bad, _) -> + {error, {decode_failed, Bad}} + end) + ], + megaco_codec_test_lib:expect_exec(Instructions, InitialData). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +expect_codec(Expect, Codec, Msg, Conf) -> + t("expect_codec -> entry with" + "~n Expect: ~p" + "~n Msg: ~p", [Expect, Msg]), + case (catch encode_message(Codec, [?EC_V3|Conf], Msg)) of + {error, _Reason} when Expect =:= error -> + d("expect_codec -> encode failed as expected" + "~n _Reason: ~w", [_Reason]), + ok; + {error, Reason} -> + e("expect_codec -> encode failed unexpectedly: " + "~n Reason: ~w", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} when Expect =:= error -> + e("expect_codec -> encode succeded unexpectedly: " + "~n ~w", [binary_to_list(Bin)]), + exit({unexpected_encode_result, binary_to_list(Bin)}); + {ok, Bin} -> + d("expect_codec -> successfull encode as expected:" + "~n~s", [binary_to_list(Bin)]), + case (catch decode_message(Codec, false, [?EC_V3|Conf], Bin)) of + {ok, Msg} -> + d("expect_codec -> successfull decode~n", []), + ok; + {ok, Msg2} -> + e("expect_codec -> successfull decode" + " - but not equal", []), + chk_MegacoMessage(Msg, Msg2); + %% exit({unexpected_decode_result, Msg, Msg2}); + Else -> + e("expect_codec -> decode failed:~n~p", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + e("expect_codec -> encode failed:~n~p", [Else]), + exit({unexpected_encode_result, Else}) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +msgs() -> + [M || {_, M, _, _} <- msgs(text)]. + +msgs(Encoding) -> + msgs1(Encoding) ++ + msgs2(Encoding) ++ msgs3(Encoding) ++ msgs4(Encoding) ++ + msgs5(Encoding) ++ msgs6(Encoding). + +msgs1(_) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [ + {msg01a, msg1a(), Plain, [{dbg,false}]}, + {msg01b, msg1b(), Plain, [{dbg,false}]}, + {msg02, msg2(), Plain, [{dbg,false}]}, + {msg03, msg3(), Plain, [{dbg,false}]}, + {msg04, msg4(), Plain, [{dbg,false}]}, + {msg05, msg5(), Plain, [{dbg,false}]}, + {msg06a, msg6a(), Plain, [{dbg,false}]}, + {msg06b, msg6b(), Plain, [{dbg,false}]}, + {msg07, msg7(), Plain, [{dbg,false}]}, + {msg08a, msg8a(), Plain, [{dbg,false}]}, + {msg08b, msg8b(), Plain, [{dbg,false}]}, + {msg09, msg9(), Plain, [{dbg,false}]}, + {msg10, msg10(), Plain, [{dbg,false}]}, + {msg11, msg11(), Plain, [{dbg,false}]}, + {msg12, msg12(), Plain, [{dbg,false}]}, + {msg13, msg13(), Plain, [{dbg,false}]}, + {msg14, msg14(), Plain, [{dbg,false}]}, + {msg15, msg15(), Plain, [{dbg,false}]}, + {msg16, msg16(), Plain, [{dbg,false}]}, + {msg17, msg17(), Plain, [{dbg,false}]}, + {msg18, msg18(), Plain, [{dbg,false}]}, + {msg19, msg19(), Plain, [{dbg,false}]}, + {msg20, msg20(), Plain, [{dbg,false}]}, + {msg21, msg21(), Plain, [{dbg,false}]}, + {msg22a, msg22a(), Plain, [{dbg,false}]}, + {msg22b, msg22b(), Plain, [{dbg,false}]}, + {msg22c, msg22c(), Plain, [{dbg,false}]}, + {msg22d, msg22d(), Plain, [{dbg,false}]}, + {msg22e, msg22e(), Plain, [{dbg,false}]}, + {msg22f, msg22f(), Plain, [{dbg,false}]}, + {msg23a, msg23a(), Plain, [{dbg,false}]}, + {msg23b, msg23b(), Plain, [{dbg,false}]}, + {msg23c, msg23c(), Plain, [{dbg,false}]}, + {msg23d, msg23d(), Plain, [{dbg,false}]}, + {msg24, msg24(), Plain, [{dbg,false}]}, + {msg25, msg25(), Plain, [{dbg,false}]}, + {msg30a, msg30a(), Plain, [{dbg,false}]}, + {msg30b, msg30b(), Plain, [{dbg,false}]}, + {msg30c, msg30c(), Plain, [{dbg,false}]}, + {msg30d, msg30d(), Plain, [{dbg,false}]} + ]. + + +msgs2(_) -> + TransFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:trans_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + ActionsFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:actions_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + ActionFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:action_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + [ + {msg01a_tf, msg1a(), TransFirst, [{dbg,false}]}, + {msg02_tf, msg2(), TransFirst, [{dbg,false}]}, + {msg10_tf, msg10(), TransFirst, [{dbg,false}]}, + {msg11_tf, msg11(), TransFirst, [{dbg,false}]}, + {msg23d_tf, msg23d(), TransFirst, [{dbg,false}]}, + {msg30b_tf, msg30b(), TransFirst, [{dbg,false}]}, + {msg30c_tf, msg30c(), TransFirst, [{dbg,false}]}, + {msg01a_asf, msg1a(), ActionsFirst, [{dbg,false}]}, + {msg02_asf, msg2(), ActionsFirst, [{dbg,false}]}, + {msg10_asf, msg10(), ActionsFirst, [{dbg,false}]}, + {msg23d_asf, msg23d(), ActionsFirst, [{dbg,false}]}, + {msg01a_af, msg1a(), ActionFirst, [{dbg,false}]}, + {msg02_af, msg2(), ActionFirst, [{dbg,false}]}, + {msg10_af, msg10(), ActionFirst, [{dbg,false}]}, + {msg23d_af, msg23d(), ActionFirst, [{dbg,false}]} + ]. + + +msgs3(_) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [{msgs3_name(Name), rfc3525_decode(M), Plain, [{dbg, false}]} || + {Name, M} <- rfc3525_msgs()]. + +msgs3_name(N) -> + list_to_atom("rfc3525_" ++ atom_to_list(N)). + +rfc3525_decode(M) when is_list(M) -> + rfc3525_decode(list_to_binary(M)); +rfc3525_decode(M) when is_binary(M) -> + case (catch decode_message(megaco_pretty_text_encoder, false, ?EC, M)) of + {ok, Msg} -> + Msg; + Error -> + {error, {rfc3525_decode_error, Error}} + end. + + +msgs4(_) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [ + {msg51a, msg51a(), Plain, [{dbg, false}]}, + {msg51b, msg51b(), Plain, [{dbg, false}]}, + {msg51c, msg51c(), Plain, [{dbg, false}]}, + {msg51d, msg51d(), Plain, [{dbg, false}]}, + {msg51e, msg51e(), Plain, [{dbg, false}]}, + {msg51f, msg51f(), Plain, [{dbg, false}]}, + {msg51g, msg51g(), Plain, [{dbg, false}]}, + {msg51h, msg51h(), Plain, [{dbg, false}]}, + {msg51i, msg51i(), Plain, [{dbg, false}]}, + {msg52, msg52(), Plain, [{dbg, false}]}, + {msg53, msg53(), Plain, [{dbg, false}]}, + {msg54a, msg54a(), Plain, [{dbg, false}]}, + {msg54b, msg54b(), Plain, [{dbg, false}]}, + {msg54c, msg54c(), Plain, [{dbg, false}]}, + {msg55, msg55(), Plain, [{dbg, false}]}, + {msg56, msg56(), Plain, [{dbg, false}]}, + {msg57, msg57(), Plain, [{dbg, false}]}, + {msg58a, msg58a(), Plain, [{dbg, false}]}, + {msg58b, msg58b(), Plain, [{dbg, false}]} + ]. + + +msgs5(Encoding) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + + PlainEDFail = + fun(Codec, DD, Ver, EC, M) -> + Res = + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M), + case Res of + {error, {message_encode_failed, Reason, _M}} -> + case Reason of + {error, {{deprecated, _}, _}} -> + ok; + _ -> + Res + end; + _ -> + Res + end + end, + + PlainDE = + fun(Codec, _DD, Ver, EC, B) -> + Res = + megaco_codec_test_lib:decode_message(Codec, false, Ver, + EC, B), + case Res of + {ok, M} -> + #'MegacoMessage'{mess = Mess} = M, + #'Message'{messageBody = {transactions, TRs}} = Mess, + [{transactionRequest, TR}] = TRs, + #'TransactionRequest'{actions = Actions} = TR, + [Action] = Actions, + #'ActionRequest'{commandRequests = CmdReqs} = Action, + [CmdReq] = CmdReqs, + #'CommandRequest'{command = Cmd} = CmdReq, + {addReq,AmmReq} = Cmd, + #'AmmRequest'{descriptors = []} = AmmReq, + ok; + _ -> + Res + end + end, + + Msgs = + [ + {msg61a, msg61a(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg61b, msg61b(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg61c, msg61c(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg62a, msg62a(), PlainEDFail, [{dbg,false}],[text,binary,erlang]}, + {msg62b, msg62b(), PlainDE, [{dbg,false}],[text]} + ], + [{N,M,F,C}||{N,M,F,C,E} <- Msgs,lists:member(Encoding,E)]. + +msgs6(Encoding) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + + Msgs = + [ + {msg71a, msg71a(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b01, msg71b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b02, msg71b02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b03, msg71b03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b04, msg71b04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b05, msg71b05(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b06, msg71b06(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b07, msg71b07(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b08, msg71b08(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b09, msg71b09(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b10, msg71b10(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b11, msg71b11(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b12, msg71b12(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b13, msg71b13(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b14, msg71b14(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b15, msg71b15(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b16, msg71b16(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c01, msg71c01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c02, msg71c02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c03, msg71c03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c04, msg71c04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c05, msg71c05(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c06, msg71c06(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c07, msg71c07(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c08, msg71c08(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c09, msg71c09(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71d01, msg71d01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71d02, msg71d02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72a01, msg72a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72a02, msg72a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72a03, msg72a03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72b01, msg72b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72b02, msg72b02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72b03, msg72b03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72c01, msg72c01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72c02, msg72c02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72c03, msg72c03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73a, msg73a(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73b01, msg73b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73b02, msg73b02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73c01, msg73c01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73c02, msg73c02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a01, msg74a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a02, msg74a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a03, msg74a03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a04, msg74a04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a05, msg74a05(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a06, msg74a06(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg75a01, msg75a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg75a02, msg75a02(), Plain, [{dbg,false}],[text,binary,erlang]} + ], + [{N,M,F,C}||{N,M,F,C,E} <- Msgs,lists:member(Encoding,E)]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +msg_actions([], Actions) -> + lists:reverse(Actions); +msg_actions([{CtxId, CmdReqs}|ActionInfo], Actions) -> + Action = ?MSG_LIB:cre_ActionRequest(CtxId,CmdReqs), + msg_actions(ActionInfo, [Action|Actions]). + +megaco_trans_req([], Transactions) -> + {transactions, lists:reverse(Transactions)}; +megaco_trans_req([{TransId, ActionInfo}|TransInfo], Transactions) -> + Actions = msg_actions(ActionInfo, []), + TR = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + megaco_trans_req(TransInfo, [Trans|Transactions]). + +megaco_message(Version, Mid, Body) -> + Mess = ?MSG_LIB:cre_Message(Version, Mid, Body), + cre_MegacoMessage(Mess). + +msg_request(Mid, TransInfo) -> + TransReq = megaco_trans_req(TransInfo, []), + megaco_message(?VERSION, Mid, TransReq). + +msg_request(Mid, TransId, ContextId, CmdReq) -> + Action = ?MSG_LIB:cre_ActionRequest(ContextId, CmdReq), + Actions = [Action], + TR = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg_request(Auth, Mid, TransId, ContextId, CmdReq) -> + Action = ?MSG_LIB:cre_ActionRequest(ContextId, CmdReq), + Actions = [Action], + TR = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + cre_MegacoMessage(Auth, Mess). + +msg_reply(Mid, TransId, Actions) -> + TR = cre_TransRep(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg_reply(Mid, TransId, ContextId, CmdReply) -> + Action = cre_ActRep(ContextId, CmdReply), + Actions = [Action], + msg_reply(Mid, TransId, Actions). + +msg_ack(Mid, [Range|_] = Ranges) when is_tuple(Range) -> + msg_ack(Mid, [Ranges]); + +msg_ack(Mid, Ranges) -> + %% TRAs = make_tras(Ranges, []), + TRAs = make_tras(Ranges), + Req = {transactions, TRAs}, + cre_MegacoMessage(?VERSION, Mid, Req). + +make_tras(TRARanges) -> + F = fun(R) -> {transactionResponseAck, make_tra(R)} end, + lists:map(F, TRARanges). + +make_tra(Ranges) -> + F = fun({F,L}) -> cre_TransAck(F,L) end, + lists:map(F, Ranges). + + +%% ------------------------------------------------------------------------- + + +msg1(Mid, Tid) -> + Gain = cre_PropParm("tdmc/gain", "2"), + Ec = cre_PropParm("tdmc/ec", "g165"), + LCD = cre_LocalControlDesc(sendRecv,[Gain, Ec]), + V = cre_PropParm("v", "0"), + %% C = cre_PropParm("c", "IN IP4 $ "), + C = cre_PropParm("c", [$I,$N,$ ,$I,$P,$4,$ ,$$,$ ]), + M = cre_PropParm("m", "audio $ RTP/AVP 0"), + A = cre_PropParm("a", "fmtp:PCMU VAD=X-NNVAD"), + LD = cre_LocalRemoteDesc([[V, C, M, A]]), + Parms = cre_StreamParms(LCD,LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + ReqEvent = cre_ReqedEv("al/of"), + EventsDesc = cre_EvsDesc(2222,[ReqEvent]), + AmmReq = cre_AmmReq([#megaco_term_id{id = Tid}], + [{mediaDescriptor, MediaDesc}, + {eventsDescriptor, EventsDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + Msg = msg_request(Mid, 9999, ?megaco_null_context_id, [CmdReq]), + Msg. + +msg1a() -> + msg1a(?MGC_MID). +msg1a(Mid) -> + msg1(Mid, ?A4444). + +msg1b() -> + msg1b(?MGC_MID). +msg1b(Mid) -> + msg1(Mid, ?A4445). + + +%% -------------------------- + + +msg2() -> + msg2(?MGC_MID). +msg2(Mid) -> + msg2(Mid, ?A4444). +msg2(Mid, Tid) -> + Gain = cre_PropParm("tdmc/gain", "2"), + Ec = cre_PropParm("tdmc/ec", "g165"), + LCD = cre_LocalControlDesc(sendRecv,[Gain, Ec]), + V = cre_PropParm("v", "0"), + %% C = cre_PropParm("c", "IN IP4 $ "), + C = cre_PropParm("c", [$I,$N,$ ,$I,$P,$4,$ ,$$,$ ]), + M = cre_PropParm("m", "audio $ RTP/AVP 0"), + A = cre_PropParm("a", "fmtp:PCMU VAD=X-NNVAD"), + LD = cre_LocalRemoteDesc([[V, C, M, A]]), + Parms = cre_StreamParms(LCD,LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + EventParm = cre_EvParm("strict",["exact"]), + ReqEvent = cre_ReqedEv("al/of", [EventParm]), + EventsDesc = cre_EvsDesc(2222,[ReqEvent]), + AmmReq = cre_AmmReq([#megaco_term_id{id = Tid}], + [{mediaDescriptor, MediaDesc}, + {eventsDescriptor, EventsDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 9999, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg3() -> + msg3(?MG1_MID). +msg3(Mid) -> + TimeStamp = cre_TimeNot("19990729", "22000000"), + Event = cre_ObsEv("al/of",TimeStamp), + Desc = cre_ObsEvsDesc(2222,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 10000, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg4() -> + msg4(?MG1_MID_NO_PORT, "901 mg col boot"). +msg4(Mid, Reason) when is_list(Reason) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChParm(restart,Address,[Reason],Profile), + Req = cre_SvcChReq([?megaco_root_termination_id],Parm), + CmdReq = cre_CmdReq({serviceChangeReq, Req}), + msg_request(Mid, 9998, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg5() -> + msg5(?MGC_MID). +msg5(Mid) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChResParm(Address,Profile), + Reply = cre_SvcChRep([?megaco_root_termination_id], + {serviceChangeResParms,Parm}), + msg_reply(Mid, 9998, ?megaco_null_context_id, + [{serviceChangeReply, Reply}]). + + +%% -------------------------- + +msg6(Mid, Tid) -> + Reply = cre_AmmsReply([#megaco_term_id{id = Tid}]), + msg_reply(Mid, 9999, ?megaco_null_context_id, [{modReply, Reply}]). + +msg6a() -> + msg6a(?MG1_MID). +msg6a(Mid) -> + msg6(Mid, ?A4444). + +msg6b() -> + msg6b(?MG2_MID). +msg6b(Mid) -> + msg6(Mid, ?A5555). + + +%% -------------------------- + +msg7() -> + msg7(?MGC_MID). +msg7(Mid) -> + Reply = cre_NotifyRep([#megaco_term_id{id = ?A4444}]), + msg_reply(Mid, 10000, ?megaco_null_context_id, [{notifyReply, Reply}]). + + +%% -------------------------- + +msg8(Mid, DigitMapValue) -> + Strict = cre_EvParm("strict",["state"]), + On = cre_ReqedEv("al/on", [Strict]), + Name = "dialplan00", + Action = cre_ReqedActs(Name), + Ce = cre_ReqedEv("dd/ce", Action), + EventsDesc = cre_EvsDesc(2223,[On, Ce]), + Signal = cre_Sig("cg/rt"), + DigMapDesc = cre_DigitMapDesc(Name, DigitMapValue), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, [{signal, Signal}]}, + {digitMapDescriptor, DigMapDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 10001, ?megaco_null_context_id, [CmdReq]). + +msg8a() -> + msg8a(?MGC_MID). +msg8a(Mid) -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body), + msg8(Mid, Value). + +msg8b() -> + msg8b(?MGC_MID). +msg8b(Mid) -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body, 1, 23, 99), + msg8(Mid, Value). + + +%% -------------------------- + +msg9() -> + msg9(?MG1_MID). +msg9(Mid) -> + TimeStamp = cre_TimeNot("19990729","22010001"), + Parm = cre_EvParm("ds",["916135551212"]), + Event = cre_ObsEv("dd/ce",TimeStamp,[Parm]), + Desc = cre_ObsEvsDesc(2223,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A4444}], Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 10002, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg10() -> + msg10(?MGC_MID). +msg10(Mid) -> + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}],[]), + CmdReq = cre_CmdReq({addReq, AmmReq}), + Jit = cre_PropParm("nt/jit", "40"), + LCD = cre_LocalControlDesc(recvOnly,[Jit]), + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 $ "), + M = cre_PropParm("m", "audio $ RTP/AVP 4"), + A = cre_PropParm("a", "ptime:30"), + V2 = cre_PropParm("v", "0"), + C2 = cre_PropParm("c", "IN IP4 $ "), + M2 = cre_PropParm("m", "audio $ RTP/AVP 0"), + LD = cre_LocalRemoteDesc([[V, C, M, A], [V2, C2, M2]]), + Parms = cre_StreamParms(LCD, LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + ChooseTid = #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}, + AmmReq2 = cre_AmmReq([ChooseTid],[{mediaDescriptor, MediaDesc}]), + CmdReq2 = cre_CmdReq({addReq, AmmReq2}), + msg_request(Mid, 10003, ?megaco_choose_context_id, [CmdReq, CmdReq2]). + + +msg11() -> + msg11(?MG1_MID). +msg11(Mid) -> + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 124.124.124.222"), + M = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + A = cre_PropParm("a", "ptime:30"), + A2 = cre_PropParm("a", "recvonly"), + LD = cre_LocalRemoteDesc([[V, C, M, A, A2]]), + Parms = cre_StreamParmsL(LD), + StreamDesc = cre_StreamDesc(1, Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + msg_reply(Mid, 10003, 2000, [{addReply, Reply}, {addReply, Reply2}]). + + +%% -------------------------- + +msg12() -> + msg12(?MGC_MID). +msg12(Mid) -> + LCD = cre_LocalControlDesc(sendRecv), + Parms = cre_StreamParms(LCD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Signal = cre_Sig("al/ri"), + Descs = [{mediaDescriptor, MediaDesc}, + {signalsDescriptor, [{signal, Signal}]}], + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A5555}], Descs), + CmdReq = cre_CmdReq({addReq, AmmReq}), + Jit = cre_PropParm("nt/jit", "40"), + LCD2 = cre_LocalControlDesc(sendRecv, [Jit]), + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 $ "), + M = cre_PropParm("m", "audio $ RTP/AVP 4"), + A = cre_PropParm("a", "ptime:30"), + LD2 = cre_LocalRemoteDesc([[V, C, M, A]]), + V2 = cre_PropParm("v", "0"), + C2 = cre_PropParm("c", "IN IP4 124.124.124.222"), + M2 = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + RD2 = cre_LocalRemoteDesc([[V2, C2, M2]]), + Parms2 = cre_StreamParms(LCD2,LD2,RD2), + StreamDesc2 = cre_StreamDesc(1,Parms2), + MediaDesc2 = cre_MediaDesc(StreamDesc2), + ChooseTid = #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}, + AmmReq2 = cre_AmmReq([ChooseTid],[{mediaDescriptor, MediaDesc2}]), + CmdReq2 = cre_CmdReq({addReq, AmmReq2}), + msg_request(Mid, 50003, ?megaco_choose_context_id, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg13() -> + msg13(?MG2_MID). +msg13(Mid) -> + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 125.125.125.111"), + M = cre_PropParm("m", "audio 1111 RTP/AVP 4"), + LD = cre_LocalRemoteDesc([[V, C, M]]), + Parms = cre_StreamParmsL(LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Reply = cre_AmmsReply([#megaco_term_id{id = ?A5556}], + [{mediaDescriptor, MediaDesc}]), + msg_reply(Mid, 50003, 5000, [{addReply, Reply}]). + + +%% -------------------------- + +msg14() -> + msg14(?MGC_MID). +msg14(Mid) -> + Signal = cre_Sig("cg/rt"), + AmmReq1 = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{signalsDescriptor, [{signal, Signal}]}]), + CmdReq1 = cre_CmdReq({modReq, AmmReq1}), + + Gain = cre_PropParm("tdmc/gain", "2"), + Ec = cre_PropParm("tdmc/ec", "g165"), + LCD = cre_LocalControlDesc(sendRecv, [Gain, Ec]), + Parms2 = cre_StreamParms(LCD), + StreamDesc2 = cre_StreamDesc(1,Parms2), + MediaDesc2 = cre_MediaDesc(StreamDesc2), + AmmReq2 = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc2}]), + CmdReq2 = cre_CmdReq({modReq, AmmReq2}), + + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 125.125.125.111"), + M = cre_PropParm("m", "audio 1111 RTP/AVP 4"), + RD = cre_LocalRemoteDesc([[V, C, M]]), + Parms3 = cre_StreamParmsR(RD), + StreamDesc3 = cre_StreamDesc(2,Parms3), + MediaDesc3 = cre_MediaDesc(StreamDesc3), + AmmReq3 = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc3}]), + CmdReq3 = cre_CmdReq({modReq, AmmReq3}), + msg_request(Mid, 10005, 2000, [CmdReq1, CmdReq2, CmdReq3]). + + +%% -------------------------- + +msg15() -> + msg15(?MG1_MID). +msg15(Mid) -> + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A4445}]), + msg_reply(Mid, 10005, 2000, [{modReply, Reply}, {modReply, Reply2}]). + + +%% -------------------------- + +msg16() -> + msg16(?MG2_MID). +msg16(Mid) -> + TimeStamp = cre_TimeNot("19990729","22020002"), + Event = cre_ObsEv("al/of",TimeStamp), + Desc = cre_ObsEvsDesc(1234,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 50005, 5000, [CmdReq]). + + +%% -------------------------- + +msg17() -> + msg17(?MGC_MID). +msg17(Mid) -> + Reply = cre_NotifyRep([#megaco_term_id{id = ?A5555}]), + msg_reply(Mid, 50005, ?megaco_null_context_id, [{notifyReply, Reply}]). + + +%% -------------------------- + +msg18() -> + msg18(?MGC_MID). +msg18(Mid) -> + On = cre_ReqedEv("al/on"), + EventsDesc = cre_EvsDesc(1235,[On]), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A5555}], + [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, []}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 50006, 5000, [CmdReq]). + + +%% -------------------------- + +msg19() -> + msg19(?MG2_MID). +msg19(Mid) -> + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4445}]), + msg_reply(Mid, 50006, 5000, [{modReply, Reply}]). + + +%% -------------------------- + +msg20() -> + msg20(?MGC_MID). +msg20(Mid) -> + LCD = cre_LocalControlDesc(sendRecv), + Parms = cre_StreamParms(LCD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + AmmReq2 = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{signalsDescriptor, []}]), + CmdReq2 = cre_CmdReq({modReq, AmmReq2}), + msg_request(Mid, 10006, 2000, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg21() -> + msg21(?MGC_MID). +msg21(Mid) -> + Tokens = [mediaToken, eventsToken, signalsToken, + digitMapToken, statsToken, packagesToken], + AuditDesc = cre_AuditDesc(Tokens), + Req = cre_AuditReq(#megaco_term_id{id = ?A5556},AuditDesc), + CmdReq = cre_CmdReq({auditValueRequest, Req}), + msg_request(Mid, 50007, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg22a() -> + msg22(1). + +msg22b() -> + msg22(10). + +msg22c() -> + msg22(25). + +msg22d() -> + msg22(50). + +msg22e() -> + msg22(75). + +msg22f() -> + msg22(100). + +msg22(N) -> + msg22(?MG2_MID, N). +msg22(Mid, N) -> + Jit = cre_PropParm("nt/jit", "40"), + LCD = cre_LocalControlDesc(sendRecv,[Jit]), + LDV = cre_PropParm("v", "0"), + LDC = cre_PropParm("c", "IN IP4 125.125.125.111"), + LDM = cre_PropParm("m", "audio 1111 RTP/AVP 4"), + LDA = cre_PropParm("a", "ptime:30"), + LD = cre_LocalRemoteDesc([[LDV, LDC, LDM, LDA]]), + RDV = cre_PropParm("v", "0"), + RDC = cre_PropParm("c", "IN IP4 124.124.124.222"), + RDM = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + RDA = cre_PropParm("a", "ptime:30"), + RD = cre_LocalRemoteDesc([[RDV, RDC, RDM, RDA]]), + StreamParms = cre_StreamParms(LCD,LD,RD), + StreamDesc = cre_StreamDesc(1,StreamParms), + Media = cre_MediaDesc(StreamDesc), + PackagesItem = cre_PkgsItem("nt",1), + PackagesItem2 = cre_PkgsItem("rtp",1), + Stat = cre_StatsParm("rtp/ps","1200"), + Stat2 = cre_StatsParm("nt/os","62300"), + Stat3 = cre_StatsParm("rtp/pr","700"), + Stat4 = cre_StatsParm("nt/or","45100"), + Stat5 = cre_StatsParm("rtp/pl","0.2"), + Stat6 = cre_StatsParm("rtp/jit","20"), + Stat7 = cre_StatsParm("rtp/delay","40"), + Statistics = [Stat, Stat2, Stat3, Stat4, Stat5, Stat6, Stat7], + Audits = [{mediaDescriptor, Media}, + {packagesDescriptor, [PackagesItem, PackagesItem2]}, + {statisticsDescriptor, Statistics}], + Reply = {auditResult, + cre_AuditRes(#megaco_term_id{id = ?A5556},Audits)}, + msg_reply(Mid, 50007, ?megaco_null_context_id, + lists:duplicate(N,{auditValueReply, Reply})). +%% msg_reply(Mid, 50007, ?megaco_null_context_id, +%% lists.duplicate([{auditValueReply, Reply}]). + + +%% -------------------------- + +msg23a() -> + msg23a(?MG2_MID). +msg23a(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 50008, 5000, [CmdReq]). + + +msg23b() -> + msg23b(?MG2_MID). +msg23b(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq1 = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_CmdReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_NotifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_CmdReq({notifyReq, NotifyReq2}), + ActionInfo = [{5000, [CmdReq1]}, {5001, [CmdReq2]}], + TransInfo = [{50008, ActionInfo}], + msg_request(Mid, TransInfo). + + +msg23c() -> + msg23c(?MG2_MID). +msg23c(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq1 = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_CmdReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_NotifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_CmdReq({notifyReq, NotifyReq2}), + ActionInfo1 = [{5000, [CmdReq1]}], + ActionInfo2 = [{5001, [CmdReq2]}], + TransInfo = [{50008, ActionInfo1}, {50009, ActionInfo2}], + msg_request(Mid, TransInfo). + + +msg23d() -> + msg23d(?MG2_MID). +msg23d(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq1 = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_CmdReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_NotifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_CmdReq({notifyReq, NotifyReq2}), + NotifyReq3 = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc), + CmdReq3 = cre_CmdReq({notifyReq, NotifyReq3}), + NotifyReq4 = cre_NotifyReq([#megaco_term_id{id = ?A4445}],Desc), + CmdReq4 = cre_CmdReq({notifyReq, NotifyReq4}), + ActionInfo1 = [{5000, [CmdReq1]}, {5001, [CmdReq2]}], + ActionInfo2 = [{5003, [CmdReq3]}, {5004, [CmdReq4]}], + TransInfo = [{50008, ActionInfo1}, {50009, ActionInfo2}], + msg_request(Mid, TransInfo). + + +%% -------------------------- + +msg24() -> + msg24(?MGC_MID). +msg24(Mid) -> + AuditDesc = cre_AuditDesc([statsToken]), + SubReq = cre_SubReq([#megaco_term_id{id = ?A5555}], AuditDesc), + SubReq2 = cre_SubReq([#megaco_term_id{id = ?A5556}], AuditDesc), + CmdReq = cre_CmdReq({subtractReq, SubReq}), + CmdReq2 = cre_CmdReq({subtractReq, SubReq2}), + msg_request(Mid, 50009, 5000, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg25() -> + msg25(?MG2_MID). +msg25(Mid) -> + Stat11 = cre_StatsParm("nt/os","45123"), + Stat12 = cre_StatsParm("nt/dur", "40"), + Stats1 = [Stat11, Stat12], + Reply1 = cre_AmmsReply([#megaco_term_id{id = ?A5555}], + [{statisticsDescriptor, Stats1}]), + Stat21 = cre_StatsParm("rtp/ps","1245"), + Stat22 = cre_StatsParm("nt/os", "62345"), + Stat23 = cre_StatsParm("rtp/pr", "780"), + Stat24 = cre_StatsParm("nt/or", "45123"), + Stat25 = cre_StatsParm("rtp/pl", "10"), + Stat26 = cre_StatsParm("rtp/jit", "27"), + Stat27 = cre_StatsParm("rtp/delay","48"), + Stats2 = [Stat21, Stat22, Stat23, Stat24, Stat25, Stat26, Stat27], + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A5556}], + [{statisticsDescriptor, Stats2}]), + msg_reply(Mid, 50009, 5000, + [{subtractReply, Reply1}, {subtractReply, Reply2}]). + + +msg30a() -> + msg_ack(?MG2_MID, [{9,9}]). + +msg30b() -> + msg_ack(?MG2_MID, [{9,13}]). + +msg30c() -> + msg_ack(?MG2_MID, + [{9,13}, {15,15}, {33,40}, {50,60}, {70,80}, {85,90}, + {101,105},{109,119},{121,130},{140,160},{170,175},{180,189}, + {201,205},{209,219},{221,230},{240,260},{270,275},{280,289}, + {301,305},{309,319},{321,330},{340,360},{370,375},{380,389}, + {401,405},{409,419},{421,430},{440,460},{470,475},{480,489}, + {501,505},{509,519},{521,530},{540,560},{570,575},{580,589} + ]). + +%% Don't think this will be used by the megaco stack, but since it +%% seem's to be a valid construction... +msg30d() -> + msg_ack(?MG2_MID, + [[{9,13}, {15,15}, {33,40}, {50,60}, {70,80}, {85,90}], + [{101,105},{109,119},{121,130},{140,160},{170,175},{180,189}], + [{201,205},{209,219},{221,230},{240,260},{270,275},{280,289}], + [{301,305},{309,319},{321,330},{340,360},{370,375},{380,389}], + [{401,405},{409,419},{421,430},{440,460},{470,475},{480,489}], + [{501,505},{509,519},{521,530},{540,560},{570,575},{580,589}] + ]). + + + +msg40() -> + msg40(?MG1_MID_NO_PORT, "901 mg col boot"). +msg40(Mid, Reason) when is_list(Reason) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChParm(restart,Address,[Reason],Profile), + Req = cre_SvcChReq([?megaco_root_termination_id],Parm), + CmdReq = cre_CmdReq({serviceChangeReq, Req}), + Auth = cre_AuthHeader(), + msg_request(Auth, Mid, 9998, ?megaco_null_context_id, [CmdReq]). + + +msg50(Mid, APT) -> + AD = cre_AuditDesc(asn1_NOVALUE, APT), + Req = cre_AuditReq(#megaco_term_id{id = ?A5556},AD), + CmdReq = cre_CmdReq({auditValueRequest, Req}), + msg_request(Mid, 50007, ?megaco_null_context_id, [CmdReq]). + +%% IndAudMediaDescriptor: +msg51(Mid, IATSDorStream) -> + IAMD = cre_IndAudMediaDesc(IATSDorStream), + IAP = cre_IndAudParam(IAMD), + APT = [IAP], + msg50(Mid, APT). + +msg51a() -> + msg51a(?MG2_MID). +msg51a(Mid) -> + PP = cre_IndAudPropertyParm("tdmc/gain"), + PPs = [PP], + IATSD = cre_IndAudTermStateDesc(PPs), + msg51(Mid, IATSD). + +msg51b() -> + msg51b(?MG2_MID). +msg51b(Mid) -> + PP = cre_IndAudPropertyParm("nt/jit"), + PPs = [PP], + IATSD = cre_IndAudTermStateDesc(PPs), + msg51(Mid, IATSD). + +msg51c() -> + msg51c(?MG2_MID). +msg51c(Mid) -> + IATSD = cre_IndAudTermStateDesc([], asn1_NOVALUE, 'NULL'), + msg51(Mid, IATSD). + +msg51d() -> + msg51d(?MG2_MID). +msg51d(Mid) -> + IATSD = cre_IndAudTermStateDesc([], 'NULL', asn1_NOVALUE), + msg51(Mid, IATSD). + +msg51e() -> + msg51e(?MG2_MID). +msg51e(Mid) -> + IALCD = cre_IndAudLocalControlDesc('NULL', asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE), + IASP = cre_IndAudStreamParms(IALCD), + msg51(Mid, IASP). + +msg51f() -> + msg51f(?MG2_MID). +msg51f(Mid) -> + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, 'NULL', + asn1_NOVALUE, asn1_NOVALUE), + IASP = cre_IndAudStreamParms(IALCD), + msg51(Mid, IASP). + +msg51g() -> + msg51g(?MG2_MID). +msg51g(Mid) -> + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, asn1_NOVALUE, + 'NULL', asn1_NOVALUE), + IASP = cre_IndAudStreamParms(IALCD), + msg51(Mid, IASP). + +msg51h() -> + msg51h(?MG2_MID). +msg51h(Mid) -> + Name = "nt/jit", + IAPP = cre_IndAudPropertyParm(Name), + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, asn1_NOVALUE, + asn1_NOVALUE, [IAPP]), + IASP = cre_IndAudStreamParms(IALCD), + SID = 123, + IASD = cre_IndAudStreamDesc(SID, IASP), + msg51(Mid, [IASD]). + + +msg51i() -> + msg51i(?MG2_MID). +msg51i(Mid) -> + Name = "nt/jit", + Name2 = "tdmc/ec", + IAPP = cre_IndAudPropertyParm(Name), + IAPP2 = cre_IndAudPropertyParm(Name2), + IALCD = cre_IndAudLocalControlDesc('NULL', 'NULL', 'NULL', + [IAPP, IAPP2]), + IASP = cre_IndAudStreamParms(IALCD), + SID = 123, + IASD = cre_IndAudStreamDesc(SID, IASP), + msg51(Mid, [IASD]). + + +%% IndAudEventsDescriptor: +msg52() -> + msg52(?MG2_MID). +msg52(Mid) -> + RequestID = 1235, + PkgdName = "tonedet/std", + IAED = cre_IndAudEvsDesc(RequestID, PkgdName), + IAP = cre_IndAudParam(IAED), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudEventBufferDescriptor: +msg53() -> + msg53(?MG2_MID). +msg53(Mid) -> + EN = "tonedet/std", + SID = 1, + IAEBD = cre_IndAudEvBufDesc(EN, SID), + IAP = cre_IndAudParam(IAEBD), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudSignalsDescriptor: +msg54(Mid, Sig) -> + IASD = cre_IndAudSigsDesc(Sig), + IAP = cre_IndAudParam(IASD), + APT = [IAP], + msg50(Mid, APT). + +msg54a() -> + msg54a(?MG2_MID). +msg54a(Mid) -> + SN = "tonegen/pt", + Sig = cre_IndAudSig(SN), + msg54(Mid, Sig). + +msg54b() -> + msg54b(?MG2_MID). +msg54b(Mid) -> + SN = "dg/d0", + Sig = cre_IndAudSig(SN), + msg54(Mid, Sig). + +msg54c() -> + msg54c(?MG2_MID). +msg54c(Mid) -> + SN = "ct/ct", + Sig = cre_IndAudSig(SN), + ID = 4321, + SSL = cre_IndAudSeqSigList(ID, Sig), + msg54(Mid, SSL). + +%% IndAudDigitMapDescriptor: +msg55() -> + msg55(?MG2_MID). +msg55(Mid) -> + DMN = "dialplan00", + IADMD = cre_IndAudDigitMapDesc(DMN), + IAP = cre_IndAudParam(IADMD), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudStatisticsDescriptor: +msg56() -> + msg56(?MG2_MID). +msg56(Mid) -> + SN = "nt/dur", + IASD = cre_IndAudStatsDesc(SN), + IAP = cre_IndAudParam(IASD), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudPackagesDescriptor: +msg57() -> + msg57(?MG2_MID). +msg57(Mid) -> + PN = "al", + PV = 1, + IAPD = cre_IndAudPkgsDesc(PN, PV), + IAP = cre_IndAudParam(IAPD), + APT = [IAP], + msg50(Mid, APT). + +%% Sum it up: +msg58_iaMediaDesc_iap(IATSD) -> + IAMD = cre_IndAudMediaDesc(IATSD), + cre_IndAudParam(IAMD). + +msg58_iaMediaDesc_iap_a() -> + PP = cre_IndAudPropertyParm("tdmc/gain"), + PPs = [PP], + IATSD = cre_IndAudTermStateDesc(PPs), + msg58_iaMediaDesc_iap(IATSD). + +msg58_iaMediaDesc_iap_b() -> + IATSD = cre_IndAudTermStateDesc([], 'NULL', asn1_NOVALUE), + msg58_iaMediaDesc_iap(IATSD). + +msg58_iaEvsDesc_iap() -> + RequestID = 1235, + PkgdName = "tonedet/std", + IAED = cre_IndAudEvsDesc(RequestID, PkgdName), + cre_IndAudParam(IAED). + +msg58_iaEvBufDesc_iap() -> + EN = "tonedet/std", + SID = 1, + IAEBD = cre_IndAudEvBufDesc(EN, SID), + cre_IndAudParam(IAEBD). + +msg58_iaSigsDesc_iap(S) -> + IASD = cre_IndAudSigsDesc(S), + cre_IndAudParam(IASD). + +msg58_iaSigsDesc_iap_a() -> + SN = "tonegen/pt", + Sig = cre_IndAudSig(SN), + msg58_iaSigsDesc_iap(Sig). + +msg58_iaSigsDesc_iap_b() -> + SN = "ct/ct", + Sig = cre_IndAudSig(SN), + ID = 4321, + SSL = cre_IndAudSeqSigList(ID, Sig), + msg58_iaSigsDesc_iap(SSL). + +msg58_iaDigMapDesc_iap() -> + DMN = "dialplan00", + IADMD = cre_IndAudDigitMapDesc(DMN), + cre_IndAudParam(IADMD). + +msg58_iaStatsDesc_iap() -> + SN = "nt/dur", + IASD = cre_IndAudStatsDesc(SN), + cre_IndAudParam(IASD). + +msg58_iaPacksDesc_iap() -> + PN = "al", + PV = 1, + IAPD = cre_IndAudPkgsDesc(PN, PV), + cre_IndAudParam(IAPD). + +msg58a() -> + msg58a(?MG2_MID). +msg58a(Mid) -> + IAMD = msg58_iaMediaDesc_iap_a(), + IAED = msg58_iaEvsDesc_iap(), + IAEBD = msg58_iaEvBufDesc_iap(), + IASiD = msg58_iaSigsDesc_iap_a(), + IADMD = msg58_iaDigMapDesc_iap(), + IAStD = msg58_iaStatsDesc_iap(), + IAPD = msg58_iaPacksDesc_iap(), + APT = [IAMD, IAED, IAEBD, IASiD, IADMD, IAStD, IAPD], + msg50(Mid, APT). + +msg58b() -> + msg58b(?MG2_MID). +msg58b(Mid) -> + IAMD = msg58_iaMediaDesc_iap_b(), + IAED = msg58_iaEvsDesc_iap(), + IAEBD = msg58_iaEvBufDesc_iap(), + IASiD = msg58_iaSigsDesc_iap_b(), + IADMD = msg58_iaDigMapDesc_iap(), + IAStD = msg58_iaStatsDesc_iap(), + IAPD = msg58_iaPacksDesc_iap(), + APT = [IAMD, IAED, IAEBD, IASiD, IADMD, IAStD, IAPD], + msg50(Mid, APT). + + +%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +%% Tests some of the changes in the v2 corr 1 (EmergencyOff and ModemDesc) + +%% Emergency On/Off (optional) tests +msg61(EM) -> + TS = cre_TimeNot("19990729", "22000000"), + Event = cre_ObsEv("al/of",TS), + Desc = cre_ObsEvsDesc(2222,[Event]), + NotReq = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc), + Cmd = ?MSG_LIB:cre_Command(notifyReq, NotReq), + CmdReq = cre_CmdReq(Cmd), + CtxReq = ?MSG_LIB:cre_ContextRequest(15, EM), + ActReq = ?MSG_LIB:cre_ActionRequest(1, CtxReq, [CmdReq]), + Acts = [ActReq], + TR = ?MSG_LIB:cre_TransactionRequest(9898, Acts), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, ?MG1_MID, [Trans]), + cre_MegacoMessage(Mess). + +msg61a() -> + msg61(false). + +msg61b() -> + msg61(true). + +msg61c() -> + msg61(asn1_NOVALUE). + + +msg62a() -> + MT = ?MSG_LIB:cre_ModemType(v18), + PP = cre_PropParm("c", "IN IP4 $ "), + MD = ?MSG_LIB:cre_ModemDescriptor([MT], [PP]), + AmmDesc = ?MSG_LIB:cre_AmmDescriptor(MD), + TermIDs = [#megaco_term_id{id = ?A4444}], + AmmReq = ?MSG_LIB:cre_AmmRequest(TermIDs, [AmmDesc]), + Cmd = ?MSG_LIB:cre_Command(addReq, AmmReq), + CmdReq = ?MSG_LIB:cre_CommandRequest(Cmd), + ActReq = ?MSG_LIB:cre_ActionRequest(2, [CmdReq]), + Acts = [ActReq], + TR = ?MSG_LIB:cre_TransactionRequest(9898, Acts), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, ?MG1_MID, [Trans]), + cre_MegacoMessage(Mess). + +msg62b() -> + MP = +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 +Transaction = 9898 { + Context = 2 { + Add = 11111111/00000000/00000000 { + Modem[V18] { + tdmc/gain=2 + } + } + } +}", +% MC = +% "!/" ?VERSION_STR " [124.124.124.222]:55555\nT=9898{C=2{A=11111111/00000000/00000000{MD[V18]{tdmc/gain=2}}}}", + list_to_binary(MP). + +%% ActionRequest with various combinations of ContextRequest and +%% ContextAttrAuditRequest +msg71(CR, CAAR) -> + TS1 = cre_TimeNot("19990729", "22000000"), + TS2 = cre_TimeNot("19990729", "22000111"), + Event1 = cre_ObsEv("al/of",TS1), + Event2 = cre_ObsEv("al/on",TS2), + Desc1 = cre_ObsEvsDesc(2222,[Event1]), + Desc2 = cre_ObsEvsDesc(2222,[Event2]), + NR1 = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc1), + NR2 = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc2), + Cmd1 = ?MSG_LIB:cre_Command(notifyReq, NR1), + Cmd2 = ?MSG_LIB:cre_Command(notifyReq, NR2), + CR1 = cre_CmdReq(Cmd1), + CR2 = cre_CmdReq(Cmd2), + ActReq = ?MSG_LIB:cre_ActionRequest(1, CR, CAAR, [CR1, CR2]), + Acts = [ActReq], + TR = ?MSG_LIB:cre_TransactionRequest(9898, Acts), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, ?MG1_MID, [Trans]), + cre_MegacoMessage(Mess). + +msg71a() -> + CR = cre_ContextRequest(), + CAAR = cre_ContextAttrAuditRequest(), + msg71(CR, CAAR). + +msg71b(CR) -> + CAAR = asn1_NOVALUE, + msg71(CR, CAAR). + +msg71b01() -> + CR = cre_ContextRequest(15), + msg71b(CR). + +msg71b02() -> + CR = cre_ContextRequest(true), + msg71b(CR). + +msg71b03() -> + CR = cre_ContextRequest(false), + msg71b(CR). + +msg71b04() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(Top), + msg71b(CR). + +msg71b05() -> + CR = cre_ContextRequest(15, true), + msg71b(CR). + +msg71b06() -> + CR = cre_ContextRequest(15, false), + msg71b(CR). + +msg71b07() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, Top), + msg71b(CR). + +msg71b08() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, true, Top), + msg71b(CR). + +msg71b09() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, false, Top), + msg71b(CR). + +msg71b10() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, true, Top, true), + msg71b(CR). + +msg71b11() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, true, Top, false), + msg71b(CR). + +msg71b12() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", "2"), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, Props), + msg71b(CR). + +msg71b13() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2"], relation, greaterThan), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, Props), + msg71b(CR). + +msg71b14() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","10"], range, true), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, Props), + msg71b(CR). + +msg71b15() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("nt/jit", ["40","50","50"], sublist, true), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, Props), + msg71b(CR). + +msg71b16() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, true, Props), + msg71b(CR). + +msg71c(CAAR) -> + CR = asn1_NOVALUE, + msg71(CR, CAAR). + +msg71c01() -> + CAAR = cre_ContextAttrAuditRequest('NULL', 'NULL', 'NULL'), + msg71c(CAAR). + +msg71c02() -> + CAAR = cre_ContextAttrAuditRequest('NULL', 'NULL', asn1_NOVALUE), + msg71c(CAAR). + +msg71c03() -> + CAAR = cre_ContextAttrAuditRequest('NULL', asn1_NOVALUE, 'NULL'), + msg71c(CAAR). + +msg71c04() -> + CAAR = cre_ContextAttrAuditRequest(asn1_NOVALUE, 'NULL', 'NULL'), + msg71c(CAAR). + +msg71c05() -> + CAAR = cre_ContextAttrAuditRequest(asn1_NOVALUE, asn1_NOVALUE, 'NULL'), + msg71c(CAAR). + +msg71c06() -> + CAAR = cre_ContextAttrAuditRequest(asn1_NOVALUE, 'NULL', asn1_NOVALUE), + msg71c(CAAR). + +msg71c07() -> + CAAR = cre_ContextAttrAuditRequest('NULL', asn1_NOVALUE, asn1_NOVALUE), + msg71c(CAAR). + +msg71c08() -> + CAAR = cre_ContextAttrAuditRequest('NULL', asn1_NOVALUE, 'NULL', 'NULL'), + msg71c(CAAR). + +msg71c09() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + CAAR = cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, CPA), + msg71c(CAAR). + +msg71d01() -> + CR = cre_ContextRequest(15, true), + CAAR = cre_ContextAttrAuditRequest('NULL', 'NULL', 'NULL'), + msg71(CR, CAAR). + +msg71d02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2"], relation, unequalTo), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, true, Props), + + CAAR_Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + CAAR = cre_ContextAttrAuditRequest(CAAR_Top, Em, Prio, Ieps, CPA), + + msg71(CR, CAAR). + +msg72(ED, CR) -> + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 124.124.124.222"), + M = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + A = cre_PropParm("a", "a=ptime:30"), + A2 = cre_PropParm("a", "recvonly"), + LD = cre_LocalRemoteDesc([[V, C, M, A, A2]]), + Parms = cre_StreamParmsL(LD), + StreamDesc = cre_StreamDesc(1, Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + CmdRep = [{addReply, Reply}, {addReply, Reply2}], + Action = cre_ActRep(2000, ED, CR, CmdRep), + msg_reply(?MGC_MID, 10003, [Action]). + +msg72a(CR) -> + ED = asn1_NOVALUE, + msg72(ED, CR). + +msg72a01() -> + CR = cre_ContextRequest(false), + msg72a(CR). + +msg72a02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(Top), + msg72a(CR). + +msg72a03() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, Top), + msg72a(CR). + +msg72b(CR) -> + EC = ?MSG_LIB:cre_ErrorCode(?megaco_not_ready), + ED = ?MSG_LIB:cre_ErrorDescriptor(EC), + msg72(ED, CR). + +msg72b01() -> + CR = cre_ContextRequest(15, false), + msg72b(CR). + +msg72b02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, false, Top), + msg72b(CR). + +msg72b03() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, true, Top, true), + msg72b(CR). + +msg72c(CR) -> + EC = ?MSG_LIB:cre_ErrorCode(?megaco_not_ready), + ET = ?MSG_LIB:cre_ErrorText("Just another error string"), + ED = ?MSG_LIB:cre_ErrorDescriptor(EC, ET), + msg72(ED, CR). + +msg72c01() -> + CR = cre_ContextRequest(15), + msg72c(CR). + +msg72c02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", "2"), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, Props), + msg72c(CR). + +msg72c03() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, true, Props), + msg72c(CR). + + +msg73() -> + Stat1 = cre_StatsParm("rtp/ps"), + Stat2 = cre_StatsParm("nt/os","62300"), + Stat3 = cre_StatsParm("rtp/pr","700"), + Stat4 = cre_StatsParm("nt/or","45100"), + Stat5 = cre_StatsParm("rtp/pl","0.2"), + Stat6 = cre_StatsParm("rtp/jit","20"), + Stat7 = cre_StatsParm("rtp/delay","40"), + Stats = [Stat1, Stat2, Stat3, Stat4, Stat5, Stat6, Stat7], + cre_StatsDesc(Stats). + +%% StatisticsDescriptor in AmmDescriptor +msg73a() -> + StatDesc = msg73(), + AmmDesc = cre_AmmDesc(StatDesc), + TermIDs = [#megaco_term_id{id = ["11111111", "00001111", "00000000"]}], + AmmReq = cre_AmmReq(TermIDs, [AmmDesc]), + Cmd = cre_Cmd(addReq, AmmReq), + CmdReq = cre_CmdReq(Cmd), + CID = cre_CtxID(7301), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(7302), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + + +%% StatisticsDescriptor in IndAudStreamParms +msg73b1() -> + IASD = cre_IndAudStatsDesc("nt/dur"), + cre_IndAudStreamParms(IASD). + +msg73b2(IAMD) -> + IAP = cre_IndAudParam(IAMD), + AD = cre_AuditDesc([IAP]), + TermID = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + AudReq = cre_AuditReq(TermID, AD), + Cmd = cre_Cmd(auditValueRequest, AudReq), + CmdReq = cre_CmdReq(Cmd), + CID = cre_CtxID(7311), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(7312), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg73b01() -> + IASP = msg73b1(), + IAMD = cre_IndAudMediaDesc(IASP), + msg73b2(IAMD). + +msg73b02() -> + IASP = msg73b1(), + SID = cre_StreamID(303), + IASD = cre_IndAudStreamDesc(SID, IASP), + IAMD = cre_IndAudMediaDesc([IASD]), + msg73b2(IAMD). + +%% StatisticsDescriptor in StreamParms +msg73c1() -> + StatDesc = msg73(), + SP = cre_StreamParms(StatDesc), + SID = cre_StreamID(505), + cre_StreamDesc(SID, SP). + +msg73c2(MD) -> + ARP = cre_AuditRetParam(MD), + TA = cre_TermAudit([ARP]), + TermIDs = [#megaco_term_id{id = ["11111111", "00001111", "00000000"]}], + AmmsRep = cre_AmmsReply(TermIDs, TA), + CmdRep = cre_CmdRep(moveReply, AmmsRep), + CID = cre_CtxID(606), + ActRep = cre_ActRep(CID, [CmdRep]), + TransId = cre_TransId(8899), + TransRep = cre_TransRep(TransId, [ActRep]), + Trans = cre_Trans(TransRep), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg73c01() -> + SD = msg73c1(), + MD = cre_MediaDesc(SD), + msg73c2(MD). + +msg73c02() -> + SD = msg73c1(), + MD = cre_MediaDesc([SD]), + msg73c2(MD). + + +%% New Signal (direction and requestID); msg74 +msg74a1(D) -> + Dir = cre_SigDir(D), + cre_Sig("cg/rt", Dir, asn1_NOVALUE). + +msg74a2(D, RID) -> + Dir = cre_SigDir(D), + cre_Sig("cg/rt", Dir, RID). + +msg74a3(D, RID) -> + Name = "al/ri", + SID = cre_StreamID(7401), + ST = cre_SigType(brief), + Dur = 7499, + NC = cre_NotifCompl([onTimeOut,otherReason]), + KA = cre_BOOLEAN(true), + SPL = [], + Dir = cre_SigDir(D), + cre_Sig(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID). + +msg74a4(Sig) -> + SR = cre_SigReq(Sig), + SD = cre_SigsDesc([SR]), + AD = cre_AmmDesc(SD), + TermIDs = [#megaco_term_id{id = ?A4444}], + AR = cre_AmmReq(TermIDs, [AD]), + Cmd = cre_Cmd(modReq, AR), + cre_CmdReq(Cmd). + +msg74a01() -> + Sig = msg74a1(internal), + CR = msg74a4(Sig), + CID = cre_CtxID(7411), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7421), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a02() -> + Sig = msg74a1(both), + CR = msg74a4(Sig), + CID = cre_CtxID(7412), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7422), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a03() -> + RID = cre_ReqID(7433), + Sig = msg74a2(external, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7413), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7423), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a04() -> + RID = cre_ReqID(7434), + Sig = msg74a2(both, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7414), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7424), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a05() -> + RID = cre_ReqID(7435), + Sig = msg74a3(both, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7415), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7425), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a06() -> + RID = cre_ReqID(7436), + Sig = msg74a3(internal, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7416), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7426), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + + + +%% New ServiceChangeParm (serviceChangeIncompleteFlag); msg75 +msg75a(IncFlag) -> + Method = cre_SvcChMethod(restart), + Address = cre_SvcChAddr(portNumber, ?DEFAULT_PORT), + Reason = "901 mg col boot", + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChParm(Method, Address, [Reason], Profile, IncFlag), + TermIDs = [?megaco_root_termination_id], + Req = cre_SvcChReq(TermIDs, Parm), + Cmd = cre_Cmd(serviceChangeReq, Req), + CR = cre_CmdReq(Cmd), + CID = cre_CtxID(7501), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7502), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg75a01() -> + msg75a(asn1_NOVALUE). + +msg75a02() -> + msg75a('NULL'). + + +%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +%% Pretty RFC 3525 messages: + +%% Added Reason +rfc3525_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + +rfc3525_msg2() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +%% Removed "," after LocalControl ending "}" +rfc3525_msg3() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 9999 { + Context = - { + Modify = A4444 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive, + tdmc/gain=2, ; in dB, + tdmc/ec=on + } + } + }, + Events = 2222 { + al/of {strict=state} + } + } + } +}". + +%% Removed the outermost "{}" pair (before the Reply token) +rfc3525_msg4() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 9999 { + Context = - { + Modify = A4444 + } +}". + +rfc3525_msg6() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Transaction = 10000 { + Context = - { + Notify = A4444 { + ObservedEvents =2222 { + 19990729T22000000:al/of{init=false} + } + } + } +}". + + +rfc3525_msg7() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 10000 { + Context = - { + Notify = A4444 + } +}". + +rfc3525_msg8() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10001 { + Context = - { + Modify = A4444 { + Events = 2223 { + al/on {strict=state}, + dd/ce {DigitMap=Dialplan0} + }, + Signals {cg/dt}, + DigitMap = Dialplan0 { + (0| 00|[1-7]xxx|8xxxxxxx|fxxxxxxx|exx|91xxxxxxxxxx|9011x.) + } + } + } +}". + +rfc3525_msg9() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10001 { + Context = - { + Modify = A4444 + } +}". + +rfc3525_msg10() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Transaction = 10002 { + Context = - { + Notify = A4444 { + ObservedEvents =2223 { + 19990729T22010001:dd/ce { + ds=\"916135551212\", + Meth=UM + } + } + } + } +}". + + +rfc3525_msg11() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 10002 { + Context = - { + Notify = A4444 + } +}". + +%% Added ? +rfc3525_msg12() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10003 { + Context = $ { + Add = A4444, + Add = $ { + Media { + Stream = 1 { + LocalControl { + Mode = ReceiveOnly, + nt/jit=40 ; in ms + }, + Local { + v=0 c=IN IP4 $ m=audio $ RTP/AVP 4 a=ptime:30 v=0 c=IN IP4 $ m=audio $ RTP/AVP 0 + } + } + } + } + } +}". + +%% Added ? +rfc3525_msg13() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a=recvonly + } ; RTP profile for G.723.1 is 4 + } + } + } + } +}". + +%% +%% Added ? +rfc3525_msg14() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50003 { + Context = $ { + Add = A5555 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive + } + } + }, + Events = 1234 { + al/of {strict=state} + }, + Signals {al/ri} + }, + Add = $ { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive, + nt/jit=40 ; in ms + }, + Local { + v=0 c=IN IP4 $ m=audio $ RTP/AVP 4 a=ptime:30 + }, + Remote { + v=0 c=IN IP4 124.124.124.222 m=audio 2222 RTP/AVP 4 a=ptime:30 + } ; RTP profile for G.723.1 is 4 + } + } + } + } +}". + +%% Added ? +rfc3525_msg15() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50003 { + Context = 5000 { + Add = A5555, + Add = A5556 { + Media { + Stream = 1 { + Local { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 + } ; RTP profile for G723.1 is 4 + } + } + } + } +}". + +%% Added ? +rfc3525_msg16a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10005 { + Context = 2000 { + Modify = A4444 { + Signals {cg/rt} + }, + Modify = A4445 { + Media { + Stream = 1 { + Remote { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 + } ; RTP profile for G723.1 is 4 + } + } + } + } +}". + +rfc3525_msg16b() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10005 { + Context = 2000 { + Modify = A4444, + Modify = A4445 + } +}". + +rfc3525_msg17a() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Transaction = 50005 { + Context = 5000 { + Notify = A5555 { + ObservedEvents = 1234 { + 19990729T22020002:al/of{init=false} + } + } + } +}". + +rfc3525_msg17b() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 50005 { + Context = - { + Notify = A5555 + } +}". + +%% Removed "{ }" after Signals +rfc3525_msg17c() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50006 { + Context = 5000 { + Modify = A5555 { + Events = 1235 { + al/on{strict=state} + }, + Signals ; to turn off ringing + } + } +}". + +rfc3525_msg17d() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50006 { + Context = 5000 { + Modify = A4445 + } +}". + +%% Removed "{ }" after Signals +rfc3525_msg18a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10006 { + Context = 2000 { + Modify = A4445 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive + } + } + } + }, + Modify = A4444 { + Signals + } + } +}". + +rfc3525_msg18b() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10006 { + Context = 2000 { + Modify = A4445, + Modify = A4444 + } +}". + +rfc3525_msg19() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50007 { + Context = - { + AuditValue = A5556 { + Audit { + Media, DigitMap, Events, Signals, Packages, Statistics + } + } + } +}". + +%% Added ? +rfc3525_msg20() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50007 { + Context = - { + AuditValue = A5556 { + Media { + TerminationState { + ServiceStates = InService, + Buffer = OFF + }, + Stream = 1 { + LocalControl { + Mode = SendReceive, + nt/jit=40 + }, + Local { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 a=ptime:30 + }, + Remote { + v=0 o=- 2890844526 2890842807 IN IP4 124.124.124.222 s=- t= 0 0 c=IN IP4 124.124.124.222 m=audio 2222 RTP/AVP 4 a=ptime:30 + } + } + }, + Events, + Signals, + DigitMap, + Packages {nt-1, rtp-1}, + Statistics { + rtp/ps=1200, ; packets sent + nt/os=62300, ; octets sent + rtp/pr=700, ; packets received + nt/or=45100, ; octets received + rtp/pl=0.2, ; % packet loss + rtp/jit=20, + rtp/delay=40 ; avg latency + } + } + } +}". + +rfc3525_msg21a() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Transaction = 50008 { + Context = 5000 { + Notify = A5555 { + ObservedEvents =1235 { + 19990729T24020002:al/on {init=false} + } + } + } +}". + +rfc3525_msg21b() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 50008 { + Context = - { + Notify = A5555 + } +}". + +rfc3525_msg22a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50009 { + Context = 5000 { + Subtract = A5555 { + Audit { + Statistics + } + }, + Subtract = A5556 { + Audit { + Statistics + } + } + } +}". + +%% Added ? +rfc3525_msg22b() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50009 { + Context = 5000 { + Subtract = A5555 { + Statistics { + nt/os=45123, ; Octets Sent + nt/dur=40 ; in seconds + } + }, + Subtract = A5556 { + Statistics { + rtp/ps=1245, ; packets sent + nt/os=62345, ; octets sent + rtp/pr=780, ; packets received + nt/or=45123, ; octets received + rtp/pl=10, ; % packets lost + rtp/jit=27, + rtp/delay=48 ; average latency + } + } + } +}". + +rfc3525_msgs() -> + [ + {msg1, rfc3525_msg1()}, + {msg2, rfc3525_msg2()}, + {msg3, rfc3525_msg3()}, + {msg4, rfc3525_msg4()}, + {msg6, rfc3525_msg6()}, + {msg7, rfc3525_msg7()}, + {msg8, rfc3525_msg8()}, + {msg9, rfc3525_msg9()}, + {msg10, rfc3525_msg10()}, + {msg11, rfc3525_msg11()}, + {msg12, rfc3525_msg12()}, + {msg13, rfc3525_msg13()}, + {msg14, rfc3525_msg14()}, + {msg15, rfc3525_msg15()}, + {msg16a, rfc3525_msg16a()}, + {msg16b, rfc3525_msg16b()}, + {msg17a, rfc3525_msg17a()}, + {msg17b, rfc3525_msg17b()}, + {msg17c, rfc3525_msg17c()}, + {msg17d, rfc3525_msg17d()}, + {msg18a, rfc3525_msg18a()}, + {msg18b, rfc3525_msg18b()}, + {msg19, rfc3525_msg19()}, + {msg20, rfc3525_msg20()}, + {msg21a, rfc3525_msg21a()}, + {msg21b, rfc3525_msg21b()}, + {msg22a, rfc3525_msg22a()}, + {msg22b, rfc3525_msg22b()} + ]. + +rfc3525_msgs_display() -> + Msgs = rfc3525_msgs(), + Fun = fun({Name, Msg}) -> + io:format("~w: ~n~s~n~n", [Name, Msg]) + end, + lists:foreach(Fun, Msgs). + +rfc3525_msgs_test() -> + put(dbg,true), + Res = rfc3525_msgs_test(megaco_pretty_text_encoder, [], 2), + erase(dbg), + io:format("~w~n", [Res]). + +rfc3525_msgs_test(Codec, Config, Ver) -> + io:format("-----------------------------------------" + "~ntesting with" + "~n Codec: ~w" + "~n Config: ~w" + "~n Version: ~w" + "~n", [Codec, Config, Ver]), + Msgs = rfc3525_msgs(), + Test = fun({N,M1}) -> + %% io:format("testing ~w: ", [N]), + io:format("~n*** testing ~w *** ~n~s~n", [N,M1]), + Bin1 = erlang:list_to_binary(M1), + case (catch Codec:decode_message(Config, Ver, Bin1)) of + {ok, M2} -> + %% io:format("d", []), + io:format("decoded:~n~p~n", [M2]), + case (catch Codec:encode_message(Config, Ver, M2)) of + {ok, Bin2} when is_binary(Bin2) -> + %% io:format("e~n", []), + io:format("encode: ~n~s~n", [erlang:binary_to_list(Bin2)]), + {N,ok}; + {ok, M3} -> + %% io:format("e~n", []), + io:format("encode: ~n~s~n", [M3]), + {N,ok}; + E -> + io:format("~n~p~n", [E]), + {N,encode_error} + end; + E -> + io:format("~n~p~n", [E]), + {N,decode_error} + end + end, + [Test(M) || M <- Msgs]. + +%% -------------------------- + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +skip(Reason) -> + megaco_codec_test_lib:skip(Reason). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +decode_message(Codec, DynamicDecode, Conf, Bin) -> + megaco_codec_test_lib:decode_message(Codec, DynamicDecode, ?VERSION, + Conf, Bin). +encode_message(Codec, Conf, Msg) -> + megaco_codec_test_lib:encode_message(Codec, ?VERSION, Conf, Msg). + +test_msgs(Codec, DynamicDecode, Conf, Msgs) -> + megaco_codec_test_lib:test_msgs(Codec, DynamicDecode, ?VERSION, Conf, + fun chk_MegacoMessage/2, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +chk_MegacoMessage(M1, M2) -> + ?MSG_LIB:chk_MegacoMessage(M1, M2). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +cre_MegacoMessage(Mess) -> + ?MSG_LIB:cre_MegacoMessage(Mess). + +cre_MegacoMessage(Auth, Mess) -> + ?MSG_LIB:cre_MegacoMessage(Auth, Mess). + +cre_MegacoMessage(V, Mid, Body) -> + Mess = ?MSG_LIB:cre_Message(V, Mid, Body), + cre_MegacoMessage(Mess). + +cre_AuthHeader() -> + SecParmIdx = [239, 205, 171, 137], + SeqNum = [18, 52, 86, 120], + AD = [18, 52, 86, 120, 137, 171, 205, 239, 118, 84, 50, 16], + cre_AuthHeader(SecParmIdx, SeqNum, AD). + +cre_AuthHeader(Idx, Num, D) -> + ?MSG_LIB:cre_AuthenticationHeader(Idx, Num, D). + +cre_Msg(Mid, Body) -> + cre_Msg(?VERSION, Mid, Body). + +cre_Msg(V, Mid, Body) -> + ?MSG_LIB:cre_Message(V, Mid, Body). + +cre_TransId(TransId) -> + ?MSG_LIB:cre_TransactionId(TransId). + +cre_Trans(Trans) -> + ?MSG_LIB:cre_Transaction(Trans). + +cre_TransReq(TransId, Actions) -> + ?MSG_LIB:cre_TransactionRequest(TransId, Actions). + +cre_TransRep(TransId, Actions) -> + ?MSG_LIB:cre_TransactionReply(TransId, Actions). + +cre_TransAck(First, Last) -> + ?MSG_LIB:cre_TransactionAck(First, Last). + +cre_ActReq(CtxId, CmdReqs) -> + ?MSG_LIB:cre_ActionRequest(CtxId, CmdReqs). + +cre_ActRep(CtxId, CmdReps) -> + ?MSG_LIB:cre_ActionReply(CtxId, CmdReps). + +cre_ActRep(CtxId, ED, CR, CmdReps) -> + ?MSG_LIB:cre_ActionReply(CtxId, ED, CR, CmdReps). + +cre_CtxID(Id) -> + ?MSG_LIB:cre_ContextID(Id). + +cre_ContextRequest() -> + ?MSG_LIB:cre_ContextRequest(). + +cre_ContextRequest(A) -> + ?MSG_LIB:cre_ContextRequest(A). + +cre_ContextRequest(A, B) -> + ?MSG_LIB:cre_ContextRequest(A, B). + +cre_ContextRequest(A, B, C) -> + ?MSG_LIB:cre_ContextRequest(A, B, C). + +cre_ContextRequest(A, B, C, D) -> + ?MSG_LIB:cre_ContextRequest(A, B, C, D). + +cre_ContextRequest(A, B, C, D, E) -> + ?MSG_LIB:cre_ContextRequest(A, B, C, D, E). + +cre_ContextAttrAuditRequest() -> + ?MSG_LIB:cre_ContextAttrAuditRequest(). + +% cre_ContextAttrAuditRequest(A) -> +% ?MSG_LIB:cre_ContextAttrAuditRequest(A). + +% cre_ContextAttrAuditRequest(A, B) -> +% ?MSG_LIB:cre_ContextAttrAuditRequest(A, B). + +cre_ContextAttrAuditRequest(A, B, C) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(A, B, C). + +cre_ContextAttrAuditRequest(A, B, C, D) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(A, B, C, D). + +cre_ContextAttrAuditRequest(A, B, C, D, E) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(A, B, C, D, E). + +cre_TopologyRequest(From, To, Dir) -> + ?MSG_LIB:cre_TopologyRequest(From, To, Dir). + +%% Ind Aud related: + +cre_IndAudParam(IAP) -> + ?MSG_LIB:cre_IndAuditParameter(IAP). + +cre_IndAudMediaDesc(D) -> + ?MSG_LIB:cre_IndAudMediaDescriptor(D). + +cre_IndAudStreamDesc(SID, SP) -> + ?MSG_LIB:cre_IndAudStreamDescriptor(SID, SP). + +cre_IndAudStreamParms(LCD) -> + ?MSG_LIB:cre_IndAudStreamParms(LCD). + +cre_IndAudLocalControlDesc(SM, RV, RG, PP) -> + ?MSG_LIB:cre_IndAudLocalControlDescriptor(SM, RV, RG, PP). + +cre_IndAudPropertyParm(Name) -> + ?MSG_LIB:cre_IndAudPropertyParm(Name). + +cre_IndAudTermStateDesc(PP) -> + ?MSG_LIB:cre_IndAudTerminationStateDescriptor(PP). + +cre_IndAudTermStateDesc(PP, EBC, SS) -> + ?MSG_LIB:cre_IndAudTerminationStateDescriptor(PP, EBC, SS). + +cre_IndAudEvsDesc(RID, PN) + when is_integer(RID) -> + ?MSG_LIB:cre_IndAudEventsDescriptor(RID, PN). + +cre_IndAudEvBufDesc(EN, SID) -> + ?MSG_LIB:cre_IndAudEventBufferDescriptor(EN, SID). + +cre_IndAudSigsDesc(D) -> + ?MSG_LIB:cre_IndAudSignalsDescriptor(D). + +cre_IndAudSig(SN) -> + ?MSG_LIB:cre_IndAudSignal(SN). + +cre_IndAudSeqSigList(ID, SL) -> + ?MSG_LIB:cre_IndAudSeqSigList(ID, SL). + +cre_IndAudDigitMapDesc(DMN) -> + ?MSG_LIB:cre_IndAudDigitMapDescriptor(DMN). + +cre_IndAudStatsDesc(SN) -> + ?MSG_LIB:cre_IndAudStatisticsDescriptor(SN). + +cre_IndAudPkgsDesc(PN, PV) -> + ?MSG_LIB:cre_IndAudPackagesDescriptor(PN, PV). + +%% Parameter related +cre_PropParm(Name, Val) -> + ?MSG_LIB:cre_PropertyParm(Name, [Val]). + +cre_PropParm(Name, Vals, Tag, EI) -> + ?MSG_LIB:cre_PropertyParm(Name, Vals, Tag, EI). + + +%% Statistics related +cre_StatsDesc(SPs) -> + ?MSG_LIB:cre_StatisticsDescriptor(SPs). + +cre_StatsParm(Name) -> + ?MSG_LIB:cre_StatisticsParameter(Name). + +cre_StatsParm(Name, Val) -> + ?MSG_LIB:cre_StatisticsParameter(Name, [Val]). + + +% Event related +cre_EvParm(Name, Val) -> + ?MSG_LIB:cre_EventParameter(Name, Val). + +cre_ObsEv(Name, Not) -> + ?MSG_LIB:cre_ObservedEvent(Name, Not). +cre_ObsEv(Name, Not, Par) -> + ?MSG_LIB:cre_ObservedEvent(Name, Par, Not). + +cre_ReqedEv(Name) -> + ?MSG_LIB:cre_RequestedEvent(Name). +cre_ReqedEv(Name, Action) -> + ?MSG_LIB:cre_RequestedEvent(Name, Action). + + +cre_ObsEvsDesc(Id, EvList) -> + ?MSG_LIB:cre_ObservedEventsDescriptor(Id, EvList). + +cre_EvsDesc(Id, EvList) -> + ?MSG_LIB:cre_EventsDescriptor(Id, EvList). + + +%% Service change related +cre_SvcChParm(M, A, R, P) -> + ?MSG_LIB:cre_ServiceChangeParm(M, A, P, R). + +cre_SvcChParm(M, A, R, P, IF) -> + ?MSG_LIB:cre_ServiceChangeParm(M, A, asn1_NOVALUE, P, R, asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE, IF). + +cre_SvcChResParm(A, P) -> + ?MSG_LIB:cre_ServiceChangeResParm(A, P). + +cre_SvcChReq(Tids, P) -> + ?MSG_LIB:cre_ServiceChangeRequest(Tids, P). + +cre_SvcChProf(Name, Ver) -> + ?MSG_LIB:cre_ServiceChangeProfile(Name, Ver). + +cre_SvcChAddr(Tag, Val) -> + ?MSG_LIB:cre_ServiceChangeAddress(Tag, Val). + +cre_SvcChMethod(M) -> + ?MSG_LIB:cre_ServiceChangeMethod(M). + +cre_SvcChRep(Tids, Res) -> + ?MSG_LIB:cre_ServiceChangeReply(Tids, Res). + + +%% Stream related +cre_StreamID(Id) -> + ?MSG_LIB:cre_StreamID(Id). + +cre_StreamParms(Lcd) -> + ?MSG_LIB:cre_StreamParms(Lcd). +cre_StreamParms(Lcd, Ld) -> + ?MSG_LIB:cre_StreamParms(Lcd, Ld). +cre_StreamParms(Lcd, Ld, Rd) -> + ?MSG_LIB:cre_StreamParms(Lcd, Ld, Rd). +cre_StreamParmsL(Ld) -> + ?MSG_LIB:cre_StreamParms(asn1_NOVALUE, Ld, asn1_NOVALUE). +cre_StreamParmsR(Rd) -> + ?MSG_LIB:cre_StreamParms(asn1_NOVALUE, asn1_NOVALUE, Rd). + +cre_StreamDesc(Id, P) -> + ?MSG_LIB:cre_StreamDescriptor(Id, P). + + +%% "Local" related +cre_LocalControlDesc(Mode) -> + ?MSG_LIB:cre_LocalControlDescriptor(Mode). +cre_LocalControlDesc(Mode, Parms) -> + ?MSG_LIB:cre_LocalControlDescriptor(Mode, Parms). + +cre_LocalRemoteDesc(Grps) -> + ?MSG_LIB:cre_LocalRemoteDescriptor(Grps). + + +%% DigitMap related +cre_DigitMapDesc() -> + ?MSG_LIB:cre_DigitMapDescriptor(). +cre_DigitMapDesc(NameOrVal) -> + ?MSG_LIB:cre_DigitMapDescriptor(NameOrVal). +cre_DigitMapDesc(Name, Val) -> + ?MSG_LIB:cre_DigitMapDescriptor(Name, Val). + +cre_DigitMapValue(Body) -> + ?MSG_LIB:cre_DigitMapValue(Body). + +cre_DigitMapValue(Body, Start, Short, Long) -> + ?MSG_LIB:cre_DigitMapValue(Start, Short, Long, Body). + +%% Media related +cre_MediaDesc(SD) when is_record(SD, 'StreamDescriptor') -> + cre_MediaDesc([SD]); +cre_MediaDesc(SDs) -> + ?MSG_LIB:cre_MediaDescriptor(SDs). + + +%% Notify related +cre_NotifyReq(Tids, EvsDesc) -> + ?MSG_LIB:cre_NotifyRequest(Tids, EvsDesc). + +cre_NotifyRep(Tids) -> + ?MSG_LIB:cre_NotifyReply(Tids). + + +%% Subtract related +cre_SubReq(Tids, Desc) -> + ?MSG_LIB:cre_SubtractRequest(Tids, Desc). + + +%% Audit related +cre_AuditDesc(Tokens) -> + ?MSG_LIB:cre_AuditDescriptor(Tokens). + +cre_AuditDesc(Tokens, PropertTokens) -> + ?MSG_LIB:cre_AuditDescriptor(Tokens, PropertTokens). + +cre_AuditReq(Tid, Desc) -> + ?MSG_LIB:cre_AuditRequest(Tid, Desc). + +cre_AuditRes(Tid, Res) -> + ?MSG_LIB:cre_AuditResult(Tid, Res). + +cre_TermAudit(ARP) -> + ?MSG_LIB:cre_TerminationAudit(ARP). + +cre_AuditRetParam(D) -> + ?MSG_LIB:cre_AuditReturnParameter(D). + + +%% AMM/AMMS related +cre_AmmDesc(D) -> + ?MSG_LIB:cre_AmmDescriptor(D). + +cre_AmmReq(Tids, Descs) -> + ?MSG_LIB:cre_AmmRequest(Tids, Descs). + +cre_AmmsReply(Tids) -> + ?MSG_LIB:cre_AmmsReply(Tids). +cre_AmmsReply(Tids, Descs) -> + ?MSG_LIB:cre_AmmsReply(Tids, Descs). + + +%% Command related +cre_Cmd(Tag, Req) -> + ?MSG_LIB:cre_Command(Tag, Req). + +cre_CmdReq(Cmd) -> + ?MSG_LIB:cre_CommandRequest(Cmd). + +cre_CmdRep(Tag, Rep) -> + ?MSG_LIB:cre_CommandReply(Tag, Rep). + + +%% Actions related +cre_ReqedActs(DmName) -> + EDM = ?MSG_LIB:cre_EventDM(DmName), + ?MSG_LIB:cre_RequestedActions(EDM). + + +%% Signal related +cre_SigDir(D) -> + ?MSG_LIB:cre_SignalDirection(D). + +cre_Sig(Name) -> + cre_Sig(Name, []). + +cre_Sig(Name, SPL) -> + ?MSG_LIB:cre_Signal(Name, SPL). + +cre_Sig(Name, Dir, RID) -> + cre_Sig(Name, [], Dir, RID). + +cre_Sig(Name, SPL, Dir, RID) -> + cre_Sig(Name, asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE, + asn1_NOVALUE, SPL, Dir, RID). + +cre_Sig(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID) -> + ?MSG_LIB:cre_Signal(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID). + +cre_SigReq(S) -> + ?MSG_LIB:cre_SignalRequest(S). + +cre_NotifCompl(NC) -> + ?MSG_LIB:cre_NotifyCompletion(NC). + +cre_SigType(ST) -> + ?MSG_LIB:cre_SignalType(ST). + +cre_SigsDesc(D) -> + ?MSG_LIB:cre_SignalsDescriptor(D). + +%% Others +cre_ReqID(RID) -> + ?MSG_LIB:cre_RequestID(RID). + +cre_TimeNot(D,T) -> + ?MSG_LIB:cre_TimeNotation(D, T). + +cre_PkgsItem(Name, Ver) -> + ?MSG_LIB:cre_PackagesItem(Name, Ver). + +cre_BOOLEAN(B) -> + ?MSG_LIB:cre_BOOLEAN(B). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_init(Config) -> + megaco_codec_flex_lib:init(Config). + +flex_finish(Config) -> + megaco_codec_flex_lib:finish(Config). + +flex_scanner_conf(Config) -> + megaco_codec_flex_lib:scanner_conf(Config). + +start_flex_scanner() -> + megaco_codec_flex_lib:start(). + +stop_flex_scanner(Pid) -> + megaco_codec_flex_lib:stop(Pid). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +t(F,A) -> + p(printable(get(severity),trc),trc,F,A). + +d(F,A) -> + p(printable(get(severity),dbg),dbg,F,A). + +l(F,A) -> + p(printable(get(severity),log),log,F,A). + +e(F,A) -> + p(printable(get(severity),err),err,F,A). + + +printable(trc,_) -> + true; +printable(dbg,trc) -> + false; +printable(dbg,_) -> + true; +printable(log,log) -> + true; +printable(log,err) -> + true; +printable(err,err) -> + true; +printable(_,_) -> + false. + + +p(true,L,F,A) -> + io:format("~s:" ++ F ++ "~n", [image_of(L)|A]); +p(_,_,_,_) -> + ok. + +image_of(trc) -> + "TRC"; +image_of(dbg) -> + "DBG"; +image_of(log) -> + "LOG"; +image_of(err) -> + "ERR"; +image_of(L) -> + io_lib:format("~p",[L]). + diff --git a/lib/megaco/test/megaco_codec_prev3b_test.erl b/lib/megaco/test/megaco_codec_prev3b_test.erl new file mode 100644 index 0000000000..b5fe4d2038 --- /dev/null +++ b/lib/megaco/test/megaco_codec_prev3b_test.erl @@ -0,0 +1,7828 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test encoding/decoding (codec) module of Megaco/H.248 +%%---------------------------------------------------------------------- +-module(megaco_codec_prev3b_test). + +%% ---- + +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_prev3b.hrl"). +-include("megaco_test_lib.hrl"). + +%% ---- + +-export([msgs/0]). +-export([rfc3525_msgs_display/0, rfc3525_msgs_test/0]). + +-export([t/0, t/1]). + +-export([all/1, + + text/1, + + pretty/1, + pretty_test_msgs/1, + + compact/1, + compact_test_msgs/1, + + flex_pretty/1, + flex_pretty_init/1, + flex_pretty_finish/1, + flex_pretty_test_msgs/1, + + flex_compact/1, + flex_compact_init/1, + flex_compact_finish/1, + flex_compact_test_msgs/1, + + flex_compact_dm_timers1/1, + flex_compact_dm_timers2/1, + flex_compact_dm_timers3/1, + flex_compact_dm_timers4/1, + flex_compact_dm_timers5/1, + flex_compact_dm_timers6/1, + flex_compact_dm_timers7/1, + flex_compact_dm_timers8/1, + + binary/1, + + bin/1, + bin_test_msgs/1, + + ber/1, + ber_test_msgs/1, + + ber_bin/1, + ber_bin_test_msgs/1, + + per/1, + per_test_msgs/1, + + per_bin/1, + per_bin_test_msgs/1, + + erl_dist/1, + erl_dist_m/1, + erl_dist_m_test_msgs/1, + + tickets/0, + tickets/1, + + compact_tickets/1, + compact_otp4011_msg1/1, + compact_otp4011_msg2/1, + compact_otp4011_msg3/1, + compact_otp4013_msg1/1, + compact_otp4085_msg1/1, + compact_otp4085_msg2/1, + compact_otp4280_msg1/1, + compact_otp4299_msg1/1, + compact_otp4299_msg2/1, + compact_otp4359_msg1/1, + compact_otp4920_msg0/1, + compact_otp4920_msg1/1, + compact_otp4920_msg2/1, + compact_otp4920_msg3/1, + compact_otp4920_msg4/1, + compact_otp4920_msg5/1, + compact_otp4920_msg6/1, + compact_otp4920_msg7/1, + compact_otp4920_msg8/1, + compact_otp4920_msg9/1, + compact_otp4920_msg10/1, + compact_otp4920_msg11/1, + compact_otp4920_msg12/1, + compact_otp4920_msg20/1, + compact_otp4920_msg21/1, + compact_otp4920_msg22/1, + compact_otp4920_msg23/1, + compact_otp4920_msg24/1, + compact_otp4920_msg25/1, + compact_otp5186_msg01/1, + compact_otp5186_msg02/1, + compact_otp5186_msg03/1, + compact_otp5186_msg04/1, + compact_otp5186_msg05/1, + compact_otp5186_msg06/1, + compact_otp5793_msg01/1, + compact_otp5836_msg01/1, + compact_otp5993_msg01/1, + compact_otp5993_msg02/1, + compact_otp5993_msg03/1, + compact_otp6017_msg01/1, + compact_otp6017_msg02/1, + compact_otp6017_msg03/1, + + flex_compact_tickets/1, + flex_compact_otp7431_msg01/1, + flex_compact_otp7431_msg02/1, + flex_compact_otp7431_msg03/1, + flex_compact_otp7431_msg04/1, + flex_compact_otp7431_msg05/1, + flex_compact_otp7431_msg06/1, + flex_compact_otp7431_msg07/1, + + pretty_tickets/1, + pretty_otp4632_msg1/1, + pretty_otp4632_msg2/1, + pretty_otp4632_msg3/1, + pretty_otp4632_msg4/1, + pretty_otp4710_msg1/1, + pretty_otp4710_msg2/1, + pretty_otp4945_msg1/1, + pretty_otp4945_msg2/1, + pretty_otp4945_msg3/1, + pretty_otp4945_msg4/1, + pretty_otp4945_msg5/1, + pretty_otp4945_msg6/1, + pretty_otp4949_msg1/1, + pretty_otp4949_msg2/1, + pretty_otp4949_msg3/1, + pretty_otp5042_msg1/1, + pretty_otp5068_msg1/1, + pretty_otp5085_msg1/1, + pretty_otp5085_msg2/1, + pretty_otp5085_msg3/1, + pretty_otp5085_msg4/1, + pretty_otp5085_msg5/1, + pretty_otp5085_msg6/1, + pretty_otp5085_msg7/1, + pretty_otp5085_msg8/1, + pretty_otp5600_msg1/1, + pretty_otp5600_msg2/1, + pretty_otp5601_msg1/1, + pretty_otp5793_msg01/1, + pretty_otp5803_msg01/1, + pretty_otp5803_msg02/1, + pretty_otp5805_msg01/1, + pretty_otp5836_msg01/1, + pretty_otp5882_msg01/1, + pretty_otp6490_msg01/1, + pretty_otp6490_msg02/1, + pretty_otp6490_msg03/1, + pretty_otp6490_msg04/1, + pretty_otp6490_msg05/1, + pretty_otp6490_msg06/1, + pretty_otp7671_msg01/1, + pretty_otp7671_msg02/1, + pretty_otp7671_msg03/1, + pretty_otp7671_msg04/1, + pretty_otp7671_msg05/1, + pretty_otp8114_msg01/1, + + flex_pretty_tickets/1, + flex_pretty_otp5042_msg1/1, + flex_pretty_otp5085_msg1/1, + flex_pretty_otp5085_msg2/1, + flex_pretty_otp5085_msg3/1, + flex_pretty_otp5085_msg4/1, + flex_pretty_otp5085_msg5/1, + flex_pretty_otp5085_msg6/1, + flex_pretty_otp5085_msg7/1, + flex_pretty_otp5085_msg8/1, + flex_pretty_otp5600_msg1/1, + flex_pretty_otp5600_msg2/1, + flex_pretty_otp5601_msg1/1, + flex_pretty_otp5793_msg01/1, + flex_pretty_otp5803_msg01/1, + flex_pretty_otp5803_msg02/1, + flex_pretty_otp5805_msg01/1, + flex_pretty_otp5836_msg01/1, + flex_pretty_otp7431_msg01/1, + flex_pretty_otp7431_msg02/1, + flex_pretty_otp7431_msg03/1, + flex_pretty_otp7431_msg04/1, + flex_pretty_otp7431_msg05/1, + flex_pretty_otp7431_msg06/1, + flex_pretty_otp7431_msg07/1, + + init_per_testcase/2, fin_per_testcase/2]). + +-export([display_text_messages/0, generate_text_messages/0]). + + +%% ---- + +-define(V3, prev3b). +-define(EC_V3, {version3,?V3}). +-define(EC, [?EC_V3]). + +-define(VERSION, 3). +-define(VERSION_STR, "3"). +-define(MSG_LIB, megaco_test_msg_prev3b_lib). +-define(DEFAULT_PORT, 55555). +-define(MG1_MID_NO_PORT, {ip4Address, + #'IP4Address'{address = [124, 124, 124, 222]}}). +-define(MG1_MID, {ip4Address, #'IP4Address'{address = [124, 124, 124, 222], + portNumber = ?DEFAULT_PORT}}). +-define(MG2_MID, {ip4Address, #'IP4Address'{address = [125, 125, 125, 111], + portNumber = ?DEFAULT_PORT}}). +-define(MGC_MID, {ip4Address, #'IP4Address'{address = [123, 123, 123, 4], + portNumber = ?DEFAULT_PORT}}). + +-define(A4444, ["11111111", "00000000", "00000000"]). +-define(A4445, ["11111111", "00000000", "11111111"]). +-define(A5555, ["11111111", "11111111", "00000000"]). +-define(A5556, ["11111111", "11111111", "11111111"]). + + +%% ---- + +display_text_messages() -> + Msgs = msgs1(text) ++ msgs4(text) ++ msgs5(text) ++ msgs6(text), + %% Msgs = msgs1(text), + %% Msgs = msgs4(text), + %% Msgs = msgs5(text), + %% Msgs = msgs6(text), + megaco_codec_test_lib:display_text_messages(?VERSION, ?EC, Msgs). + + +generate_text_messages() -> + Msgs = msgs1(text) ++ msgs4(text) ++ msgs5(text) ++ msgs6(text), + megaco_codec_test_lib:generate_text_messages(?V3, ?VERSION, ?EC, Msgs). + + +%% ---- + + +expand(RootCase) -> + expand([RootCase], []). + +expand([], Acc) -> + lists:flatten(lists:reverse(Acc)); +expand([Case|Cases], Acc) -> + case (catch apply(?MODULE,Case,[suite])) of + [] -> + expand(Cases, [Case|Acc]); + C when is_list(C) -> + expand(Cases, [expand(C, [])|Acc]); + _ -> + expand(Cases, [Case|Acc]) + end. + + +%% ---- + +tickets() -> + Flag = process_flag(trap_exit, true), + Cases = expand(tickets), + Fun = fun(Case) -> + C = init_per_testcase(Case, [{tc_timeout, + timer:minutes(10)}]), + io:format("Eval ~w~n", [Case]), + Result = + case (catch apply(?MODULE, Case, [C])) of + {'EXIT', Reason} -> + io:format("~n~p exited:~n ~p~n", + [Case, Reason]), + {error, {Case, Reason}}; + Res -> + Res + end, + fin_per_testcase(Case, C), + Result + end, + process_flag(trap_exit, Flag), + lists:map(Fun, Cases). + + +%% ---- + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + +init_per_testcase(Case, Config) -> + %% CaseString = io_lib:format("~p", [Case]), + C = + case lists:suffix("time_test", atom_to_list(Case)) of + true -> + [{tc_timeout, timer:minutes(10)}|Config]; + false -> + put(verbosity,trc), + Config + end, + megaco_test_lib:init_per_testcase(Case, C). + +fin_per_testcase(Case, Config) -> + erase(verbosity), + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top test case + +all(suite) -> + [ + text, + binary, + erl_dist, + tickets + ]. + +text(suite) -> + [ + pretty, + flex_pretty, + compact, + flex_compact + ]. + +binary(suite) -> + [ + bin, + ber, + ber_bin, + per, + per_bin + ]. + +erl_dist(suite) -> + [ + erl_dist_m + ]. + +pretty(suite) -> + [ + pretty_test_msgs + ]. + + +compact(suite) -> + [ + compact_test_msgs + ]. + + +flex_pretty(suite) -> + {req, [], + {conf, flex_pretty_init, flex_pretty_cases(), flex_pretty_finish}}. + +flex_pretty_cases() -> + [ + flex_pretty_test_msgs + ]. + +flex_compact(suite) -> + {req, [], + {conf, flex_compact_init, flex_compact_cases(), flex_compact_finish}}. + +flex_compact_cases() -> + [ + flex_compact_test_msgs, + flex_compact_dm_timers1, + flex_compact_dm_timers2, + flex_compact_dm_timers3, + flex_compact_dm_timers4, + flex_compact_dm_timers5, + flex_compact_dm_timers6, + flex_compact_dm_timers7, + flex_compact_dm_timers8 + ]. + + +bin(suite) -> + [ + bin_test_msgs + ]. + + +ber(suite) -> + [ + ber_test_msgs + ]. + + +ber_bin(suite) -> + [ + ber_bin_test_msgs + ]. + + +per(suite) -> + [ + per_test_msgs + ]. + + +%% Support for per_bin was added to ASN.1 as of version +%% 1.3.2 (R8). And later merged into 1.3.1.3 (R7). These +%% releases are identical (as far as I know). +%% +per_bin(suite) -> + [ + per_bin_test_msgs + ]. + + +erl_dist_m(suite) -> + [ + erl_dist_m_test_msgs + ]. + +tickets(suite) -> + [ + compact_tickets, + flex_compact_tickets, + pretty_tickets, + flex_pretty_tickets + ]. + + +compact_tickets(suite) -> + [ + compact_otp4011_msg1, + compact_otp4011_msg2, + compact_otp4011_msg3, + compact_otp4013_msg1, + compact_otp4085_msg1, + compact_otp4085_msg2, + compact_otp4280_msg1, + compact_otp4299_msg1, + compact_otp4299_msg2, + compact_otp4359_msg1, + compact_otp4920_msg0, + compact_otp4920_msg1, + compact_otp4920_msg2, + compact_otp4920_msg3, + compact_otp4920_msg4, + compact_otp4920_msg5, + compact_otp4920_msg6, + compact_otp4920_msg7, + compact_otp4920_msg8, + compact_otp4920_msg9, + compact_otp4920_msg10, + compact_otp4920_msg11, + compact_otp4920_msg12, + compact_otp4920_msg20, + compact_otp4920_msg21, + compact_otp4920_msg22, + compact_otp4920_msg23, + compact_otp4920_msg24, + compact_otp4920_msg25, + compact_otp5186_msg01, + compact_otp5186_msg02, + compact_otp5186_msg03, + compact_otp5186_msg04, + compact_otp5186_msg05, + compact_otp5186_msg06, + compact_otp5793_msg01, + compact_otp5836_msg01, + compact_otp5993_msg01, + compact_otp5993_msg02, + compact_otp5993_msg03, + compact_otp6017_msg01, + compact_otp6017_msg02, + compact_otp6017_msg03 + ]. + +flex_compact_tickets(suite) -> + {req, [], + {conf, flex_compact_init, flex_compact_tickets_cases(), + flex_compact_finish}}. + +flex_compact_tickets_cases() -> + [ + flex_compact_otp7431_msg01, + flex_compact_otp7431_msg02, + flex_compact_otp7431_msg03, + flex_compact_otp7431_msg04, + flex_compact_otp7431_msg05, + flex_compact_otp7431_msg06, + flex_compact_otp7431_msg07 + ]. + +pretty_tickets(suite) -> + [ + pretty_otp4632_msg1, + pretty_otp4632_msg2, + pretty_otp4632_msg3, + pretty_otp4632_msg4, + pretty_otp4710_msg1, + pretty_otp4710_msg2, + pretty_otp4945_msg1, + pretty_otp4945_msg2, + pretty_otp4945_msg3, + pretty_otp4945_msg4, + pretty_otp4945_msg5, + pretty_otp4945_msg6, + pretty_otp4949_msg1, + pretty_otp4949_msg2, + pretty_otp4949_msg3, + pretty_otp5042_msg1, + pretty_otp5068_msg1, + pretty_otp5085_msg1, + pretty_otp5085_msg2, + pretty_otp5085_msg3, + pretty_otp5085_msg4, + pretty_otp5085_msg5, + pretty_otp5085_msg6, + pretty_otp5085_msg7, + pretty_otp5085_msg8, + pretty_otp5600_msg1, + pretty_otp5600_msg2, + pretty_otp5601_msg1, + pretty_otp5793_msg01, + pretty_otp5803_msg01, + pretty_otp5803_msg02, + pretty_otp5805_msg01, + pretty_otp5836_msg01, + pretty_otp5882_msg01, + pretty_otp6490_msg01, + pretty_otp6490_msg02, + pretty_otp6490_msg03, + pretty_otp6490_msg04, + pretty_otp6490_msg05, + pretty_otp6490_msg06, + pretty_otp7671_msg01, + pretty_otp7671_msg02, + pretty_otp7671_msg03, + pretty_otp7671_msg04, + pretty_otp7671_msg05, + pretty_otp8114_msg01 + ]. + +flex_pretty_tickets(suite) -> + {req, [], + {conf, flex_pretty_init, flex_pretty_tickets_cases(), + flex_pretty_finish}}. + +flex_pretty_tickets_cases() -> + [ + flex_pretty_otp5042_msg1, + flex_pretty_otp5085_msg1, + flex_pretty_otp5085_msg2, + flex_pretty_otp5085_msg3, + flex_pretty_otp5085_msg4, + flex_pretty_otp5085_msg5, + flex_pretty_otp5085_msg6, + flex_pretty_otp5085_msg7, + flex_pretty_otp5085_msg8, + flex_pretty_otp5600_msg1, + flex_pretty_otp5600_msg2, + flex_pretty_otp5601_msg1, + flex_pretty_otp5793_msg01, + flex_pretty_otp5803_msg01, + flex_pretty_otp5803_msg02, + flex_pretty_otp5805_msg01, + flex_pretty_otp5836_msg01, + flex_pretty_otp7431_msg01, + flex_pretty_otp7431_msg02, + flex_pretty_otp7431_msg03, + flex_pretty_otp7431_msg04, + flex_pretty_otp7431_msg05, + flex_pretty_otp7431_msg06, + flex_pretty_otp7431_msg07 + ]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +pretty_test_msgs(suite) -> + []; +pretty_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(text) ++ msgs2(text) ++ msgs3(text) ++ msgs4(text) ++ + msgs5(text) ++ msgs6(text), + %% Msgs = msgs1(text), + %% Msgs = msgs2(text), + %% Msgs = msgs3(text), + %% Msgs = msgs4(text), + %% Msgs = msgs5(text), + %% Msgs = msgs6(text), + DynamicDecode = false, + test_msgs(megaco_pretty_text_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_pretty_init(Config) -> + flex_init(Config). + +flex_pretty_finish(Config) -> + flex_finish(Config). + +flex_pretty_test_msgs(suite) -> + []; +flex_pretty_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(text) ++ msgs2(text) ++ msgs3(text) ++ msgs4(text) ++ + msgs5(text) ++ msgs6(text), + Conf = flex_scanner_conf(Config), + DynamicDecode = false, + test_msgs(megaco_pretty_text_encoder, DynamicDecode, [?EC_V3,Conf], Msgs). + + +flex_pretty_otp5042_msg1(suite) -> + []; +flex_pretty_otp5042_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5042_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp5042_msg1(), + Bin0 = list_to_binary(Msg0), + case pretty_decode_message(false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {_, _Mod, {bad_timeStamp, TimeStamp}} -> + exit({bad_timeStamp, TimeStamp}); + _ -> + io:format("flex_pretty_otp5042_msg1 -> " + "~n Reason: ~w" + "~n", [Reason]), + exit({unexpected_decode_result, Reason}) + end; + {ok, M} -> + t("flex_pretty_otp5042_msg1 -> successfull decode:" + "~n~p", [M]), + ok + end. + + +flex_pretty_otp5085_msg1(suite) -> + []; +flex_pretty_otp5085_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg1(), [Conf]). + +flex_pretty_otp5085_msg2(suite) -> + []; +flex_pretty_otp5085_msg2(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(error, pretty_otp5085_msg2(), [Conf]). + +flex_pretty_otp5085_msg3(suite) -> + []; +flex_pretty_otp5085_msg3(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg3(), [Conf]). + +flex_pretty_otp5085_msg4(suite) -> + []; +flex_pretty_otp5085_msg4(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg4(), [Conf]). + +flex_pretty_otp5085_msg5(suite) -> + []; +flex_pretty_otp5085_msg5(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg5(), [Conf]). + +flex_pretty_otp5085_msg6(suite) -> + []; +flex_pretty_otp5085_msg6(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg6(), [Conf]). + +flex_pretty_otp5085_msg7(suite) -> + []; +flex_pretty_otp5085_msg7(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg7(), [Conf]). + +flex_pretty_otp5085_msg8(suite) -> + []; +flex_pretty_otp5085_msg8(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg8 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg8(), [Conf]). + +flex_pretty_otp5600_msg1(suite) -> + []; +flex_pretty_otp5600_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5600_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5600(ok, pretty_otp5600_msg1(), [Conf]). + +flex_pretty_otp5600_msg2(suite) -> + []; +flex_pretty_otp5600_msg2(Config) when is_list(Config) -> + d("flex_pretty_otp5600_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5600(ok, pretty_otp5600_msg2(), [Conf]). + +flex_pretty_otp5601_msg1(suite) -> + []; +flex_pretty_otp5601_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5601_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5601(ok, pretty_otp5601_msg1(), [Conf]). + + +flex_pretty_otp5793_msg01(suite) -> + []; +flex_pretty_otp5793_msg01(Config) when is_list(Config) -> + d("flex_pretty_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5793(ok, pretty_otp5793_msg1(), [Conf]). + + +flex_pretty_otp5803_msg01(suite) -> + []; +flex_pretty_otp5803_msg01(Config) when is_list(Config) -> + d("flex_pretty_otp5803_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), +%% put(severity,trc), +%% put(dbg,true), + Conf = flex_scanner_conf(Config), + pretty_otp5803(pretty_otp5803_msg1(), [Conf]). + +flex_pretty_otp5803_msg02(suite) -> + []; +flex_pretty_otp5803_msg02(Config) when is_list(Config) -> + d("flex_pretty_otp5803_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), +%% put(severity,trc), +%% put(dbg,true), + Conf = flex_scanner_conf(Config), + pretty_otp5803(pretty_otp5803_msg2(), [Conf]). + + +flex_pretty_otp5805_msg01(suite) -> + []; +flex_pretty_otp5805_msg01(Config) when is_list(Config) -> + d("flex_pretty_otp5805_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), +%% put(severity,trc), +%% put(dbg,true), + Conf = flex_scanner_conf(Config), + pretty_otp5805(pretty_otp5805_msg1(), [Conf]). + + +flex_pretty_otp5836_msg01(suite) -> + []; +flex_pretty_otp5836_msg01(Config) when is_list(Config) -> + d("flex_pretty_otp5836_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), +%% put(severity,trc), +%% put(dbg,true), + Conf = flex_scanner_conf(Config), + pretty_otp5836(compact_otp5836_msg1(), [Conf]). + + +flex_pretty_otp7431_msg01(suite) -> + []; +flex_pretty_otp7431_msg01(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(ok, flex_pretty_otp7431_msg1(), [Conf]). + +flex_pretty_otp7431_msg02(suite) -> + []; +flex_pretty_otp7431_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp7431_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg2(), [Conf]). + +flex_pretty_otp7431_msg03(suite) -> + []; +flex_pretty_otp7431_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp7431_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg3(), [Conf]). + +flex_pretty_otp7431_msg04(suite) -> + []; +flex_pretty_otp7431_msg04(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg04 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg4(), [Conf]). + +flex_pretty_otp7431_msg05(suite) -> + []; +flex_pretty_otp7431_msg05(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg05 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg5(), [Conf]). + +flex_pretty_otp7431_msg06(suite) -> + []; +flex_pretty_otp7431_msg06(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg06 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg6(), [Conf]). + +flex_pretty_otp7431_msg07(suite) -> + []; +flex_pretty_otp7431_msg07(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg07 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg7(), [Conf]). + +flex_pretty_otp7431(Expected, Msg, Conf) -> + otp7431(Expected, megaco_pretty_text_encoder, Msg, Conf). + +otp7431(Expected, Codec, Msg0, Conf) -> + Bin0 = list_to_binary(Msg0), + case decode_message(Codec, false, Conf, Bin0) of + {ok, _Msg1} when Expected =:= ok -> + io:format(" decoded", []); + {error, {bad_property_parm, Reason}} when (Expected =:= error) andalso + is_list(Reason) -> + io:format("expected result: ~s", [Reason]), + ok; + Else -> + io:format("unexpected result", []), + exit({unexpected_decode_result, Else}) + end. + + +flex_pretty_otp7431_msg1() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a=recvonly + } ; RTP profile for G.723.1 is 4 + } + } + } + } + }". + +flex_pretty_otp7431_msg2() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a= } + } + } + } + } + }". + +flex_pretty_otp7431_msg3() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a } + } + } + } + } + }". + +flex_pretty_otp7431_msg4() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a} + } + } + } + } + }". + +flex_pretty_otp7431_msg5() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v= } + } + } + } + } + }". + +flex_pretty_otp7431_msg6() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v } + } + } + } + } + }". + +flex_pretty_otp7431_msg7() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v} + } + } + } + } + }". + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +compact_test_msgs(suite) -> + []; +compact_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(text) ++ msgs2(text) ++ msgs3(text) ++ msgs4(text) ++ + msgs5(text) ++ msgs6(text), + %% Msgs = msgs6(text), + DynamicDecode = false, + test_msgs(megaco_compact_text_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_compact_init(Config) -> + flex_init(Config). + +flex_compact_finish(Config) -> + flex_finish(Config). + +flex_compact_test_msgs(suite) -> + []; +flex_compact_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(text) ++ msgs2(text) ++ msgs3(text) ++ msgs4(text) ++ + msgs5(text) ++ msgs6(text), + Conf = flex_scanner_conf(Config), + DynamicDecode = true, + test_msgs(megaco_compact_text_encoder, DynamicDecode, [?EC_V3,Conf], Msgs). + + +flex_compact_dm_timers1(suite) -> + []; +flex_compact_dm_timers1(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("1", "2", "3"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers1 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({1,2,3}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers2(suite) -> + []; +flex_compact_dm_timers2(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("02", "03", "04"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers2 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({2,3,4}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers3(suite) -> + []; +flex_compact_dm_timers3(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("1", "02", "31"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers3 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({1,2,31}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers4(suite) -> + []; +flex_compact_dm_timers4(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("10", "21", "99"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers4 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({10,21,99}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers5(suite) -> + []; +flex_compact_dm_timers5(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("99", "23", "11"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers5 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({99,23,11}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers6(suite) -> + []; +flex_compact_dm_timers6(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("77", "09", "1"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers6 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({77,9,1}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers7(suite) -> + []; +flex_compact_dm_timers7(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("77", "09", "1", "99"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers7 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({77,9,1,99}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers8(suite) -> + []; +flex_compact_dm_timers8(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("01", "09", "01", "02"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers8 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({1,9,1,2}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +build_dm_timers_message(T, S, L) -> + TMRs = lists:flatten(io_lib:format("T:~s,S:~s,L:~s", [T, S, L])), + build_dm_timers_message(TMRs). + +build_dm_timers_message(T, S, L, Z) -> + TMRs = lists:flatten(io_lib:format("T:~s,S:~s,L:~s,Z:~s", [T, S, L,Z])), + build_dm_timers_message(TMRs). + +build_dm_timers_message(TMRs) -> + M = io_lib:format("!/" ?VERSION_STR " [123.123.123.4]:55555\nT=10001{C=-{MF=11111111/00000000/00000000{E=2223{al/on,dd/ce{DM=dialplan00}},SG{cg/rt},DM=dialplan00{~s,(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)}}}}", [TMRs]), + lists:flatten(M). + + +verify_dm_timers(TMRs, #'MegacoMessage'{mess = Mess}) -> + #'Message'{messageBody = Body} = Mess, + case get_dm_timers(Body) of + TMRs -> + ok; + {error, Reason} -> + exit({invalid_timer, {TMRs, Reason}}); + TMRs1 -> + exit({invalid_timer_values, {TMRs, TMRs1}}) + end. + +get_dm_timers({transactions, T}) when is_list(T) -> + get_dm_timers1(T); +get_dm_timers(Other) -> + {error, {invalid_transactions, Other}}. + +get_dm_timers1([{transactionRequest,T}|Ts]) + when is_record(T,'TransactionRequest') -> + case get_dm_timers2(T) of + {ok, Timers} -> + Timers; + _ -> + get_dm_timers1(Ts) + end; +get_dm_timers1([_|Ts]) -> + get_dm_timers1(Ts); +get_dm_timers1([]) -> + {error, {no_timers, 'TransactionRequest'}}. + + +get_dm_timers2(#'TransactionRequest'{actions = Actions}) when is_list(Actions) -> + get_dm_timers3(Actions). + + +get_dm_timers3([#'ActionRequest'{commandRequests = Cmds}|Ars]) when is_list(Cmds) -> + case get_dm_timers4(Cmds) of + {ok, Timers} -> + {ok, Timers}; + _ -> + get_dm_timers3(Ars) + end; +get_dm_timers3([_|Ars]) -> + get_dm_timers3(Ars); +get_dm_timers3([]) -> + {error, {no_timers, 'ActionRequest'}}. + +get_dm_timers4([#'CommandRequest'{command = Cmd}|Cmds]) -> + case get_dm_timers5(Cmd) of + {ok, Timers} -> + {ok, Timers}; + _ -> + get_dm_timers4(Cmds) + end; +get_dm_timers4([_|Cmds]) -> + get_dm_timers4(Cmds); +get_dm_timers4([]) -> + {error, {no_timers, 'CommandRequest'}}. + + +get_dm_timers5({modReq, #'AmmRequest'{descriptors = Descriptors}}) -> + get_dm_timers6(Descriptors); +get_dm_timers5(R) -> + {error, {no_modReq, R}}. + + +get_dm_timers6([{digitMapDescriptor, #'DigitMapDescriptor'{digitMapValue = Val}}|_]) -> + case Val of + #'DigitMapValue'{startTimer = T, + shortTimer = S, + longTimer = L, + durationTimer = asn1_NOVALUE} -> + {ok, {T, S, L}}; + #'DigitMapValue'{startTimer = T, + shortTimer = S, + longTimer = L, + durationTimer = Z} -> + {ok, {T, S, L, Z}}; + _ -> + {error, no_value_in_dm} + end; +get_dm_timers6([_|Descs]) -> + get_dm_timers6(Descs); +get_dm_timers6([]) -> + {error, {no_timers, descriptors}}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bin_test_msgs(suite) -> + []; +bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(binary) ++ msgs4(binary) ++ msgs5(binary) ++ msgs6(binary), + %% Msgs = msgs5(binary), + DynamicDecode = false, + test_msgs(megaco_binary_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ber_test_msgs(suite) -> + []; +ber_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(binary) ++ msgs4(binary) ++ msgs5(binary) ++ msgs6(binary), + %% Msgs = msgs6(binary), + DynamicDecode = false, + test_msgs(megaco_ber_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ber_bin_test_msgs(suite) -> + []; +ber_bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(binary) ++ msgs4(binary) ++ msgs5(binary) ++ msgs6(binary), + DynamicDecode = true, + test_msgs(megaco_ber_bin_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +per_test_msgs(suite) -> + []; +per_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(binary) ++ msgs4(binary) ++ msgs5(binary) ++ msgs6(binary), + DynamicDecode = false, + test_msgs(megaco_per_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +per_bin_test_msgs(suite) -> + []; +per_bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(binary) ++ msgs4(binary) ++ msgs5(binary) ++ msgs6(binary), + DynamicDecode = false, + test_msgs(megaco_per_bin_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +erl_dist_m_test_msgs(suite) -> + []; +erl_dist_m_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(erlang) ++ + msgs2(erlang) ++ + msgs3(erlang) ++ + msgs4(erlang) ++ + msgs5(erlang) ++ + msgs6(erlang), + DynamicDecode = false, + Conf = [megaco_compressed], + test_msgs(megaco_erl_dist_encoder, DynamicDecode, Conf, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +%% Ticket test cases: + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg1(suite) -> + []; +compact_otp4011_msg1(Config) when is_list(Config) -> +% put(severity,trc), +% put(dbg,true), + d("compact_otp4011_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR " ML T=233350{C=${A=stedevice/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SR}}}}}", + ok = compact_otp4011(M), +% erase(severity), +% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg2(suite) -> + []; +compact_otp4011_msg2(Config) when is_list(Config) -> + d("compact_otp4011_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR " ML T=233350{C=${A=stedevice/01{M{O{MO=SO,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SR}}}}}", +% put(severity,trc), +% put(dbg,true), + ok = compact_otp4011(M). + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg3(suite) -> + []; +compact_otp4011_msg3(Config) when is_list(Config) -> + d("compact_otp4011_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR " ML T=233350{C=${A=stedevice/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SO}}}}}", + %% put(severity,trc), + %% put(dbg,true), + ok = compact_otp4011(M). + + +compact_otp4011(M) -> + d("compact_otp4011 -> entry with" + "~n M: '~s'", [M]), + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, _} -> + exit({decoded_erroneous_message,M}); + {error, Error} when is_list(Error) -> % Expected result + d("compact_otp4011 -> expected error result (so far)", []), + case lists:keysearch(reason,1,Error) of + {value, {reason,Reason}} -> + d("compact_otp4011 -> expected error: " + "~n Reason: ~p", [Reason]), + case Reason of + {0, megaco_text_parser_prev3b, + {do_merge_control_streamParms, [A,B]}} + when is_list(A) andalso is_record(B, 'LocalControlDescriptor') -> + case lists:keysearch(mode,1,A) of + {value, {mode, _Mode}} + when B#'LocalControlDescriptor'.streamMode =/= asn1_NOVALUE -> + d("compact_otp4011 -> expected error",[]), + ok; + Other -> + exit({unexpected_mode_reason, {A,B,Other}}) + end; + Other -> + exit({unexpected_reason, Other}) + end; + + false -> + d("compact_otp4011 -> OUPS, wrong kind of error", []), + exit({unexpected_result, Error}) + end; + Else -> + d("compact_otp4011 -> unexpected decode result: ~p", [Else]), + exit({unexpected_decode_result, Else}) + end. + + +%% -------------------------------------------------------------- +%% Note that this decode SHALL fail, because of the misspelled +%% MEGCAO instead of the correct MEGACO. +compact_otp4013_msg1(suite) -> + []; +compact_otp4013_msg1(Config) when is_list(Config) -> + d("compact_otp4013_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "MEGCAO/3 MG1 T=12345678{C=-{SC=root{SV{MT=RS,RE=901}}}}", + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, _} -> + exit({decoded_erroneous_message,M}); + {error, Reason} when is_list(Reason) -> + {value, {reason, no_version_found, _}} = + lists:keysearch(reason, 1, Reason), + {value, {token, [{'SafeChars',_,"megcao/3"}|_]}} = + lists:keysearch(token, 1, Reason), + ok; + Else -> + exit({unexpected_decode_result,Else}) + end. + + + +%% -------------------------------------------------------------- +%% +%% +compact_otp4085_msg1(suite) -> + []; +compact_otp4085_msg1(Config) when is_list(Config) -> + d("compact_otp4085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = compact_otp4085_erroneous_msg(), + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, M} -> + exit({decoded_erroneous_message,M}); + {error, Error} when is_list(Error) -> % Expected result + t("compact_otp4085_msg1 -> decode failed", []), + case lists:keysearch(reason, 1, Error) of + {value, {reason,{999999, Module, Crap}}} -> + t("compact_otp4085_msg1 -> THE ACTUAL ERROR: " + "~n LINE NUMBER: 999999" + "~n Module: ~p" + "~n Crap: ~p", [Module, Crap]), + %% ok; + exit({decode_failed_999999, Module, Crap}); + {value, {reason,{Line, Module, Crap}}} -> + t("compact_otp4085_msg1 -> Expected: " + "~n Line: ~p" + "~n Module: ~p" + "~n Crap: ~p", [Line, Module, Crap]), + ok; + false -> + exit({unexpected_result, Error}) + end; + Else -> + exit({unexpected_decode_result, Else}) + end. + + +%% -------------------------------------------------------------- +%% This test case is just to show that the message used in +%% compact_otp4085_msg1 is actually ok when you add '}' at the end. +compact_otp4085_msg2(suite) -> + []; +compact_otp4085_msg2(Config) when is_list(Config) -> + d("compact_otp4085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M1 = compact_otp4085_erroneous_msg() ++ "}", + Bin = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, M2} -> + l("compact_otp4085_msg1 -> successfull decode" + "~n M2: ~p", [M2]), + ok; + Else -> + e("compact_otp4085_msg1 -> decode error" + "~n Else: ~p", [Else]), + exit({unexpected_decode_result,Else}) + end. + + +%% This message lack the ending parentesis (}). +compact_otp4085_erroneous_msg() -> + M = "!/" + ?VERSION_STR + " ML T=11223342{C=${A=${M{O{MO=SR,RV=OFF,RG=OFF},L{v=0," + "c=ATM NSAP $ ," + "a=eecid:$ ," + "m=audio - AAL1/ATMF -," + "}}},A=stee1181/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=off}}}}", + M. + +%% -------------------------------------------------------------- +%% +%% +compact_otp4280_msg1(suite) -> + []; +compact_otp4280_msg1(Config) when is_list(Config) -> + d("compact_otp4280_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Bin = list_to_binary(compact_otp4280_msg()), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, _Msg} -> + ok; + {error, Error} when is_list(Error) -> + t("compact_otp4280_msg1 -> decode failed", []), + case lists:keysearch(reason, 1, Error) of + {value, {reason,{Line, Module, Reason} = R}} -> + t("compact_otp4280_msg1 -> " + "~n Line: ~w" + "~n Module: ~w" + "~n Reason: ~w", [Line, Module, Reason]), + exit({decode_failed, R}); + false -> + exit({unexpected_result, Error}) + end; + Else -> + exit({unexpected_decode_result, Else}) + end. + +compact_otp4280_msg() -> + M = "!/" + ?VERSION_STR + " mgw1 P=71853646{C=-{AV=root{M{TS{root/maxnumberofcontexts=49500," + "root/maxterminationspercontext=2,root/normalmgexecutiontime=200," + "root/normalmgcexecutiontime=150," + "root/provisionalresponsetimervalue=2000,BF=OFF,SI=IV}}}}}", + M. + + +%% -------------------------------------------------------------- +%% This ticket is about comments in a message +compact_otp4299_msg1(suite) -> + []; +compact_otp4299_msg1(Config) when is_list(Config) -> + d("compact_otp4299_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Bin = list_to_binary(compact_otp4299_msg()), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, _Msg} -> + ok; + + {error, Reason} -> + exit({decode_error, Reason}); + + Else -> + exit({unexpected_decode_result, Else}) + end. + + +%% Same message, but this time decoded using the flex scanner +compact_otp4299_msg2(suite) -> + []; +compact_otp4299_msg2(Config) when is_list(Config) -> + d("compact_otp4299_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + + {Pid, Conf} = compact_otp4299_msg2_init(), + + %% put(severity,trc), + %% put(dbg,true), + + M1 = compact_otp4299_msg(), + d("compact_otp4299_msg2 -> M1: ~n~s", [M1]), + Bin = list_to_binary(M1), + Res = decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], Bin), + compact_otp4299_msg2_finish(Pid), + + case Res of + {ok, M2} -> + d("compact_otp4299_msg2 -> M2: ~n~p", [M2]), + ok; + + {error, Reason} -> + exit({decode_error, Reason}); + + Else -> + exit({unexpected_decode_result, Else}) + end. + + +compact_otp4299_msg2_init() -> + Flag = process_flag(trap_exit, true), + Res = (catch start_flex_scanner()), + process_flag(trap_exit, Flag), + case Res of + {error, Reason} -> + skip(Reason); + {ok, FlexConfig} -> + FlexConfig + end. + +compact_otp4299_msg2_finish(Pid) -> + stop_flex_scanner(Pid). + + +compact_otp4299_msg() -> + M = ";KALLE\n" + "!/" + ?VERSION_STR + " mg58_1 P=005197711{; YET ANOTHER COMMENT\n" + "C=035146207{A=mg58_1_1_4_1_23/19; BEFORE COMMA\n" + ",; AFTER COMMA\n" + "A=eph58_1/0xA4023371{M{L{\n" + "v=0\n" + "c=ATM NSAP 39.0102.0304.0506.0708.090a.0b58.0100.0000.0000.00\n" + "m=audio - AAL1/ATMF -\n" + "a=eecid:A4023371\n" + "}}; HOBBE\n}; KALLE \"HOBBE \n}}" + ";KALLE\n\n", + M. + + +%% -------------------------------------------------------------- +%% +%% +compact_otp4359_msg1(suite) -> + []; +compact_otp4359_msg1(Config) when is_list(Config) -> + d("compact_otp4359_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Bin = list_to_binary(compact_otp4359_msg()), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, #'MegacoMessage'{mess = Mess}} -> + {transactions, Trans} = Mess#'Message'.messageBody, + case Trans of + [{transactionRequest,#'TransactionRequest'{transactionId = asn1_NOVALUE}}] -> + ok; + _ -> + exit({unexpected_transactions, Trans}) + end; + Else -> + t("compact_otp4359_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +compact_otp4359_msg() -> + M = "!/" ?VERSION_STR " ml2 T={C=${A=${M{O {MO=SR,RG=OFF,RV=OFF}}}}}", + M. + + +%% -------------------------------------------------------------- +%% +%% +compact_otp4920_msg0(suite) -> + []; +compact_otp4920_msg0(Config) when is_list(Config) -> + d("compact_otp4920_msg0 -> entry", []), + ?ACQUIRE_NODES(1, Config), + % put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg0(), true). + +compact_otp4920_msg1(suite) -> + []; +compact_otp4920_msg1(Config) when is_list(Config) -> + d("compact_otp4920_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + % put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg1(), false). + +compact_otp4920_msg2(suite) -> + []; +compact_otp4920_msg2(Config) when is_list(Config) -> + d("compact_otp4920_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg2(), false). + +compact_otp4920_msg3(suite) -> + []; +compact_otp4920_msg3(Config) when is_list(Config) -> + d("compact_otp4920_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg3(), true). + +compact_otp4920_msg4(suite) -> + []; +compact_otp4920_msg4(Config) when is_list(Config) -> + d("compact_otp4920_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg4(), true). + +compact_otp4920_msg5(suite) -> + []; +compact_otp4920_msg5(Config) when is_list(Config) -> + d("compact_otp4920_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg5(), true). + +compact_otp4920_msg6(suite) -> + []; +compact_otp4920_msg6(Config) when is_list(Config) -> + d("compact_otp4920_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg6(), true). + +compact_otp4920_msg7(suite) -> + []; +compact_otp4920_msg7(Config) when is_list(Config) -> + d("compact_otp4920_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + % put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg7(), true). + +compact_otp4920_msg8(suite) -> + []; +compact_otp4920_msg8(Config) when is_list(Config) -> + d("compact_otp4920_msg8 -> entry", []), + ?ACQUIRE_NODES(1, Config), + % put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg8(), false). + +compact_otp4920_msg9(suite) -> + []; +compact_otp4920_msg9(Config) when is_list(Config) -> + d("compact_otp4920_msg9 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg9(), false). + +compact_otp4920_msg10(suite) -> + []; +compact_otp4920_msg10(Config) when is_list(Config) -> + d("compact_otp4920_msg10 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg10(), false). + +compact_otp4920_msg11(suite) -> + []; +compact_otp4920_msg11(Config) when is_list(Config) -> + d("compact_otp4920_msg11 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg11(), false). + +compact_otp4920_msg12(suite) -> + []; +compact_otp4920_msg12(Config) when is_list(Config) -> + d("compact_otp4920_msg12 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg12(), true). + +%% Duplicate padding +compact_otp4920_msg20(suite) -> + []; +compact_otp4920_msg20(Config) when is_list(Config) -> + d("compact_otp4920_msg20 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg20(), bad_mid_duplicate_padding). + +%% Length +compact_otp4920_msg21(suite) -> + []; +compact_otp4920_msg21(Config) when is_list(Config) -> + d("compact_otp4920_msg21 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg21(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg22(suite) -> + []; +compact_otp4920_msg22(Config) when is_list(Config) -> + d("compact_otp4920_msg22 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg22(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg23(suite) -> + []; +compact_otp4920_msg23(Config) when is_list(Config) -> + d("compact_otp4920_msg23 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg23(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg24(suite) -> + []; +compact_otp4920_msg24(Config) when is_list(Config) -> + d("compact_otp4920_msg24 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg24(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg25(suite) -> + []; +compact_otp4920_msg25(Config) when is_list(Config) -> + d("compact_otp4920_msg25 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg25(), bad_mid_ip6addr_length). + +compact_otp4920_msg_1(M1, CheckEqual) -> + Bin1 = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin1) of + {ok, Msg} -> + io:format(" decoded", []), + case encode_message(megaco_compact_text_encoder, ?EC, Msg) of + {ok, Bin1} -> + io:format(", encoded - equal:", []), + ok; + {ok, Bin2} when CheckEqual =:= true -> + M2 = binary_to_list(Bin2), + io:format(", encoded - not equal:", []), + exit({messages_not_equal, M1, M2}); + {ok, _} -> + io:format(", encoded:", []), + ok; + Else -> + io:format(", encode failed:", []), + exit({unexpected_encode_result, Else}) + end; + Else -> + io:format("decode failed:", []), + exit({unexpected_decode_result, Else}) + end. + +compact_otp4920_msg_2(M1, ExpectedReason) -> + Bin = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, Msg} -> + io:format("unexpected successfull decode", []), + exit({unexpected_encode_ok, Msg}); + {error, [{reason, {__Line, _Mod, Reason}}|_]} -> + case element(1, Reason) of + ExpectedReason -> + ok; + _ -> + exit({unexpected_decode_error_reason, + ExpectedReason, Reason}) + end; + {error, [{reason, {_Mod, Reason}}|_]} -> + case element(1, Reason) of + ExpectedReason -> + ok; + _ -> + exit({unexpected_decode_error_reason, + ExpectedReason, Reason}) + end; + Else -> + io:format("unexpected decode result", []), + exit({unexpected_decode_result, Else}) + + end. + +compact_otp4920_msg0() -> + M = "!/" ?VERSION_STR " [192.168.30.1]\nT=100{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg1() -> + M = "!/" ?VERSION_STR " [2031:0000:130F:0000:0000:09C0:876A:130B]\nT=101{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg2() -> + M = "!/" ?VERSION_STR " [2031:0:130F:0:0:9C0:876A:130B]\nT=102{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg3() -> + M = "!/" ?VERSION_STR " [2031:0:130F::9C0:876A:130B]\nT=103{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg4() -> + M = "!/" ?VERSION_STR " [::1]\nT=104{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg5() -> + M = "!/" ?VERSION_STR " [::]\nT=105{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg6() -> + M = "!/" ?VERSION_STR " [1::]\nT=106{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg7() -> + M = "!/" ?VERSION_STR " [FEDC:1::]\nT=107{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg8() -> + M = "!/" ?VERSION_STR " [2031:0:130F:0:0:9C0:135.106.19.11]\nT=108{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg9() -> + M = "!/" ?VERSION_STR " [2031:0:130F::9C0:135.106.19.11]\nT=109{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg10() -> + M = "!/" ?VERSION_STR " [::FFFF:192.168.30.1]\nT=110{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg11() -> + M = "!/" ?VERSION_STR " [::192.168.30.1]\nT=111{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg12() -> + M = "!/" ?VERSION_STR " [::C0A8:1E01]\nT=112{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: only one :: allowed +compact_otp4920_msg20() -> + M = "!/" ?VERSION_STR " [2031::130F::9C0]\nT=120{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg21() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:0000:0000:09C0:876A:130B]\nT=121{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg22() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0:130F:0:0:9C0:135.106.19.11]\nT=122{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg23() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:2132:4354::09C0:876A:130B]\nT=123{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg24() -> + M = "!/" ?VERSION_STR " [::2031:FFEE:0000:130F:2132:4354:09C0:876A:130B]\nT=124{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg25() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:2132:4354:09C0:876A:130B::]\nT=125{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + + +compact_otp5186_msg01(suite) -> + []; +compact_otp5186_msg01(Config) when is_list(Config) -> + d("compact_otp5186_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_1(compact_otp5186_msg01(), error, ignore). + +compact_otp5186_msg02(suite) -> + []; +compact_otp5186_msg02(Config) when is_list(Config) -> + d("compact_otp5186_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_1(compact_otp5186_msg02(), ok, ok). + +compact_otp5186_msg03(suite) -> + []; +compact_otp5186_msg03(Config) when is_list(Config) -> + d("compact_otp5186_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg03(), ok, ok). + +compact_otp5186_msg04(suite) -> + []; +compact_otp5186_msg04(Config) when is_list(Config) -> + d("compact_otp5186_msg04 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg04(), ok, ok). + +compact_otp5186_msg05(suite) -> + []; +compact_otp5186_msg05(Config) when is_list(Config) -> + d("compact_otp5186_msg05 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg05(), ok, ok). + +compact_otp5186_msg06(suite) -> + []; +compact_otp5186_msg06(Config) when is_list(Config) -> + d("compact_otp5186_msg06 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg06(), ok, ok). + +compact_otp5186_msg_1(M1, DecodeExpect, EncodeExpect) -> + Bin1 = list_to_binary(M1), + case compact_decode_message(false, ?EC, Bin1) of + {ok, Msg} when DecodeExpect =:= ok -> + io:format(" decoded", []), + case compact_encode_message(?EC, Msg) of + {ok, Bin1} when EncodeExpect =:= ok -> + io:format(", encoded - equal:", []), + ok; + {ok, Bin2} when EncodeExpect =:= ok -> + M2 = binary_to_list(Bin2), + io:format(", encoded - not equal:", []), + exit({messages_not_equal, Msg, M1, M2}); + {ok, Bin3} when EncodeExpect =:= error -> + M3 = binary_to_list(Bin3), + io:format(", unexpected encode:", []), + exit({unexpected_encode_success, Msg, M1, M3}); + _Else when EncodeExpect =:= error -> + io:format(", encode failed ", []), + ok + end; + {ok, Msg} when DecodeExpect =:= error -> + io:format(" decoded", []), + exit({unexpected_decode_success, Msg}); + _Else when DecodeExpect =:= error -> + io:format(" decode failed ", []), + ok; + Else when DecodeExpect =:= ok -> + io:format(" decode failed ", []), + exit({unexpected_decode_result, Else}) + end. + +compact_otp5186_msg_2(Msg1, EncodeExpect, DecodeExpect) -> + case encode_message(megaco_compact_text_encoder, ?EC, Msg1) of + {ok, Bin} when EncodeExpect =:= ok -> + io:format(" encoded", []), + case decode_message(megaco_compact_text_encoder, false, ?EC, Bin) of + {ok, Msg1} when DecodeExpect =:= ok -> + io:format(", decoded - equal:", []), + ok; + {ok, Msg2} when DecodeExpect =:= ok -> + M = binary_to_list(Bin), + case (catch compact_otp5186_check_megamsg(Msg1, Msg2)) of + ok -> + io:format(", decoded - not equal - ok:", []), + ok; + {'EXIT', Reason} -> + io:format(", decoded - not equal:", []), + exit({messages_not_equal, M, Reason, Msg1, Msg2}) + end; + {ok, Msg3} when DecodeExpect =:= error -> + M = binary_to_list(Bin), + io:format(", decoded:", []), + exit({unexpected_decode_success, M, Msg1, Msg3}); + Else when DecodeExpect =:= ok -> + M = binary_to_list(Bin), + io:format(", decode failed ", []), + exit({unexpected_decode_success, Msg1, M, Else}); + _Else when DecodeExpect =:= error -> + io:format(", decode failed ", []), + ok + end; + {ok, Bin} when EncodeExpect =:= error -> + M = binary_to_list(Bin), + io:format(" encoded", []), + exit({unexpected_encode_success, Msg1, M}); + _Else when EncodeExpect =:= error -> + io:format(" encode failed ", []), + ok; + Else when EncodeExpect =:= ok -> + io:format(" encode failed ", []), + exit({unexpected_encode_result, Else}) + end. + + +%% -- + +compact_otp5186_msg01() -> + "!/" ?VERSION_STR " <mg5>\nP=67111298{C=2699{AV=mg5_ipeph/0x0f0001{}}}". + +compact_otp5186_msg02() -> + "!/" ?VERSION_STR " <mg5>\nP=67111298{C=2699{AV=mg5_ipeph/0x0f0001}}". + +compact_otp5186_msg03() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]}, + [ + ] + } + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +compact_otp5186_msg04() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',?VERSION,{domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]}, + [ + {emptyDescriptors, + {'AuditDescriptor',asn1_NOVALUE,asn1_NOVALUE} + } + ] + } + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +compact_otp5186_msg05() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {addReply, + {'AmmsReply', + [ + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]} + ], + [ + ] + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +compact_otp5186_msg06() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',?VERSION,{domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {addReply, + {'AmmsReply', + [ + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]} + ], + [ + {emptyDescriptors, + {'AuditDescriptor',asn1_NOVALUE,asn1_NOVALUE} + } + ] + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +%% -- + +compact_otp5186_check_megamsg(M1, M1) -> + ok; +compact_otp5186_check_megamsg(#'MegacoMessage'{authHeader = AH, + mess = M1}, + #'MegacoMessage'{authHeader = AH, + mess = M2}) -> + compact_otp5186_check_mess(M1, M2); +compact_otp5186_check_megamsg(#'MegacoMessage'{authHeader = AH1}, + #'MegacoMessage'{authHeader = AH2}) -> + exit({not_equal, authHeader, AH1, AH2}). + +compact_otp5186_check_mess(M, M) -> + ok; +compact_otp5186_check_mess(#'Message'{version = V, + mId = MId, + messageBody = B1}, + #'Message'{version = V, + mId = MId, + messageBody = B2}) -> + compact_otp5186_check_body(B1, B2); +compact_otp5186_check_mess(#'Message'{version = V, + mId = MId1}, + #'Message'{version = V, + mId = MId2}) -> + exit({not_equal, mId, MId1, MId2}); +compact_otp5186_check_mess(#'Message'{version = V1, + mId = MId}, + #'Message'{version = V2, + mId = MId}) -> + exit({not_equal, version, V1, V2}). + +compact_otp5186_check_body(B, B) -> + ok; +compact_otp5186_check_body({transactions, T1}, {transactions, T2}) -> + compact_otp5186_check_trans(T1, T2); +compact_otp5186_check_body({messageError, E1}, {messageError, E2}) -> + compact_otp5186_check_merr(E1, E2); +compact_otp5186_check_body(B1, B2) -> + exit({not_equal, messageBody, B1, B2}). + +compact_otp5186_check_trans([], []) -> + ok; +compact_otp5186_check_trans([], T2) -> + exit({not_equal, transactions, [], T2}); +compact_otp5186_check_trans(T1, []) -> + exit({not_equal, transactions, T1, []}); +compact_otp5186_check_trans([Tran1|Trans1], [Tran2|Trans2]) -> + compact_otp5186_check_trans(Trans1, Trans2), + compact_otp5186_check_transaction(Tran1, Tran2). + +compact_otp5186_check_merr(ME, ME) -> + ok; +compact_otp5186_check_merr(#'ErrorDescriptor'{errorCode = EC, + errorText = ET1}, + #'ErrorDescriptor'{errorCode = EC, + errorText = ET2}) -> + exit({not_equal, errorText, ET1, ET2}); +compact_otp5186_check_merr(#'ErrorDescriptor'{errorCode = EC1, + errorText = ET}, + #'ErrorDescriptor'{errorCode = EC2, + errorText = ET}) -> + exit({not_equal, errorCode, EC1, EC2}). + +compact_otp5186_check_transaction(T, T) -> + ok; +compact_otp5186_check_transaction({transactionReply, TR1}, + {transactionReply, TR2}) -> + compact_otp5186_check_transRep(TR1, TR2); +compact_otp5186_check_transaction(T1, T2) -> + exit({unexpected_transactions, T1, T2}). + +compact_otp5186_check_transRep(T, T) -> + ok; +compact_otp5186_check_transRep(#'TransactionReply'{transactionId = TId, + immAckRequired = IAR, + transactionResult = TR1}, + #'TransactionReply'{transactionId = TId, + immAckRequired = IAR, + transactionResult = TR2}) -> + compact_otp5186_check_transRes(TR1, TR2); +compact_otp5186_check_transRep(T1, T2) -> + exit({unexpected_transaction_reply, T1, T2}). + +compact_otp5186_check_transRes(TR, TR) -> + ok; +compact_otp5186_check_transRes({actionReplies, AR1}, + {actionReplies, AR2}) -> + compact_otp5186_check_actReps(AR1, AR2); +compact_otp5186_check_transRes(TR1, TR2) -> + exit({unexpected_transaction_result, TR1, TR2}). + +compact_otp5186_check_actReps([], []) -> + ok; +compact_otp5186_check_actReps(AR1, []) -> + exit({not_equal, actionReplies, AR1, []}); +compact_otp5186_check_actReps([], AR2) -> + exit({not_equal, actionReplies, [], AR2}); +compact_otp5186_check_actReps([AR1|ARs1], [AR2|ARs2]) -> + compact_otp5186_check_actRep(AR1, AR2), + compact_otp5186_check_actReps(ARs1, ARs2). + +compact_otp5186_check_actRep(AR, AR) -> + ok; +compact_otp5186_check_actRep(#'ActionReply'{contextId = ID, + errorDescriptor = ED, + contextReply = CtxRep, + commandReply = CmdRep1}, + #'ActionReply'{contextId = ID, + errorDescriptor = ED, + contextReply = CtxRep, + commandReply = CmdRep2}) -> + compact_otp5186_check_cmdReps(CmdRep1, CmdRep2); +compact_otp5186_check_actRep(AR1, AR2) -> + exit({unexpected_actionReply, AR1, AR2}). + +compact_otp5186_check_cmdReps([], []) -> + ok; +compact_otp5186_check_cmdReps(CR1, []) -> + exit({not_equal, commandReplies, CR1, []}); +compact_otp5186_check_cmdReps([], CR2) -> + exit({not_equal, commandReplies, [], CR2}); +compact_otp5186_check_cmdReps([CR1|CRs1], [CR2|CRs2]) -> + compact_otp5186_check_cmdRep(CR1, CR2), + compact_otp5186_check_cmdReps(CRs1, CRs2). + +compact_otp5186_check_cmdRep(CR, CR) -> + ok; +compact_otp5186_check_cmdRep({auditValueReply, AVR1}, + {auditValueReply, AVR2}) -> + compact_otp5186_check_auditReply(AVR1, AVR2); +compact_otp5186_check_cmdRep({addReply, AVR1}, + {addReply, AVR2}) -> + compact_otp5186_check_ammsReply(AVR1, AVR2); +compact_otp5186_check_cmdRep(CR1, CR2) -> + exit({unexpected_commandReply, CR1, CR2}). + +compact_otp5186_check_auditReply(AR, AR) -> + ok; +compact_otp5186_check_auditReply({auditResult, AR1}, + {auditResult, AR2}) -> + compact_otp5186_check_auditRes(AR1, AR2); +compact_otp5186_check_auditReply(AR1, AR2) -> + exit({unexpected_auditReply, AR1, AR2}). + +compact_otp5186_check_ammsReply(AR, AR) -> + ok; +compact_otp5186_check_ammsReply(#'AmmsReply'{terminationID = ID, + terminationAudit = TA1}, + #'AmmsReply'{terminationID = ID, + terminationAudit = TA2}) -> + %% This is just to simplify the test + F = fun(asn1_NOVALUE) -> []; + (E) -> E + end, + compact_otp5186_check_termAudit(F(TA1), F(TA2)); +compact_otp5186_check_ammsReply(AR1, AR2) -> + exit({unexpected_ammsReply, AR1, AR2}). + +compact_otp5186_check_auditRes(AR, AR) -> + ok; +compact_otp5186_check_auditRes(#'AuditResult'{terminationID = ID, + terminationAuditResult = TAR1}, + #'AuditResult'{terminationID = ID, + terminationAuditResult = TAR2}) -> + compact_otp5186_check_termAuditRes(TAR1, TAR2); +compact_otp5186_check_auditRes(AR1, AR2) -> + exit({unexpected_auditResult, AR1, AR2}). + +compact_otp5186_check_termAuditRes([], []) -> + ok; +%% An empty empty descriptor is removed +compact_otp5186_check_termAuditRes([{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = asn1_NOVALUE}}|TAR1], []) -> + compact_otp5186_check_termAuditRes(TAR1, []); +compact_otp5186_check_termAuditRes(TAR1, []) -> + exit({not_equal, termAuditRes, TAR1, []}); +%% An empty empty descriptor is removed +compact_otp5186_check_termAuditRes([], [{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = asn1_NOVALUE}}|TAR2]) -> + compact_otp5186_check_termAuditRes([], TAR2); +compact_otp5186_check_termAuditRes([], TAR2) -> + exit({not_equal, termAuditRes, [], TAR2}); +compact_otp5186_check_termAuditRes([ARP1|TAR1], [ARP2|TAR2]) -> + compact_otp5186_check_auditRetParm(ARP1, ARP2), + compact_otp5186_check_termAuditRes(TAR1, TAR2). + +compact_otp5186_check_termAudit([], []) -> + ok; +%% An empty empty descriptor is removed +compact_otp5186_check_termAudit([{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = asn1_NOVALUE}}|TAR1], []) -> + compact_otp5186_check_termAudit(TAR1, []); +compact_otp5186_check_termAudit(TAR1, []) -> + exit({not_equal, termAudit, TAR1, []}); +%% An empty empty descriptor is removed +compact_otp5186_check_termAudit([], + [{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = asn1_NOVALUE}}|TAR2]) -> + compact_otp5186_check_termAudit([], TAR2); +compact_otp5186_check_termAudit([], TAR2) -> + exit({not_equal, termAudit, [], TAR2}); +compact_otp5186_check_termAudit([ARP1|TAR1], [ARP2|TAR2]) -> + compact_otp5186_check_auditRetParm(ARP1, ARP2), + compact_otp5186_check_termAudit(TAR1, TAR2). + +compact_otp5186_check_auditRetParm(ARP, ARP) -> + ok; +compact_otp5186_check_auditRetParm({emptyDescriptors, AD1}, + {emptyDescriptors, AD2}) -> + compact_otp5186_check_auditDesc(AD1, AD2); +compact_otp5186_check_auditRetParm(ARP1, ARP2) -> + exit({unexpected_auditRetParm, ARP1, ARP2}). + +compact_otp5186_check_auditDesc(AD, AD) -> + ok; +compact_otp5186_check_auditDesc(#'AuditDescriptor'{auditToken = L1, + auditPropertyToken = asn1_NOVALUE}, + #'AuditDescriptor'{auditToken = L2, + auditPropertyToken = asn1_NOVALUE}) -> + compact_otp5186_check_auditDesc_auditItems(L1, L2); +compact_otp5186_check_auditDesc(#'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = APT1}, + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = APT2}) -> + compact_otp5186_check_auditDesc_apt(APT1, APT2); +compact_otp5186_check_auditDesc(AD1, AD2) -> + exit({unexpected_auditDesc, AD1, AD2}). + +compact_otp5186_check_auditDesc_auditItems([], []) -> + ok; +compact_otp5186_check_auditDesc_auditItems(AI1, []) -> + exit({not_equal, auditItems, AI1, []}); +compact_otp5186_check_auditDesc_auditItems([], AI2) -> + exit({not_equal, auditItems, [], AI2}); +compact_otp5186_check_auditDesc_auditItems([AI1|AIs1], [AI2|AIs2]) -> + compact_otp5186_check_auditDesc_auditItem(AI1, AI2), + compact_otp5186_check_auditDesc_auditItems(AIs1, AIs2). + +compact_otp5186_check_auditDesc_auditItem(AI, AI) -> + ok; +compact_otp5186_check_auditDesc_auditItem(AI1, AI2) -> + exit({not_equal, auditItem, AI1, AI2}). + +compact_otp5186_check_auditDesc_apt(APT, APT) -> + ok; +compact_otp5186_check_auditDesc_apt(APT1, APT2) -> + exit({not_equal, auditPropertyToken, APT1, APT2}). + + +compact_otp5793_msg01(suite) -> + []; +compact_otp5793_msg01(Config) when is_list(Config) -> + d("compact_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5793(ok, pretty_otp5793_msg1()). + +compact_otp5793(Expected, Msg) -> + expect_codec_e(Expected, megaco_compact_text_encoder, Msg, []). + + +compact_otp5836_msg01(suite) -> + []; +compact_otp5836_msg01(Config) when is_list(Config) -> + d("compact_otp5836_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), +%% put(severity,trc), +%% put(dbg,true), + compact_otp5836(ok, compact_otp5836_msg1()). + +compact_otp5836(Expected, Msg) -> + expect_codec_e(Expected, megaco_compact_text_encoder, Msg, []). + + +compact_otp5836_msg1() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + 3, + {deviceName,"bs_sbg_4/34"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 12, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 4294967295, + asn1_NOVALUE, + asn1_NOVALUE, + [{auditValueReply, + {error, {'ErrorDescriptor', 431, asn1_NOVALUE}}} + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +%% -------------------------------------------------------------- + +compact_otp5993_msg01(suite) -> + []; +compact_otp5993_msg01(Config) when is_list(Config) -> + d("compact_otp5993_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5993(ok, compact_otp5993_msg01()). + +compact_otp5993_msg02(suite) -> + []; +compact_otp5993_msg02(Config) when is_list(Config) -> + d("compact_otp5993_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5993(ok, compact_otp5993_msg02()). + +compact_otp5993_msg03(suite) -> + []; +compact_otp5993_msg03(Config) when is_list(Config) -> + d("compact_otp5993_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5993(ok, compact_otp5993_msg03()). + +compact_otp5993(Expected, Msg) -> + expect_codec_e(Expected, megaco_compact_text_encoder, Msg, []). + +compact_otp5993_msg01() -> + MT = h221, + T = #megaco_term_id{id = ?A4444}, + TL = [T], + MD = #'MuxDescriptor'{muxType = MT, + termList = TL}, + compact_otp5993_msg(MD). + +compact_otp5993_msg02() -> + MT = h223, + T1 = #megaco_term_id{id = ?A4445}, + T2 = #megaco_term_id{id = ?A5556}, + TL = [T1, T2], + MD = #'MuxDescriptor'{muxType = MT, + termList = TL}, + compact_otp5993_msg(MD). + +compact_otp5993_msg(MD) when is_record(MD, 'MuxDescriptor') -> + AmmDesc = {muxDescriptor, MD}, + AmmReq = #'AmmRequest'{terminationID = [hd(MD#'MuxDescriptor'.termList)], + descriptors = [AmmDesc]}, + Cmd = {addReq, AmmReq}, + CmdReq = #'CommandRequest'{command = Cmd}, + ActReq = #'ActionRequest'{contextId = 5993, + commandRequests = [CmdReq]}, + TransReq = #'TransactionRequest'{transactionId = 3995, + actions = [ActReq]}, + Trans = {transactionRequest, TransReq}, + Body = {transactions, [Trans]}, + Msg = #'Message'{version = ?VERSION, + mId = ?MG1_MID, + messageBody = Body}, + #'MegacoMessage'{mess = Msg}. + +compact_otp5993_msg03() -> + T1 = #megaco_term_id{id = ?A4445}, + T2 = #megaco_term_id{id = ?A5556}, + TIDs = [T1, T2], + AudRep = {contextAuditResult, TIDs}, + CmdRep = {auditValueReply, AudRep}, + ActRep = #'ActionReply'{contextId = 5993, + commandReply = [CmdRep]}, + TransRes = {actionReplies, [ActRep]}, + TransRep = #'TransactionReply'{transactionId = 3995, + transactionResult = TransRes}, + Trans = {transactionReply, TransRep}, + Body = {transactions, [Trans]}, + Msg = #'Message'{version = ?VERSION, + mId = ?MG1_MID, + messageBody = Body}, + #'MegacoMessage'{mess = Msg}. + + +%% -------------------------------------------------------------- + +compact_otp6017_msg01(suite) -> + []; +compact_otp6017_msg01(Config) when is_list(Config) -> + d("compact_otp6017_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(0), + ok. + +compact_otp6017_msg02(suite) -> + []; +compact_otp6017_msg02(Config) when is_list(Config) -> + d("compact_otp6017_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(16#FFFFFFFE), + ok. + +compact_otp6017_msg03(suite) -> + []; +compact_otp6017_msg03(Config) when is_list(Config) -> + d("compact_otp6017_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(16#FFFFFFFF), + ok. + +compact_otp6017(BadCID) -> + Conf = ?EC, + M = compact_otp6017_msg(BadCID), + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, Conf, Bin) of + {ok, Msg} -> + exit({unexpected_decode_success, {Msg, M}}); + {error, Reason} when is_list(Reason) -> % Expected result + case lists:keysearch(reason, 1, Reason) of + {value, {reason, {_Line, _Mod, {bad_ContextID, BadCID}}}} -> + io:format(" ~w", [BadCID]), + ok; + {value, {reason, ActualReason}} -> + exit({unexpected_reason, ActualReason}); + false -> + exit({reason_not_found, Reason}) + end; + Crap -> + exit({unexpected_decode_result, Crap}) + end. + +compact_otp6017_msg(CID) when is_integer(CID) -> + "MEGACO/" ?VERSION_STR " MG1 T=12345678{C=" ++ + integer_to_list(CID) ++ + "{SC=root{SV{MT=RS,RE=901}}}}". + + +%% ============================================================== +%% +%% F l e x C o m p a c t T e s t c a s e s +%% + +flex_compact_otp7431_msg01(suite) -> + []; +flex_compact_otp7431_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg01 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(ok, flex_compact_otp7431_msg1(), [Conf]). + +flex_compact_otp7431_msg02(suite) -> + []; +flex_compact_otp7431_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg02 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg2(), [Conf]). + +flex_compact_otp7431_msg03(suite) -> + []; +flex_compact_otp7431_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg03 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg3(), [Conf]). + +flex_compact_otp7431_msg04(suite) -> + []; +flex_compact_otp7431_msg04(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg04 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg4(), [Conf]). + +flex_compact_otp7431_msg05(suite) -> + []; +flex_compact_otp7431_msg05(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg05 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg5(), [Conf]). + +flex_compact_otp7431_msg06(suite) -> + []; +flex_compact_otp7431_msg06(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg06 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg6(), [Conf]). + +flex_compact_otp7431_msg07(suite) -> + []; +flex_compact_otp7431_msg07(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg07 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg7(), [Conf]). + + +flex_compact_otp7431(Expected, Msg, Conf) -> + otp7431(Expected, megaco_compact_text_encoder, Msg, Conf). + +flex_compact_otp7431_msg1() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a=recvonly +}}}}}}". + +flex_compact_otp7431_msg2() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a= } +}}}}}". + + +flex_compact_otp7431_msg3() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a } +}}}}}". + + +flex_compact_otp7431_msg4() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a} +}}}}}". + + +flex_compact_otp7431_msg5() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v= } +}}}}}". + + +flex_compact_otp7431_msg6() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v } +}}}}}". + +flex_compact_otp7431_msg7() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v} +}}}}}". + + +%% ============================================================== +%% +%% P r e t t y T e s t c a s e s +%% + +pretty_otp4632_msg1(suite) -> + []; +pretty_otp4632_msg1(Config) when is_list(Config) -> + d("pretty_otp4632_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg1(), + case pretty_encode_message(?EC, Msg0) of + {ok, BinMsg} when is_binary(BinMsg) -> + {ok, Msg1} = decode_message(megaco_pretty_text_encoder, false, + ?EC, BinMsg), + ok = chk_MegacoMessage(Msg0, Msg1); + Else -> + t("pretty_otp4632_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4632_msg1() -> + msg4(?MG1_MID_NO_PORT, "901 mg col boot"). + +pretty_otp4632_msg2(suite) -> + []; +pretty_otp4632_msg2(Config) when is_list(Config) -> + d("pretty_otp4632_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg2(), + case encode_message(megaco_pretty_text_encoder, ?EC, Msg0) of + {ok, BinMsg} when is_binary(BinMsg) -> + {ok, Msg1} = decode_message(megaco_pretty_text_encoder, false, + ?EC, BinMsg), + ok = chk_MegacoMessage(Msg0,Msg1); + Else -> + t("pretty_otp4632_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4632_msg2() -> + msg4(?MG1_MID_NO_PORT, "901"). + + +pretty_otp4632_msg3(suite) -> + []; +pretty_otp4632_msg3(Config) when is_list(Config) -> + d("pretty_otp4632_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg3(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, + false, ?EC, Bin0) of + {ok, Msg} when is_record(Msg, 'MegacoMessage') -> + {ok, Bin1} = encode_message(megaco_pretty_text_encoder, ?EC, Msg), + Msg1 = binary_to_list(Bin1), + %% io:format("Msg1:~n~s~n", [Msg1]), + Msg0 = Msg1, + ok; + Else -> + t("pretty_otp4632_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4632_msg3() -> + M = "MEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = \"901\"\n\t\t\t}\n\t\t}\n\t}\n}", + M. + + +pretty_otp4632_msg4(suite) -> + []; +pretty_otp4632_msg4(Config) when is_list(Config) -> + d("pretty_otp4632_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg4(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {ok, Msg} when is_record(Msg, 'MegacoMessage') -> + {ok, Bin1} = encode_message(megaco_pretty_text_encoder, ?EC, Msg), + Msg1 = binary_to_list(Bin1), + %% io:format("Msg1:~n~s~n", [Msg1]), + pretty_otp4632_msg4_chk(Msg0,Msg1); + Else -> + t("pretty_otp4632_msg4 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + + +pretty_otp4632_msg4() -> + M = "MEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = 901\n\t\t\t}\n\t\t}\n\t}\n}", + M. + + +pretty_otp4632_msg4_chk([], []) -> + exit(messages_not_eq); +pretty_otp4632_msg4_chk([], Rest1) -> + exit({messages_not_eq1, Rest1}); +pretty_otp4632_msg4_chk(Rest0, []) -> + exit({messages_not_eq0, Rest0}); +pretty_otp4632_msg4_chk([$R,$e,$a,$s,$o,$n,$ ,$=,$ ,$9,$0,$1|_Rest0], + [$R,$e,$a,$s,$o,$n,$ ,$=,$ ,$",$9,$0,$1,$"|_Rest1]) -> + ok; +pretty_otp4632_msg4_chk([_|Rest0], [_|Rest1]) -> + pretty_otp4632_msg4_chk(Rest0,Rest1). + + +pretty_otp4710_msg1(suite) -> + []; +pretty_otp4710_msg1(Config) when is_list(Config) -> + d("pretty_otp4710_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4710_msg1(), + case encode_message(megaco_pretty_text_encoder, ?EC, Msg0) of + {ok, Bin} when is_binary(Bin) -> + {ok, Msg1} = decode_message(megaco_pretty_text_encoder, false, + ?EC, Bin), + ok = chk_MegacoMessage(Msg0,Msg1); + Else -> + t("pretty_otp4710_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4710_msg1() -> + msg40(). + + +pretty_otp4710_msg2(suite) -> + []; +pretty_otp4710_msg2(Config) when is_list(Config) -> + d("pretty_otp4710_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4710_msg2(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {ok, Msg} when is_record(Msg, 'MegacoMessage') -> + {ok, Bin1} = encode_message(megaco_pretty_text_encoder, ?EC, Msg), + Msg1 = binary_to_list(Bin1), + %% io:format("Msg1:~n~s~n", [Msg1]), + pretty_otp4710_msg2_chk(Msg0,Msg1); + Else -> + t("pretty_otp4710_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4710_msg2() -> + "Authentication = 0xEFCDAB89:0x12345678:0x1234567889ABCDEF76543210\nMEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = \"901 mg col boot\"\n\t\t\t}\n\t\t}\n\t}\n}". + +pretty_otp4710_msg2_chk(Msg,Msg) -> + ok; +pretty_otp4710_msg2_chk( + [$A,$u,$t,$h,$e,$n,$t,$i,$c,$a,$t,$i,$o,$n,$=,$ |Msg0], + [$A,$u,$t,$h,$e,$n,$t,$i,$c,$a,$t,$i,$o,$n,$=,$ |Msg1]) -> + {AH0, Rest0} = pretty_otp4710_msg2_chk_ah(Msg0, []), + {AH1, Rest1} = pretty_otp4710_msg2_chk_ah(Msg1, []), + case AH0 == AH1 of + true -> + exit({message_not_equal, Rest0, Rest1}); + false -> + exit({auth_header_not_equal, AH0, AH1}) + end. + +pretty_otp4710_msg2_chk_ah([], _Acc) -> + exit(no_auth_header_found); +pretty_otp4710_msg2_chk_ah([$M,$E,$G,$A,$C,$O,$/,_|Rest], Acc) -> + {lists:reverse(Acc), Rest}; +pretty_otp4710_msg2_chk_ah([C|R], Acc) -> + pretty_otp4710_msg2_chk_ah(R, [C|Acc]). + + +pretty_otp4945_msg1(suite) -> + []; +pretty_otp4945_msg1(Config) when is_list(Config) -> + d("pretty_otp4945_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg1(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {missing_required_serviceChangeParm, [serviceChangeReason]} -> + ok; + Else -> + t("pretty_otp4945_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + io:format("pretty_otp4945_msg1 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg2(suite) -> + []; +pretty_otp4945_msg2(Config) when is_list(Config) -> + d("pretty_otp4945_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg2(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {missing_required_serviceChangeParm, [serviceChangeMethod]} -> + ok; + Else -> + t("pretty_otp4945_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg2() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg3(suite) -> + []; +pretty_otp4945_msg3(Config) when is_list(Config) -> + d("pretty_otp4945_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg3(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {missing_required_serviceChangeParm, [serviceChangeReason, serviceChangeMethod]} -> + ok; + {missing_required_serviceChangeParm, [serviceChangeMethod, serviceChangeReason]} -> + ok; + Else -> + t("pretty_otp4945_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg3() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg4(suite) -> + []; +pretty_otp4945_msg4(Config) when is_list(Config) -> + d("pretty_otp4945_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg4(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {ok, _} -> + ok; + Else -> + t("pretty_otp4945_msg4 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg4() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg5(suite) -> + []; +pretty_otp4945_msg5(Config) when is_list(Config) -> + d("pretty_otp4945_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg5(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {at_most_once_serviceChangeParm, {profile, _Val1, _Val2}} -> + ok; + Else -> + io:format("pretty_otp4945_msg6 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg5 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg5() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + Profile = ResGW/1, + ServiceChangeAddress = 55555, + Profile = ResGW/2 + } + } + } +}". + + +pretty_otp4945_msg6(suite) -> + []; +pretty_otp4945_msg6(Config) when is_list(Config) -> + d("pretty_otp4945_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg6(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {not_both_address_mgcid_serviceChangeParm, _Val1, _Val2} -> + ok; + Else -> + io:format("pretty_otp4945_msg6 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg6 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg6() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + MgcIdToTry = kalle, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4949_msg1(suite) -> + []; +pretty_otp4949_msg1(Config) when is_list(Config) -> + d("pretty_otp4949_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4949_msg1(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {ok, _} -> + ok; + Else -> + t("pretty_otp4949_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4949_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4949_msg2(suite) -> + []; +pretty_otp4949_msg2(Config) when is_list(Config) -> + d("pretty_otp4949_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4949_msg2(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {at_most_once_servChgReplyParm, {profile, _Val1, _Val2}} -> + ok; + Else -> + io:format("pretty_otp4949_msg2 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4949_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4949_msg2() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Profile = ResGW/1, + ServiceChangeAddress = 55555, + Profile = ResGW/2 + } + } + } +}". + + +pretty_otp4949_msg3(suite) -> + []; +pretty_otp4949_msg3(Config) when is_list(Config) -> + d("pretty_otp4949_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4949_msg3(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {not_both_address_mgcid_servChgReplyParm, _Val1, _Val2} -> + ok; + Else -> + io:format("pretty_otp4949_msg3 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4949_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4949_msg3() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + MgcIdToTry = kalle, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp5042_msg1(suite) -> + []; +pretty_otp5042_msg1(Config) when is_list(Config) -> + d("pretty_otp5042_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp5042_msg1(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {_, _Mod, {bad_timeStamp, TimeStamp}} -> + exit({bad_timeStamp, TimeStamp}); + _ -> + io:format("pretty_otp5042_msg1 -> " + "~n Reason: ~w" + "~n", [Reason]), + exit({unexpected_decode_result, Reason}) + end; + {ok, M} -> + t("pretty_otp5042_msg1 -> successfull decode:" + "~n~p", [M]), + ok + end. + +pretty_otp5042_msg1() -> +"MEGACO/" ?VERSION_STR " <CATAPULT>:2944 +Transaction = 102 { +Context = 5 { Notify = MUX/1 { ObservedEvents = 1 { +h245bh/h245msgin { Stream = 1 +, h245enc = +0270020600088175000653401004100403E802E00180018001780680000034301160000700088175010101007A0100020001800001320000C0000219D005027F0070500100040100021080000319D005027F00504001008000041C001250000700088175010000400280010003000880000518AA027F400006850130008011020100000001030002000300040005000006 + } } + } } }". + + +pretty_otp5068_msg1(suite) -> + []; +pretty_otp5068_msg1(Config) when is_list(Config) -> + d("pretty_otp5068_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = pretty_otp5068_msg1(), + case encode_message(megaco_pretty_text_encoder, ?EC, Msg) of + {error, Reason} -> +% io:format("pretty_otp5068_msg1 -> " +% "~n Reason: ~w" +% "~n", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} -> +% io:format("pretty_otp5068_msg1 -> successfull encode:" +% "~n~s~n", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, ?EC, Bin) of + {ok, _} -> +% io:format("pretty_otp5068_msg1 -> ok~n", []), + ok; + Else -> +% io:format("pretty_otp5068_msg1 -> ~n~p~n", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + +pretty_otp5068_msg1() -> +{'MegacoMessage', + asn1_NOVALUE, + {'Message', + 2, + {deviceName,[109,103,51,51]}, + {transactions, + [{transactionReply, + {'TransactionReply', + 190, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', %% Comments: Detta upprepas m�nga g�nger + 0, + asn1_NOVALUE, + asn1_NOVALUE, + [{auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false, + [[99,101,100,101,118,49,47,52,47,49,47,49],[51,49]]}, + [{mediaDescriptor, + {'MediaDescriptor', + {'TerminationStateDescriptor', + [], + asn1_NOVALUE, + inSvc}, + asn1_NOVALUE} + } + ] + } + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } +}. + + + +pretty_otp5085_msg1(suite) -> + []; +pretty_otp5085_msg1(Config) when is_list(Config) -> + d("pretty_otp5085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg1()). + +pretty_otp5085_msg2(suite) -> + []; +pretty_otp5085_msg2(Config) when is_list(Config) -> + d("pretty_otp5085_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(error, pretty_otp5085_msg2()). + +pretty_otp5085_msg3(suite) -> + []; +pretty_otp5085_msg3(Config) when is_list(Config) -> + d("pretty_otp5085_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg3()). + +pretty_otp5085_msg4(suite) -> + []; +pretty_otp5085_msg4(Config) when is_list(Config) -> + d("pretty_otp5085_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg4()). + +pretty_otp5085_msg5(suite) -> + []; +pretty_otp5085_msg5(Config) when is_list(Config) -> + d("pretty_otp5085_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg5()). + +pretty_otp5085_msg6(suite) -> + []; +pretty_otp5085_msg6(Config) when is_list(Config) -> + d("pretty_otp5085_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg6()). + +pretty_otp5085_msg7(suite) -> + []; +pretty_otp5085_msg7(Config) when is_list(Config) -> + d("pretty_otp5085_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg7()). + +pretty_otp5085_msg8(suite) -> + []; +pretty_otp5085_msg8(Config) when is_list(Config) -> + d("pretty_otp5085_msg8 -> entry", []), + ?ACQUIRE_NODES(1, Config), +% put(dbg,true), +% put(severity, trc), + Res = (catch pretty_otp5085(ok, pretty_otp5085_msg8())), +% erase(dbg), +% erase(severity), + case Res of + ok -> + ok; + {'EXIT', Reason} -> + exit(Reason) + end. + +pretty_otp5085(Expected, Msg) -> + pretty_otp5085(Expected, Msg, []). + +pretty_otp5085(Expected, Msg, Conf) -> + t("pretty_otp5085 -> entry with" + "~n Expected: ~p" + "~n Msg: ~p", [Expected, Msg]), + case (catch encode_message(megaco_pretty_text_encoder, [?EC_V3|Conf], Msg)) of + {error, Reason} when Expected == error -> + d("pretty_otp5085 -> encode failed as expected" + "~n Reason: ~w", [Reason]), + ok; + {error, Reason} -> + e("pretty_otp5085 -> encode failed unexpectedly: " + "~n Reason: ~w", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} when Expected == error -> + e("pretty_otp5085 -> encode succeded unexpectedly: " + "~n ~w", [binary_to_list(Bin)]), + exit({unexpected_encode_result, binary_to_list(Bin)}); + {ok, Bin} -> + d("pretty_otp5085 -> successfull encode as expected:" + "~n~s", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, [?EC_V3|Conf], Bin) of + {ok, Msg} -> + d("pretty_otp5085 -> successfull decode~n", []), + ok; + {ok, Msg2} -> + e("pretty_otp5085 -> successfull decode" + " - but not equal", []), + exit({unexpected_decode_result, Msg, Msg2}); + Else -> + e("pretty_otp5085 -> decode failed:~n~p", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + +pretty_otp5085_msg1() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + asn1_NOVALUE, + [] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +pretty_otp5085_msg2() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + asn1_NOVALUE, + [] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +pretty_otp5085_msg3() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + #'ContextRequest'{priority = 3}, + [] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +pretty_otp5085_msg4() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + asn1_NOVALUE, + [{addReply, cre_AmmsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +pretty_otp5085_msg5() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + #'ContextRequest'{priority = 5}, + [{addReply, cre_AmmsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +pretty_otp5085_msg6() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 6}, + [{addReply, cre_AmmsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +pretty_otp5085_msg7() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 7}, + [{notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg8() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 8, + emergency = true, + topologyReq = + [#'TopologyRequest'{terminationFrom = From1, + terminationTo = To1, + topologyDirection = bothway}, + #'TopologyRequest'{terminationFrom = From2, + terminationTo = To2, + topologyDirection = oneway} + ], + iepscallind = true, + contextProp = [cre_PropParm("tdmc/gain", "2")]}, + [{notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +pretty_otp5600_msg1(suite) -> + []; +pretty_otp5600_msg1(Config) when is_list(Config) -> + d("pretty_otp5600_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5600(ok, pretty_otp5600_msg1()). + +pretty_otp5600_msg2(suite) -> + []; +pretty_otp5600_msg2(Config) when is_list(Config) -> + d("pretty_otp5600_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5600(ok, pretty_otp5600_msg2()). + +pretty_otp5600(Expected, Msg) -> + pretty_otp5600(Expected, Msg, []). + +pretty_otp5600(Expected, Msg, Conf) -> + t("pretty_otp5600 -> entry with" + "~n Expected: ~p" + "~n Msg: ~p", [Expected, Msg]), + case (catch encode_message(megaco_pretty_text_encoder, [?EC_V3|Conf], Msg)) of + {error, Reason} when Expected == error -> + d("pretty_otp5600 -> encode failed as expected" + "~n Reason: ~w", [Reason]), + ok; + {error, Reason} -> + e("pretty_otp5600 -> encode failed unexpectedly: " + "~n Reason: ~w", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} when Expected == error -> + e("pretty_otp5600 -> encode succeded unexpectedly: " + "~n ~w", [binary_to_list(Bin)]), + exit({unexpected_encode_result, binary_to_list(Bin)}); + {ok, Bin} -> + d("pretty_otp5600 -> successfull encode as expected:" + "~n~s", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, [?EC_V3|Conf], Bin) of + {ok, Msg} -> + d("pretty_otp5600 -> successfull decode~n", []), + ok; + {ok, Msg2} -> + e("pretty_otp5600 -> successfull decode" + " - but not equal", []), + exit({unexpected_decode_result, Msg, Msg2}); + Else -> + e("pretty_otp5600 -> decode failed:~n~p", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + +pretty_otp5600_msg1() -> + SRE = #'SecondRequestedEvent'{ pkgdName = "al/on", + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE ] }, + + SIG = { signal, #'Signal'{ signalName = "cg/dt", + sigParList = [] } }, + + RA = #'RequestedActions'{ secondEvent = SED, + signalsDescriptor = [ SIG ] }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + +pretty_otp5600_msg2() -> + SIG = { signal, #'Signal'{ signalName = "cg/dt", + sigParList = [] } }, + + SRA = #'SecondRequestedActions'{ signalsDescriptor = [ SIG ] }, + + SRE = #'SecondRequestedEvent'{ pkgdName = "al/on", + eventAction = SRA, + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE ] }, + + RA = #'RequestedActions'{ secondEvent = SED }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + + +pretty_otp5601_msg1(suite) -> + []; +pretty_otp5601_msg1(Config) when is_list(Config) -> + d("pretty_otp5601_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5601(ok, pretty_otp5601_msg1()). + +pretty_otp5601(Expected, Msg) -> + pretty_otp5601(Expected, Msg, []). + +pretty_otp5601(Expected, Msg, Conf) -> + t("pretty_otp5601 -> entry with" + "~n Expected: ~p" + "~n Msg: ~p", [Expected, Msg]), + case (catch encode_message(megaco_pretty_text_encoder, [?EC_V3|Conf], Msg)) of + {error, Reason} when Expected == error -> + d("pretty_otp5601 -> encode failed as expected" + "~n Reason: ~w", [Reason]), + ok; + {error, Reason} -> + e("pretty_otp5601 -> encode failed unexpectedly: " + "~n Reason: ~w", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} when Expected == error -> + e("pretty_otp5601 -> encode succeded unexpectedly: " + "~n ~w", [binary_to_list(Bin)]), + exit({unexpected_encode_result, binary_to_list(Bin)}); + {ok, Bin} -> + d("pretty_otp5601 -> successfull encode as expected:" + "~n~s", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, [?EC_V3|Conf], Bin) of + {ok, Msg} -> + d("pretty_otp5601 -> successfull decode~n", []), + ok; + {ok, Msg2} -> + e("pretty_otp5601 -> successfull decode" + " - but not equal", []), + exit({unexpected_decode_result, Msg, Msg2}); + Else -> + e("pretty_otp5601 -> decode failed:~n~p", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + +pretty_otp5601_msg1() -> + SRE1 = #'SecondRequestedEvent'{ pkgdName = "al/on", + evParList = [] }, + + SRA = #'SecondRequestedActions'{ eventDM = { digitMapName, "dialllan0" }}, + + SRE2 = #'SecondRequestedEvent'{ pkgdName = "dd/ce", + eventAction = SRA, + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE1, SRE2 ] }, + + RA = #'RequestedActions'{ secondEvent = SED }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + + +pretty_otp5793_msg01(suite) -> + []; +pretty_otp5793_msg01(Config) when is_list(Config) -> + d("pretty_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), +% put(severity,trc), +% put(dbg,true), + pretty_otp5793(ok, pretty_otp5793_msg1()). + +pretty_otp5793(Expected, Msg) -> + expect_codec_e(Expected, megaco_pretty_text_encoder, Msg, []). + +pretty_otp5793(Expected, Msg, Conf) -> + expect_codec_e(Expected, megaco_pretty_text_encoder, Msg, Conf). + + +pretty_otp5793_msg1() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',3, + {deviceName,"bs_sbg_4/99"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 370, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 3, + asn1_NOVALUE, + asn1_NOVALUE, + [{auditValueReply, + {contextAuditResult, + [{megaco_term_id, + false, + ["ip", + "104", + "1", + "18"]}]}}, + {auditValueReply, + {contextAuditResult, + [{megaco_term_id, + false, + ["ip", + "104", + "2", + "19"] + } + ] + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + + +pretty_otp5803_msg01(suite) -> + []; +pretty_otp5803_msg01(Config) when is_list(Config) -> + d("pretty_otp5803_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5803(pretty_otp5803_msg1()). + +pretty_otp5803_msg02(suite) -> + []; +pretty_otp5803_msg02(Config) when is_list(Config) -> + d("pretty_otp5803_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5803(pretty_otp5803_msg2()). + +pretty_otp5803(Msg) -> + expect_codec_d(ok, megaco_pretty_text_encoder, Msg, []). + +pretty_otp5803(Msg, Conf) -> + expect_codec_d(ok, megaco_pretty_text_encoder, Msg, Conf). + + +pretty_otp5803_msg1() -> +"MEGACO/" ?VERSION_STR " [134.138.234.29]Transaction=384{ + Context=27{ + Modify=ip/104/1/76{ + Media{ + Stream=1{ + Local{}, + Remote{} + }, + Stream=2{ + Local{}, + Remote{} + } + }, + Audit{ + Media{ + Stream=1{ + Statistics{*/*} + }, + Stream=2{ + Statistics{*/*} + } + } + } + }, + Modify=ip/104/2/77{ + Media{ + Stream=1{ + Local{}, + Remote{} + }, + Stream=2{ + Local{}, + Remote{} + } + } + } + } +}". + + +pretty_otp5803_msg2() -> +"MEGACO/" ?VERSION_STR " [134.138.234.29]Transaction=384{ + Context=27{ + Modify=ip/104/1/76{ + Media{ + Stream=1{ + Local{}, + Remote{} + }, + Stream=2{ + Local{}, + Remote{} + } + }, + Audit{ + Media{ + Stream=1{ + Statistics{*/*} + } + } + } + }, + Modify=ip/104/2/77{ + Media{ + Stream=1{ + Local{}, + Remote{} + }, + Stream=2{ + Local{}, + Remote{} + } + } + } + } +}". + + +pretty_otp5805_msg01(suite) -> + []; +pretty_otp5805_msg01(Config) when is_list(Config) -> + d("pretty_otp5805_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), +%% put(severity,trc), +%% put(dbg,true), + pretty_otp5805(pretty_otp5805_msg1()). + +pretty_otp5805(Msg) -> + expect_codec_d(error, megaco_pretty_text_encoder, Msg, []). + +pretty_otp5805(Msg, Conf) -> + expect_codec_d(error, megaco_pretty_text_encoder, Msg, Conf). + + +pretty_otp5805_msg1() -> +"MEGACO/4 [134.138.234.29] +Transaction=1{ + Context=*{ + AuditValue=ip/0/*{ + Audit{} + } + } +}". + + +pretty_otp5836_msg01(suite) -> + []; +pretty_otp5836_msg01(Config) when is_list(Config) -> + d("pretty_otp5836_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), +%% put(severity,trc), +%% put(dbg,true), + pretty_otp5836(compact_otp5836_msg1()). + +pretty_otp5836(Msg) -> + expect_codec_e(ok, megaco_pretty_text_encoder, Msg, []). + +pretty_otp5836(Msg, Conf) -> + expect_codec_e(ok, megaco_pretty_text_encoder, Msg, Conf). + + +pretty_otp5882_msg01(suite) -> + []; +pretty_otp5882_msg01(Config) when is_list(Config) -> + d("pretty_otp5882_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5882(). + +pretty_otp5882() -> + otp5882(megaco_pretty_text_encoder, []). + +otp5882(Codec, Conf) -> + Msg = pretty_otp5882_msg01(), + case (catch encode_message(Codec, [?EC_V3|Conf], Msg)) of + {error, {message_encode_failed, {error, {ActualReason, _}}, _}} -> + case ActualReason of + {invalid_LocalControlDescriptor, empty} -> + ok; + _ -> + exit({unexpected_error_actual_reason, ActualReason}) + end; + {error, Reason} -> + exit({unexpected_error_reason, Reason}); + {ok, Bin} -> + exit({unexpected_encode_sucess, binary_to_list(Bin)}) + end. + +pretty_otp5882_msg01() -> + LCD = #'LocalControlDescriptor'{}, % Create illegal LCD + Parms = cre_StreamParms(LCD), + StreamDesc = cre_StreamDesc(1, Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + CID = cre_CtxID(7301), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(7302), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + + +%% -------------------------------------------------------------- +%% +pretty_otp6490_msg01(suite) -> + []; +pretty_otp6490_msg01(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg01 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg01(), [] ), + %% erase(dbg), + %% erase(severity), + ok. + +pretty_otp6490_msg02(suite) -> + []; +pretty_otp6490_msg02(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg02 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg02(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg03(suite) -> + []; +pretty_otp6490_msg03(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg03 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg03(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg04(suite) -> + []; +pretty_otp6490_msg04(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg04 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg04(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg05(suite) -> + []; +pretty_otp6490_msg05(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg05 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg05(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg06(suite) -> + []; +pretty_otp6490_msg06(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg06 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg06(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490(Msg, Conf) -> + pretty_otp6490(Msg, Conf, ok). + +pretty_otp6490(Msg, Conf, ExpectedEncode) -> + pretty_otp6490(Msg, Conf, ExpectedEncode, ok). + +pretty_otp6490(Msg, Conf, ExpectedEncode, ExpectedDecode) -> + otp6490(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode). + +otp6490(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode) -> + case (catch encode_message(Codec, [?EC_V3|Conf], Msg)) of + {error, _Reason} when ExpectedEncode == error -> + ok; + {error, Reason} when ExpectedEncode == ok -> + exit({unexpected_encode_failure, Reason}); + {ok, Bin} when ExpectedEncode == error -> + exit({unexpected_encode_success, Msg, binary_to_list(Bin)}); + {ok, Bin} when ExpectedEncode == ok -> + case decode_message(Codec, false, [?EC_V3|Conf], Bin) of + {ok, Msg} when ExpectedDecode == ok -> + ok; + {ok, Msg} when ExpectedDecode == error -> + exit({unexpected_decode_success, Msg}); + {ok, Msg2} when ExpectedDecode == ok -> + exit({unexpected_decode_result, Msg, Msg2}); + {ok, Msg2} when ExpectedDecode == error -> + exit({unexpected_decode_success, Msg, Msg2}); + {error, _Reason} when ExpectedDecode == error -> + ok; + {error, Reason} when ExpectedDecode == ok -> + exit({unexpected_decode_failure, Msg, Reason}) + end + end. + + +pretty_otp6490_msg(EBD) -> + AmmDesc = ?MSG_LIB:cre_AmmDescriptor(EBD), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4445}], [AmmDesc]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + CID = cre_CtxID(64901), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(64902), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +pretty_otp6490_msg01() -> + EvSpecs = [], % This will result in an error + EBD = EvSpecs, % This is because the lib checks that the size is valid + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg02() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg03() -> + EvPar1 = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + EvPar2 = ?MSG_LIB:cre_EventParameter("kalle", ["anka"]), + EvPar3 = ?MSG_LIB:cre_EventParameter("flippa", ["ur"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar1,EvPar2,EvPar3]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg04() -> + EvPar1 = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + EvPar2 = ?MSG_LIB:cre_EventParameter("kalle", ["anka"]), + EvPar3 = ?MSG_LIB:cre_EventParameter("flippa", ["ur"]), + PkgdName1 = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName1 = ?MSG_LIB:cre_EventName(PkgdName1), + EvSpec1 = ?MSG_LIB:cre_EventSpec(EvName1, [EvPar1,EvPar2,EvPar3]), + EvPar4 = ?MSG_LIB:cre_EventParameter("hej", ["hopp"]), + PkgdName2 = ?MSG_LIB:cre_PkgdName("bar", "b"), + EvName2 = ?MSG_LIB:cre_EventName(PkgdName2), + EvSpec2 = ?MSG_LIB:cre_EventSpec(EvName2, [EvPar4]), + EvSpecs = [EvSpec1,EvSpec2], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg05() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", root), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg06() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName(root, root), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + + +%% -------------------------------------------------------------- +%% + +pretty_otp7671_msg01(suite) -> + []; +pretty_otp7671_msg01(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg01 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg01(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg02(suite) -> + []; +pretty_otp7671_msg02(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg02 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg02(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg03(suite) -> + []; +pretty_otp7671_msg03(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg03 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg03(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg04(suite) -> + []; +pretty_otp7671_msg04(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg04 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg04(), [] , error, ignore), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg05(suite) -> + []; +pretty_otp7671_msg05(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg05 -> entry", []), + Check = fun(M1, M2) -> cmp_otp7671_msg05(M1, M2) end, + ok = pretty_otp7671( pretty_otp7671_msg05(), [] , ok, ok, Check), +%% erase(dbg), +%% erase(severity), + ok. + + +pretty_otp7671(Msg, Conf) -> + pretty_otp7671(Msg, Conf, ok). + +pretty_otp7671(Msg, Conf, ExpectedEncode) -> + pretty_otp7671(Msg, Conf, ExpectedEncode, ok). + +pretty_otp7671(Msg, Conf, ExpectedEncode, ExpectedDecode) -> + otp7671(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode). + +pretty_otp7671(Msg, Conf, ExpectedEncode, ExpectedDecode, Check) -> + otp7671(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode, Check). + +otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode) -> + Check = fun(M1, M2) -> + exit({unexpected_decode_result, M1, M2}) + end, + otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode, Check). + +otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode, Check) -> + case (catch encode_message(Codec, Conf, Msg)) of + {error, _Reason} when ExpectedEncode =:= error -> + ok; + {error, Reason} when ExpectedEncode =:= ok -> + exit({unexpected_encode_failure, Reason}); + {ok, Bin} when ExpectedEncode =:= error -> + exit({unexpected_encode_success, Msg, binary_to_list(Bin)}); + {ok, Bin} when ExpectedEncode =:= ok -> + case decode_message(Codec, false, Conf, Bin) of + {ok, Msg} when ExpectedDecode =:= ok -> + ok; + {ok, Msg2} when ExpectedDecode =:= ok -> + Check(Msg, Msg2); + {ok, Msg} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg}); + {ok, Msg2} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg, Msg2}); + {error, _Reason} when ExpectedDecode =:= error -> + ok; + {error, Reason} when ExpectedDecode == ok -> + exit({unexpected_decode_failure, Msg, Reason}) + end + end. + + +pretty_otp7671_msg(DigitMapDesc) -> + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{digitMapDescriptor, DigitMapDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(?MGC_MID, 10001, ?megaco_null_context_id, [CmdReq]). + +pretty_otp7671_msg01() -> + Name = "dialplan01", + DigitMapDesc = cre_DigitMapDesc(Name), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg02() -> + Name = "dialplan02", + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body), + DigitMapDesc = cre_DigitMapDesc(Name, Value), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg03() -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body), + DigitMapDesc = cre_DigitMapDesc(Value), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg04() -> + DigitMapDesc = cre_DigitMapDesc(), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg05() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',?VERSION, + {domainName,{'DomainName',"tgc",asn1_NOVALUE}}, + {transactions, + [{transactionRequest, + {'TransactionRequest',12582952, + [{'ActionRequest',0,asn1_NOVALUE,asn1_NOVALUE, + [{'CommandRequest', + {modReq, + {'AmmRequest', + [{megaco_term_id,false,["root"]}], + [{digitMapDescriptor, + {'DigitMapDescriptor',"dialplan1", + {'DigitMapValue',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,[], + asn1_NOVALUE}}}]}}, + asn1_NOVALUE,asn1_NOVALUE}]}]}}]}}}. + +cmp_otp7671_msg05(#'MegacoMessage'{authHeader = asn1_NOVALUE, + mess = M1}, + #'MegacoMessage'{authHeader = asn1_NOVALUE, + mess = M2}) -> + #'Message'{messageBody = Body1} = M1, + #'Message'{messageBody = Body2} = M2, + {transactions, Trans1} = Body1, + {transactions, Trans2} = Body2, + [{transactionRequest, TR1}] = Trans1, + [{transactionRequest, TR2}] = Trans2, + #'TransactionRequest'{actions = Acts1} = TR1, + #'TransactionRequest'{actions = Acts2} = TR2, + [#'ActionRequest'{commandRequests = CR1}] = Acts1, + [#'ActionRequest'{commandRequests = CR2}] = Acts2, + [#'CommandRequest'{command = Cmd1}] = CR1, + [#'CommandRequest'{command = Cmd2}] = CR2, + {modReq, #'AmmRequest'{descriptors = Descs1}} = Cmd1, + {modReq, #'AmmRequest'{descriptors = Descs2}} = Cmd2, + [{digitMapDescriptor, + #'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value1}}] = Descs1, + [{digitMapDescriptor, + #'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value2}}] = Descs2, + #'DigitMapValue'{startTimer = asn1_NOVALUE, + shortTimer = asn1_NOVALUE, + longTimer = asn1_NOVALUE, + digitMapBody = [], + durationTimer = asn1_NOVALUE} = Value1, + asn1_NOVALUE = Value2, + ok. + + +%% -------------------------------------------------------------- +%% + + +pretty_otp8114_msg01(suite) -> + []; +pretty_otp8114_msg01(Config) when is_list(Config) -> + put(severity, trc), + put(dbg, true), + d("pretty_otp8114_msg01 -> entry", []), + ok = otp8114( pretty_otp8114_msg01(), megaco_pretty_text_encoder, ?EC), + erase(dbg), + erase(severity), + ok. + +pretty_otp8114_msg01() -> + "MEGACO/" ?VERSION_STR " [10.10.10.10]:1234\nTransaction = 1 {\n\tContext =\n1 {\n\t\tModify = ip/1/1/1 {\n\t\t\tMedia {\n\t\t\t\tStream = 1\n{\n\t\t\t\t\t\tLocalControl {\n\t\t\t\t\t\tMode =\nSendReceive\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tEvents = 1\n{\n\t\t\t\tadid/ipstop\n{\n\t\t\t\t\tdt=30,\n\t\t\t\t\tdir=\"BOTH\"\n\t\t\t\t},\n\t\t\t\tg/cause\n\n\t\t\t}\n\t\t}\n\t}\n}". + + +otp8114(InitialMessage, Codec, Conf) -> + Decode = fun(M) -> Codec:decode_message(Conf, M) end, + Encode = fun(B) -> Codec:encode_message(Conf, B) end, + InitialData = InitialMessage, + Instructions = + [ + %% List to binary + megaco_codec_test_lib:expect_instruction( + "Convert (initial) message to a binary", + fun(Msg) when is_list(Msg) -> + %% io:format("~s~n", [Msg]), + {ok, list_to_binary(Msg)}; + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Bin}, _Msg) when is_binary(Bin) -> + {ok, Bin}; + (Bad, _Msg) -> + {error, {failed_to_binary, Bad}} + end), + + %% Initial decode + megaco_codec_test_lib:expect_instruction( + "Decode (initial) message", + fun(Bin) when is_binary(Bin) -> + (catch Decode(Bin)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Msg}, _Bin) when is_record(Msg, 'MegacoMessage') -> + %% io:format("~p~n", [Msg]), + {ok, Msg}; + (Bad, _) -> + {error, {initial_decode_failed, Bad}} + end), + + %% Encode + megaco_codec_test_lib:expect_instruction( + "Encode message", + fun(Msg) when is_record(Msg, 'MegacoMessage') -> + (catch Encode(Msg)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Bin}, _Msg) when is_binary(Bin) -> + %% io:format("~s~n", [binary_to_list(Bin)]), + {ok, Bin}; + (Bad, _) -> + {error, {encode_failed, Bad}} + end), + + %% Decode + megaco_codec_test_lib:expect_instruction( + "(final) Decode message", + fun(Bin) when is_binary(Bin) -> + (catch Decode(Bin)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Msg}, _Bin) when is_record(Msg, 'MegacoMessage') -> + %% io:format("~p~n", [Msg]), + {ok, Msg}; + (Bad, _) -> + {error, {decode_failed, Bad}} + end) + ], + megaco_codec_test_lib:expect_exec(Instructions, InitialData). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +expect_codec_e(error, Codec, Msg, Conf) -> + Exec = + [ + {1, "Encode (initial) message", + fun(M) -> + (catch encode_message(Codec, [?EC_V3|Conf], M)) + end, + fun({error, _}, _) -> + {ok, done}; + ({ok, Bin}, _) -> + {error, {unexpected_encode_success, binary_to_list(Bin)}}; + (Else, _) -> + {error, {unexpected_encode_result, Else}} + end} + ], + exec(Exec, Msg); + +expect_codec_e(ok, Codec, Msg, Conf0) -> + Conf = [?EC_V3|Conf0], + Exec = + [ + {1, "Encode (initial) message", + fun(M) -> + (catch encode_message(Codec, Conf, M)) + end, + fun({ok, Bin}, M) -> + {ok, {Bin, M}}; + ({error, Reason}, _) -> + {error, {unexpected_encode_failure, Reason}}; + (Else, _) -> + {error, {unexpected_encode_result, Else}} + end}, + {2, "Decode message", + fun({Bin, _}) -> + (catch decode_message(Codec, false, Conf, Bin)) + end, + fun({ok, Msg1}, {_, Msg1}) -> + {ok, done}; + ({ok, Msg2}, {_, Msg1}) -> + case (catch chk_MegacoMessage(Msg1, Msg2)) of + ok -> + {ok, done}; + Error -> + Error + end; + (Else, _) -> + {error, {unexpected_decode_result, Else}} + end} + ], + exec(Exec, Msg). + + +expect_codec_d(error, Codec, Msg, Conf0) -> + Conf = [?EC_V3|Conf0], + Exec = + [ + {1, "Decode (initial) message", + fun(Bin) -> + (catch decode_message(Codec, false, Conf, Bin)) + end, + fun({error, _}, _) -> + {ok, done}; + ({ok, DecMsg}, _) -> + {error, {unexpected_decode_success, DecMsg}}; + (Else, _) -> + {error, {unexpected_decode_result, Else}} + end} + ], + exec(Exec, list_to_binary(Msg)); + +expect_codec_d(ok, Codec, Msg, Conf0) -> + Conf = [?EC_V3|Conf0], + Exec = + [ + {1, "Decode (initial) message", + fun(Bin) -> + (catch decode_message(Codec, false, Conf, Bin)) + end, + fun({ok, DecMsg}, Bin) -> + {ok, {DecMsg, Bin}}; + ({error, R}, _) -> + {Line, Mod, Reason} = + case lists:keysearch(reason, 1, R) of + {value, {reason, {L, M, Raw}}} when is_list(Raw) -> + {L, M, lists:flatten(Raw)}; + {value, {reason, {L, M, Raw}}} -> + {L, M, Raw} + end, + {value, {token, Tokens}} = lists:keysearch(token, 1, R), + {error, {unexpected_decode_failure, {Mod, Line, Reason, Tokens}}}; + (Else, _) -> + {error, {unexpected_decode_result, Else}} + end}, + {2, "Encode message", + fun({DecMsg, _}) -> + (catch encode_message(Codec, Conf, DecMsg)) + end, + fun({ok, Bin}, {_, Bin}) -> + {ok, done}; + ({ok, Bin}, {DecMsg, _}) -> + {ok, {DecMsg, Bin}}; + ({error, Reason}, _) -> + {error, {unexpected_encode_failure, Reason}}; + (Else, _) -> + {error, {unexpected_encode_result, Else}} + end}, + {3, "Decode message (if binaries not equal)", + fun(done) -> + done; + ({_, Bin}) -> + (catch decode_message(Codec, false, Conf, Bin)) + end, + fun(done, _) -> + {ok, done}; + ({ok, DecMsg}, {DecMsg, _}) -> + {ok, done}; + ({ok, DecMsg2}, {DecMsg1, _}) -> + case (catch chk_MegacoMessage(DecMsg1, DecMsg2)) of + ok -> + {ok, done}; + Error -> + Error + end; + ({error, Reason}, _) -> + {error, {unexpected_decode_failure, Reason}}; + (Else, _) -> + {error, {unexpected_decode_result, Else}} + end} + ], + exec(Exec, list_to_binary(Msg)). + + +exec([], _) -> + io:format("~n", []), + ok; +exec([{Num, _Desc, Cmd, Verify}|T], Data) -> + io:format("~n Exec command ~w: ~s => ", [Num, _Desc]), + case Verify((catch Cmd(Data)), Data) of + {ok, NewData} -> + io:format("ok", []), + exec(T, NewData); + {error, Reason} -> + io:format("error", []), + {error, {Num, Reason}} + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +msgs() -> + [M || {_, M, _, _} <- msgs(text)]. + +msgs(Encoding) -> + msgs1(Encoding) ++ + msgs2(Encoding) ++ msgs3(Encoding) ++ msgs4(Encoding) ++ + msgs5(Encoding) ++ msgs6(Encoding). + +msgs1(_) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [ + {msg01a, msg1a(), Plain, [{dbg,false}]}, + {msg01b, msg1b(), Plain, [{dbg,false}]}, + {msg02, msg2(), Plain, [{dbg,false}]}, + {msg03, msg3(), Plain, [{dbg,false}]}, + {msg04, msg4(), Plain, [{dbg,false}]}, + {msg05, msg5(), Plain, [{dbg,false}]}, + {msg06a, msg6a(), Plain, [{dbg,false}]}, + {msg06b, msg6b(), Plain, [{dbg,false}]}, + {msg07, msg7(), Plain, [{dbg,false}]}, + {msg08a, msg8a(), Plain, [{dbg,false}]}, + {msg08b, msg8b(), Plain, [{dbg,false}]}, + {msg09, msg9(), Plain, [{dbg,false}]}, + {msg10, msg10(), Plain, [{dbg,false}]}, + {msg11, msg11(), Plain, [{dbg,false}]}, + {msg12, msg12(), Plain, [{dbg,false}]}, + {msg13, msg13(), Plain, [{dbg,false}]}, + {msg14, msg14(), Plain, [{dbg,false}]}, + {msg15, msg15(), Plain, [{dbg,false}]}, + {msg16, msg16(), Plain, [{dbg,false}]}, + {msg17, msg17(), Plain, [{dbg,false}]}, + {msg18, msg18(), Plain, [{dbg,false}]}, + {msg19, msg19(), Plain, [{dbg,false}]}, + {msg20, msg20(), Plain, [{dbg,false}]}, + {msg21, msg21(), Plain, [{dbg,false}]}, + {msg22a, msg22a(), Plain, [{dbg,false}]}, + {msg22b, msg22b(), Plain, [{dbg,false}]}, + {msg22c, msg22c(), Plain, [{dbg,false}]}, + {msg22d, msg22d(), Plain, [{dbg,false}]}, + {msg22e, msg22e(), Plain, [{dbg,false}]}, + {msg22f, msg22f(), Plain, [{dbg,false}]}, + {msg23a, msg23a(), Plain, [{dbg,false}]}, + {msg23b, msg23b(), Plain, [{dbg,false}]}, + {msg23c, msg23c(), Plain, [{dbg,false}]}, + {msg23d, msg23d(), Plain, [{dbg,false}]}, + {msg24, msg24(), Plain, [{dbg,false}]}, + {msg25, msg25(), Plain, [{dbg,false}]}, + {msg30a, msg30a(), Plain, [{dbg,false}]}, + {msg30b, msg30b(), Plain, [{dbg,false}]}, + {msg30c, msg30c(), Plain, [{dbg,false}]}, + {msg30d, msg30d(), Plain, [{dbg,false}]} + ]. + + +msgs2(_) -> + TransFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:trans_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + ActionsFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:actions_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + ActionFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:action_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + [ + {msg01a_tf, msg1a(), TransFirst, [{dbg,false}]}, + {msg02_tf, msg2(), TransFirst, [{dbg,false}]}, + {msg10_tf, msg10(), TransFirst, [{dbg,false}]}, + {msg11_tf, msg11(), TransFirst, [{dbg,false}]}, + {msg23d_tf, msg23d(), TransFirst, [{dbg,false}]}, + {msg30b_tf, msg30b(), TransFirst, [{dbg,false}]}, + {msg30c_tf, msg30c(), TransFirst, [{dbg,false}]}, + {msg01a_asf, msg1a(), ActionsFirst, [{dbg,false}]}, + {msg02_asf, msg2(), ActionsFirst, [{dbg,false}]}, + {msg10_asf, msg10(), ActionsFirst, [{dbg,false}]}, + {msg23d_asf, msg23d(), ActionsFirst, [{dbg,false}]}, + {msg01a_af, msg1a(), ActionFirst, [{dbg,false}]}, + {msg02_af, msg2(), ActionFirst, [{dbg,false}]}, + {msg10_af, msg10(), ActionFirst, [{dbg,false}]}, + {msg23d_af, msg23d(), ActionFirst, [{dbg,false}]} + ]. + + +msgs3(_) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [{msgs3_name(Name), rfc3525_decode(M), Plain, [{dbg, false}]} || + {Name, M} <- rfc3525_msgs()]. + +msgs3_name(N) -> + list_to_atom("rfc3525_" ++ atom_to_list(N)). + +rfc3525_decode(M) when is_list(M) -> + rfc3525_decode(list_to_binary(M)); +rfc3525_decode(M) when is_binary(M) -> + case (catch decode_message(megaco_pretty_text_encoder, false, ?EC, M)) of + {ok, Msg} -> + Msg; + Error -> + {error, {rfc3525_decode_error, Error}} + end. + + +msgs4(_) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [ + {msg51a, msg51a(), Plain, [{dbg, false}]}, + {msg51b, msg51b(), Plain, [{dbg, false}]}, + {msg51c, msg51c(), Plain, [{dbg, false}]}, + {msg51d, msg51d(), Plain, [{dbg, false}]}, + {msg51e, msg51e(), Plain, [{dbg, false}]}, + {msg51f, msg51f(), Plain, [{dbg, false}]}, + {msg51g, msg51g(), Plain, [{dbg, false}]}, + {msg51h, msg51h(), Plain, [{dbg, false}]}, + {msg51i, msg51i(), Plain, [{dbg, false}]}, + {msg52, msg52(), Plain, [{dbg, false}]}, + {msg53, msg53(), Plain, [{dbg, false}]}, + {msg54a, msg54a(), Plain, [{dbg, false}]}, + {msg54b, msg54b(), Plain, [{dbg, false}]}, + {msg54c, msg54c(), Plain, [{dbg, false}]}, + {msg55, msg55(), Plain, [{dbg, false}]}, + {msg56, msg56(), Plain, [{dbg, false}]}, + {msg57, msg57(), Plain, [{dbg, false}]}, + {msg58a, msg58a(), Plain, [{dbg, false}]}, + {msg58b, msg58b(), Plain, [{dbg, false}]} + ]. + + +msgs5(Encoding) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + + PlainEDFail = + fun(Codec, DD, Ver, EC, M) -> + Res = + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M), + case Res of + {error, {message_encode_failed, Reason, _M}} -> + case Reason of + {error, {{deprecated, _}, _}} -> + ok; + _ -> + Res + end; + _ -> + Res + end + end, + + PlainDE = + fun(Codec, _DD, Ver, EC, B) -> + Res = + megaco_codec_test_lib:decode_message(Codec, false, Ver, + EC, B), + case Res of + {ok, M} -> + #'MegacoMessage'{mess = Mess} = M, + #'Message'{messageBody = {transactions, TRs}} = Mess, + [{transactionRequest, TR}] = TRs, + #'TransactionRequest'{actions = Actions} = TR, + [Action] = Actions, + #'ActionRequest'{commandRequests = CmdReqs} = Action, + [CmdReq] = CmdReqs, + #'CommandRequest'{command = Cmd} = CmdReq, + {addReq,AmmReq} = Cmd, + #'AmmRequest'{descriptors = []} = AmmReq, + ok; + _ -> + Res + end + end, + + Msgs = + [ + {msg61a, msg61a(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg61b, msg61b(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg61c, msg61c(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg62a, msg62a(), PlainEDFail, [{dbg,false}],[text,binary,erlang]}, + {msg62b, msg62b(), PlainDE, [{dbg,false}],[text]} + ], + [{N,M,F,C}||{N,M,F,C,E} <- Msgs,lists:member(Encoding,E)]. + +msgs6(Encoding) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + + Msgs = + [ + {msg71a, msg71a(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b01, msg71b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b02, msg71b02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b03, msg71b03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b04, msg71b04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b05, msg71b05(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b06, msg71b06(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b07, msg71b07(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b08, msg71b08(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b09, msg71b09(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b10, msg71b10(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b11, msg71b11(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b12, msg71b12(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b13, msg71b13(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b14, msg71b14(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b15, msg71b15(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b16, msg71b16(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b17, msg71b17(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b18, msg71b18(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c01, msg71c01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c02, msg71c02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c03, msg71c03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c04, msg71c04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c05, msg71c05(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c06, msg71c06(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c07, msg71c07(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c08, msg71c08(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c09, msg71c09(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71d01, msg71d01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71d02, msg71d02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71d03, msg71d03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72a01, msg72a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72a02, msg72a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72a03, msg72a03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72b01, msg72b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72b02, msg72b02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72b03, msg72b03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72b04, msg72b04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72c01, msg72c01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72c02, msg72c02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72c03, msg72c03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72c04, msg72c04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73a, msg73a(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73b01, msg73b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73b02, msg73b02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73c01, msg73c01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73c02, msg73c02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a01, msg74a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a02, msg74a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a03, msg74a03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a04, msg74a04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a05, msg74a05(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a06, msg74a06(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg75a01, msg75a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg75a02, msg75a02(), Plain, [{dbg,false}],[text,binary,erlang]} + ], + [{N,M,F,C}||{N,M,F,C,E} <- Msgs,lists:member(Encoding,E)]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +msg_actions([], Actions) -> + lists:reverse(Actions); +msg_actions([{CtxId, CmdReqs}|ActionInfo], Actions) -> + Action = ?MSG_LIB:cre_ActionRequest(CtxId,CmdReqs), + msg_actions(ActionInfo, [Action|Actions]). + +megaco_trans_req([], Transactions) -> + {transactions, lists:reverse(Transactions)}; +megaco_trans_req([{TransId, ActionInfo}|TransInfo], Transactions) -> + Actions = msg_actions(ActionInfo, []), + TR = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + megaco_trans_req(TransInfo, [Trans|Transactions]). + +megaco_message(Version, Mid, Body) -> + Mess = ?MSG_LIB:cre_Message(Version, Mid, Body), + cre_MegacoMessage(Mess). + +msg_request(Mid, TransInfo) -> + TransReq = megaco_trans_req(TransInfo, []), + megaco_message(?VERSION, Mid, TransReq). + +msg_request(Mid, TransId, ContextId, CmdReq) -> + Action = ?MSG_LIB:cre_ActionRequest(ContextId, CmdReq), + Actions = [Action], + TR = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg_request(Auth, Mid, TransId, ContextId, CmdReq) -> + Action = ?MSG_LIB:cre_ActionRequest(ContextId, CmdReq), + Actions = [Action], + TR = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + cre_MegacoMessage(Auth, Mess). + +msg_reply(Mid, TransId, Actions) -> + TR = cre_TransRep(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg_reply(Mid, TransId, ContextId, CmdReply) -> + Action = cre_ActRep(ContextId, CmdReply), + Actions = [Action], + msg_reply(Mid, TransId, Actions). + +msg_ack(Mid, [Range|_] = Ranges) when is_tuple(Range) -> + msg_ack(Mid, [Ranges]); + +msg_ack(Mid, Ranges) -> + %% TRAs = make_tras(Ranges, []), + TRAs = make_tras(Ranges), + Req = {transactions, TRAs}, + cre_MegacoMessage(?VERSION, Mid, Req). + +make_tras(TRARanges) -> + F = fun(R) -> {transactionResponseAck, make_tra(R)} end, + lists:map(F, TRARanges). + +make_tra(Ranges) -> + F = fun({F,L}) -> cre_TransAck(F,L) end, + lists:map(F, Ranges). + + +%% ------------------------------------------------------------------------- + + +msg1(Mid, Tid) -> + Gain = cre_PropParm("tdmc/gain", "2"), + Ec = cre_PropParm("tdmc/ec", "g165"), + LCD = cre_LocalControlDesc(sendRecv,[Gain, Ec]), + V = cre_PropParm("v", "0"), + %% C = cre_PropParm("c", "IN IP4 $ "), + C = cre_PropParm("c", [$I,$N,$ ,$I,$P,$4,$ ,$$,$ ]), + M = cre_PropParm("m", "audio $ RTP/AVP 0"), + A = cre_PropParm("a", "fmtp:PCMU VAD=X-NNVAD"), + LD = cre_LocalRemoteDesc([[V, C, M, A]]), + Parms = cre_StreamParms(LCD,LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + ReqEvent = cre_ReqedEv("al/of"), + EventsDesc = cre_EvsDesc(2222,[ReqEvent]), + AmmReq = cre_AmmReq([#megaco_term_id{id = Tid}], + [{mediaDescriptor, MediaDesc}, + {eventsDescriptor, EventsDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + Msg = msg_request(Mid, 9999, ?megaco_null_context_id, [CmdReq]), + Msg. + +msg1a() -> + msg1a(?MGC_MID). +msg1a(Mid) -> + msg1(Mid, ?A4444). + +msg1b() -> + msg1b(?MGC_MID). +msg1b(Mid) -> + msg1(Mid, ?A4445). + + +%% -------------------------- + + +msg2() -> + msg2(?MGC_MID). +msg2(Mid) -> + msg2(Mid, ?A4444). +msg2(Mid, Tid) -> + Gain = cre_PropParm("tdmc/gain", "2"), + Ec = cre_PropParm("tdmc/ec", "g165"), + LCD = cre_LocalControlDesc(sendRecv,[Gain, Ec]), + V = cre_PropParm("v", "0"), + %% C = cre_PropParm("c", "IN IP4 $ "), + C = cre_PropParm("c", [$I,$N,$ ,$I,$P,$4,$ ,$$,$ ]), + M = cre_PropParm("m", "audio $ RTP/AVP 0"), + A = cre_PropParm("a", "fmtp:PCMU VAD=X-NNVAD"), + LD = cre_LocalRemoteDesc([[V, C, M, A]]), + Parms = cre_StreamParms(LCD,LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + EventParm = cre_EvParm("strict",["exact"]), + ReqEvent = cre_ReqedEv("al/of", [EventParm]), + EventsDesc = cre_EvsDesc(2222,[ReqEvent]), + AmmReq = cre_AmmReq([#megaco_term_id{id = Tid}], + [{mediaDescriptor, MediaDesc}, + {eventsDescriptor, EventsDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 9999, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg3() -> + msg3(?MG1_MID). +msg3(Mid) -> + TimeStamp = cre_TimeNot("19990729", "22000000"), + Event = cre_ObsEv("al/of",TimeStamp), + Desc = cre_ObsEvsDesc(2222,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 10000, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg4() -> + msg4(?MG1_MID_NO_PORT, "901 mg col boot"). +msg4(Mid, Reason) when is_list(Reason) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChParm(restart,Address,[Reason],Profile), + Req = cre_SvcChReq([?megaco_root_termination_id],Parm), + CmdReq = cre_CmdReq({serviceChangeReq, Req}), + msg_request(Mid, 9998, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg5() -> + msg5(?MGC_MID). +msg5(Mid) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChResParm(Address,Profile), + Reply = cre_SvcChRep([?megaco_root_termination_id], + {serviceChangeResParms,Parm}), + msg_reply(Mid, 9998, ?megaco_null_context_id, + [{serviceChangeReply, Reply}]). + + +%% -------------------------- + +msg6(Mid, Tid) -> + Reply = cre_AmmsReply([#megaco_term_id{id = Tid}]), + msg_reply(Mid, 9999, ?megaco_null_context_id, [{modReply, Reply}]). + +msg6a() -> + msg6a(?MG1_MID). +msg6a(Mid) -> + msg6(Mid, ?A4444). + +msg6b() -> + msg6b(?MG2_MID). +msg6b(Mid) -> + msg6(Mid, ?A5555). + + +%% -------------------------- + +msg7() -> + msg7(?MGC_MID). +msg7(Mid) -> + Reply = cre_NotifyRep([#megaco_term_id{id = ?A4444}]), + msg_reply(Mid, 10000, ?megaco_null_context_id, [{notifyReply, Reply}]). + + +%% -------------------------- + +msg8(Mid, DigitMapValue) -> + Strict = cre_EvParm("strict",["state"]), + On = cre_ReqedEv("al/on", [Strict]), + Name = "dialplan00", + Action = cre_ReqedActs(Name), + Ce = cre_ReqedEv("dd/ce", Action), + EventsDesc = cre_EvsDesc(2223,[On, Ce]), + Signal = cre_Sig("cg/rt"), + DigMapDesc = cre_DigitMapDesc(Name, DigitMapValue), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, [{signal, Signal}]}, + {digitMapDescriptor, DigMapDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 10001, ?megaco_null_context_id, [CmdReq]). + +msg8a() -> + msg8a(?MGC_MID). +msg8a(Mid) -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body), + msg8(Mid, Value). + +msg8b() -> + msg8b(?MGC_MID). +msg8b(Mid) -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body, 1, 23, 99), + msg8(Mid, Value). + + +%% -------------------------- + +msg9() -> + msg9(?MG1_MID). +msg9(Mid) -> + TimeStamp = cre_TimeNot("19990729","22010001"), + Parm = cre_EvParm("ds",["916135551212"]), + Event = cre_ObsEv("dd/ce",TimeStamp,[Parm]), + Desc = cre_ObsEvsDesc(2223,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A4444}], Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 10002, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg10() -> + msg10(?MGC_MID). +msg10(Mid) -> + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}],[]), + CmdReq = cre_CmdReq({addReq, AmmReq}), + Jit = cre_PropParm("nt/jit", "40"), + LCD = cre_LocalControlDesc(recvOnly,[Jit]), + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 $ "), + M = cre_PropParm("m", "audio $ RTP/AVP 4"), + A = cre_PropParm("a", "ptime:30"), + V2 = cre_PropParm("v", "0"), + C2 = cre_PropParm("c", "IN IP4 $ "), + M2 = cre_PropParm("m", "audio $ RTP/AVP 0"), + LD = cre_LocalRemoteDesc([[V, C, M, A], [V2, C2, M2]]), + Parms = cre_StreamParms(LCD, LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + ChooseTid = #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}, + AmmReq2 = cre_AmmReq([ChooseTid],[{mediaDescriptor, MediaDesc}]), + CmdReq2 = cre_CmdReq({addReq, AmmReq2}), + msg_request(Mid, 10003, ?megaco_choose_context_id, [CmdReq, CmdReq2]). + + +msg11() -> + msg11(?MG1_MID). +msg11(Mid) -> + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 124.124.124.222"), + M = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + A = cre_PropParm("a", "ptime:30"), + A2 = cre_PropParm("a", "recvonly"), + LD = cre_LocalRemoteDesc([[V, C, M, A, A2]]), + Parms = cre_StreamParmsL(LD), + StreamDesc = cre_StreamDesc(1, Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + msg_reply(Mid, 10003, 2000, [{addReply, Reply}, {addReply, Reply2}]). + + +%% -------------------------- + +msg12() -> + msg12(?MGC_MID). +msg12(Mid) -> + LCD = cre_LocalControlDesc(sendRecv), + Parms = cre_StreamParms(LCD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Signal = cre_Sig("al/ri"), + Descs = [{mediaDescriptor, MediaDesc}, + {signalsDescriptor, [{signal, Signal}]}], + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A5555}], Descs), + CmdReq = cre_CmdReq({addReq, AmmReq}), + Jit = cre_PropParm("nt/jit", "40"), + LCD2 = cre_LocalControlDesc(sendRecv, [Jit]), + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 $ "), + M = cre_PropParm("m", "audio $ RTP/AVP 4"), + A = cre_PropParm("a", "ptime:30"), + LD2 = cre_LocalRemoteDesc([[V, C, M, A]]), + V2 = cre_PropParm("v", "0"), + C2 = cre_PropParm("c", "IN IP4 124.124.124.222"), + M2 = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + RD2 = cre_LocalRemoteDesc([[V2, C2, M2]]), + Parms2 = cre_StreamParms(LCD2,LD2,RD2), + StreamDesc2 = cre_StreamDesc(1,Parms2), + MediaDesc2 = cre_MediaDesc(StreamDesc2), + ChooseTid = #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}, + AmmReq2 = cre_AmmReq([ChooseTid],[{mediaDescriptor, MediaDesc2}]), + CmdReq2 = cre_CmdReq({addReq, AmmReq2}), + msg_request(Mid, 50003, ?megaco_choose_context_id, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg13() -> + msg13(?MG2_MID). +msg13(Mid) -> + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 125.125.125.111"), + M = cre_PropParm("m", "audio 1111 RTP/AVP 4"), + LD = cre_LocalRemoteDesc([[V, C, M]]), + Parms = cre_StreamParmsL(LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Reply = cre_AmmsReply([#megaco_term_id{id = ?A5556}], + [{mediaDescriptor, MediaDesc}]), + msg_reply(Mid, 50003, 5000, [{addReply, Reply}]). + + +%% -------------------------- + +msg14() -> + msg14(?MGC_MID). +msg14(Mid) -> + Signal = cre_Sig("cg/rt"), + AmmReq1 = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{signalsDescriptor, [{signal, Signal}]}]), + CmdReq1 = cre_CmdReq({modReq, AmmReq1}), + + Gain = cre_PropParm("tdmc/gain", "2"), + Ec = cre_PropParm("tdmc/ec", "g165"), + LCD = cre_LocalControlDesc(sendRecv, [Gain, Ec]), + Parms2 = cre_StreamParms(LCD), + StreamDesc2 = cre_StreamDesc(1,Parms2), + MediaDesc2 = cre_MediaDesc(StreamDesc2), + AmmReq2 = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc2}]), + CmdReq2 = cre_CmdReq({modReq, AmmReq2}), + + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 125.125.125.111"), + M = cre_PropParm("m", "audio 1111 RTP/AVP 4"), + RD = cre_LocalRemoteDesc([[V, C, M]]), + Parms3 = cre_StreamParmsR(RD), + StreamDesc3 = cre_StreamDesc(2,Parms3), + MediaDesc3 = cre_MediaDesc(StreamDesc3), + AmmReq3 = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc3}]), + CmdReq3 = cre_CmdReq({modReq, AmmReq3}), + msg_request(Mid, 10005, 2000, [CmdReq1, CmdReq2, CmdReq3]). + + +%% -------------------------- + +msg15() -> + msg15(?MG1_MID). +msg15(Mid) -> + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A4445}]), + msg_reply(Mid, 10005, 2000, [{modReply, Reply}, {modReply, Reply2}]). + + +%% -------------------------- + +msg16() -> + msg16(?MG2_MID). +msg16(Mid) -> + TimeStamp = cre_TimeNot("19990729","22020002"), + Event = cre_ObsEv("al/of",TimeStamp), + Desc = cre_ObsEvsDesc(1234,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 50005, 5000, [CmdReq]). + + +%% -------------------------- + +msg17() -> + msg17(?MGC_MID). +msg17(Mid) -> + Reply = cre_NotifyRep([#megaco_term_id{id = ?A5555}]), + msg_reply(Mid, 50005, ?megaco_null_context_id, [{notifyReply, Reply}]). + + +%% -------------------------- + +msg18() -> + msg18(?MGC_MID). +msg18(Mid) -> + On = cre_ReqedEv("al/on"), + EventsDesc = cre_EvsDesc(1235,[On]), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A5555}], + [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, []}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 50006, 5000, [CmdReq]). + + +%% -------------------------- + +msg19() -> + msg19(?MG2_MID). +msg19(Mid) -> + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4445}]), + msg_reply(Mid, 50006, 5000, [{modReply, Reply}]). + + +%% -------------------------- + +msg20() -> + msg20(?MGC_MID). +msg20(Mid) -> + LCD = cre_LocalControlDesc(sendRecv), + Parms = cre_StreamParms(LCD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + AmmReq2 = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{signalsDescriptor, []}]), + CmdReq2 = cre_CmdReq({modReq, AmmReq2}), + msg_request(Mid, 10006, 2000, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg21() -> + msg21(?MGC_MID). +msg21(Mid) -> + Tokens = [mediaToken, eventsToken, signalsToken, + digitMapToken, statsToken, packagesToken], + AuditDesc = cre_AuditDesc(Tokens), + Req = cre_AuditReq(#megaco_term_id{id = ?A5556},AuditDesc), + CmdReq = cre_CmdReq({auditValueRequest, Req}), + msg_request(Mid, 50007, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg22a() -> + msg22(1). + +msg22b() -> + msg22(10). + +msg22c() -> + msg22(25). + +msg22d() -> + msg22(50). + +msg22e() -> + msg22(75). + +msg22f() -> + msg22(100). + +msg22(N) -> + msg22(?MG2_MID, N). +msg22(Mid, N) -> + Jit = cre_PropParm("nt/jit", "40"), + LCD = cre_LocalControlDesc(sendRecv,[Jit]), + LDV = cre_PropParm("v", "0"), + LDC = cre_PropParm("c", "IN IP4 125.125.125.111"), + LDM = cre_PropParm("m", "audio 1111 RTP/AVP 4"), + LDA = cre_PropParm("a", "ptime:30"), + LD = cre_LocalRemoteDesc([[LDV, LDC, LDM, LDA]]), + RDV = cre_PropParm("v", "0"), + RDC = cre_PropParm("c", "IN IP4 124.124.124.222"), + RDM = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + RDA = cre_PropParm("a", "ptime:30"), + RD = cre_LocalRemoteDesc([[RDV, RDC, RDM, RDA]]), + StreamParms = cre_StreamParms(LCD,LD,RD), + StreamDesc = cre_StreamDesc(1,StreamParms), + Media = cre_MediaDesc(StreamDesc), + PackagesItem = cre_PkgsItem("nt",1), + PackagesItem2 = cre_PkgsItem("rtp",1), + Stat = cre_StatsParm("rtp/ps","1200"), + Stat2 = cre_StatsParm("nt/os","62300"), + Stat3 = cre_StatsParm("rtp/pr","700"), + Stat4 = cre_StatsParm("nt/or","45100"), + Stat5 = cre_StatsParm("rtp/pl","0.2"), + Stat6 = cre_StatsParm("rtp/jit","20"), + Stat7 = cre_StatsParm("rtp/delay","40"), + Statistics = [Stat, Stat2, Stat3, Stat4, Stat5, Stat6, Stat7], + Audits = [{mediaDescriptor, Media}, + {packagesDescriptor, [PackagesItem, PackagesItem2]}, + {statisticsDescriptor, Statistics}], + Reply = {auditResult, + cre_AuditRes(#megaco_term_id{id = ?A5556},Audits)}, + msg_reply(Mid, 50007, ?megaco_null_context_id, + lists:duplicate(N,{auditValueReply, Reply})). +%% msg_reply(Mid, 50007, ?megaco_null_context_id, +%% lists.duplicate([{auditValueReply, Reply}]). + + +%% -------------------------- + +msg23a() -> + msg23a(?MG2_MID). +msg23a(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 50008, 5000, [CmdReq]). + + +msg23b() -> + msg23b(?MG2_MID). +msg23b(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq1 = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_CmdReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_NotifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_CmdReq({notifyReq, NotifyReq2}), + ActionInfo = [{5000, [CmdReq1]}, {5001, [CmdReq2]}], + TransInfo = [{50008, ActionInfo}], + msg_request(Mid, TransInfo). + + +msg23c() -> + msg23c(?MG2_MID). +msg23c(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq1 = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_CmdReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_NotifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_CmdReq({notifyReq, NotifyReq2}), + ActionInfo1 = [{5000, [CmdReq1]}], + ActionInfo2 = [{5001, [CmdReq2]}], + TransInfo = [{50008, ActionInfo1}, {50009, ActionInfo2}], + msg_request(Mid, TransInfo). + + +msg23d() -> + msg23d(?MG2_MID). +msg23d(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq1 = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_CmdReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_NotifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_CmdReq({notifyReq, NotifyReq2}), + NotifyReq3 = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc), + CmdReq3 = cre_CmdReq({notifyReq, NotifyReq3}), + NotifyReq4 = cre_NotifyReq([#megaco_term_id{id = ?A4445}],Desc), + CmdReq4 = cre_CmdReq({notifyReq, NotifyReq4}), + ActionInfo1 = [{5000, [CmdReq1]}, {5001, [CmdReq2]}], + ActionInfo2 = [{5003, [CmdReq3]}, {5004, [CmdReq4]}], + TransInfo = [{50008, ActionInfo1}, {50009, ActionInfo2}], + msg_request(Mid, TransInfo). + + +%% -------------------------- + +msg24() -> + msg24(?MGC_MID). +msg24(Mid) -> + AuditDesc = cre_AuditDesc([statsToken]), + SubReq = cre_SubReq([#megaco_term_id{id = ?A5555}], AuditDesc), + SubReq2 = cre_SubReq([#megaco_term_id{id = ?A5556}], AuditDesc), + CmdReq = cre_CmdReq({subtractReq, SubReq}), + CmdReq2 = cre_CmdReq({subtractReq, SubReq2}), + msg_request(Mid, 50009, 5000, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg25() -> + msg25(?MG2_MID). +msg25(Mid) -> + Stat11 = cre_StatsParm("nt/os","45123"), + Stat12 = cre_StatsParm("nt/dur", "40"), + Stats1 = [Stat11, Stat12], + Reply1 = cre_AmmsReply([#megaco_term_id{id = ?A5555}], + [{statisticsDescriptor, Stats1}]), + Stat21 = cre_StatsParm("rtp/ps","1245"), + Stat22 = cre_StatsParm("nt/os", "62345"), + Stat23 = cre_StatsParm("rtp/pr", "780"), + Stat24 = cre_StatsParm("nt/or", "45123"), + Stat25 = cre_StatsParm("rtp/pl", "10"), + Stat26 = cre_StatsParm("rtp/jit", "27"), + Stat27 = cre_StatsParm("rtp/delay","48"), + Stats2 = [Stat21, Stat22, Stat23, Stat24, Stat25, Stat26, Stat27], + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A5556}], + [{statisticsDescriptor, Stats2}]), + msg_reply(Mid, 50009, 5000, + [{subtractReply, Reply1}, {subtractReply, Reply2}]). + + +msg30a() -> + msg_ack(?MG2_MID, [{9,9}]). + +msg30b() -> + msg_ack(?MG2_MID, [{9,13}]). + +msg30c() -> + msg_ack(?MG2_MID, + [{9,13}, {15,15}, {33,40}, {50,60}, {70,80}, {85,90}, + {101,105},{109,119},{121,130},{140,160},{170,175},{180,189}, + {201,205},{209,219},{221,230},{240,260},{270,275},{280,289}, + {301,305},{309,319},{321,330},{340,360},{370,375},{380,389}, + {401,405},{409,419},{421,430},{440,460},{470,475},{480,489}, + {501,505},{509,519},{521,530},{540,560},{570,575},{580,589} + ]). + +%% Don't think this will be used by the megaco stack, but since it +%% seem's to be a valid construction... +msg30d() -> + msg_ack(?MG2_MID, + [[{9,13}, {15,15}, {33,40}, {50,60}, {70,80}, {85,90}], + [{101,105},{109,119},{121,130},{140,160},{170,175},{180,189}], + [{201,205},{209,219},{221,230},{240,260},{270,275},{280,289}], + [{301,305},{309,319},{321,330},{340,360},{370,375},{380,389}], + [{401,405},{409,419},{421,430},{440,460},{470,475},{480,489}], + [{501,505},{509,519},{521,530},{540,560},{570,575},{580,589}] + ]). + + + +msg40() -> + msg40(?MG1_MID_NO_PORT, "901 mg col boot"). +msg40(Mid, Reason) when is_list(Reason) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChParm(restart,Address,[Reason],Profile), + Req = cre_SvcChReq([?megaco_root_termination_id],Parm), + CmdReq = cre_CmdReq({serviceChangeReq, Req}), + Auth = cre_AuthHeader(), + msg_request(Auth, Mid, 9998, ?megaco_null_context_id, [CmdReq]). + + +msg50(Mid, APT) -> + AD = cre_AuditDesc(asn1_NOVALUE, APT), + Req = cre_AuditReq(#megaco_term_id{id = ?A5556},AD), + CmdReq = cre_CmdReq({auditValueRequest, Req}), + msg_request(Mid, 50007, ?megaco_null_context_id, [CmdReq]). + +%% IndAudMediaDescriptor: +msg51(Mid, IATSDorStream) -> + IAMD = cre_IndAudMediaDesc(IATSDorStream), + IAP = cre_IndAudParam(IAMD), + APT = [IAP], + msg50(Mid, APT). + +msg51a() -> + msg51a(?MG2_MID). +msg51a(Mid) -> + PP = cre_IndAudPropertyParm("tdmc/gain"), + PPs = [PP], + IATSD = cre_IndAudTermStateDesc(PPs), + msg51(Mid, IATSD). + +msg51b() -> + msg51b(?MG2_MID). +msg51b(Mid) -> + PP = cre_IndAudPropertyParm("nt/jit"), + PPs = [PP], + IATSD = cre_IndAudTermStateDesc(PPs), + msg51(Mid, IATSD). + +msg51c() -> + msg51c(?MG2_MID). +msg51c(Mid) -> + IATSD = cre_IndAudTermStateDesc([], asn1_NOVALUE, 'NULL'), + msg51(Mid, IATSD). + +msg51d() -> + msg51d(?MG2_MID). +msg51d(Mid) -> + IATSD = cre_IndAudTermStateDesc([], 'NULL', asn1_NOVALUE), + msg51(Mid, IATSD). + +msg51e() -> + msg51e(?MG2_MID). +msg51e(Mid) -> + IALCD = cre_IndAudLocalControlDesc('NULL', asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE), + IASP = cre_IndAudStreamParms(IALCD), + msg51(Mid, IASP). + +msg51f() -> + msg51f(?MG2_MID). +msg51f(Mid) -> + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, 'NULL', + asn1_NOVALUE, asn1_NOVALUE), + IASP = cre_IndAudStreamParms(IALCD), + msg51(Mid, IASP). + +msg51g() -> + msg51g(?MG2_MID). +msg51g(Mid) -> + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, asn1_NOVALUE, + 'NULL', asn1_NOVALUE), + IASP = cre_IndAudStreamParms(IALCD), + msg51(Mid, IASP). + +msg51h() -> + msg51h(?MG2_MID). +msg51h(Mid) -> + Name = "nt/jit", + IAPP = cre_IndAudPropertyParm(Name), + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, asn1_NOVALUE, + asn1_NOVALUE, [IAPP]), + IASP = cre_IndAudStreamParms(IALCD), + SID = 123, + IASD = cre_IndAudStreamDesc(SID, IASP), + msg51(Mid, [IASD]). + + +msg51i() -> + msg51i(?MG2_MID). +msg51i(Mid) -> + Name = "nt/jit", + Name2 = "tdmc/ec", + IAPP = cre_IndAudPropertyParm(Name), + IAPP2 = cre_IndAudPropertyParm(Name2), + IALCD = cre_IndAudLocalControlDesc('NULL', 'NULL', 'NULL', + [IAPP, IAPP2]), + IASP = cre_IndAudStreamParms(IALCD), + SID = 123, + IASD = cre_IndAudStreamDesc(SID, IASP), + msg51(Mid, [IASD]). + + +%% IndAudEventsDescriptor: +msg52() -> + msg52(?MG2_MID). +msg52(Mid) -> + RequestID = 1235, + PkgdName = "tonedet/std", + IAED = cre_IndAudEvsDesc(RequestID, PkgdName), + IAP = cre_IndAudParam(IAED), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudEventBufferDescriptor: +msg53() -> + msg53(?MG2_MID). +msg53(Mid) -> + EN = "tonedet/std", + SID = 1, + IAEBD = cre_IndAudEvBufDesc(EN, SID), + IAP = cre_IndAudParam(IAEBD), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudSignalsDescriptor: +msg54(Mid, Sig) -> + IASD = cre_IndAudSigsDesc(Sig), + IAP = cre_IndAudParam(IASD), + APT = [IAP], + msg50(Mid, APT). + +msg54a() -> + msg54a(?MG2_MID). +msg54a(Mid) -> + SN = "tonegen/pt", + Sig = cre_IndAudSig(SN), + msg54(Mid, Sig). + +msg54b() -> + msg54b(?MG2_MID). +msg54b(Mid) -> + SN = "dg/d0", + Sig = cre_IndAudSig(SN), + msg54(Mid, Sig). + +msg54c() -> + msg54c(?MG2_MID). +msg54c(Mid) -> + SN = "ct/ct", + Sig = cre_IndAudSig(SN), + ID = 4321, + SSL = cre_IndAudSeqSigList(ID, Sig), + msg54(Mid, SSL). + +%% IndAudDigitMapDescriptor: +msg55() -> + msg55(?MG2_MID). +msg55(Mid) -> + DMN = "dialplan00", + IADMD = cre_IndAudDigitMapDesc(DMN), + IAP = cre_IndAudParam(IADMD), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudStatisticsDescriptor: +msg56() -> + msg56(?MG2_MID). +msg56(Mid) -> + SN = "nt/dur", + IASD = cre_IndAudStatsDesc(SN), + IAP = cre_IndAudParam(IASD), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudPackagesDescriptor: +msg57() -> + msg57(?MG2_MID). +msg57(Mid) -> + PN = "al", + PV = 1, + IAPD = cre_IndAudPkgsDesc(PN, PV), + IAP = cre_IndAudParam(IAPD), + APT = [IAP], + msg50(Mid, APT). + +%% Sum it up: +msg58_iaMediaDesc_iap(IATSD) -> + IAMD = cre_IndAudMediaDesc(IATSD), + cre_IndAudParam(IAMD). + +msg58_iaMediaDesc_iap_a() -> + PP = cre_IndAudPropertyParm("tdmc/gain"), + PPs = [PP], + IATSD = cre_IndAudTermStateDesc(PPs), + msg58_iaMediaDesc_iap(IATSD). + +msg58_iaMediaDesc_iap_b() -> + IATSD = cre_IndAudTermStateDesc([], 'NULL', asn1_NOVALUE), + msg58_iaMediaDesc_iap(IATSD). + +msg58_iaEvsDesc_iap() -> + RequestID = 1235, + PkgdName = "tonedet/std", + IAED = cre_IndAudEvsDesc(RequestID, PkgdName), + cre_IndAudParam(IAED). + +msg58_iaEvBufDesc_iap() -> + EN = "tonedet/std", + SID = 1, + IAEBD = cre_IndAudEvBufDesc(EN, SID), + cre_IndAudParam(IAEBD). + +msg58_iaSigsDesc_iap(S) -> + IASD = cre_IndAudSigsDesc(S), + cre_IndAudParam(IASD). + +msg58_iaSigsDesc_iap_a() -> + SN = "tonegen/pt", + Sig = cre_IndAudSig(SN), + msg58_iaSigsDesc_iap(Sig). + +msg58_iaSigsDesc_iap_b() -> + SN = "ct/ct", + Sig = cre_IndAudSig(SN), + ID = 4321, + SSL = cre_IndAudSeqSigList(ID, Sig), + msg58_iaSigsDesc_iap(SSL). + +msg58_iaDigMapDesc_iap() -> + DMN = "dialplan00", + IADMD = cre_IndAudDigitMapDesc(DMN), + cre_IndAudParam(IADMD). + +msg58_iaStatsDesc_iap() -> + SN = "nt/dur", + IASD = cre_IndAudStatsDesc(SN), + cre_IndAudParam(IASD). + +msg58_iaPacksDesc_iap() -> + PN = "al", + PV = 1, + IAPD = cre_IndAudPkgsDesc(PN, PV), + cre_IndAudParam(IAPD). + +msg58a() -> + msg58a(?MG2_MID). +msg58a(Mid) -> + IAMD = msg58_iaMediaDesc_iap_a(), + IAED = msg58_iaEvsDesc_iap(), + IAEBD = msg58_iaEvBufDesc_iap(), + IASiD = msg58_iaSigsDesc_iap_a(), + IADMD = msg58_iaDigMapDesc_iap(), + IAStD = msg58_iaStatsDesc_iap(), + IAPD = msg58_iaPacksDesc_iap(), + APT = [IAMD, IAED, IAEBD, IASiD, IADMD, IAStD, IAPD], + msg50(Mid, APT). + +msg58b() -> + msg58b(?MG2_MID). +msg58b(Mid) -> + IAMD = msg58_iaMediaDesc_iap_b(), + IAED = msg58_iaEvsDesc_iap(), + IAEBD = msg58_iaEvBufDesc_iap(), + IASiD = msg58_iaSigsDesc_iap_b(), + IADMD = msg58_iaDigMapDesc_iap(), + IAStD = msg58_iaStatsDesc_iap(), + IAPD = msg58_iaPacksDesc_iap(), + APT = [IAMD, IAED, IAEBD, IASiD, IADMD, IAStD, IAPD], + msg50(Mid, APT). + + +%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +%% Tests some of the changes in the v2 corr 1 (EmergencyOff and ModemDesc) + +%% Emergency On/Off (optional) tests +msg61(EM) -> + TS = cre_TimeNot("19990729", "22000000"), + Event = cre_ObsEv("al/of",TS), + Desc = cre_ObsEvsDesc(2222,[Event]), + NotReq = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc), + Cmd = ?MSG_LIB:cre_Command(notifyReq, NotReq), + CmdReq = cre_CmdReq(Cmd), + CtxReq = ?MSG_LIB:cre_ContextRequest(15, EM), + ActReq = ?MSG_LIB:cre_ActionRequest(1, CtxReq, [CmdReq]), + Acts = [ActReq], + TR = ?MSG_LIB:cre_TransactionRequest(9898, Acts), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, ?MG1_MID, [Trans]), + cre_MegacoMessage(Mess). + +msg61a() -> + msg61(false). + +msg61b() -> + msg61(true). + +msg61c() -> + msg61(asn1_NOVALUE). + + +msg62a() -> + MT = ?MSG_LIB:cre_ModemType(v18), + PP = cre_PropParm("c", "IN IP4 $ "), + MD = ?MSG_LIB:cre_ModemDescriptor([MT], [PP]), + AmmDesc = ?MSG_LIB:cre_AmmDescriptor(MD), + TermIDs = [#megaco_term_id{id = ?A4444}], + AmmReq = ?MSG_LIB:cre_AmmRequest(TermIDs, [AmmDesc]), + Cmd = ?MSG_LIB:cre_Command(addReq, AmmReq), + CmdReq = ?MSG_LIB:cre_CommandRequest(Cmd), + ActReq = ?MSG_LIB:cre_ActionRequest(2, [CmdReq]), + Acts = [ActReq], + TR = ?MSG_LIB:cre_TransactionRequest(9898, Acts), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, ?MG1_MID, [Trans]), + cre_MegacoMessage(Mess). + +msg62b() -> + MP = +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 +Transaction = 9898 { + Context = 2 { + Add = 11111111/00000000/00000000 { + Modem[V18] { + tdmc/gain=2 + } + } + } +}", +% MC = +% "!/" ?VERSION_STR " [124.124.124.222]:55555\nT=9898{C=2{A=11111111/00000000/00000000{MD[V18]{tdmc/gain=2}}}}", + list_to_binary(MP). + +%% ActionRequest with various combinations of ContextRequest and +%% ContextAttrAuditRequest +msg71(CR, CAAR) -> + TS1 = cre_TimeNot("19990729", "22000000"), + TS2 = cre_TimeNot("19990729", "22000111"), + Event1 = cre_ObsEv("al/of",TS1), + Event2 = cre_ObsEv("al/on",TS2), + Desc1 = cre_ObsEvsDesc(2222,[Event1]), + Desc2 = cre_ObsEvsDesc(2222,[Event2]), + NR1 = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc1), + NR2 = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc2), + Cmd1 = ?MSG_LIB:cre_Command(notifyReq, NR1), + Cmd2 = ?MSG_LIB:cre_Command(notifyReq, NR2), + CR1 = cre_CmdReq(Cmd1), + CR2 = cre_CmdReq(Cmd2), + ActReq = ?MSG_LIB:cre_ActionRequest(1, CR, CAAR, [CR1, CR2]), + Acts = [ActReq], + TR = ?MSG_LIB:cre_TransactionRequest(9898, Acts), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, ?MG1_MID, [Trans]), + cre_MegacoMessage(Mess). + +msg71a() -> + CR = cre_ContextRequest(), + CAAR = cre_ContextAttrAuditRequest(), + msg71(CR, CAAR). + +msg71b(CR) -> + CAAR = asn1_NOVALUE, + msg71(CR, CAAR). + +msg71b01() -> + CR = cre_ContextRequest(15), + msg71b(CR). + +msg71b02() -> + CR = cre_ContextRequest(true), + msg71b(CR). + +msg71b03() -> + CR = cre_ContextRequest(false), + msg71b(CR). + +msg71b04() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(Top), + msg71b(CR). + +msg71b05() -> + CR = cre_ContextRequest(15, true), + msg71b(CR). + +msg71b06() -> + CR = cre_ContextRequest(15, false), + msg71b(CR). + +msg71b07() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, Top), + msg71b(CR). + +msg71b08() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, true, Top), + msg71b(CR). + +msg71b09() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, false, Top), + msg71b(CR). + +msg71b10() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, true, Top, true), + msg71b(CR). + +msg71b11() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, true, Top, false), + msg71b(CR). + +msg71b12() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", "2"), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, Props), + msg71b(CR). + +msg71b13() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2"], relation, greaterThan), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, Props), + msg71b(CR). + +msg71b14() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","10"], range, true), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, Props), + msg71b(CR). + +msg71b15() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("nt/jit", ["40","50","50"], sublist, true), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, Props), + msg71b(CR). + +msg71b16() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, true, Props), + msg71b(CR). + +msg71b17() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, true, Top, false), + msg71b(CR). + +msg71b18() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, false, Props), + msg71b(CR). + +msg71c(CAAR) -> + CR = asn1_NOVALUE, + msg71(CR, CAAR). + +msg71c01() -> + CAAR = cre_ContextAttrAuditRequest('NULL', 'NULL', 'NULL'), + msg71c(CAAR). + +msg71c02() -> + CAAR = cre_ContextAttrAuditRequest('NULL', 'NULL', asn1_NOVALUE), + msg71c(CAAR). + +msg71c03() -> + CAAR = cre_ContextAttrAuditRequest('NULL', asn1_NOVALUE, 'NULL'), + msg71c(CAAR). + +msg71c04() -> + CAAR = cre_ContextAttrAuditRequest(asn1_NOVALUE, 'NULL', 'NULL'), + msg71c(CAAR). + +msg71c05() -> + CAAR = cre_ContextAttrAuditRequest(asn1_NOVALUE, asn1_NOVALUE, 'NULL'), + msg71c(CAAR). + +msg71c06() -> + CAAR = cre_ContextAttrAuditRequest(asn1_NOVALUE, 'NULL', asn1_NOVALUE), + msg71c(CAAR). + +msg71c07() -> + CAAR = cre_ContextAttrAuditRequest('NULL', asn1_NOVALUE, asn1_NOVALUE), + msg71c(CAAR). + +msg71c08() -> + CAAR = cre_ContextAttrAuditRequest('NULL', asn1_NOVALUE, 'NULL', 'NULL'), + msg71c(CAAR). + +msg71c09() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + CAAR = cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, CPA), + msg71c(CAAR). + +msg71d01() -> + CR = cre_ContextRequest(15, true), + CAAR = cre_ContextAttrAuditRequest('NULL', 'NULL', 'NULL'), + msg71(CR, CAAR). + +msg71d02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2"], relation, unequalTo), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, true, Props), + + CAAR_Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + CAAR = cre_ContextAttrAuditRequest(CAAR_Top, Em, Prio, Ieps, CPA), + + msg71(CR, CAAR). + +msg71d03() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2"], relation, unequalTo), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, false, Props), + + CAAR_Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + CAAR = cre_ContextAttrAuditRequest(CAAR_Top, Em, Prio, Ieps, CPA), + + msg71(CR, CAAR). + +msg72(ED, CR) -> + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 124.124.124.222"), + M = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + A = cre_PropParm("a", "a=ptime:30"), + A2 = cre_PropParm("a", "recvonly"), + LD = cre_LocalRemoteDesc([[V, C, M, A, A2]]), + Parms = cre_StreamParmsL(LD), + StreamDesc = cre_StreamDesc(1, Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + CmdRep = [{addReply, Reply}, {addReply, Reply2}], + Action = cre_ActRep(2000, ED, CR, CmdRep), + msg_reply(?MGC_MID, 10003, [Action]). + +msg72a(CR) -> + ED = asn1_NOVALUE, + msg72(ED, CR). + +msg72a01() -> + CR = cre_ContextRequest(false), + msg72a(CR). + +msg72a02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(Top), + msg72a(CR). + +msg72a03() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, Top), + msg72a(CR). + +msg72b(CR) -> + EC = ?MSG_LIB:cre_ErrorCode(?megaco_not_ready), + ED = ?MSG_LIB:cre_ErrorDescriptor(EC), + msg72(ED, CR). + +msg72b01() -> + CR = cre_ContextRequest(15, false), + msg72b(CR). + +msg72b02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, false, Top), + msg72b(CR). + +msg72b03() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, true, Top, true), + msg72b(CR). + +msg72b04() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_ContextRequest(15, true, Top, false), + msg72b(CR). + +msg72c(CR) -> + EC = ?MSG_LIB:cre_ErrorCode(?megaco_not_ready), + ET = ?MSG_LIB:cre_ErrorText("Just another error string"), + ED = ?MSG_LIB:cre_ErrorDescriptor(EC, ET), + msg72(ED, CR). + +msg72c01() -> + CR = cre_ContextRequest(15), + msg72c(CR). + +msg72c02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", "2"), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, Props), + msg72c(CR). + +msg72c03() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, true, Props), + msg72c(CR). + +msg72c04() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CR = cre_ContextRequest(15, true, Top, false, Props), + msg72c(CR). + + +msg73() -> + Stat1 = cre_StatsParm("rtp/ps"), + Stat2 = cre_StatsParm("nt/os","62300"), + Stat3 = cre_StatsParm("rtp/pr","700"), + Stat4 = cre_StatsParm("nt/or","45100"), + Stat5 = cre_StatsParm("rtp/pl","0.2"), + Stat6 = cre_StatsParm("rtp/jit","20"), + Stat7 = cre_StatsParm("rtp/delay","40"), + Stats = [Stat1, Stat2, Stat3, Stat4, Stat5, Stat6, Stat7], + cre_StatsDesc(Stats). + +%% StatisticsDescriptor in AmmDescriptor +msg73a() -> + StatDesc = msg73(), + AmmDesc = cre_AmmDesc(StatDesc), + TermIDs = [#megaco_term_id{id = ["11111111", "00001111", "00000000"]}], + AmmReq = cre_AmmReq(TermIDs, [AmmDesc]), + Cmd = cre_Cmd(addReq, AmmReq), + CmdReq = cre_CmdReq(Cmd), + CID = cre_CtxID(7301), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(7302), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + + +%% StatisticsDescriptor in IndAudStreamParms +msg73b1() -> + IASD = cre_IndAudStatsDesc("nt/dur"), + cre_IndAudStreamParms(IASD). + +msg73b2(IAMD) -> + IAP = cre_IndAudParam(IAMD), + AD = cre_AuditDesc([IAP]), + TermID = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + AudReq = cre_AuditReq(TermID, AD), + Cmd = cre_Cmd(auditValueRequest, AudReq), + CmdReq = cre_CmdReq(Cmd), + CID = cre_CtxID(7311), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(7312), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg73b01() -> + IASP = msg73b1(), + IAMD = cre_IndAudMediaDesc(IASP), + msg73b2(IAMD). + +msg73b02() -> + IASP = msg73b1(), + SID = cre_StreamID(303), + IASD = cre_IndAudStreamDesc(SID, IASP), + IAMD = cre_IndAudMediaDesc([IASD]), + msg73b2(IAMD). + +%% StatisticsDescriptor in StreamParms +msg73c1() -> + StatDesc = msg73(), + SP = cre_StreamParms(StatDesc), + SID = cre_StreamID(505), + cre_StreamDesc(SID, SP). + +msg73c2(MD) -> + ARP = cre_AuditRetParam(MD), + TA = cre_TermAudit([ARP]), + TermIDs = [#megaco_term_id{id = ["11111111", "00001111", "00000000"]}], + AmmsRep = cre_AmmsReply(TermIDs, TA), + CmdRep = cre_CmdRep(moveReply, AmmsRep), + CID = cre_CtxID(606), + ActRep = cre_ActRep(CID, [CmdRep]), + TransId = cre_TransId(8899), + TransRep = cre_TransRep(TransId, [ActRep]), + Trans = cre_Trans(TransRep), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg73c01() -> + SD = msg73c1(), + MD = cre_MediaDesc(SD), + msg73c2(MD). + +msg73c02() -> + SD = msg73c1(), + MD = cre_MediaDesc([SD]), + msg73c2(MD). + + +%% New Signal (direction and requestID); msg74 +msg74a1(D) -> + Dir = cre_SigDir(D), + cre_Sig("cg/rt", Dir, asn1_NOVALUE). + +msg74a2(D, RID) -> + Dir = cre_SigDir(D), + cre_Sig("cg/rt", Dir, RID). + +msg74a3(D, RID) -> + Name = "al/ri", + SID = cre_StreamID(7401), + ST = cre_SigType(brief), + Dur = 7499, + NC = cre_NotifCompl([onTimeOut,otherReason]), + KA = cre_BOOLEAN(true), + SPL = [], + Dir = cre_SigDir(D), + cre_Sig(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID). + +msg74a4(Sig) -> + SR = cre_SigReq(Sig), + SD = cre_SigsDesc([SR]), + AD = cre_AmmDesc(SD), + TermIDs = [#megaco_term_id{id = ?A4444}], + AR = cre_AmmReq(TermIDs, [AD]), + Cmd = cre_Cmd(modReq, AR), + cre_CmdReq(Cmd). + +msg74a01() -> + Sig = msg74a1(internal), + CR = msg74a4(Sig), + CID = cre_CtxID(7411), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7421), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a02() -> + Sig = msg74a1(both), + CR = msg74a4(Sig), + CID = cre_CtxID(7412), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7422), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a03() -> + RID = cre_ReqID(7433), + Sig = msg74a2(external, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7413), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7423), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a04() -> + RID = cre_ReqID(7434), + Sig = msg74a2(both, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7414), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7424), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a05() -> + RID = cre_ReqID(7435), + Sig = msg74a3(both, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7415), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7425), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a06() -> + RID = cre_ReqID(7436), + Sig = msg74a3(internal, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7416), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7426), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + + + +%% New ServiceChangeParm (serviceChangeIncompleteFlag); msg75 +msg75a(IncFlag) -> + Method = cre_SvcChMethod(restart), + Address = cre_SvcChAddr(portNumber, ?DEFAULT_PORT), + Reason = "901 mg col boot", + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChParm(Method, Address, [Reason], Profile, IncFlag), + TermIDs = [?megaco_root_termination_id], + Req = cre_SvcChReq(TermIDs, Parm), + Cmd = cre_Cmd(serviceChangeReq, Req), + CR = cre_CmdReq(Cmd), + CID = cre_CtxID(7501), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7502), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg75a01() -> + msg75a(asn1_NOVALUE). + +msg75a02() -> + msg75a('NULL'). + + +%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +%% Pretty RFC 3525 messages: + +%% Added Reason +rfc3525_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + +rfc3525_msg2() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +%% Removed "," after LocalControl ending "}" +rfc3525_msg3() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 9999 { + Context = - { + Modify = A4444 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive, + tdmc/gain=2, ; in dB, + tdmc/ec=on + } + } + }, + Events = 2222 { + al/of {strict=state} + } + } + } +}". + +%% Removed the outermost "{}" pair (before the Reply token) +rfc3525_msg4() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 9999 { + Context = - { + Modify = A4444 + } +}". + +rfc3525_msg6() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Transaction = 10000 { + Context = - { + Notify = A4444 { + ObservedEvents =2222 { + 19990729T22000000:al/of{init=false} + } + } + } +}". + + +rfc3525_msg7() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 10000 { + Context = - { + Notify = A4444 + } +}". + +rfc3525_msg8() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10001 { + Context = - { + Modify = A4444 { + Events = 2223 { + al/on {strict=state}, + dd/ce {DigitMap=Dialplan0} + }, + Signals {cg/dt}, + DigitMap = Dialplan0 { + (0| 00|[1-7]xxx|8xxxxxxx|fxxxxxxx|exx|91xxxxxxxxxx|9011x.) + } + } + } +}". + +rfc3525_msg9() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10001 { + Context = - { + Modify = A4444 + } +}". + +rfc3525_msg10() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Transaction = 10002 { + Context = - { + Notify = A4444 { + ObservedEvents =2223 { + 19990729T22010001:dd/ce { + ds=\"916135551212\", + Meth=UM + } + } + } + } +}". + + +rfc3525_msg11() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 10002 { + Context = - { + Notify = A4444 + } +}". + +%% Added ? +rfc3525_msg12() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10003 { + Context = $ { + Add = A4444, + Add = $ { + Media { + Stream = 1 { + LocalControl { + Mode = ReceiveOnly, + nt/jit=40 ; in ms + }, + Local { + v=0 c=IN IP4 $ m=audio $ RTP/AVP 4 a=ptime:30 v=0 c=IN IP4 $ m=audio $ RTP/AVP 0 + } + } + } + } + } +}". + +%% Added ? +rfc3525_msg13() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a=recvonly + } ; RTP profile for G.723.1 is 4 + } + } + } + } +}". + +%% +%% Added ? +rfc3525_msg14() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50003 { + Context = $ { + Add = A5555 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive + } + } + }, + Events = 1234 { + al/of {strict=state} + }, + Signals {al/ri} + }, + Add = $ { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive, + nt/jit=40 ; in ms + }, + Local { + v=0 c=IN IP4 $ m=audio $ RTP/AVP 4 a=ptime:30 + }, + Remote { + v=0 c=IN IP4 124.124.124.222 m=audio 2222 RTP/AVP 4 a=ptime:30 + } ; RTP profile for G.723.1 is 4 + } + } + } + } +}". + +%% Added ? +rfc3525_msg15() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50003 { + Context = 5000 { + Add = A5555, + Add = A5556 { + Media { + Stream = 1 { + Local { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 + } ; RTP profile for G723.1 is 4 + } + } + } + } +}". + +%% Added ? +rfc3525_msg16a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10005 { + Context = 2000 { + Modify = A4444 { + Signals {cg/rt} + }, + Modify = A4445 { + Media { + Stream = 1 { + Remote { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 + } ; RTP profile for G723.1 is 4 + } + } + } + } +}". + +rfc3525_msg16b() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10005 { + Context = 2000 { + Modify = A4444, + Modify = A4445 + } +}". + +rfc3525_msg17a() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Transaction = 50005 { + Context = 5000 { + Notify = A5555 { + ObservedEvents = 1234 { + 19990729T22020002:al/of{init=false} + } + } + } +}". + +rfc3525_msg17b() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 50005 { + Context = - { + Notify = A5555 + } +}". + +%% Removed "{ }" after Signals +rfc3525_msg17c() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50006 { + Context = 5000 { + Modify = A5555 { + Events = 1235 { + al/on{strict=state} + }, + Signals ; to turn off ringing + } + } +}". + +rfc3525_msg17d() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50006 { + Context = 5000 { + Modify = A4445 + } +}". + +%% Removed "{ }" after Signals +rfc3525_msg18a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10006 { + Context = 2000 { + Modify = A4445 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive + } + } + } + }, + Modify = A4444 { + Signals + } + } +}". + +rfc3525_msg18b() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10006 { + Context = 2000 { + Modify = A4445, + Modify = A4444 + } +}". + +rfc3525_msg19() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50007 { + Context = - { + AuditValue = A5556 { + Audit { + Media, DigitMap, Events, Signals, Packages, Statistics + } + } + } +}". + +%% Added ? +rfc3525_msg20() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50007 { + Context = - { + AuditValue = A5556 { + Media { + TerminationState { + ServiceStates = InService, + Buffer = OFF + }, + Stream = 1 { + LocalControl { + Mode = SendReceive, + nt/jit=40 + }, + Local { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 a=ptime:30 + }, + Remote { + v=0 o=- 2890844526 2890842807 IN IP4 124.124.124.222 s=- t= 0 0 c=IN IP4 124.124.124.222 m=audio 2222 RTP/AVP 4 a=ptime:30 + } + } + }, + Events, + Signals, + DigitMap, + Packages {nt-1, rtp-1}, + Statistics { + rtp/ps=1200, ; packets sent + nt/os=62300, ; octets sent + rtp/pr=700, ; packets received + nt/or=45100, ; octets received + rtp/pl=0.2, ; % packet loss + rtp/jit=20, + rtp/delay=40 ; avg latency + } + } + } +}". + +rfc3525_msg21a() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Transaction = 50008 { + Context = 5000 { + Notify = A5555 { + ObservedEvents =1235 { + 19990729T24020002:al/on {init=false} + } + } + } +}". + +rfc3525_msg21b() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 50008 { + Context = - { + Notify = A5555 + } +}". + +rfc3525_msg22a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50009 { + Context = 5000 { + Subtract = A5555 { + Audit { + Statistics + } + }, + Subtract = A5556 { + Audit { + Statistics + } + } + } +}". + +%% Added ? +rfc3525_msg22b() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50009 { + Context = 5000 { + Subtract = A5555 { + Statistics { + nt/os=45123, ; Octets Sent + nt/dur=40 ; in seconds + } + }, + Subtract = A5556 { + Statistics { + rtp/ps=1245, ; packets sent + nt/os=62345, ; octets sent + rtp/pr=780, ; packets received + nt/or=45123, ; octets received + rtp/pl=10, ; % packets lost + rtp/jit=27, + rtp/delay=48 ; average latency + } + } + } +}". + +rfc3525_msgs() -> + [ + {msg1, rfc3525_msg1()}, + {msg2, rfc3525_msg2()}, + {msg3, rfc3525_msg3()}, + {msg4, rfc3525_msg4()}, + {msg6, rfc3525_msg6()}, + {msg7, rfc3525_msg7()}, + {msg8, rfc3525_msg8()}, + {msg9, rfc3525_msg9()}, + {msg10, rfc3525_msg10()}, + {msg11, rfc3525_msg11()}, + {msg12, rfc3525_msg12()}, + {msg13, rfc3525_msg13()}, + {msg14, rfc3525_msg14()}, + {msg15, rfc3525_msg15()}, + {msg16a, rfc3525_msg16a()}, + {msg16b, rfc3525_msg16b()}, + {msg17a, rfc3525_msg17a()}, + {msg17b, rfc3525_msg17b()}, + {msg17c, rfc3525_msg17c()}, + {msg17d, rfc3525_msg17d()}, + {msg18a, rfc3525_msg18a()}, + {msg18b, rfc3525_msg18b()}, + {msg19, rfc3525_msg19()}, + {msg20, rfc3525_msg20()}, + {msg21a, rfc3525_msg21a()}, + {msg21b, rfc3525_msg21b()}, + {msg22a, rfc3525_msg22a()}, + {msg22b, rfc3525_msg22b()} + ]. + +rfc3525_msgs_display() -> + Msgs = rfc3525_msgs(), + Fun = fun({Name, Msg}) -> + io:format("~w: ~n~s~n~n", [Name, Msg]) + end, + lists:foreach(Fun, Msgs). + +rfc3525_msgs_test() -> + put(dbg,true), + Res = rfc3525_msgs_test(megaco_pretty_text_encoder, [], 2), + erase(dbg), + io:format("~w~n", [Res]). + +rfc3525_msgs_test(Codec, Config, Ver) -> + io:format("-----------------------------------------" + "~ntesting with" + "~n Codec: ~w" + "~n Config: ~w" + "~n Version: ~w" + "~n", [Codec, Config, Ver]), + Msgs = rfc3525_msgs(), + Test = fun({N,M1}) -> + %% io:format("testing ~w: ", [N]), + io:format("~n*** testing ~w *** ~n~s~n", [N,M1]), + Bin1 = erlang:list_to_binary(M1), + case (catch Codec:decode_message(Config, Ver, Bin1)) of + {ok, M2} -> + %% io:format("d", []), + io:format("decoded:~n~p~n", [M2]), + case (catch Codec:encode_message(Config, Ver, M2)) of + {ok, Bin2} when is_binary(Bin2) -> + %% io:format("e~n", []), + io:format("encode: ~n~s~n", [erlang:binary_to_list(Bin2)]), + {N,ok}; + {ok, M3} -> + %% io:format("e~n", []), + io:format("encode: ~n~s~n", [M3]), + {N,ok}; + E -> + io:format("~n~p~n", [E]), + {N,encode_error} + end; + E -> + io:format("~n~p~n", [E]), + {N,decode_error} + end + end, + [Test(M) || M <- Msgs]. + +%% -------------------------- + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +skip(Reason) -> + megaco_codec_test_lib:skip(Reason). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +pretty_decode_message(DynamicDecode, Conf, Bin) -> + decode_message(megaco_pretty_text_encoder, DynamicDecode, Conf, Bin). + +compact_decode_message(DynamicDecode, Conf, Bin) -> + decode_message(megaco_compact_text_encoder, DynamicDecode, Conf, Bin). + +decode_message(Codec, DynamicDecode, Conf, Bin) -> + megaco_codec_test_lib:decode_message(Codec, DynamicDecode, ?VERSION, + Conf, Bin). + +pretty_encode_message(Conf, Msg) -> + encode_message(megaco_pretty_text_encoder, Conf, Msg). + +compact_encode_message(Conf, Msg) -> + encode_message(megaco_compact_text_encoder, Conf, Msg). + +encode_message(Codec, Conf, Msg) -> + megaco_codec_test_lib:encode_message(Codec, ?VERSION, Conf, Msg). + +test_msgs(Codec, DynamicDecode, Conf, Msgs) -> + megaco_codec_test_lib:test_msgs(Codec, DynamicDecode, ?VERSION, Conf, + fun chk_MegacoMessage/2, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +chk_MegacoMessage(M1, M2) -> + ?MSG_LIB:chk_MegacoMessage(M1, M2). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +cre_MegacoMessage(Mess) -> + ?MSG_LIB:cre_MegacoMessage(Mess). + +cre_MegacoMessage(Auth, Mess) -> + ?MSG_LIB:cre_MegacoMessage(Auth, Mess). + +cre_MegacoMessage(V, Mid, Body) -> + Mess = ?MSG_LIB:cre_Message(V, Mid, Body), + cre_MegacoMessage(Mess). + +cre_AuthHeader() -> + SecParmIdx = [239, 205, 171, 137], + SeqNum = [18, 52, 86, 120], + AD = [18, 52, 86, 120, 137, 171, 205, 239, 118, 84, 50, 16], + cre_AuthHeader(SecParmIdx, SeqNum, AD). + +cre_AuthHeader(Idx, Num, D) -> + ?MSG_LIB:cre_AuthenticationHeader(Idx, Num, D). + +cre_Msg(Mid, Body) -> + cre_Msg(?VERSION, Mid, Body). + +cre_Msg(V, Mid, Body) -> + ?MSG_LIB:cre_Message(V, Mid, Body). + +cre_TransId(TransId) -> + ?MSG_LIB:cre_TransactionId(TransId). + +cre_Trans(Trans) -> + ?MSG_LIB:cre_Transaction(Trans). + +cre_TransReq(TransId, Actions) -> + ?MSG_LIB:cre_TransactionRequest(TransId, Actions). + +cre_TransRep(TransId, Actions) -> + ?MSG_LIB:cre_TransactionReply(TransId, Actions). + +cre_TransAck(First, Last) -> + ?MSG_LIB:cre_TransactionAck(First, Last). + +cre_ActReq(CtxId, CmdReqs) -> + ?MSG_LIB:cre_ActionRequest(CtxId, CmdReqs). + +cre_ActRep(CtxId, CmdReps) -> + ?MSG_LIB:cre_ActionReply(CtxId, CmdReps). + +cre_ActRep(CtxId, ED, CR, CmdReps) -> + ?MSG_LIB:cre_ActionReply(CtxId, ED, CR, CmdReps). + +cre_CtxID(Id) -> + ?MSG_LIB:cre_ContextID(Id). + +cre_ContextRequest() -> + ?MSG_LIB:cre_ContextRequest(). + +cre_ContextRequest(A) -> + ?MSG_LIB:cre_ContextRequest(A). + +cre_ContextRequest(A, B) -> + ?MSG_LIB:cre_ContextRequest(A, B). + +cre_ContextRequest(A, B, C) -> + ?MSG_LIB:cre_ContextRequest(A, B, C). + +cre_ContextRequest(A, B, C, D) -> + ?MSG_LIB:cre_ContextRequest(A, B, C, D). + +cre_ContextRequest(A, B, C, D, E) -> + ?MSG_LIB:cre_ContextRequest(A, B, C, D, E). + +cre_ContextAttrAuditRequest() -> + ?MSG_LIB:cre_ContextAttrAuditRequest(). + +% cre_ContextAttrAuditRequest(A) -> +% ?MSG_LIB:cre_ContextAttrAuditRequest(A). + +% cre_ContextAttrAuditRequest(A, B) -> +% ?MSG_LIB:cre_ContextAttrAuditRequest(A, B). + +cre_ContextAttrAuditRequest(A, B, C) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(A, B, C). + +cre_ContextAttrAuditRequest(A, B, C, D) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(A, B, C, D). + +cre_ContextAttrAuditRequest(A, B, C, D, E) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(A, B, C, D, E). + +cre_TopologyRequest(From, To, Dir) -> + ?MSG_LIB:cre_TopologyRequest(From, To, Dir). + +%% Ind Aud related: + +cre_IndAudParam(IAP) -> + ?MSG_LIB:cre_IndAuditParameter(IAP). + +cre_IndAudMediaDesc(D) -> + ?MSG_LIB:cre_IndAudMediaDescriptor(D). + +cre_IndAudStreamDesc(SID, SP) -> + ?MSG_LIB:cre_IndAudStreamDescriptor(SID, SP). + +cre_IndAudStreamParms(LCD) -> + ?MSG_LIB:cre_IndAudStreamParms(LCD). + +cre_IndAudLocalControlDesc(SM, RV, RG, PP) -> + ?MSG_LIB:cre_IndAudLocalControlDescriptor(SM, RV, RG, PP). + +cre_IndAudPropertyParm(Name) -> + ?MSG_LIB:cre_IndAudPropertyParm(Name). + +cre_IndAudTermStateDesc(PP) -> + ?MSG_LIB:cre_IndAudTerminationStateDescriptor(PP). + +cre_IndAudTermStateDesc(PP, EBC, SS) -> + ?MSG_LIB:cre_IndAudTerminationStateDescriptor(PP, EBC, SS). + +cre_IndAudEvsDesc(RID, PN) + when is_integer(RID) -> + ?MSG_LIB:cre_IndAudEventsDescriptor(RID, PN). + +cre_IndAudEvBufDesc(EN, SID) -> + ?MSG_LIB:cre_IndAudEventBufferDescriptor(EN, SID). + +cre_IndAudSigsDesc(D) -> + ?MSG_LIB:cre_IndAudSignalsDescriptor(D). + +cre_IndAudSig(SN) -> + ?MSG_LIB:cre_IndAudSignal(SN). + +cre_IndAudSeqSigList(ID, SL) -> + ?MSG_LIB:cre_IndAudSeqSigList(ID, SL). + +cre_IndAudDigitMapDesc(DMN) -> + ?MSG_LIB:cre_IndAudDigitMapDescriptor(DMN). + +cre_IndAudStatsDesc(SN) -> + ?MSG_LIB:cre_IndAudStatisticsDescriptor(SN). + +cre_IndAudPkgsDesc(PN, PV) -> + ?MSG_LIB:cre_IndAudPackagesDescriptor(PN, PV). + +%% Parameter related +cre_PropParm(Name, Val) -> + ?MSG_LIB:cre_PropertyParm(Name, [Val]). + +cre_PropParm(Name, Vals, Tag, EI) -> + ?MSG_LIB:cre_PropertyParm(Name, Vals, Tag, EI). + + +%% Statistics related +cre_StatsDesc(SPs) -> + ?MSG_LIB:cre_StatisticsDescriptor(SPs). + +cre_StatsParm(Name) -> + ?MSG_LIB:cre_StatisticsParameter(Name). + +cre_StatsParm(Name, Val) -> + ?MSG_LIB:cre_StatisticsParameter(Name, [Val]). + + +% Event related +cre_EvParm(Name, Val) -> + ?MSG_LIB:cre_EventParameter(Name, Val). + +cre_ObsEv(Name, Not) -> + ?MSG_LIB:cre_ObservedEvent(Name, Not). +cre_ObsEv(Name, Not, Par) -> + ?MSG_LIB:cre_ObservedEvent(Name, Par, Not). + +cre_ReqedEv(Name) -> + ?MSG_LIB:cre_RequestedEvent(Name). +cre_ReqedEv(Name, Action) -> + ?MSG_LIB:cre_RequestedEvent(Name, Action). + + +cre_ObsEvsDesc(Id, EvList) -> + ?MSG_LIB:cre_ObservedEventsDescriptor(Id, EvList). + +cre_EvsDesc(Id, EvList) -> + ?MSG_LIB:cre_EventsDescriptor(Id, EvList). + + +%% Service change related +cre_SvcChParm(M, A, R, P) -> + ?MSG_LIB:cre_ServiceChangeParm(M, A, P, R). + +cre_SvcChParm(M, A, R, P, IF) -> + ?MSG_LIB:cre_ServiceChangeParm(M, A, asn1_NOVALUE, P, R, asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE, IF). + +cre_SvcChResParm(A, P) -> + ?MSG_LIB:cre_ServiceChangeResParm(A, P). + +cre_SvcChReq(Tids, P) -> + ?MSG_LIB:cre_ServiceChangeRequest(Tids, P). + +cre_SvcChProf(Name, Ver) -> + ?MSG_LIB:cre_ServiceChangeProfile(Name, Ver). + +cre_SvcChAddr(Tag, Val) -> + ?MSG_LIB:cre_ServiceChangeAddress(Tag, Val). + +cre_SvcChMethod(M) -> + ?MSG_LIB:cre_ServiceChangeMethod(M). + +cre_SvcChRep(Tids, Res) -> + ?MSG_LIB:cre_ServiceChangeReply(Tids, Res). + + +%% Stream related +cre_StreamID(Id) -> + ?MSG_LIB:cre_StreamID(Id). + +cre_StreamParms(Lcd) -> + ?MSG_LIB:cre_StreamParms(Lcd). +cre_StreamParms(Lcd, Ld) -> + ?MSG_LIB:cre_StreamParms(Lcd, Ld). +cre_StreamParms(Lcd, Ld, Rd) -> + ?MSG_LIB:cre_StreamParms(Lcd, Ld, Rd). +cre_StreamParmsL(Ld) -> + ?MSG_LIB:cre_StreamParms(asn1_NOVALUE, Ld, asn1_NOVALUE). +cre_StreamParmsR(Rd) -> + ?MSG_LIB:cre_StreamParms(asn1_NOVALUE, asn1_NOVALUE, Rd). + +cre_StreamDesc(Id, P) -> + ?MSG_LIB:cre_StreamDescriptor(Id, P). + + +%% "Local" related +cre_LocalControlDesc(Mode) -> + ?MSG_LIB:cre_LocalControlDescriptor(Mode). +cre_LocalControlDesc(Mode, Parms) -> + ?MSG_LIB:cre_LocalControlDescriptor(Mode, Parms). + +cre_LocalRemoteDesc(Grps) -> + ?MSG_LIB:cre_LocalRemoteDescriptor(Grps). + + +%% DigitMap related +cre_DigitMapDesc() -> + ?MSG_LIB:cre_DigitMapDescriptor(). +cre_DigitMapDesc(NameOrVal) -> + ?MSG_LIB:cre_DigitMapDescriptor(NameOrVal). +cre_DigitMapDesc(Name, Val) -> + ?MSG_LIB:cre_DigitMapDescriptor(Name, Val). + +cre_DigitMapValue(Body) -> + ?MSG_LIB:cre_DigitMapValue(Body). + +cre_DigitMapValue(Body, Start, Short, Long) -> + ?MSG_LIB:cre_DigitMapValue(Start, Short, Long, Body). + +%% Media related +cre_MediaDesc(SD) when is_record(SD, 'StreamDescriptor') -> + cre_MediaDesc([SD]); +cre_MediaDesc(SDs) -> + ?MSG_LIB:cre_MediaDescriptor(SDs). + + +%% Notify related +cre_NotifyReq(Tids, EvsDesc) -> + ?MSG_LIB:cre_NotifyRequest(Tids, EvsDesc). + +cre_NotifyRep(Tids) -> + ?MSG_LIB:cre_NotifyReply(Tids). + + +%% Subtract related +cre_SubReq(Tids, Desc) -> + ?MSG_LIB:cre_SubtractRequest(Tids, Desc). + + +%% Audit related +cre_AuditDesc(Tokens) -> + ?MSG_LIB:cre_AuditDescriptor(Tokens). + +cre_AuditDesc(Tokens, PropertTokens) -> + ?MSG_LIB:cre_AuditDescriptor(Tokens, PropertTokens). + +cre_AuditReq(Tid, Desc) -> + ?MSG_LIB:cre_AuditRequest(Tid, Desc). + +cre_AuditRes(Tid, Res) -> + ?MSG_LIB:cre_AuditResult(Tid, Res). + +cre_TermAudit(ARP) -> + ?MSG_LIB:cre_TerminationAudit(ARP). + +cre_AuditRetParam(D) -> + ?MSG_LIB:cre_AuditReturnParameter(D). + + +%% AMM/AMMS related +cre_AmmDesc(D) -> + ?MSG_LIB:cre_AmmDescriptor(D). + +cre_AmmReq(Tids, Descs) -> + ?MSG_LIB:cre_AmmRequest(Tids, Descs). + +cre_AmmsReply(Tids) -> + ?MSG_LIB:cre_AmmsReply(Tids). +cre_AmmsReply(Tids, Descs) -> + ?MSG_LIB:cre_AmmsReply(Tids, Descs). + + +%% Command related +cre_Cmd(Tag, Req) -> + ?MSG_LIB:cre_Command(Tag, Req). + +cre_CmdReq(Cmd) -> + ?MSG_LIB:cre_CommandRequest(Cmd). + +cre_CmdRep(Tag, Rep) -> + ?MSG_LIB:cre_CommandReply(Tag, Rep). + + +%% Actions related +cre_ReqedActs(DmName) -> + EDM = ?MSG_LIB:cre_EventDM(DmName), + ?MSG_LIB:cre_RequestedActions(EDM). + + +%% Signal related +cre_SigDir(D) -> + ?MSG_LIB:cre_SignalDirection(D). + +cre_Sig(Name) -> + cre_Sig(Name, []). + +cre_Sig(Name, SPL) -> + ?MSG_LIB:cre_Signal(Name, SPL). + +cre_Sig(Name, Dir, RID) -> + cre_Sig(Name, [], Dir, RID). + +cre_Sig(Name, SPL, Dir, RID) -> + cre_Sig(Name, asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE, + asn1_NOVALUE, SPL, Dir, RID). + +cre_Sig(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID) -> + ?MSG_LIB:cre_Signal(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID). + +cre_SigReq(S) -> + ?MSG_LIB:cre_SignalRequest(S). + +cre_NotifCompl(NC) -> + ?MSG_LIB:cre_NotifyCompletion(NC). + +cre_SigType(ST) -> + ?MSG_LIB:cre_SignalType(ST). + +cre_SigsDesc(D) -> + ?MSG_LIB:cre_SignalsDescriptor(D). + +%% Others +cre_ReqID(RID) -> + ?MSG_LIB:cre_RequestID(RID). + +cre_TimeNot(D,T) -> + ?MSG_LIB:cre_TimeNotation(D, T). + +cre_PkgsItem(Name, Ver) -> + ?MSG_LIB:cre_PackagesItem(Name, Ver). + +cre_BOOLEAN(B) -> + ?MSG_LIB:cre_BOOLEAN(B). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_init(Config) -> + megaco_codec_flex_lib:init(Config). + +flex_finish(Config) -> + megaco_codec_flex_lib:finish(Config). + +flex_scanner_conf(Config) -> + megaco_codec_flex_lib:scanner_conf(Config). + +start_flex_scanner() -> + megaco_codec_flex_lib:start(). + +stop_flex_scanner(Pid) -> + megaco_codec_flex_lib:stop(Pid). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +t(F,A) -> + p(printable(get(severity),trc),trc,F,A). + +d(F,A) -> + p(printable(get(severity),dbg),dbg,F,A). + +l(F,A) -> + p(printable(get(severity),log),log,F,A). + +e(F,A) -> + p(printable(get(severity),err),err,F,A). + + +printable(trc,_) -> + true; +printable(dbg,trc) -> + false; +printable(dbg,_) -> + true; +printable(log,log) -> + true; +printable(log,err) -> + true; +printable(err,err) -> + true; +printable(_,_) -> + false. + + +p(true,L,F,A) -> + io:format("~s:" ++ F ++ "~n", [image_of(L)|A]); +p(_,_,_,_) -> + ok. + +image_of(trc) -> + "TRC"; +image_of(dbg) -> + "DBG"; +image_of(log) -> + "LOG"; +image_of(err) -> + "ERR"; +image_of(L) -> + io_lib:format("~p",[L]). + diff --git a/lib/megaco/test/megaco_codec_prev3c_test.erl b/lib/megaco/test/megaco_codec_prev3c_test.erl new file mode 100644 index 0000000000..813d0cf57d --- /dev/null +++ b/lib/megaco/test/megaco_codec_prev3c_test.erl @@ -0,0 +1,8336 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test encoding/decoding (codec) module of Megaco/H.248 +%%---------------------------------------------------------------------- + +-module(megaco_codec_prev3c_test). + +%% ---- + +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_prev3c.hrl"). +-include("megaco_test_lib.hrl"). + +%% ---- + +-export([msgs/0]). +-export([rfc3525_msgs_display/0, rfc3525_msgs_test/0]). + +-export([t/0, t/1]). + +-export([all/1, + + text/1, + + pretty/1, + pretty_test_msgs/1, + + compact/1, + compact_test_msgs/1, + + flex_pretty/1, + flex_pretty_init/1, + flex_pretty_finish/1, + flex_pretty_test_msgs/1, + + flex_compact/1, + flex_compact_init/1, + flex_compact_finish/1, + flex_compact_test_msgs/1, + + flex_compact_dm_timers1/1, + flex_compact_dm_timers2/1, + flex_compact_dm_timers3/1, + flex_compact_dm_timers4/1, + flex_compact_dm_timers5/1, + flex_compact_dm_timers6/1, + flex_compact_dm_timers7/1, + flex_compact_dm_timers8/1, + + binary/1, + + bin/1, + bin_test_msgs/1, + + ber/1, + ber_test_msgs/1, + + ber_bin/1, + ber_bin_test_msgs/1, + + per/1, + per_test_msgs/1, + + per_bin/1, + per_bin_test_msgs/1, + + erl_dist/1, + erl_dist_m/1, + erl_dist_m_test_msgs/1, + + tickets/0, + tickets/1, + + compact_tickets/1, + compact_otp4011_msg1/1, + compact_otp4011_msg2/1, + compact_otp4011_msg3/1, + compact_otp4013_msg1/1, + compact_otp4085_msg1/1, + compact_otp4085_msg2/1, + compact_otp4280_msg1/1, + compact_otp4299_msg1/1, + compact_otp4359_msg1/1, + compact_otp4920_msg0/1, + compact_otp4920_msg1/1, + compact_otp4920_msg2/1, + compact_otp4920_msg3/1, + compact_otp4920_msg4/1, + compact_otp4920_msg5/1, + compact_otp4920_msg6/1, + compact_otp4920_msg7/1, + compact_otp4920_msg8/1, + compact_otp4920_msg9/1, + compact_otp4920_msg10/1, + compact_otp4920_msg11/1, + compact_otp4920_msg12/1, + compact_otp4920_msg20/1, + compact_otp4920_msg21/1, + compact_otp4920_msg22/1, + compact_otp4920_msg23/1, + compact_otp4920_msg24/1, + compact_otp4920_msg25/1, + compact_otp5186_msg01/1, + compact_otp5186_msg02/1, + compact_otp5186_msg03/1, + compact_otp5186_msg04/1, + compact_otp5186_msg05/1, + compact_otp5186_msg06/1, + compact_otp5793_msg01/1, + compact_otp5836_msg01/1, + compact_otp5993_msg01/1, + compact_otp5993_msg02/1, + compact_otp5993_msg03/1, + compact_otp6017_msg01/1, + compact_otp6017_msg02/1, + compact_otp6017_msg03/1, + + flex_compact_tickets/1, + flex_compact_otp4299_msg1/1, + flex_compact_otp7431_msg01/1, + flex_compact_otp7431_msg02/1, + flex_compact_otp7431_msg03/1, + flex_compact_otp7431_msg04/1, + flex_compact_otp7431_msg05/1, + flex_compact_otp7431_msg06/1, + flex_compact_otp7431_msg07/1, + + pretty_tickets/1, + pretty_otp4632_msg1/1, + pretty_otp4632_msg2/1, + pretty_otp4632_msg3/1, + pretty_otp4632_msg4/1, + pretty_otp4710_msg1/1, + pretty_otp4710_msg2/1, + pretty_otp4945_msg1/1, + pretty_otp4945_msg2/1, + pretty_otp4945_msg3/1, + pretty_otp4945_msg4/1, + pretty_otp4945_msg5/1, + pretty_otp4945_msg6/1, + pretty_otp4949_msg1/1, + pretty_otp4949_msg2/1, + pretty_otp4949_msg3/1, + pretty_otp5042_msg1/1, + pretty_otp5068_msg1/1, + pretty_otp5085_msg1/1, + pretty_otp5085_msg2/1, + pretty_otp5085_msg3/1, + pretty_otp5085_msg4/1, + pretty_otp5085_msg5/1, + pretty_otp5085_msg6/1, + pretty_otp5085_msg7/1, + pretty_otp5085_msg8/1, + pretty_otp5600_msg1/1, + pretty_otp5600_msg2/1, + pretty_otp5601_msg1/1, + pretty_otp5793_msg01/1, + pretty_otp5803_msg01/1, + pretty_otp5803_msg02/1, + pretty_otp5805_msg01/1, + pretty_otp5836_msg01/1, + pretty_otp5882_msg01/1, + pretty_otp6490_msg01/1, + pretty_otp6490_msg02/1, + pretty_otp6490_msg03/1, + pretty_otp6490_msg04/1, + pretty_otp6490_msg05/1, + pretty_otp6490_msg06/1, + pretty_otp7671_msg01/1, + pretty_otp7671_msg02/1, + pretty_otp7671_msg03/1, + pretty_otp7671_msg04/1, + pretty_otp7671_msg05/1, + pretty_otp8114_msg01/1, + + flex_pretty_tickets/1, + flex_pretty_otp5042_msg1/1, + flex_pretty_otp5085_msg1/1, + flex_pretty_otp5085_msg2/1, + flex_pretty_otp5085_msg3/1, + flex_pretty_otp5085_msg4/1, + flex_pretty_otp5085_msg5/1, + flex_pretty_otp5085_msg6/1, + flex_pretty_otp5085_msg7/1, + flex_pretty_otp5085_msg8/1, + flex_pretty_otp5600_msg1/1, + flex_pretty_otp5600_msg2/1, + flex_pretty_otp5601_msg1/1, + flex_pretty_otp5793_msg01/1, + flex_pretty_otp5803_msg01/1, + flex_pretty_otp5803_msg02/1, + flex_pretty_otp5805_msg01/1, + flex_pretty_otp5836_msg01/1, + flex_pretty_otp7431_msg01/1, + flex_pretty_otp7431_msg02/1, + flex_pretty_otp7431_msg03/1, + flex_pretty_otp7431_msg04/1, + flex_pretty_otp7431_msg05/1, + flex_pretty_otp7431_msg06/1, + flex_pretty_otp7431_msg07/1, + + init_per_testcase/2, fin_per_testcase/2]). + +-export([display_text_messages/0, generate_text_messages/0]). + + +%% ---- + +-define(V3, prev3c). +-define(EC_V3, {version3,?V3}). +-define(EC, [?EC_V3]). + +-define(VERSION, 3). +-define(VERSION_STR, "3"). +-define(MSG_LIB, megaco_test_msg_prev3c_lib). +-define(DEFAULT_PORT, 55555). +-define(MG1_MID_NO_PORT, {ip4Address, + #'IP4Address'{address = [124, 124, 124, 222]}}). +-define(MG1_MID, {ip4Address, #'IP4Address'{address = [124, 124, 124, 222], + portNumber = ?DEFAULT_PORT}}). +-define(MG2_MID, {ip4Address, #'IP4Address'{address = [125, 125, 125, 111], + portNumber = ?DEFAULT_PORT}}). +-define(MGC_MID, {ip4Address, #'IP4Address'{address = [123, 123, 123, 4], + portNumber = ?DEFAULT_PORT}}). + +-define(A4444, ["11111111", "00000000", "00000000"]). +-define(A4445, ["11111111", "00000000", "11111111"]). +-define(A5555, ["11111111", "11111111", "00000000"]). +-define(A5556, ["11111111", "11111111", "11111111"]). + + +%% ---- + +display_text_messages() -> + Msgs = + msgs1a(text) ++ + msgs5(text) ++ + msgs6(text) ++ + msgs7(text), + megaco_codec_test_lib:display_text_messages(?VERSION, ?EC, Msgs). + + +generate_text_messages() -> + Msgs = + msgs1a(text) ++ + msgs5(text) ++ + msgs6(text) ++ + msgs7(text), + megaco_codec_test_lib:generate_text_messages(?V3, ?VERSION, ?EC, Msgs). + + +%% ---- + + +expand(RootCase) -> + expand([RootCase], []). + +expand([], Acc) -> + lists:flatten(lists:reverse(Acc)); +expand([Case|Cases], Acc) -> + case (catch apply(?MODULE,Case,[suite])) of + [] -> + expand(Cases, [Case|Acc]); + C when is_list(C) -> + expand(Cases, [expand(C, [])|Acc]); + _ -> + expand(Cases, [Case|Acc]) + end. + + +%% ---- + +tickets() -> + Flag = process_flag(trap_exit, true), + Cases = expand(tickets), + Fun = fun(Case) -> + C = init_per_testcase(Case, [{tc_timeout, + timer:minutes(10)}]), + io:format("Eval ~w~n", [Case]), + Result = + case (catch apply(?MODULE, Case, [C])) of + {'EXIT', Reason} -> + io:format("~n~p exited:~n ~p~n", + [Case, Reason]), + {error, {Case, Reason}}; + Res -> + Res + end, + fin_per_testcase(Case, C), + Result + end, + process_flag(trap_exit, Flag), + lists:map(Fun, Cases). + + +%% ---- + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + +init_per_testcase(Case, Config) -> + %% CaseString = io_lib:format("~p", [Case]), + C = + case lists:suffix("time_test", atom_to_list(Case)) of + true -> + [{tc_timeout, timer:minutes(10)}|Config]; + false -> + put(verbosity,trc), + Config + end, + megaco_test_lib:init_per_testcase(Case, C). + +fin_per_testcase(Case, Config) -> + erase(verbosity), + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top test case + +all(suite) -> + [ + text, + binary, + erl_dist, + tickets + ]. + +text(suite) -> + [ + pretty, + flex_pretty, + compact, + flex_compact + ]. + +binary(suite) -> + [ + bin, + ber, + ber_bin, + per, + per_bin + ]. + +erl_dist(suite) -> + [ + erl_dist_m + ]. + +pretty(suite) -> + [ + pretty_test_msgs + ]. + + +compact(suite) -> + [ + compact_test_msgs + ]. + + +flex_pretty(suite) -> + {req, [], + {conf, flex_pretty_init, flex_pretty_cases(), flex_pretty_finish}}. + +flex_pretty_cases() -> + [ + flex_pretty_test_msgs + ]. + +flex_compact(suite) -> + {req, [], + {conf, flex_compact_init, flex_compact_cases(), flex_compact_finish}}. + +flex_compact_cases() -> + [ + flex_compact_test_msgs, + flex_compact_dm_timers1, + flex_compact_dm_timers2, + flex_compact_dm_timers3, + flex_compact_dm_timers4, + flex_compact_dm_timers5, + flex_compact_dm_timers6, + flex_compact_dm_timers7, + flex_compact_dm_timers8 + ]. + + +bin(suite) -> + [ + bin_test_msgs + ]. + + +ber(suite) -> + [ + ber_test_msgs + ]. + + +ber_bin(suite) -> + [ + ber_bin_test_msgs + ]. + + +per(suite) -> + [ + per_test_msgs + ]. + + +%% Support for per_bin was added to ASN.1 as of version +%% 1.3.2 (R8). And later merged into 1.3.1.3 (R7). These +%% releases are identical (as far as I know). +%% +per_bin(suite) -> + [ + per_bin_test_msgs + ]. + + +erl_dist_m(suite) -> + [ + erl_dist_m_test_msgs + ]. + +tickets(suite) -> + [ + compact_tickets, + flex_compact_tickets, + pretty_tickets, + flex_pretty_tickets + ]. + + +compact_tickets(suite) -> + [ + compact_otp4011_msg1, + compact_otp4011_msg2, + compact_otp4011_msg3, + compact_otp4013_msg1, + compact_otp4085_msg1, + compact_otp4085_msg2, + compact_otp4280_msg1, + compact_otp4299_msg1, + compact_otp4359_msg1, + compact_otp4920_msg0, + compact_otp4920_msg1, + compact_otp4920_msg2, + compact_otp4920_msg3, + compact_otp4920_msg4, + compact_otp4920_msg5, + compact_otp4920_msg6, + compact_otp4920_msg7, + compact_otp4920_msg8, + compact_otp4920_msg9, + compact_otp4920_msg10, + compact_otp4920_msg11, + compact_otp4920_msg12, + compact_otp4920_msg20, + compact_otp4920_msg21, + compact_otp4920_msg22, + compact_otp4920_msg23, + compact_otp4920_msg24, + compact_otp4920_msg25, + compact_otp5186_msg01, + compact_otp5186_msg02, + compact_otp5186_msg03, + compact_otp5186_msg04, + compact_otp5186_msg05, + compact_otp5186_msg06, + compact_otp5793_msg01, + compact_otp5836_msg01, + compact_otp5993_msg01, + compact_otp5993_msg02, + compact_otp5993_msg03, + compact_otp6017_msg01, + compact_otp6017_msg02, + compact_otp6017_msg03 + ]. + + +flex_compact_tickets(suite) -> + {req, [], + {conf, flex_compact_init, flex_compact_tickets_cases(), + flex_compact_finish}}. + +flex_compact_tickets_cases() -> + [ + flex_compact_otp4299_msg1, + flex_compact_otp7431_msg01, + flex_compact_otp7431_msg02, + flex_compact_otp7431_msg03, + flex_compact_otp7431_msg04, + flex_compact_otp7431_msg05, + flex_compact_otp7431_msg06, + flex_compact_otp7431_msg07 + ]. + + +pretty_tickets(suite) -> + [ + pretty_otp4632_msg1, + pretty_otp4632_msg2, + pretty_otp4632_msg3, + pretty_otp4632_msg4, + pretty_otp4710_msg1, + pretty_otp4710_msg2, + pretty_otp4945_msg1, + pretty_otp4945_msg2, + pretty_otp4945_msg3, + pretty_otp4945_msg4, + pretty_otp4945_msg5, + pretty_otp4945_msg6, + pretty_otp4949_msg1, + pretty_otp4949_msg2, + pretty_otp4949_msg3, + pretty_otp5042_msg1, + pretty_otp5068_msg1, + pretty_otp5085_msg1, + pretty_otp5085_msg2, + pretty_otp5085_msg3, + pretty_otp5085_msg4, + pretty_otp5085_msg5, + pretty_otp5085_msg6, + pretty_otp5085_msg7, + pretty_otp5085_msg8, + pretty_otp5600_msg1, + pretty_otp5600_msg2, + pretty_otp5601_msg1, + pretty_otp5793_msg01, + pretty_otp5803_msg01, + pretty_otp5803_msg02, + pretty_otp5805_msg01, + pretty_otp5836_msg01, + pretty_otp5882_msg01, + pretty_otp6490_msg01, + pretty_otp6490_msg02, + pretty_otp6490_msg03, + pretty_otp6490_msg04, + pretty_otp6490_msg05, + pretty_otp6490_msg06, + pretty_otp7671_msg01, + pretty_otp7671_msg02, + pretty_otp7671_msg03, + pretty_otp7671_msg04, + pretty_otp7671_msg05, + pretty_otp8114_msg01 + ]. + + +flex_pretty_tickets(suite) -> + {req, [], + {conf, flex_pretty_init, flex_pretty_tickets_cases(), + flex_pretty_finish}}. + +flex_pretty_tickets_cases() -> + [ + flex_pretty_otp5042_msg1, + flex_pretty_otp5085_msg1, + flex_pretty_otp5085_msg2, + flex_pretty_otp5085_msg3, + flex_pretty_otp5085_msg4, + flex_pretty_otp5085_msg5, + flex_pretty_otp5085_msg6, + flex_pretty_otp5085_msg7, + flex_pretty_otp5085_msg8, + flex_pretty_otp5600_msg1, + flex_pretty_otp5600_msg2, + flex_pretty_otp5601_msg1, + flex_pretty_otp5793_msg01, + flex_pretty_otp5803_msg01, + flex_pretty_otp5803_msg02, + flex_pretty_otp5805_msg01, + flex_pretty_otp5836_msg01, + flex_pretty_otp7431_msg01, + flex_pretty_otp7431_msg02, + flex_pretty_otp7431_msg03, + flex_pretty_otp7431_msg04, + flex_pretty_otp7431_msg05, + flex_pretty_otp7431_msg06, + flex_pretty_otp7431_msg07 + ]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +pretty_test_msgs(suite) -> + []; +pretty_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(text) ++ + msgs1b(text) ++ + msgs3525(text) ++ + msgs5(text) ++ + msgs6(text) ++ + msgs7(text), + %% Msgs = msgs1a(text), + %% Msgs = msgs1b(text), + %% Msgs = msgs35525(text), + %% Msgs = msgs5(text), + %% Msgs = msgs6(text), + %% Msgs = msgs7(text), + DynamicDecode = false, + test_msgs(megaco_pretty_text_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_pretty_init(Config) -> + flex_init(Config). + +flex_pretty_finish(Config) -> + flex_finish(Config). + +flex_pretty_test_msgs(suite) -> + []; +flex_pretty_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(text) ++ + msgs1b(text) ++ + msgs3525(text) ++ + msgs5(text) ++ + msgs6(text) ++ + msgs7(text), + Conf = flex_scanner_conf(Config), + DynamicDecode = false, + test_msgs(megaco_pretty_text_encoder, DynamicDecode, [?EC_V3,Conf], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +compact_test_msgs(suite) -> + []; +compact_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(text) ++ + msgs1b(text) ++ + msgs3525(text) ++ + msgs5(text) ++ + msgs6(text) ++ + msgs7(text), + %% Msgs = msgs7(text), + DynamicDecode = false, + test_msgs(megaco_compact_text_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_compact_init(Config) -> + flex_init(Config). + +flex_compact_finish(Config) -> + flex_finish(Config). + +flex_compact_test_msgs(suite) -> + []; +flex_compact_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(text) ++ + msgs1b(text) ++ + msgs3525(text) ++ + msgs5(text) ++ + msgs6(text) ++ + msgs7(text), + Conf = flex_scanner_conf(Config), + DynamicDecode = true, + test_msgs(megaco_compact_text_encoder, DynamicDecode, [?EC_V3,Conf], Msgs). + + +flex_compact_dm_timers1(suite) -> + []; +flex_compact_dm_timers1(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("1", "2", "3"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers1 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({1,2,3}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers2(suite) -> + []; +flex_compact_dm_timers2(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("02", "03", "04"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers2 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({2,3,4}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers3(suite) -> + []; +flex_compact_dm_timers3(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("1", "02", "31"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers3 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({1,2,31}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers4(suite) -> + []; +flex_compact_dm_timers4(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("10", "21", "99"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers4 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({10,21,99}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers5(suite) -> + []; +flex_compact_dm_timers5(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("99", "23", "11"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers5 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({99,23,11}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers6(suite) -> + []; +flex_compact_dm_timers6(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("77", "09", "1"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers6 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({77,9,1}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers7(suite) -> + []; +flex_compact_dm_timers7(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("77", "09", "1", "99"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers7 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({77,9,1,99}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers8(suite) -> + []; +flex_compact_dm_timers8(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("01", "09", "01", "02"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers8 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({1,9,1,2}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +build_dm_timers_message(T, S, L) -> + TMRs = lists:flatten(io_lib:format("T:~s,S:~s,L:~s", [T, S, L])), + build_dm_timers_message(TMRs). + +build_dm_timers_message(T, S, L, Z) -> + TMRs = lists:flatten(io_lib:format("T:~s,S:~s,L:~s,Z:~s", [T, S, L,Z])), + build_dm_timers_message(TMRs). + +build_dm_timers_message(TMRs) -> + M = io_lib:format("!/" ?VERSION_STR " [123.123.123.4]:55555\nT=10001{C=-{MF=11111111/00000000/00000000{E=2223{al/on,dd/ce{DM=dialplan00}},SG{cg/rt},DM=dialplan00{~s,(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)}}}}", [TMRs]), + lists:flatten(M). + + +verify_dm_timers(TMRs, #'MegacoMessage'{mess = Mess}) -> + #'Message'{messageBody = Body} = Mess, + case get_dm_timers(Body) of + TMRs -> + ok; + {error, Reason} -> + exit({invalid_timer, {TMRs, Reason}}); + TMRs1 -> + exit({invalid_timer_values, {TMRs, TMRs1}}) + end. + +get_dm_timers({transactions, T}) when is_list(T) -> + get_dm_timers1(T); +get_dm_timers(Other) -> + {error, {invalid_transactions, Other}}. + +get_dm_timers1([{transactionRequest,T}|Ts]) + when is_record(T,'TransactionRequest') -> + case get_dm_timers2(T) of + {ok, Timers} -> + Timers; + _ -> + get_dm_timers1(Ts) + end; +get_dm_timers1([_|Ts]) -> + get_dm_timers1(Ts); +get_dm_timers1([]) -> + {error, {no_timers, 'TransactionRequest'}}. + + +get_dm_timers2(#'TransactionRequest'{actions = Actions}) when is_list(Actions) -> + get_dm_timers3(Actions). + + +get_dm_timers3([#'ActionRequest'{commandRequests = Cmds}|Ars]) when is_list(Cmds) -> + case get_dm_timers4(Cmds) of + {ok, Timers} -> + {ok, Timers}; + _ -> + get_dm_timers3(Ars) + end; +get_dm_timers3([_|Ars]) -> + get_dm_timers3(Ars); +get_dm_timers3([]) -> + {error, {no_timers, 'ActionRequest'}}. + +get_dm_timers4([#'CommandRequest'{command = Cmd}|Cmds]) -> + case get_dm_timers5(Cmd) of + {ok, Timers} -> + {ok, Timers}; + _ -> + get_dm_timers4(Cmds) + end; +get_dm_timers4([_|Cmds]) -> + get_dm_timers4(Cmds); +get_dm_timers4([]) -> + {error, {no_timers, 'CommandRequest'}}. + + +get_dm_timers5({modReq, #'AmmRequest'{descriptors = Descriptors}}) -> + get_dm_timers6(Descriptors); +get_dm_timers5(R) -> + {error, {no_modReq, R}}. + + +get_dm_timers6([{digitMapDescriptor, #'DigitMapDescriptor'{digitMapValue = Val}}|_]) -> + case Val of + #'DigitMapValue'{startTimer = T, + shortTimer = S, + longTimer = L, + durationTimer = asn1_NOVALUE} -> + {ok, {T, S, L}}; + #'DigitMapValue'{startTimer = T, + shortTimer = S, + longTimer = L, + durationTimer = Z} -> + {ok, {T, S, L, Z}}; + _ -> + {error, no_value_in_dm} + end; +get_dm_timers6([_|Descs]) -> + get_dm_timers6(Descs); +get_dm_timers6([]) -> + {error, {no_timers, descriptors}}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bin_test_msgs(suite) -> + []; +bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(binary) ++ + msgs5(binary) ++ + msgs6(binary) ++ + msgs7(binary), + %% Msgs = msgs6(binary), + DynamicDecode = false, + test_msgs(megaco_binary_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ber_test_msgs(suite) -> + []; +ber_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(binary) ++ + msgs5(binary) ++ + msgs6(binary) ++ + msgs7(binary), + %% Msgs = msgs7(binary), + DynamicDecode = false, + test_msgs(megaco_ber_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ber_bin_test_msgs(suite) -> + []; +ber_bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(binary) ++ + msgs5(binary) ++ + msgs6(binary) ++ + msgs7(binary), + DynamicDecode = true, + test_msgs(megaco_ber_bin_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +per_test_msgs(suite) -> + []; +per_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(binary) ++ + msgs5(binary) ++ + msgs6(binary) ++ + msgs7(binary), + DynamicDecode = false, + test_msgs(megaco_per_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +per_bin_test_msgs(suite) -> + []; +per_bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(binary) ++ + msgs5(binary) ++ + msgs6(binary) ++ + msgs7(binary), + DynamicDecode = false, + test_msgs(megaco_per_bin_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +erl_dist_m_test_msgs(suite) -> + []; +erl_dist_m_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(erlang) ++ + msgs1b(erlang) ++ + msgs3525(erlang) ++ + msgs5(erlang) ++ + msgs6(erlang) ++ + msgs7(erlang), + DynamicDecode = false, + Conf = [megaco_compressed], + test_msgs(megaco_erl_dist_encoder, DynamicDecode, Conf, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +%% Ticket test cases: + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg1(suite) -> + []; +compact_otp4011_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4011_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR " ML T=233350{C=${A=stedevice/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SR}}}}}", + ok = compact_otp4011(M), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg2(suite) -> + []; +compact_otp4011_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4011_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR " ML T=233350{C=${A=stedevice/01{M{O{MO=SO,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SR}}}}}", + ok = compact_otp4011(M), + %% erase(severity), + %% erase(dbg), + ok. + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +%% + +compact_otp4011_msg3(suite) -> + []; +compact_otp4011_msg3(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4011_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR " ML T=233350{C=${A=stedevice/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SO}}}}}", + ok = compact_otp4011(M), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4011(Msg) -> + compact_otp4011(Msg, ?EC). + +compact_otp4011(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(Reason) when is_list(Reason) -> + compact_otp4011_chk1(Reason); + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode(Msg, Decode, Check). + +compact_otp4011_chk1(R1) -> + case lists:keysearch(reason, 1, R1) of + {value, {reason, R2}} -> + compact_otp4011_chk2(R2); + false -> + {error, {unexpected_result, R1}} + end. + +compact_otp4011_chk2({0, ParserMod, {ParserFunc, [A, B]}}) + when (ParserMod =:= megaco_text_parser_prev3c) andalso + (ParserFunc =:= do_merge_control_streamParms) andalso + is_list(A) andalso + is_record(B, 'LocalControlDescriptor') -> + SM = B#'LocalControlDescriptor'.streamMode, + case lists:keysearch(mode, 1, A) of + {value, {mode, _Mode}} when SM /= asn1_NOVALUE -> + ok; + {value, {mode, _Mode}} -> + {error, {unexpected_streamMode_reason, {A, B}}}; + false -> + {error, {unexpected_mode_reason, {A, B}}} + end; +compact_otp4011_chk2(Bad) -> + {error, {unexpected_reason, Bad}}. + + +%% -------------------------------------------------------------- +%% Note that this decode SHALL fail, because of the misspelled +%% MEGCAO instead of the correct MEGACO. +compact_otp4013_msg1(suite) -> + []; +compact_otp4013_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4013_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "MEGCAO/3 MG1 T=12345678{C=-{SC=root{SV{MT=RS,RE=901}}}}", + ok = compact_otp4013(M), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4013(Msg) -> + compact_otp4013(Msg, ?EC). + +compact_otp4013(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(Reason) when is_list(Reason) -> + compact_otp4013_chk1(Reason); + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode(Msg, Decode, Check). + +compact_otp4013_chk1(Reason) -> + case lists:keysearch(reason, 1, Reason) of + {value, {reason, no_version_found, _}} -> + case lists:keysearch(token, 1, Reason) of + {value, {token, [{'SafeChars',_,"megcao/3"}|_]}} -> + ok; + {value, {token, Tokens}} -> + {error, {unexpected_tokens, Tokens}}; + false -> + {error, {tokens_not_found, Reason}} + end; + {value, {reason, BadReason, _}} -> + {error, {unexpected_reason, BadReason}}; + false -> + {error, {reason_not_found, Reason}} + end. + + +%% -------------------------------------------------------------- +%% +%% +compact_otp4085_msg1(suite) -> + []; +compact_otp4085_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = compact_otp4085_erroneous_msg(), + ok = compact_otp4085_1(M), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4085_1(Msg) -> + compact_otp4085_1(Msg, ?EC). + +compact_otp4085_1(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(Reason) when is_list(Reason) -> + compact_otp4085_1_chk1(Reason); + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode(Msg, Decode, Check). + +compact_otp4085_1_chk1(Reason) -> + case lists:keysearch(reason, 1, Reason) of + {value, {reason, {Line, Module, Crap}}} when is_integer(Line) and + is_atom(Module) -> + Crap2 = + case (catch lists:flatten(Crap)) of + L when is_list(L) -> + L; + _ -> + Crap + end, + t("compact_otp4085_1_chk1 -> Expected: " + "~n Line: ~p" + "~n Module: ~p" + "~n Crap2: ~p", [Line, Module, Crap2]), + ok; + {value, BadReason} -> + e("compact_otp4085_1_chk1 -> error: " + "~n BadReason: ~p", [BadReason]), + {error, {unexpected_reason, Reason}}; + false -> + {error, {reason_not_found, Reason}} + end. + + +%% -------------------------------------------------------------- +%% This test case is just to show that the message used in +%% compact_otp4085_msg1 is actually ok when you add '}' at the end. +compact_otp4085_msg2(suite) -> + []; +compact_otp4085_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = compact_otp4085_erroneous_msg() ++ "}", + ok = compact_otp4085_2(M), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4085_2(Msg) -> + compact_otp4085_2(Msg, ?EC). + +compact_otp4085_2(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(M) when is_record(M, 'MegacoMessage') -> + ok; + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode_only(Msg, Decode, Check). + + +%% This message lack the ending parentesis (}). +compact_otp4085_erroneous_msg() -> + M = "!/" + ?VERSION_STR + " ML T=11223342{C=${A=${M{O{MO=SR,RV=OFF,RG=OFF},L{v=0," + "c=ATM NSAP $ ," + "a=eecid:$ ," + "m=audio - AAL1/ATMF -," + "}}},A=stee1181/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=off}}}}", + M. + +%% -------------------------------------------------------------- +%% +%% +compact_otp4280_msg1(suite) -> + []; +compact_otp4280_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4280_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = compact_otp4280_msg(), + ok = compact_otp4280(M), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4280(Msg) -> + compact_otp4280(Msg, ?EC). + +compact_otp4280(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(M) when is_record(M, 'MegacoMessage') -> + ok; + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode_only(Msg, Decode, Check). + +compact_otp4280_msg() -> + M = "!/" + ?VERSION_STR + " mgw1 P=71853646{C=-{AV=root{M{TS{root/maxnumberofcontexts=49500," + "root/maxterminationspercontext=2,root/normalmgexecutiontime=200," + "root/normalmgcexecutiontime=150," + "root/provisionalresponsetimervalue=2000,BF=OFF,SI=IV}}}}}", + M. + + +%% -------------------------------------------------------------- +%% This ticket is about comments in a message +%% +compact_otp4299_msg1(suite) -> + []; +compact_otp4299_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4299_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = compact_otp4299_msg(), + ok = compact_otp4299(Msg), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4299(Msg) -> + compact_otp4299(Msg, ?EC). + +compact_otp4299(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(M) when is_record(M, 'MegacoMessage') -> + ok; + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode_only(Msg, Decode, Check). + +compact_otp4299_msg() -> + M = ";KALLE\n" + "!/" + ?VERSION_STR + " mg58_1 P=005197711{; YET ANOTHER COMMENT\n" + "C=035146207{A=mg58_1_1_4_1_23/19; BEFORE COMMA\n" + ",; AFTER COMMA\n" + "A=eph58_1/0xA4023371{M{L{\n" + "v=0\n" + "c=ATM NSAP 39.0102.0304.0506.0708.090a.0b58.0100.0000.0000.00\n" + "m=audio - AAL1/ATMF -\n" + "a=eecid:A4023371\n" + "}}; HOBBE\n}; KALLE \"HOBBE \n}}" + ";KALLE\n\n", + M. + + +%% -------------------------------------------------------------- +%% + +compact_otp4359_msg1(suite) -> + []; +compact_otp4359_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4359_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = compact_otp4359_msg(), + ok = compact_otp4359(Msg), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4359_msg() -> + M = "!/" ?VERSION_STR " ml2 T={C=${A=${M{O {MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4359(Msg) -> + compact_otp4359(Msg, ?EC). + +compact_otp4359(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(M) when is_record(M, 'MegacoMessage') -> + compact_otp4359_chk(M); + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode_only(Msg, Decode, Check). + +compact_otp4359_chk(#'MegacoMessage'{mess = Mess}) -> + case Mess#'Message'.messageBody of + {transactions, Trans} -> + case Trans of + [{transactionRequest, TR}] -> + case TR of + #'TransactionRequest'{transactionId = asn1_NOVALUE} -> + ok; + _ -> + {error, {unexpected_trans_req, TR}} + end; + _ -> + {error, {unexpected_trans, Trans}} + end; + Body -> + {error, {unexpected_messageBody, Body}} + end. + + +%% -------------------------------------------------------------- +%% +compact_otp4920_msg0(suite) -> + []; +compact_otp4920_msg0(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg0 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg0() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg1(suite) -> + []; +compact_otp4920_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg2(suite) -> + []; +compact_otp4920_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg2() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg3(suite) -> + []; +compact_otp4920_msg3(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg3() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg4(suite) -> + []; +compact_otp4920_msg4(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg4() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg5(suite) -> + []; +compact_otp4920_msg5(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg5() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg6(suite) -> + []; +compact_otp4920_msg6(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg6() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg7(suite) -> + []; +compact_otp4920_msg7(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg7() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg8(suite) -> + []; +compact_otp4920_msg8(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg8 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg8() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg9(suite) -> + []; +compact_otp4920_msg9(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg9 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg9() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg10(suite) -> + []; +compact_otp4920_msg10(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg10 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg10() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg11(suite) -> + []; +compact_otp4920_msg11(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg11 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg11() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg12(suite) -> + []; +compact_otp4920_msg12(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg12 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg12() ), + %% erase(severity), + %% erase(dbg), + ok. + +%% Duplicate padding +compact_otp4920_msg20(suite) -> + []; +compact_otp4920_msg20(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg20 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp4920(compact_otp4920_msg20(), bad_mid_duplicate_padding), + %% erase(severity), + %% erase(dbg), + ok. + +%% Length +compact_otp4920_msg21(suite) -> + []; +compact_otp4920_msg21(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg21 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp4920(compact_otp4920_msg21(), bad_mid_ip6addr_length), + %% erase(severity), + %% erase(dbg), + ok. + +%% Length +compact_otp4920_msg22(suite) -> + []; +compact_otp4920_msg22(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg22 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp4920(compact_otp4920_msg22(), bad_mid_ip6addr_length), + %% erase(severity), + %% erase(dbg), + ok. + +%% Length +compact_otp4920_msg23(suite) -> + []; +compact_otp4920_msg23(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg23 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp4920(compact_otp4920_msg23(), bad_mid_ip6addr_length), + %% erase(severity), + %% erase(dbg), + ok. + +%% Length +compact_otp4920_msg24(suite) -> + []; +compact_otp4920_msg24(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg24 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp4920(compact_otp4920_msg24(), bad_mid_ip6addr_length), + %% erase(severity), + %% erase(dbg), + ok. + +%% Length +compact_otp4920_msg25(suite) -> + []; +compact_otp4920_msg25(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg25 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp4920(compact_otp4920_msg25(), bad_mid_ip6addr_length), + %% erase(severity), + %% erase(dbg), + ok. + + +compact_otp4920(Msg, ExpectedReason) -> + compact_otp4920(Msg, ?EC, ExpectedReason). + +compact_otp4920(Msg, Conf, ExpectedReason) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(Reason) when is_list(Reason) -> + compact_otp4920_chk(Reason, ExpectedReason); + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode(Msg, Decode, Check). + +compact_otp4920_chk(Reason, ExpectedReason) -> + case lists:keysearch(reason, 1, Reason) of + {value, {reason, {__Line, _Mod, ActualReason}}} -> + case element(1, ActualReason) of + ExpectedReason -> + ok; + _ -> + {error, {unexpected_decode_reason, + {ActualReason, ExpectedReason}}} + end; + {value, {reason, {_Mod, ActualReason}}} -> + case element(1, ActualReason) of + ExpectedReason -> + ok; + _ -> + {error, {unexpected_decode_reason, + {ActualReason, ExpectedReason}}} + end; + {value, UnknownReason} -> + {error, {unexpected_decode_reason, UnknownReason}}; + false -> + {error, {reason_not_found, Reason}} + end. + +compact_otp4920_msg0() -> + M = "!/" ?VERSION_STR " [192.168.30.1]\nT=100{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg1() -> + M = "!/" ?VERSION_STR " [2031:0000:130F:0000:0000:09C0:876A:130B]\nT=101{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg2() -> + M = "!/" ?VERSION_STR " [2031:0:130F:0:0:9C0:876A:130B]\nT=102{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg3() -> + M = "!/" ?VERSION_STR " [2031:0:130F::9C0:876A:130B]\nT=103{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg4() -> + M = "!/" ?VERSION_STR " [::1]\nT=104{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg5() -> + M = "!/" ?VERSION_STR " [::]\nT=105{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg6() -> + M = "!/" ?VERSION_STR " [1::]\nT=106{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg7() -> + M = "!/" ?VERSION_STR " [FEDC:1::]\nT=107{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg8() -> + M = "!/" ?VERSION_STR " [2031:0:130F:0:0:9C0:135.106.19.11]\nT=108{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg9() -> + M = "!/" ?VERSION_STR " [2031:0:130F::9C0:135.106.19.11]\nT=109{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg10() -> + M = "!/" ?VERSION_STR " [::FFFF:192.168.30.1]\nT=110{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg11() -> + M = "!/" ?VERSION_STR " [::192.168.30.1]\nT=111{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg12() -> + M = "!/" ?VERSION_STR " [::C0A8:1E01]\nT=112{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: only one :: allowed +compact_otp4920_msg20() -> + M = "!/" ?VERSION_STR " [2031::130F::9C0]\nT=120{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg21() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:0000:0000:09C0:876A:130B]\nT=121{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg22() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0:130F:0:0:9C0:135.106.19.11]\nT=122{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg23() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:2132:4354::09C0:876A:130B]\nT=123{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg24() -> + M = "!/" ?VERSION_STR " [::2031:FFEE:0000:130F:2132:4354:09C0:876A:130B]\nT=124{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg25() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:2132:4354:09C0:876A:130B::]\nT=125{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + + +%% -------------------------------------------------------------- +%% + +compact_otp5186_msg01(suite) -> + []; +compact_otp5186_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5186_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_error( compact_otp5186_msg01() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5186_msg02(suite) -> + []; +compact_otp5186_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5186_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp5186_msg02() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5186_msg03(suite) -> + []; +compact_otp5186_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5186_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% ok = compact_otp5186_msg_2(compact_otp5186_msg03(), ok, ok), + ok = ticket_compact_encode_decode_ok( compact_otp5186_msg03() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5186_msg04(suite) -> + []; +compact_otp5186_msg04(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5186_msg04 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% ok = compact_otp5186_msg_2(compact_otp5186_msg04(), ok, ok), + ok = ticket_compact_encode_decode_ok( compact_otp5186_msg04() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5186_msg05(suite) -> + []; +compact_otp5186_msg05(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5186_msg05 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% ok = compact_otp5186_msg_2(compact_otp5186_msg05(), ok, ok), + ok = ticket_compact_encode_decode_ok( compact_otp5186_msg05() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5186_msg06(suite) -> + []; +compact_otp5186_msg06(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5186_msg06 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% ok = compact_otp5186_msg_2(compact_otp5186_msg06(), ok, ok), + ok = ticket_compact_encode_decode_ok( compact_otp5186_msg06() ), + %% erase(severity), + %% erase(dbg), + ok. + +%% -- + +compact_otp5186_msg01() -> + "!/" ?VERSION_STR " <mg5>\nP=67111298{C=2699{AV=mg5_ipeph/0x0f0001{}}}". + +compact_otp5186_msg02() -> + "!/" ?VERSION_STR " <mg5>\nP=67111298{C=2699{AV=mg5_ipeph/0x0f0001}}". + +compact_otp5186_msg03() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]}, + [ + ] + } + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +compact_otp5186_msg04() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',?VERSION,{domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]}, + [ + {emptyDescriptors, + {'AuditDescriptor',asn1_NOVALUE,asn1_NOVALUE} + } + ] + } + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +compact_otp5186_msg05() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {addReply, + {'AmmsReply', + [ + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]} + ], + [ + ] + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +compact_otp5186_msg06() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',?VERSION,{domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {addReply, + {'AmmsReply', + [ + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]} + ], + [ + {emptyDescriptors, + {'AuditDescriptor',asn1_NOVALUE,asn1_NOVALUE} + } + ] + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +%% -------------------------------------------------------------- + +compact_otp5793_msg01(suite) -> + []; +compact_otp5793_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_encode_decode_ok(pretty_otp5793_msg1()), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- + +compact_otp5836_msg01(suite) -> + []; +compact_otp5836_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5836_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_encode_decode_ok(compact_otp5836_msg1()), + %% erase(severity), + %% erase(dbg), + ok. + + +compact_otp5836_msg1() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + 3, + {deviceName,"bs_sbg_4/34"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 12, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 4294967295, + asn1_NOVALUE, + asn1_NOVALUE, + [{auditValueReply, + {error, {'ErrorDescriptor', 431, asn1_NOVALUE}}} + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +%% -------------------------------------------------------------- + +compact_otp5993_msg01(suite) -> + []; +compact_otp5993_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5993_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_encode_decode_ok( compact_otp5993_msg01() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5993_msg01() -> + MT = h221, + T = #megaco_term_id{id = ?A4444}, + TL = [T], + MD = #'MuxDescriptor'{muxType = MT, + termList = TL}, + compact_otp5993_msg(MD). + + +compact_otp5993_msg02(suite) -> + []; +compact_otp5993_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5993_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_encode_decode_ok( compact_otp5993_msg02() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5993_msg02() -> + MT = h223, + T1 = #megaco_term_id{id = ?A4445}, + T2 = #megaco_term_id{id = ?A5556}, + TL = [T1, T2], + MD = #'MuxDescriptor'{muxType = MT, + termList = TL}, + compact_otp5993_msg(MD). + + +compact_otp5993_msg03(suite) -> + []; +compact_otp5993_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5993_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_encode_decode_ok( compact_otp5993_msg03() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5993_msg03() -> + T1 = #megaco_term_id{id = ?A4445}, + T2 = #megaco_term_id{id = ?A5556}, + TIDs = [T1, T2], + AudRep = {contextAuditResult, TIDs}, + CmdRep = {auditValueReply, AudRep}, + ActRep = #'ActionReply'{contextId = 5993, + commandReply = [CmdRep]}, + TransRes = {actionReplies, [ActRep]}, + TransRep = #'TransactionReply'{transactionId = 3995, + transactionResult = TransRes}, + Trans = {transactionReply, TransRep}, + Body = {transactions, [Trans]}, + Msg = #'Message'{version = ?VERSION, + mId = ?MG1_MID, + messageBody = Body}, + #'MegacoMessage'{mess = Msg}. + + +compact_otp5993_msg(MD) when is_record(MD, 'MuxDescriptor') -> + AmmDesc = {muxDescriptor, MD}, + AmmReq = #'AmmRequest'{terminationID = [hd(MD#'MuxDescriptor'.termList)], + descriptors = [AmmDesc]}, + Cmd = {addReq, AmmReq}, + CmdReq = #'CommandRequest'{command = Cmd}, + ActReq = #'ActionRequest'{contextId = 5993, + commandRequests = [CmdReq]}, + TransReq = #'TransactionRequest'{transactionId = 3995, + actions = [ActReq]}, + Trans = {transactionRequest, TransReq}, + Body = {transactions, [Trans]}, + Msg = #'Message'{version = ?VERSION, + mId = ?MG1_MID, + messageBody = Body}, + #'MegacoMessage'{mess = Msg}. + + +%% -------------------------------------------------------------- + +compact_otp6017_msg01(suite) -> + []; +compact_otp6017_msg01(Config) when is_list(Config) -> + d("compact_otp6017_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(0), + ok. + +compact_otp6017_msg02(suite) -> + []; +compact_otp6017_msg02(Config) when is_list(Config) -> + d("compact_otp6017_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(16#FFFFFFFE), + ok. + +compact_otp6017_msg03(suite) -> + []; +compact_otp6017_msg03(Config) when is_list(Config) -> + d("compact_otp6017_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(16#FFFFFFFF), + ok. + +compact_otp6017(BadCID) -> + Conf = ?EC, + M = compact_otp6017_msg(BadCID), + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, Conf, Bin) of + {ok, Msg} -> + exit({unexpected_decode_success, {Msg, M}}); + {error, Reason} when is_list(Reason) -> % Expected result + case lists:keysearch(reason, 1, Reason) of + {value, {reason, {_Line, _Mod, {bad_ContextID, BadCID}}}} -> + io:format(" ~w", [BadCID]), + ok; + {value, {reason, ActualReason}} -> + exit({unexpected_reason, ActualReason}); + false -> + exit({reason_not_found, Reason}) + end; + Crap -> + exit({unexpected_decode_result, Crap}) + end. + +compact_otp6017_msg(CID) when is_integer(CID) -> + "MEGACO/" ?VERSION_STR " MG1 T=12345678{C=" ++ + integer_to_list(CID) ++ + "{SC=root{SV{MT=RS,RE=901}}}}". + + +%% ============================================================== +%% +%% F l e x C o m p a c t T e s t c a s e s +%% + +flex_compact_otp4299_msg1(suite) -> + []; +flex_compact_otp4299_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp4299_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = compact_otp4299_msg(), + Conf = flex_scanner_conf(Config), + ok = compact_otp4299(Msg, [?EC_V3,Conf]), + %% erase(severity), + %% erase(dbg), + ok. + + +flex_compact_otp7431_msg01(suite) -> + []; +flex_compact_otp7431_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg01 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(ok, flex_compact_otp7431_msg1(), [Conf]). + +flex_compact_otp7431_msg02(suite) -> + []; +flex_compact_otp7431_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg02 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg2(), [Conf]). + +flex_compact_otp7431_msg03(suite) -> + []; +flex_compact_otp7431_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg03 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg3(), [Conf]). + +flex_compact_otp7431_msg04(suite) -> + []; +flex_compact_otp7431_msg04(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg04 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg4(), [Conf]). + +flex_compact_otp7431_msg05(suite) -> + []; +flex_compact_otp7431_msg05(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg05 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg5(), [Conf]). + +flex_compact_otp7431_msg06(suite) -> + []; +flex_compact_otp7431_msg06(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg06 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg6(), [Conf]). + +flex_compact_otp7431_msg07(suite) -> + []; +flex_compact_otp7431_msg07(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg07 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg7(), [Conf]). + + +flex_compact_otp7431(Expected, Msg, Conf) -> + otp7431(Expected, megaco_compact_text_encoder, Msg, Conf). + +flex_compact_otp7431_msg1() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a=recvonly +}}}}}}". + +flex_compact_otp7431_msg2() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a= } +}}}}}". + + +flex_compact_otp7431_msg3() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a } +}}}}}". + + +flex_compact_otp7431_msg4() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a} +}}}}}". + + +flex_compact_otp7431_msg5() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v= } +}}}}}". + + +flex_compact_otp7431_msg6() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v } +}}}}}". + +flex_compact_otp7431_msg7() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v} +}}}}}". + + +%% ============================================================== +%% +%% P r e t t y T e s t c a s e s +%% + +pretty_otp4632_msg1(suite) -> + []; +pretty_otp4632_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4632_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp4632_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4632_msg1() -> + msg4(?MG1_MID_NO_PORT, "901 mg col boot"). + +pretty_otp4632_msg2(suite) -> + []; +pretty_otp4632_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4632_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp4632_msg2() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4632_msg2() -> + msg4(?MG1_MID_NO_PORT, "901"). + + +pretty_otp4632_msg3(suite) -> + []; +pretty_otp4632_msg3(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4632_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_encode_ok( pretty_otp4632_msg3() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4632_msg3() -> + M = "MEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = \"901\"\n\t\t\t}\n\t\t}\n\t}\n}", + M. + + +pretty_otp4632_msg4(suite) -> + []; +pretty_otp4632_msg4(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4632_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(B2, B1) -> pretty_otp4632_msg4_chk(B1, B2) end, + ok = ticket_pretty_decode_encode_only(pretty_otp4632_msg4(), Check), + %% erase(severity), + %% erase(dbg), + ok. + + +pretty_otp4632_msg4() -> + M = "MEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = 901\n\t\t\t}\n\t\t}\n\t}\n}", + M. + +pretty_otp4632_msg4_chk(B1, B2) when is_binary(B1) and is_binary(B2) -> + S1 = binary_to_list(B1), + S2 = binary_to_list(B2), + %% io:format("~n" + %% "S1: ~s~n" + %% "S2: ~s~n", [S1, S2]), + pretty_otp4632_msg4_chk(S1, S2); + +pretty_otp4632_msg4_chk([], []) -> + messages_not_eq; +pretty_otp4632_msg4_chk([], Rest2) -> + {messages_not_eq2, Rest2}; +pretty_otp4632_msg4_chk(Rest1, []) -> + {messages_not_eq1, Rest1}; +pretty_otp4632_msg4_chk([$R,$e,$a,$s,$o,$n,$ ,$=,$ ,$",$9,$0,$1,$"|_Rest1], + [$R,$e,$a,$s,$o,$n,$ ,$=,$ ,$9,$0,$1|_Rest2]) -> + ok; +pretty_otp4632_msg4_chk([_H1|Rest1], [_H2|Rest2]) -> + pretty_otp4632_msg4_chk(Rest1, Rest2). + + +%% -------------------------------------------------------------- +%% +pretty_otp4710_msg1(suite) -> + []; +pretty_otp4710_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4710_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp4710_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4710_msg1() -> + msg40(). + + +pretty_otp4710_msg2(suite) -> + []; +pretty_otp4710_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4710_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(B1, B2) -> pretty_otp4710_msg2_chk(B1, B2) end, + ok = ticket_pretty_decode_encode_only(pretty_otp4710_msg2(), Check), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4710_msg2() -> + "Authentication = 0xEFCDAB89:0x12345678:0x1234567889ABCDEF76543210\nMEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = \"901 mg col boot\"\n\t\t\t}\n\t\t}\n\t}\n}". + +pretty_otp4710_msg2_chk(B1, B2) when is_binary(B1) and is_binary(B2) -> + S1 = binary_to_list(B1), + S2 = binary_to_list(B2), + pretty_otp4710_msg2_chk(S1, S2); + +pretty_otp4710_msg2_chk(Msg, Msg) -> + ok; + +pretty_otp4710_msg2_chk( + [$A,$u,$t,$h,$e,$n,$t,$i,$c,$a,$t,$i,$o,$n,$=,$ |Msg0], + [$A,$u,$t,$h,$e,$n,$t,$i,$c,$a,$t,$i,$o,$n,$=,$ |Msg1]) -> + {AH0, Rest0} = pretty_otp4710_msg2_chk_ah(Msg0, []), + {AH1, Rest1} = pretty_otp4710_msg2_chk_ah(Msg1, []), + case AH0 == AH1 of + true -> + exit({message_not_equal, Rest0, Rest1}); + false -> + exit({auth_header_not_equal, AH0, AH1}) + end. + +pretty_otp4710_msg2_chk_ah([], _Acc) -> + exit(no_auth_header_found); +pretty_otp4710_msg2_chk_ah([$M,$E,$G,$A,$C,$O,$/,_|Rest], Acc) -> + {lists:reverse(Acc), Rest}; +pretty_otp4710_msg2_chk_ah([C|R], Acc) -> + pretty_otp4710_msg2_chk_ah(R, [C|Acc]). + + +%% -------------------------------------------------------------- +%% +pretty_otp4945_msg1(suite) -> + []; +pretty_otp4945_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4945_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp4945_msg1_chk(R) end, + ok = ticket_pretty_decode_error(pretty_otp4945_msg1(), Check), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4945_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + +pretty_otp4945_msg1_chk(R) when is_list(R) -> + ExpMissing = [serviceChangeReason], + Check = fun(Reason) -> + pretty_otp4945_chk(Reason, ExpMissing) + end, + ticket_check_decode_only_error_reason(R, Check). + + +pretty_otp4945_msg2(suite) -> + []; +pretty_otp4945_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4945_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp4945_msg2_chk(R) end, + ok = ticket_pretty_decode_error(pretty_otp4945_msg2(), Check), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4945_msg2() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + +pretty_otp4945_msg2_chk(R) when is_list(R) -> + ExpMissing = [serviceChangeMethod], + Check = fun(Reason) -> + pretty_otp4945_chk(Reason, ExpMissing) + end, + ticket_check_decode_only_error_reason(R, Check). + + +pretty_otp4945_msg3(suite) -> + []; +pretty_otp4945_msg3(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4945_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp4945_msg3_chk(R) end, + ok = ticket_pretty_decode_error(pretty_otp4945_msg3(), Check), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4945_msg3() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + +pretty_otp4945_msg3_chk(R) when is_list(R) -> + ExpMissing = [serviceChangeReason, serviceChangeMethod], + Check = fun(Reason) -> + pretty_otp4945_chk(Reason, ExpMissing) + end, + ticket_check_decode_only_error_reason(R, Check). + + +pretty_otp4945_msg4(suite) -> + []; +pretty_otp4945_msg4(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4945_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_only( pretty_otp4945_msg4() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4945_msg4() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg5(suite) -> + []; +pretty_otp4945_msg5(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4945_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp4945_msg5_chk(R) end, + ok = ticket_pretty_decode_error(pretty_otp4945_msg5(), Check), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4945_msg5() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + Profile = ResGW/1, + ServiceChangeAddress = 55555, + Profile = ResGW/2 + } + } + } +}". + +pretty_otp4945_msg5_chk(R) when is_list(R) -> + Check = fun({at_most_once_serviceChangeParm, {profile, _, _}}) -> + ok; + (Reason) -> + {error, {unexpected_reason, Reason}} + end, + ticket_check_decode_only_error_reason(R, Check). + + +pretty_otp4945_msg6(suite) -> + []; +pretty_otp4945_msg6(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4945_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp4945_msg6_chk(R) end, + ok = ticket_pretty_decode_error(pretty_otp4945_msg6(), Check), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4945_msg6() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + MgcIdToTry = kalle, + Profile = ResGW/1 + } + } + } +}". + +pretty_otp4945_msg6_chk(R) when is_list(R) -> + Check = fun({not_both_address_mgcid_serviceChangeParm, _, _}) -> + ok; + (Reason) -> + {error, {unexpected_reason, Reason}} + end, + ticket_check_decode_only_error_reason(R, Check). + + +pretty_otp4945_chk({missing_required_serviceChangeParm, Missing}, + ExpMissing) when is_list(Missing) -> + case ExpMissing -- Missing of + [] -> + ok; + Diff -> + {error, {unexpected_missing_serviceChangeParm, Diff}} + end; +pretty_otp4945_chk(Reason, _ExpMissing) -> + {error, {unexpected_reason, Reason}}. + + +%% -------------------------------------------------------------- +%% +pretty_otp4949_msg1(suite) -> + []; +pretty_otp4949_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4949_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_only( pretty_otp4949_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4949_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4949_msg2(suite) -> + []; +pretty_otp4949_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4949_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp4949_msg2_chk(R) end, + ok = ticket_pretty_decode_error( pretty_otp4949_msg2(), Check), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4949_msg2() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Profile = ResGW/1, + ServiceChangeAddress = 55555, + Profile = ResGW/2 + } + } + } +}". + +pretty_otp4949_msg2_chk(R) when is_list(R) -> + Check = fun({at_most_once_servChgReplyParm, {profile, _, _}}) -> + ok; + (Reason) -> + {error, {unexpected_reason, Reason}} + end, + ticket_check_decode_only_error_reason(R, Check). + + +pretty_otp4949_msg3(suite) -> + []; +pretty_otp4949_msg3(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4949_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp4949_msg3_chk(R) end, + ok = ticket_pretty_decode_error( pretty_otp4949_msg3(), Check ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4949_msg3() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + MgcIdToTry = kalle, + Profile = ResGW/1 + } + } + } +}". + +pretty_otp4949_msg3_chk(R) when is_list(R) -> + Check = fun({not_both_address_mgcid_servChgReplyParm, _, _}) -> + ok; + (Reason) -> + {error, {unexpected_reason, Reason}} + end, + ticket_check_decode_only_error_reason(R, Check). + + +%% -------------------------------------------------------------- +%% +pretty_otp5042_msg1(suite) -> + []; +pretty_otp5042_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5042_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_only( pretty_otp5042_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5042_msg1() -> +"MEGACO/" ?VERSION_STR " <CATAPULT>:2944 +Transaction = 102 { +Context = 5 { Notify = MUX/1 { ObservedEvents = 1 { +h245bh/h245msgin { Stream = 1 +, h245enc = +0270020600088175000653401004100403E802E00180018001780680000034301160000700088175010101007A0100020001800001320000C0000219D005027F0070500100040100021080000319D005027F00504001008000041C001250000700088175010000400280010003000880000518AA027F400006850130008011020100000001030002000300040005000006 + } } + } } }". + + +%% -------------------------------------------------------------- +%% +pretty_otp5068_msg1(suite) -> + []; +pretty_otp5068_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5068_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_only( pretty_otp5068_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5068_msg1() -> +{'MegacoMessage', + asn1_NOVALUE, + {'Message', + 2, + {deviceName,[109,103,51,51]}, + {transactions, + [{transactionReply, + {'TransactionReply', + 190, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', %% Comments: Detta upprepas m�nga g�nger + 0, + asn1_NOVALUE, + asn1_NOVALUE, + [{auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false, + [[99,101,100,101,118,49,47,52,47,49,47,49],[51,49]]}, + [{mediaDescriptor, + {'MediaDescriptor', + {'TerminationStateDescriptor', + [], + asn1_NOVALUE, + inSvc}, + asn1_NOVALUE + } + } + ] + } + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } +}. + + + +%% -------------------------------------------------------------- +%% +pretty_otp5085_msg1(suite) -> + []; +pretty_otp5085_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg1() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + asn1_NOVALUE, + [] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg2(suite) -> + []; +pretty_otp5085_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg2() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg2() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + asn1_NOVALUE, + [] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg3(suite) -> + []; +pretty_otp5085_msg3(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg3() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg3() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + #'ContextRequest'{priority = 3}, + [] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg4(suite) -> + []; +pretty_otp5085_msg4(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg4() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg4() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + asn1_NOVALUE, + [{addReply, cre_AmmsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg5(suite) -> + []; +pretty_otp5085_msg5(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg5() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg5() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + #'ContextRequest'{priority = 5}, + [{addReply, cre_AmmsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg6(suite) -> + []; +pretty_otp5085_msg6(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg6() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg6() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 6}, + [{addReply, cre_AmmsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg7(suite) -> + []; +pretty_otp5085_msg7(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg7() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg7() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 7}, + [{notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg8(suite) -> + []; +pretty_otp5085_msg8(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg8 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg8() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg8() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 8, + emergency = true, + topologyReq = + [#'TopologyRequest'{terminationFrom = From1, + terminationTo = To1, + topologyDirection = bothway}, + #'TopologyRequest'{terminationFrom = From2, + terminationTo = To2, + topologyDirection = oneway} + ], + iepscallind = true, + contextProp = [cre_PropParm("tdmc/gain", "2")]}, + [{notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +%% -------------------------------------------------------------- +%% +pretty_otp5600_msg1(suite) -> + []; +pretty_otp5600_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5600_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5600_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5600_msg1() -> + SRE = #'SecondRequestedEvent'{ pkgdName = "al/on", + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE ] }, + + SIG = { signal, #'Signal'{ signalName = "cg/dt", + sigParList = [] } }, + + RA = #'RequestedActions'{ secondEvent = SED, + signalsDescriptor = [ SIG ] }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + + +pretty_otp5600_msg2(suite) -> + []; +pretty_otp5600_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5600_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5600_msg2() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5600_msg2() -> + SIG = { signal, #'Signal'{ signalName = "cg/dt", + sigParList = [] } }, + + SRA = #'SecondRequestedActions'{ signalsDescriptor = [ SIG ] }, + + SRE = #'SecondRequestedEvent'{ pkgdName = "al/on", + eventAction = SRA, + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE ] }, + + RA = #'RequestedActions'{ secondEvent = SED }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + + +%% -------------------------------------------------------------- +%% +pretty_otp5601_msg1(suite) -> + []; +pretty_otp5601_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5601_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5601_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5601_msg1() -> + SRE1 = #'SecondRequestedEvent'{ pkgdName = "al/on", + evParList = [] }, + + SRA = #'SecondRequestedActions'{ eventDM = { digitMapName, "dialllan0" }}, + + SRE2 = #'SecondRequestedEvent'{ pkgdName = "dd/ce", + eventAction = SRA, + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE1, SRE2 ] }, + + RA = #'RequestedActions'{ secondEvent = SED }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + + +%% -------------------------------------------------------------- +%% +pretty_otp5793_msg01(suite) -> + []; +pretty_otp5793_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5793_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5793_msg1() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',3, + {deviceName,"bs_sbg_4/99"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 370, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 3, + asn1_NOVALUE, + asn1_NOVALUE, + [{auditValueReply, + {contextAuditResult, + [{megaco_term_id, + false, + ["ip", + "104", + "1", + "18"]}]}}, + {auditValueReply, + {contextAuditResult, + [{megaco_term_id, + false, + ["ip", + "104", + "2", + "19"] + } + ] + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + + +%% -------------------------------------------------------------- +%% +pretty_otp5803_msg01(suite) -> + []; +pretty_otp5803_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5803_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_encode_ok( pretty_otp5803_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5803_msg1() -> +"MEGACO/" ?VERSION_STR " [134.138.234.29]Transaction=384{ + Context=27{ + Modify=ip/104/1/76{ + Media{ + Stream=1{ + Local{}, + Remote{} + }, + Stream=2{ + Local{}, + Remote{} + } + }, + Audit{ + Media{ + Stream=1{ + Statistics{*/*} + }, + Stream=2{ + Statistics{*/*} + } + } + } + }, + Modify=ip/104/2/77{ + Media{ + Stream=1{ + Local{}, + Remote{} + }, + Stream=2{ + Local{}, + Remote{} + } + } + } + } +}". + + +pretty_otp5803_msg02(suite) -> + []; +pretty_otp5803_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5803_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_encode_ok( pretty_otp5803_msg2() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5803_msg2() -> +"MEGACO/" ?VERSION_STR " [134.138.234.29]Transaction=384{ + Context=27{ + Modify=ip/104/1/76{ + Media{ + Stream=1{ + Local{}, + Remote{} + }, + Stream=2{ + Local{}, + Remote{} + } + }, + Audit{ + Media{ + Stream=1{ + Statistics{*/*} + } + } + } + }, + Modify=ip/104/2/77{ + Media{ + Stream=1{ + Local{}, + Remote{} + }, + Stream=2{ + Local{}, + Remote{} + } + } + } + } +}". + + +%% -------------------------------------------------------------- +%% +pretty_otp5805_msg01(suite) -> + []; +pretty_otp5805_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5805_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_error( pretty_otp5805_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5805_msg1() -> +"MEGACO/4 [134.138.234.29] +Transaction=1{ + Context=*{ + AuditValue=ip/0/*{ + Audit{} + } + } +}". + + +%% -------------------------------------------------------------- +%% +pretty_otp5836_msg01(suite) -> + []; +pretty_otp5836_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5836_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( compact_otp5836_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +pretty_otp5882_msg01(suite) -> + []; +pretty_otp5882_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5882_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp5882_msg01_chk(R) end, + ok = ticket_pretty_encode_error( pretty_otp5882_msg01(), Check ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5882_msg01_chk({message_encode_failed, {error, {Reason, _}}, _}) -> + case Reason of + {invalid_LocalControlDescriptor, empty} -> + ok; + _ -> + {error, {unexpected_error_actual_reason, Reason}} + end; +pretty_otp5882_msg01_chk(Reason) -> + {error, {unexpected_reason, Reason}}. + + +pretty_otp5882_msg01() -> + LCD = #'LocalControlDescriptor'{}, % Create illegal LCD + Parms = cre_StreamParms(LCD), + StreamDesc = cre_StreamDesc(1, Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + CID = cre_CtxID(7301), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(7302), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + + + +%% -------------------------------------------------------------- +%% +pretty_otp6490_msg01(suite) -> + []; +pretty_otp6490_msg01(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg01 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp6490_msg01(), [] ), + %% erase(dbg), + erase(severity), + ok. + +pretty_otp6490_msg02(suite) -> + []; +pretty_otp6490_msg02(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg02 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp6490_msg02(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg03(suite) -> + []; +pretty_otp6490_msg03(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg03 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp6490_msg03(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg04(suite) -> + []; +pretty_otp6490_msg04(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg04 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp6490_msg04(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg05(suite) -> + []; +pretty_otp6490_msg05(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg05 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp6490_msg05(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg06(suite) -> + []; +pretty_otp6490_msg06(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg06 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp6490_msg06(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg(EBD) -> + AmmDesc = ?MSG_LIB:cre_AmmDescriptor(EBD), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4445}], [AmmDesc]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + CID = cre_CtxID(64901), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(64902), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +pretty_otp6490_msg01() -> + EvSpecs = [], % This will result in an error + EBD = EvSpecs, % This is because the lib checks that the size is valid + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg02() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg03() -> + EvPar1 = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + EvPar2 = ?MSG_LIB:cre_EventParameter("kalle", ["anka"]), + EvPar3 = ?MSG_LIB:cre_EventParameter("flippa", ["ur"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar1,EvPar2,EvPar3]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg04() -> + EvPar1 = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + EvPar2 = ?MSG_LIB:cre_EventParameter("kalle", ["anka"]), + EvPar3 = ?MSG_LIB:cre_EventParameter("flippa", ["ur"]), + PkgdName1 = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName1 = ?MSG_LIB:cre_EventName(PkgdName1), + EvSpec1 = ?MSG_LIB:cre_EventSpec(EvName1, [EvPar1,EvPar2,EvPar3]), + EvPar4 = ?MSG_LIB:cre_EventParameter("hej", ["hopp"]), + PkgdName2 = ?MSG_LIB:cre_PkgdName("bar", "b"), + EvName2 = ?MSG_LIB:cre_EventName(PkgdName2), + EvSpec2 = ?MSG_LIB:cre_EventSpec(EvName2, [EvPar4]), + EvSpecs = [EvSpec1,EvSpec2], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg05() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", root), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg06() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName(root, root), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + + +%% -------------------------------------------------------------- +%% + +pretty_otp7671_msg01(suite) -> + []; +pretty_otp7671_msg01(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg01 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg01(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg02(suite) -> + []; +pretty_otp7671_msg02(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg02 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg02(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg03(suite) -> + []; +pretty_otp7671_msg03(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg03 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg03(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg04(suite) -> + []; +pretty_otp7671_msg04(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg04 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg04(), [] , error, ignore), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg05(suite) -> + []; +pretty_otp7671_msg05(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg05 -> entry", []), + Check = fun(M1, M2) -> cmp_otp7671_msg05(M1, M2) end, + ok = pretty_otp7671( pretty_otp7671_msg05(), [] , ok, ok, Check), +%% erase(dbg), +%% erase(severity), + ok. + + +pretty_otp7671(Msg, Conf) -> + pretty_otp7671(Msg, Conf, ok). + +pretty_otp7671(Msg, Conf, ExpectedEncode) -> + pretty_otp7671(Msg, Conf, ExpectedEncode, ok). + +pretty_otp7671(Msg, Conf, ExpectedEncode, ExpectedDecode) -> + otp7671(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode). + +pretty_otp7671(Msg, Conf, ExpectedEncode, ExpectedDecode, Check) -> + otp7671(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode, Check). + +otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode) -> + Check = fun(M1, M2) -> + exit({unexpected_decode_result, M1, M2}) + end, + otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode, Check). + +otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode, Check) -> + case (catch encode_message(Codec, Conf, Msg)) of + {error, _Reason} when ExpectedEncode =:= error -> + ok; + {error, Reason} when ExpectedEncode =:= ok -> + exit({unexpected_encode_failure, Reason}); + {ok, Bin} when ExpectedEncode =:= error -> + exit({unexpected_encode_success, Msg, binary_to_list(Bin)}); + {ok, Bin} when ExpectedEncode =:= ok -> + case decode_message(Codec, false, Conf, Bin) of + {ok, Msg} when ExpectedDecode =:= ok -> + ok; + {ok, Msg2} when ExpectedDecode =:= ok -> + Check(Msg, Msg2); + {ok, Msg} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg}); + {ok, Msg2} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg, Msg2}); + {error, _Reason} when ExpectedDecode =:= error -> + ok; + {error, Reason} when ExpectedDecode == ok -> + exit({unexpected_decode_failure, Msg, Reason}) + end + end. + + +pretty_otp7671_msg(DigitMapDesc) -> + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{digitMapDescriptor, DigitMapDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(?MGC_MID, 10001, ?megaco_null_context_id, [CmdReq]). + +pretty_otp7671_msg01() -> + Name = "dialplan01", + DigitMapDesc = cre_DigitMapDesc(Name), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg02() -> + Name = "dialplan02", + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body), + DigitMapDesc = cre_DigitMapDesc(Name, Value), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg03() -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body), + DigitMapDesc = cre_DigitMapDesc(Value), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg04() -> + DigitMapDesc = cre_DigitMapDesc(), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg05() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',?VERSION, + {domainName,{'DomainName',"tgc",asn1_NOVALUE}}, + {transactions, + [{transactionRequest, + {'TransactionRequest',12582952, + [{'ActionRequest',0,asn1_NOVALUE,asn1_NOVALUE, + [{'CommandRequest', + {modReq, + {'AmmRequest', + [{megaco_term_id,false,["root"]}], + [{digitMapDescriptor, + {'DigitMapDescriptor',"dialplan1", + {'DigitMapValue',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,[], + asn1_NOVALUE}}}]}}, + asn1_NOVALUE,asn1_NOVALUE}]}]}}]}}}. + +cmp_otp7671_msg05(#'MegacoMessage'{authHeader = asn1_NOVALUE, + mess = M1}, + #'MegacoMessage'{authHeader = asn1_NOVALUE, + mess = M2}) -> + #'Message'{messageBody = Body1} = M1, + #'Message'{messageBody = Body2} = M2, + {transactions, Trans1} = Body1, + {transactions, Trans2} = Body2, + [{transactionRequest, TR1}] = Trans1, + [{transactionRequest, TR2}] = Trans2, + #'TransactionRequest'{actions = Acts1} = TR1, + #'TransactionRequest'{actions = Acts2} = TR2, + [#'ActionRequest'{commandRequests = CR1}] = Acts1, + [#'ActionRequest'{commandRequests = CR2}] = Acts2, + [#'CommandRequest'{command = Cmd1}] = CR1, + [#'CommandRequest'{command = Cmd2}] = CR2, + {modReq, #'AmmRequest'{descriptors = Descs1}} = Cmd1, + {modReq, #'AmmRequest'{descriptors = Descs2}} = Cmd2, + [{digitMapDescriptor, + #'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value1}}] = Descs1, + [{digitMapDescriptor, + #'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value2}}] = Descs2, + #'DigitMapValue'{startTimer = asn1_NOVALUE, + shortTimer = asn1_NOVALUE, + longTimer = asn1_NOVALUE, + digitMapBody = [], + durationTimer = asn1_NOVALUE} = Value1, + asn1_NOVALUE = Value2, + ok. + + +%% -------------------------------------------------------------- +%% + + +pretty_otp8114_msg01(suite) -> + []; +pretty_otp8114_msg01(Config) when is_list(Config) -> + put(severity, trc), + put(dbg, true), + d("pretty_otp8114_msg01 -> entry", []), + ok = otp8114( pretty_otp8114_msg01(), megaco_pretty_text_encoder, ?EC), + erase(dbg), + erase(severity), + ok. + +pretty_otp8114_msg01() -> + "MEGACO/" ?VERSION_STR " [10.10.10.10]:1234\nTransaction = 1 {\n\tContext =\n1 {\n\t\tModify = ip/1/1/1 {\n\t\t\tMedia {\n\t\t\t\tStream = 1\n{\n\t\t\t\t\t\tLocalControl {\n\t\t\t\t\t\tMode =\nSendReceive\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tEvents = 1\n{\n\t\t\t\tadid/ipstop\n{\n\t\t\t\t\tdt=30,\n\t\t\t\t\tdir=\"BOTH\"\n\t\t\t\t},\n\t\t\t\tg/cause\n\n\t\t\t}\n\t\t}\n\t}\n}". + + +otp8114(InitialMessage, Codec, Conf) -> + Decode = fun(M) -> Codec:decode_message(Conf, M) end, + Encode = fun(B) -> Codec:encode_message(Conf, B) end, + InitialData = InitialMessage, + Instructions = + [ + %% List to binary + megaco_codec_test_lib:expect_instruction( + "Convert (initial) message to a binary", + fun(Msg) when is_list(Msg) -> + %% io:format("~s~n", [Msg]), + {ok, list_to_binary(Msg)}; + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Bin}, _Msg) when is_binary(Bin) -> + {ok, Bin}; + (Bad, _Msg) -> + {error, {failed_to_binary, Bad}} + end), + + %% Initial decode + megaco_codec_test_lib:expect_instruction( + "Decode (initial) message", + fun(Bin) when is_binary(Bin) -> + (catch Decode(Bin)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Msg}, _Bin) when is_record(Msg, 'MegacoMessage') -> + %% io:format("~p~n", [Msg]), + {ok, Msg}; + (Bad, _) -> + {error, {initial_decode_failed, Bad}} + end), + + %% Encode + megaco_codec_test_lib:expect_instruction( + "Encode message", + fun(Msg) when is_record(Msg, 'MegacoMessage') -> + (catch Encode(Msg)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Bin}, _Msg) when is_binary(Bin) -> + %% io:format("~s~n", [binary_to_list(Bin)]), + {ok, Bin}; + (Bad, _) -> + {error, {encode_failed, Bad}} + end), + + %% Decode + megaco_codec_test_lib:expect_instruction( + "(final) Decode message", + fun(Bin) when is_binary(Bin) -> + (catch Decode(Bin)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Msg}, _Bin) when is_record(Msg, 'MegacoMessage') -> + %% io:format("~p~n", [Msg]), + {ok, Msg}; + (Bad, _) -> + {error, {decode_failed, Bad}} + end) + ], + megaco_codec_test_lib:expect_exec(Instructions, InitialData). + + +%% ============================================================== +%% +%% F l e x P r e t t y T e s t c a s e s +%% + +flex_pretty_otp5042_msg1(suite) -> + []; +flex_pretty_otp5042_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5042_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_only( pretty_otp5042_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +flex_pretty_otp5085_msg1(suite) -> + []; +flex_pretty_otp5085_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5085_msg2(suite) -> + []; +flex_pretty_otp5085_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5085_msg3(suite) -> + []; +flex_pretty_otp5085_msg3(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5085_msg4(suite) -> + []; +flex_pretty_otp5085_msg4(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5085_msg5(suite) -> + []; +flex_pretty_otp5085_msg5(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5085_msg6(suite) -> + []; +flex_pretty_otp5085_msg6(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5085_msg7(suite) -> + []; +flex_pretty_otp5085_msg7(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5085_msg8(suite) -> + []; +flex_pretty_otp5085_msg8(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg8 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +flex_pretty_otp5600_msg1(suite) -> + []; +flex_pretty_otp5600_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5600_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5600_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5600_msg2(suite) -> + []; +flex_pretty_otp5600_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5600_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5600_msg2(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +flex_pretty_otp5601_msg1(suite) -> + []; +flex_pretty_otp5601_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5601_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5601_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +flex_pretty_otp5793_msg01(suite) -> + []; +flex_pretty_otp5793_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5793_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +flex_pretty_otp5803_msg01(suite) -> + []; +flex_pretty_otp5803_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5803_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_decode_encode_ok( pretty_otp5803_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5803_msg02(suite) -> + []; +flex_pretty_otp5803_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5803_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_decode_encode_ok( pretty_otp5803_msg2(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +flex_pretty_otp5805_msg01(suite) -> + []; +flex_pretty_otp5805_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5805_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_decode_error( pretty_otp5805_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +flex_pretty_otp5836_msg01(suite) -> + []; +flex_pretty_otp5836_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5836_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( compact_otp5836_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + + +flex_pretty_otp7431_msg01(suite) -> + []; +flex_pretty_otp7431_msg01(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(ok, flex_pretty_otp7431_msg1(), [Conf]). + +flex_pretty_otp7431_msg02(suite) -> + []; +flex_pretty_otp7431_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp7431_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg2(), [?EC_V3,Conf]). + +flex_pretty_otp7431_msg03(suite) -> + []; +flex_pretty_otp7431_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp7431_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg3(), [?EC_V3,Conf]). + +flex_pretty_otp7431_msg04(suite) -> + []; +flex_pretty_otp7431_msg04(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg04 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg4(), [?EC_V3,Conf]). + +flex_pretty_otp7431_msg05(suite) -> + []; +flex_pretty_otp7431_msg05(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg05 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg5(), [?EC_V3,Conf]). + +flex_pretty_otp7431_msg06(suite) -> + []; +flex_pretty_otp7431_msg06(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg06 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg6(), [?EC_V3,Conf]). + +flex_pretty_otp7431_msg07(suite) -> + []; +flex_pretty_otp7431_msg07(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg07 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg7(), [?EC_V3,Conf]). + +flex_pretty_otp7431(Expected, Msg, Conf) -> + otp7431(Expected, megaco_pretty_text_encoder, Msg, Conf). + +otp7431(Expected, Codec, Msg0, Conf) -> + Bin0 = list_to_binary(Msg0), + case decode_message(Codec, false, Conf, Bin0) of + {ok, _Msg1} when Expected =:= ok -> + io:format(" decoded", []); + {error, {bad_property_parm, Reason}} when (Expected =:= error) andalso + is_list(Reason) -> + io:format("expected result: ~s", [Reason]), + ok; + Else -> + io:format("unexpected result", []), + exit({unexpected_decode_result, Else}) + end. + + +flex_pretty_otp7431_msg1() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a=recvonly + } ; RTP profile for G.723.1 is 4 + } + } + } + } + }". + +flex_pretty_otp7431_msg2() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a= } + } + } + } + } + }". + +flex_pretty_otp7431_msg3() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a } + } + } + } + } + }". + +flex_pretty_otp7431_msg4() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a} + } + } + } + } + }". + +flex_pretty_otp7431_msg5() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v= } + } + } + } + } + }". + +flex_pretty_otp7431_msg6() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v } + } + } + } + } + }". + +flex_pretty_otp7431_msg7() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v} + } + } + } + } + }". + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +msgs() -> + [M || {_, M, _, _} <- msgs(text)]. + +msgs(Encoding) -> + msgs1a(Encoding) ++ + msgs1b(Encoding) ++ + msgs3525(Encoding) ++ + msgs5(Encoding) ++ + msgs6(Encoding) ++ + msgs7(Encoding). + +msgs1a(_) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [ + {msg01a, msg1a(), Plain, [{dbg,false}]}, + {msg01b, msg1b(), Plain, [{dbg,false}]}, + {msg02, msg2(), Plain, [{dbg,false}]}, + {msg03, msg3(), Plain, [{dbg,false}]}, + {msg04, msg4(), Plain, [{dbg,false}]}, + {msg05, msg5(), Plain, [{dbg,false}]}, + {msg06a, msg6a(), Plain, [{dbg,false}]}, + {msg06b, msg6b(), Plain, [{dbg,false}]}, + {msg07, msg7(), Plain, [{dbg,false}]}, + {msg08a, msg8a(), Plain, [{dbg,false}]}, + {msg08b, msg8b(), Plain, [{dbg,false}]}, + {msg09, msg9(), Plain, [{dbg,false}]}, + {msg10, msg10(), Plain, [{dbg,false}]}, + {msg11, msg11(), Plain, [{dbg,false}]}, + {msg12, msg12(), Plain, [{dbg,false}]}, + {msg13, msg13(), Plain, [{dbg,false}]}, + {msg14, msg14(), Plain, [{dbg,false}]}, + {msg15, msg15(), Plain, [{dbg,false}]}, + {msg16, msg16(), Plain, [{dbg,false}]}, + {msg17, msg17(), Plain, [{dbg,false}]}, + {msg18, msg18(), Plain, [{dbg,false}]}, + {msg19, msg19(), Plain, [{dbg,false}]}, + {msg20, msg20(), Plain, [{dbg,false}]}, + {msg21, msg21(), Plain, [{dbg,false}]}, + {msg22a, msg22a(), Plain, [{dbg,false}]}, + {msg22b, msg22b(), Plain, [{dbg,false}]}, + {msg22c, msg22c(), Plain, [{dbg,false}]}, + {msg22d, msg22d(), Plain, [{dbg,false}]}, + {msg22e, msg22e(), Plain, [{dbg,false}]}, + {msg22f, msg22f(), Plain, [{dbg,false}]}, + {msg23a, msg23a(), Plain, [{dbg,false}]}, + {msg23b, msg23b(), Plain, [{dbg,false}]}, + {msg23c, msg23c(), Plain, [{dbg,false}]}, + {msg23d, msg23d(), Plain, [{dbg,false}]}, + {msg24, msg24(), Plain, [{dbg,false}]}, + {msg25, msg25(), Plain, [{dbg,false}]}, + {msg30a, msg30a(), Plain, [{dbg,false}]}, + {msg30b, msg30b(), Plain, [{dbg,false}]}, + {msg30c, msg30c(), Plain, [{dbg,false}]}, + {msg30d, msg30d(), Plain, [{dbg,false}]} + ]. + + +msgs1b(_) -> + TransFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:trans_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + ActionsFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:actions_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + ActionFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:action_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + [ + {msg01a_tf, msg1a(), TransFirst, [{dbg,false}]}, + {msg02_tf, msg2(), TransFirst, [{dbg,false}]}, + {msg10_tf, msg10(), TransFirst, [{dbg,false}]}, + {msg11_tf, msg11(), TransFirst, [{dbg,false}]}, + {msg23d_tf, msg23d(), TransFirst, [{dbg,false}]}, + {msg30b_tf, msg30b(), TransFirst, [{dbg,false}]}, + {msg30c_tf, msg30c(), TransFirst, [{dbg,false}]}, + {msg01a_asf, msg1a(), ActionsFirst, [{dbg,false}]}, + {msg02_asf, msg2(), ActionsFirst, [{dbg,false}]}, + {msg10_asf, msg10(), ActionsFirst, [{dbg,false}]}, + {msg23d_asf, msg23d(), ActionsFirst, [{dbg,false}]}, + {msg01a_af, msg1a(), ActionFirst, [{dbg,false}]}, + {msg02_af, msg2(), ActionFirst, [{dbg,false}]}, + {msg10_af, msg10(), ActionFirst, [{dbg,false}]}, + {msg23d_af, msg23d(), ActionFirst, [{dbg,false}]} + ]. + + +msgs3525(_) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [{msgs3_name(Name), rfc3525_decode(M), Plain, [{dbg, false}]} || + {Name, M} <- rfc3525_msgs()]. + +msgs3_name(N) -> + list_to_atom("rfc3525_" ++ atom_to_list(N)). + +rfc3525_decode(M) when is_list(M) -> + rfc3525_decode(list_to_binary(M)); +rfc3525_decode(M) when is_binary(M) -> + case (catch decode_message(megaco_pretty_text_encoder, false, ?EC, M)) of + {ok, Msg} -> + Msg; + Error -> + {error, {rfc3525_decode_error, Error}} + end. + + +msgs5(_) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [ + {msg51a, msg51a(), Plain, [{dbg, false}]}, + {msg51b, msg51b(), Plain, [{dbg, false}]}, + {msg51c, msg51c(), Plain, [{dbg, false}]}, + {msg51d, msg51d(), Plain, [{dbg, false}]}, + {msg51e, msg51e(), Plain, [{dbg, false}]}, + {msg51f, msg51f(), Plain, [{dbg, false}]}, + {msg51g, msg51g(), Plain, [{dbg, false}]}, + {msg51h, msg51h(), Plain, [{dbg, false}]}, + {msg51i, msg51i(), Plain, [{dbg, false}]}, + {msg52, msg52(), Plain, [{dbg, false}]}, + {msg53, msg53(), Plain, [{dbg, false}]}, + {msg54a, msg54a(), Plain, [{dbg, false}]}, + {msg54b, msg54b(), Plain, [{dbg, false}]}, + {msg54c, msg54c(), Plain, [{dbg, false}]}, + {msg55, msg55(), Plain, [{dbg, false}]}, + {msg56, msg56(), Plain, [{dbg, false}]}, + {msg57, msg57(), Plain, [{dbg, false}]}, + {msg58a, msg58a(), Plain, [{dbg, false}]}, + {msg58b, msg58b(), Plain, [{dbg, false}]} + ]. + + +msgs6(Encoding) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + + PlainEDFail = + fun(Codec, DD, Ver, EC, M) -> + Res = + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M), + case Res of + {error, {message_encode_failed, Reason, _M}} -> + case Reason of + {error, {{deprecated, _}, _}} -> + ok; + _ -> + Res + end; + _ -> + Res + end + end, + + PlainDE = + fun(Codec, _DD, Ver, EC, B) -> + Res = + megaco_codec_test_lib:decode_message(Codec, false, Ver, + EC, B), + case Res of + {ok, M} -> + #'MegacoMessage'{mess = Mess} = M, + #'Message'{messageBody = {transactions, TRs}} = Mess, + [{transactionRequest, TR}] = TRs, + #'TransactionRequest'{actions = Actions} = TR, + [Action] = Actions, + #'ActionRequest'{commandRequests = CmdReqs} = Action, + [CmdReq] = CmdReqs, + #'CommandRequest'{command = Cmd} = CmdReq, + {addReq,AmmReq} = Cmd, + #'AmmRequest'{descriptors = []} = AmmReq, + ok; + _ -> + Res + end + end, + + Msgs = + [ + {msg61a, msg61a(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg61b, msg61b(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg61c, msg61c(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg62a, msg62a(), PlainEDFail, [{dbg,false}],[text,binary,erlang]}, + {msg62b, msg62b(), PlainDE, [{dbg,false}],[text]} + ], + [{N,M,F,C}||{N,M,F,C,E} <- Msgs,lists:member(Encoding,E)]. + + +msgs7(Encoding) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + + Msgs = + [ + {msg71a, msg71a(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b01, msg71b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b02, msg71b02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b03, msg71b03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b04, msg71b04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b05, msg71b05(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b06, msg71b06(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b07, msg71b07(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b08, msg71b08(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b09, msg71b09(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b10, msg71b10(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b11, msg71b11(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b12, msg71b12(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b13, msg71b13(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b14, msg71b14(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b15, msg71b15(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b16, msg71b16(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b17, msg71b17(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b18, msg71b18(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b19, msg71b19(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b20, msg71b20(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b21, msg71b21(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b22, msg71b22(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c01, msg71c01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c02, msg71c02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c03, msg71c03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c04, msg71c04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c05, msg71c05(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c06, msg71c06(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c07, msg71c07(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c08, msg71c08(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c09, msg71c09(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c10, msg71c10(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c11, msg71c11(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c12, msg71c12(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c13, msg71c13(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c14, msg71c14(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c15, msg71c15(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71d01, msg71d01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71d02, msg71d02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71d03, msg71d03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71d04, msg71d04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72a01, msg72a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72a02, msg72a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72a03, msg72a03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72b01, msg72b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72b02, msg72b02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72b03, msg72b03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72b04, msg72b04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72c01, msg72c01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72c02, msg72c02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72c03, msg72c03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72c04, msg72c04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73a, msg73a(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73b01, msg73b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73b02, msg73b02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73c01, msg73c01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73c02, msg73c02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a01, msg74a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a02, msg74a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a03, msg74a03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a04, msg74a04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a05, msg74a05(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a06, msg74a06(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg75a01, msg75a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg75a02, msg75a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg76a01, msg76a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg76a02, msg76a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg76b01, msg76b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + %% {msg76b02, msg76b02(), Plain, [{dbg,true}],[text,binary,erlang]}, + {msg77a01, msg77a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a01, msg78a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a02, msg78a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a03, msg78a03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a04, msg78a04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a05, msg78a05(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a06, msg78a06(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a07, msg78a07(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a08, msg78a08(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a09, msg78a09(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg79a01, msg79a01(), Plain, [{dbg,false}],[text,binary,erlang]} + ], + [{N,M,F,C}||{N,M,F,C,E} <- Msgs,lists:member(Encoding,E)]. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +msg_actions([], Actions) -> + lists:reverse(Actions); +msg_actions([{CtxId, CmdReqs}|ActionInfo], Actions) -> + Action = ?MSG_LIB:cre_ActionRequest(CtxId,CmdReqs), + msg_actions(ActionInfo, [Action|Actions]). + +megaco_trans_req([], Transactions) -> + {transactions, lists:reverse(Transactions)}; +megaco_trans_req([{TransId, ActionInfo}|TransInfo], Transactions) -> + Actions = msg_actions(ActionInfo, []), + TR = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + megaco_trans_req(TransInfo, [Trans|Transactions]). + +megaco_message(Version, Mid, Body) -> + Mess = ?MSG_LIB:cre_Message(Version, Mid, Body), + cre_MegacoMessage(Mess). + +msg_request(Mid, TransInfo) -> + TransReq = megaco_trans_req(TransInfo, []), + megaco_message(?VERSION, Mid, TransReq). + +msg_request(Mid, TransId, ContextId, CmdReq) -> + Action = ?MSG_LIB:cre_ActionRequest(ContextId, CmdReq), + Actions = [Action], + TR = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg_request(Auth, Mid, TransId, ContextId, CmdReq) -> + Action = ?MSG_LIB:cre_ActionRequest(ContextId, CmdReq), + Actions = [Action], + TR = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + cre_MegacoMessage(Auth, Mess). + +msg_reply(Mid, TransId, Actions) -> + TR = cre_TransRep(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg_reply(Mid, TransId, ContextId, CmdReply) -> + Action = cre_ActRep(ContextId, CmdReply), + Actions = [Action], + msg_reply(Mid, TransId, Actions). + +msg_ack(Mid, [Range|_] = Ranges) when is_tuple(Range) -> + msg_ack(Mid, [Ranges]); + +msg_ack(Mid, Ranges) -> + %% TRAs = make_tras(Ranges, []), + TRAs = make_tras(Ranges), + Req = {transactions, TRAs}, + cre_MegacoMessage(?VERSION, Mid, Req). + +make_tras(TRARanges) -> + F = fun(R) -> {transactionResponseAck, make_tra(R)} end, + lists:map(F, TRARanges). + +make_tra(Ranges) -> + F = fun({F,L}) -> cre_TransAck(F,L) end, + lists:map(F, Ranges). + + +%% ------------------------------------------------------------------------- + + +msg1(Mid, Tid) -> + Gain = cre_PropParm("tdmc/gain", "2"), + Ec = cre_PropParm("tdmc/ec", "g165"), + LCD = cre_LocalControlDesc(sendRecv,[Gain, Ec]), + V = cre_PropParm("v", "0"), + %% C = cre_PropParm("c", "IN IP4 $ "), + C = cre_PropParm("c", [$I,$N,$ ,$I,$P,$4,$ ,$$,$ ]), + M = cre_PropParm("m", "audio $ RTP/AVP 0"), + A = cre_PropParm("a", "fmtp:PCMU VAD=X-NNVAD"), + LD = cre_LocalRemoteDesc([[V, C, M, A]]), + Parms = cre_StreamParms(LCD,LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + ReqEvent = cre_ReqEv("al/of"), + EventsDesc = cre_EvsDesc(2222,[ReqEvent]), + AmmReq = cre_AmmReq([#megaco_term_id{id = Tid}], + [{mediaDescriptor, MediaDesc}, + {eventsDescriptor, EventsDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + Msg = msg_request(Mid, 9999, ?megaco_null_context_id, [CmdReq]), + Msg. + +msg1a() -> + msg1a(?MGC_MID). +msg1a(Mid) -> + msg1(Mid, ?A4444). + +msg1b() -> + msg1b(?MGC_MID). +msg1b(Mid) -> + msg1(Mid, ?A4445). + + +%% -------------------------- + + +msg2() -> + msg2(?MGC_MID). +msg2(Mid) -> + msg2(Mid, ?A4444). +msg2(Mid, Tid) -> + Gain = cre_PropParm("tdmc/gain", "2"), + Ec = cre_PropParm("tdmc/ec", "g165"), + LCD = cre_LocalControlDesc(sendRecv,[Gain, Ec]), + V = cre_PropParm("v", "0"), + %% C = cre_PropParm("c", "IN IP4 $ "), + C = cre_PropParm("c", [$I,$N,$ ,$I,$P,$4,$ ,$$,$ ]), + M = cre_PropParm("m", "audio $ RTP/AVP 0"), + A = cre_PropParm("a", "fmtp:PCMU VAD=X-NNVAD"), + LD = cre_LocalRemoteDesc([[V, C, M, A]]), + Parms = cre_StreamParms(LCD,LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + EventParm = cre_EvParm("strict",["exact"]), + ReqEvent = cre_ReqEv("al/of", [EventParm]), + EventsDesc = cre_EvsDesc(2222,[ReqEvent]), + AmmReq = cre_AmmReq([#megaco_term_id{id = Tid}], + [{mediaDescriptor, MediaDesc}, + {eventsDescriptor, EventsDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 9999, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg3() -> + msg3(?MG1_MID). +msg3(Mid) -> + TimeStamp = cre_TimeNot("19990729", "22000000"), + Event = cre_ObsEv("al/of",TimeStamp), + Desc = cre_ObsEvsDesc(2222,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 10000, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg4() -> + msg4(?MG1_MID_NO_PORT, "901 mg col boot"). +msg4(Mid, Reason) when is_list(Reason) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChParm(restart,Address,[Reason],Profile), + Req = cre_SvcChReq([?megaco_root_termination_id],Parm), + CmdReq = cre_CmdReq({serviceChangeReq, Req}), + msg_request(Mid, 9998, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg5() -> + msg5(?MGC_MID). +msg5(Mid) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChResParm(Address,Profile), + Reply = cre_SvcChRep([?megaco_root_termination_id], + {serviceChangeResParms,Parm}), + msg_reply(Mid, 9998, ?megaco_null_context_id, + [{serviceChangeReply, Reply}]). + + +%% -------------------------- + +msg6(Mid, Tid) -> + Reply = cre_AmmsReply([#megaco_term_id{id = Tid}]), + msg_reply(Mid, 9999, ?megaco_null_context_id, [{modReply, Reply}]). + +msg6a() -> + msg6a(?MG1_MID). +msg6a(Mid) -> + msg6(Mid, ?A4444). + +msg6b() -> + msg6b(?MG2_MID). +msg6b(Mid) -> + msg6(Mid, ?A5555). + + +%% -------------------------- + +msg7() -> + msg7(?MGC_MID). +msg7(Mid) -> + Reply = cre_NotifyRep([#megaco_term_id{id = ?A4444}]), + msg_reply(Mid, 10000, ?megaco_null_context_id, [{notifyReply, Reply}]). + + +%% -------------------------- + +msg8(Mid, DigitMapValue) -> + Strict = cre_EvParm("strict",["state"]), + On = cre_ReqEv("al/on", [Strict]), + Name = "dialplan00", + EDM = cre_EvDM(Name), + Action = cre_ReqActs(EDM), + Ce = cre_ReqEv("dd/ce", Action), + EventsDesc = cre_EvsDesc(2223, [On, Ce]), + Signal = cre_Sig("cg/rt"), + DigMapDesc = cre_DigitMapDesc(Name, DigitMapValue), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, [{signal, Signal}]}, + {digitMapDescriptor, DigMapDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 10001, ?megaco_null_context_id, [CmdReq]). + +msg8a() -> + msg8a(?MGC_MID). +msg8a(Mid) -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body), + msg8(Mid, Value). + +msg8b() -> + msg8b(?MGC_MID). +msg8b(Mid) -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body, 1, 23, 99), + msg8(Mid, Value). + + +%% -------------------------- + +msg9() -> + msg9(?MG1_MID). +msg9(Mid) -> + TimeStamp = cre_TimeNot("19990729","22010001"), + Parm = cre_EvParm("ds",["916135551212"]), + Event = cre_ObsEv("dd/ce",TimeStamp,[Parm]), + Desc = cre_ObsEvsDesc(2223,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A4444}], Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 10002, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg10() -> + msg10(?MGC_MID). +msg10(Mid) -> + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}],[]), + CmdReq = cre_CmdReq({addReq, AmmReq}), + Jit = cre_PropParm("nt/jit", "40"), + LCD = cre_LocalControlDesc(recvOnly,[Jit]), + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 $ "), + M = cre_PropParm("m", "audio $ RTP/AVP 4"), + A = cre_PropParm("a", "ptime:30"), + V2 = cre_PropParm("v", "0"), + C2 = cre_PropParm("c", "IN IP4 $ "), + M2 = cre_PropParm("m", "audio $ RTP/AVP 0"), + LD = cre_LocalRemoteDesc([[V, C, M, A], [V2, C2, M2]]), + Parms = cre_StreamParms(LCD, LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + ChooseTid = #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}, + AmmReq2 = cre_AmmReq([ChooseTid],[{mediaDescriptor, MediaDesc}]), + CmdReq2 = cre_CmdReq({addReq, AmmReq2}), + msg_request(Mid, 10003, ?megaco_choose_context_id, [CmdReq, CmdReq2]). + + +msg11() -> + msg11(?MG1_MID). +msg11(Mid) -> + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 124.124.124.222"), + M = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + A = cre_PropParm("a", "ptime:30"), + A2 = cre_PropParm("a", "recvonly"), + LD = cre_LocalRemoteDesc([[V, C, M, A, A2]]), + Parms = cre_StreamParmsL(LD), + StreamDesc = cre_StreamDesc(1, Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + msg_reply(Mid, 10003, 2000, [{addReply, Reply}, {addReply, Reply2}]). + + +%% -------------------------- + +msg12() -> + msg12(?MGC_MID). +msg12(Mid) -> + LCD = cre_LocalControlDesc(sendRecv), + Parms = cre_StreamParms(LCD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Signal = cre_Sig("al/ri"), + Descs = [{mediaDescriptor, MediaDesc}, + {signalsDescriptor, [{signal, Signal}]}], + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A5555}], Descs), + CmdReq = cre_CmdReq({addReq, AmmReq}), + Jit = cre_PropParm("nt/jit", "40"), + LCD2 = cre_LocalControlDesc(sendRecv, [Jit]), + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 $ "), + M = cre_PropParm("m", "audio $ RTP/AVP 4"), + A = cre_PropParm("a", "ptime:30"), + LD2 = cre_LocalRemoteDesc([[V, C, M, A]]), + V2 = cre_PropParm("v", "0"), + C2 = cre_PropParm("c", "IN IP4 124.124.124.222"), + M2 = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + RD2 = cre_LocalRemoteDesc([[V2, C2, M2]]), + Parms2 = cre_StreamParms(LCD2,LD2,RD2), + StreamDesc2 = cre_StreamDesc(1,Parms2), + MediaDesc2 = cre_MediaDesc(StreamDesc2), + ChooseTid = #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}, + AmmReq2 = cre_AmmReq([ChooseTid],[{mediaDescriptor, MediaDesc2}]), + CmdReq2 = cre_CmdReq({addReq, AmmReq2}), + msg_request(Mid, 50003, ?megaco_choose_context_id, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg13() -> + msg13(?MG2_MID). +msg13(Mid) -> + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 125.125.125.111"), + M = cre_PropParm("m", "audio 1111 RTP/AVP 4"), + LD = cre_LocalRemoteDesc([[V, C, M]]), + Parms = cre_StreamParmsL(LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Reply = cre_AmmsReply([#megaco_term_id{id = ?A5556}], + [{mediaDescriptor, MediaDesc}]), + msg_reply(Mid, 50003, 5000, [{addReply, Reply}]). + + +%% -------------------------- + +msg14() -> + msg14(?MGC_MID). +msg14(Mid) -> + Signal = cre_Sig("cg/rt"), + AmmReq1 = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{signalsDescriptor, [{signal, Signal}]}]), + CmdReq1 = cre_CmdReq({modReq, AmmReq1}), + + Gain = cre_PropParm("tdmc/gain", "2"), + Ec = cre_PropParm("tdmc/ec", "g165"), + LCD = cre_LocalControlDesc(sendRecv, [Gain, Ec]), + Parms2 = cre_StreamParms(LCD), + StreamDesc2 = cre_StreamDesc(1,Parms2), + MediaDesc2 = cre_MediaDesc(StreamDesc2), + AmmReq2 = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc2}]), + CmdReq2 = cre_CmdReq({modReq, AmmReq2}), + + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 125.125.125.111"), + M = cre_PropParm("m", "audio 1111 RTP/AVP 4"), + RD = cre_LocalRemoteDesc([[V, C, M]]), + Parms3 = cre_StreamParmsR(RD), + StreamDesc3 = cre_StreamDesc(2,Parms3), + MediaDesc3 = cre_MediaDesc(StreamDesc3), + AmmReq3 = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc3}]), + CmdReq3 = cre_CmdReq({modReq, AmmReq3}), + msg_request(Mid, 10005, 2000, [CmdReq1, CmdReq2, CmdReq3]). + + +%% -------------------------- + +msg15() -> + msg15(?MG1_MID). +msg15(Mid) -> + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A4445}]), + msg_reply(Mid, 10005, 2000, [{modReply, Reply}, {modReply, Reply2}]). + + +%% -------------------------- + +msg16() -> + msg16(?MG2_MID). +msg16(Mid) -> + TimeStamp = cre_TimeNot("19990729","22020002"), + Event = cre_ObsEv("al/of",TimeStamp), + Desc = cre_ObsEvsDesc(1234,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 50005, 5000, [CmdReq]). + + +%% -------------------------- + +msg17() -> + msg17(?MGC_MID). +msg17(Mid) -> + Reply = cre_NotifyRep([#megaco_term_id{id = ?A5555}]), + msg_reply(Mid, 50005, ?megaco_null_context_id, [{notifyReply, Reply}]). + + +%% -------------------------- + +msg18() -> + msg18(?MGC_MID). +msg18(Mid) -> + On = cre_ReqEv("al/on"), + EventsDesc = cre_EvsDesc(1235,[On]), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A5555}], + [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, []}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 50006, 5000, [CmdReq]). + + +%% -------------------------- + +msg19() -> + msg19(?MG2_MID). +msg19(Mid) -> + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4445}]), + msg_reply(Mid, 50006, 5000, [{modReply, Reply}]). + + +%% -------------------------- + +msg20() -> + msg20(?MGC_MID). +msg20(Mid) -> + LCD = cre_LocalControlDesc(sendRecv), + Parms = cre_StreamParms(LCD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + AmmReq2 = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{signalsDescriptor, []}]), + CmdReq2 = cre_CmdReq({modReq, AmmReq2}), + msg_request(Mid, 10006, 2000, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg21() -> + msg21(?MGC_MID). +msg21(Mid) -> + Tokens = [mediaToken, eventsToken, signalsToken, + digitMapToken, statsToken, packagesToken], + AuditDesc = cre_AuditDesc(Tokens), + Req = cre_AuditReq(#megaco_term_id{id = ?A5556},AuditDesc), + CmdReq = cre_CmdReq({auditValueRequest, Req}), + msg_request(Mid, 50007, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg22a() -> + msg22(1). + +msg22b() -> + msg22(10). + +msg22c() -> + msg22(25). + +msg22d() -> + msg22(50). + +msg22e() -> + msg22(75). + +msg22f() -> + msg22(100). + +msg22(N) -> + msg22(?MG2_MID, N). +msg22(Mid, N) -> + Jit = cre_PropParm("nt/jit", "40"), + LCD = cre_LocalControlDesc(sendRecv,[Jit]), + LDV = cre_PropParm("v", "0"), + LDC = cre_PropParm("c", "IN IP4 125.125.125.111"), + LDM = cre_PropParm("m", "audio 1111 RTP/AVP 4"), + LDA = cre_PropParm("a", "ptime:30"), + LD = cre_LocalRemoteDesc([[LDV, LDC, LDM, LDA]]), + RDV = cre_PropParm("v", "0"), + RDC = cre_PropParm("c", "IN IP4 124.124.124.222"), + RDM = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + RDA = cre_PropParm("a", "ptime:30"), + RD = cre_LocalRemoteDesc([[RDV, RDC, RDM, RDA]]), + StreamParms = cre_StreamParms(LCD,LD,RD), + StreamDesc = cre_StreamDesc(1,StreamParms), + Media = cre_MediaDesc(StreamDesc), + PackagesItem = cre_PkgsItem("nt",1), + PackagesItem2 = cre_PkgsItem("rtp",1), + Stat = cre_StatsParm("rtp/ps","1200"), + Stat2 = cre_StatsParm("nt/os","62300"), + Stat3 = cre_StatsParm("rtp/pr","700"), + Stat4 = cre_StatsParm("nt/or","45100"), + Stat5 = cre_StatsParm("rtp/pl","0.2"), + Stat6 = cre_StatsParm("rtp/jit","20"), + Stat7 = cre_StatsParm("rtp/delay","40"), + Statistics = [Stat, Stat2, Stat3, Stat4, Stat5, Stat6, Stat7], + Audits = [{mediaDescriptor, Media}, + {packagesDescriptor, [PackagesItem, PackagesItem2]}, + {statisticsDescriptor, Statistics}], + Reply = {auditResult, + cre_AuditRes(#megaco_term_id{id = ?A5556},Audits)}, + msg_reply(Mid, 50007, ?megaco_null_context_id, + lists:duplicate(N,{auditValueReply, Reply})). +%% msg_reply(Mid, 50007, ?megaco_null_context_id, +%% lists.duplicate([{auditValueReply, Reply}]). + + +%% -------------------------- + +msg23a() -> + msg23a(?MG2_MID). +msg23a(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 50008, 5000, [CmdReq]). + + +msg23b() -> + msg23b(?MG2_MID). +msg23b(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq1 = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_CmdReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_NotifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_CmdReq({notifyReq, NotifyReq2}), + ActionInfo = [{5000, [CmdReq1]}, {5001, [CmdReq2]}], + TransInfo = [{50008, ActionInfo}], + msg_request(Mid, TransInfo). + + +msg23c() -> + msg23c(?MG2_MID). +msg23c(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq1 = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_CmdReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_NotifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_CmdReq({notifyReq, NotifyReq2}), + ActionInfo1 = [{5000, [CmdReq1]}], + ActionInfo2 = [{5001, [CmdReq2]}], + TransInfo = [{50008, ActionInfo1}, {50009, ActionInfo2}], + msg_request(Mid, TransInfo). + + +msg23d() -> + msg23d(?MG2_MID). +msg23d(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq1 = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_CmdReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_NotifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_CmdReq({notifyReq, NotifyReq2}), + NotifyReq3 = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc), + CmdReq3 = cre_CmdReq({notifyReq, NotifyReq3}), + NotifyReq4 = cre_NotifyReq([#megaco_term_id{id = ?A4445}],Desc), + CmdReq4 = cre_CmdReq({notifyReq, NotifyReq4}), + ActionInfo1 = [{5000, [CmdReq1]}, {5001, [CmdReq2]}], + ActionInfo2 = [{5003, [CmdReq3]}, {5004, [CmdReq4]}], + TransInfo = [{50008, ActionInfo1}, {50009, ActionInfo2}], + msg_request(Mid, TransInfo). + + +%% -------------------------- + +msg24() -> + msg24(?MGC_MID). +msg24(Mid) -> + AuditDesc = cre_AuditDesc([statsToken]), + SubReq = cre_SubReq([#megaco_term_id{id = ?A5555}], AuditDesc), + SubReq2 = cre_SubReq([#megaco_term_id{id = ?A5556}], AuditDesc), + CmdReq = cre_CmdReq({subtractReq, SubReq}), + CmdReq2 = cre_CmdReq({subtractReq, SubReq2}), + msg_request(Mid, 50009, 5000, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg25() -> + msg25(?MG2_MID). +msg25(Mid) -> + Stat11 = cre_StatsParm("nt/os","45123"), + Stat12 = cre_StatsParm("nt/dur", "40"), + Stats1 = [Stat11, Stat12], + Reply1 = cre_AmmsReply([#megaco_term_id{id = ?A5555}], + [{statisticsDescriptor, Stats1}]), + Stat21 = cre_StatsParm("rtp/ps","1245"), + Stat22 = cre_StatsParm("nt/os", "62345"), + Stat23 = cre_StatsParm("rtp/pr", "780"), + Stat24 = cre_StatsParm("nt/or", "45123"), + Stat25 = cre_StatsParm("rtp/pl", "10"), + Stat26 = cre_StatsParm("rtp/jit", "27"), + Stat27 = cre_StatsParm("rtp/delay","48"), + Stats2 = [Stat21, Stat22, Stat23, Stat24, Stat25, Stat26, Stat27], + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A5556}], + [{statisticsDescriptor, Stats2}]), + msg_reply(Mid, 50009, 5000, + [{subtractReply, Reply1}, {subtractReply, Reply2}]). + + +msg30a() -> + msg_ack(?MG2_MID, [{9,9}]). + +msg30b() -> + msg_ack(?MG2_MID, [{9,13}]). + +msg30c() -> + msg_ack(?MG2_MID, + [{9,13}, {15,15}, {33,40}, {50,60}, {70,80}, {85,90}, + {101,105},{109,119},{121,130},{140,160},{170,175},{180,189}, + {201,205},{209,219},{221,230},{240,260},{270,275},{280,289}, + {301,305},{309,319},{321,330},{340,360},{370,375},{380,389}, + {401,405},{409,419},{421,430},{440,460},{470,475},{480,489}, + {501,505},{509,519},{521,530},{540,560},{570,575},{580,589} + ]). + +%% Don't think this will be used by the megaco stack, but since it +%% seem's to be a valid construction... +msg30d() -> + msg_ack(?MG2_MID, + [[{9,13}, {15,15}, {33,40}, {50,60}, {70,80}, {85,90}], + [{101,105},{109,119},{121,130},{140,160},{170,175},{180,189}], + [{201,205},{209,219},{221,230},{240,260},{270,275},{280,289}], + [{301,305},{309,319},{321,330},{340,360},{370,375},{380,389}], + [{401,405},{409,419},{421,430},{440,460},{470,475},{480,489}], + [{501,505},{509,519},{521,530},{540,560},{570,575},{580,589}] + ]). + + + +msg40() -> + msg40(?MG1_MID_NO_PORT, "901 mg col boot"). +msg40(Mid, Reason) when is_list(Reason) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChParm(restart,Address,[Reason],Profile), + Req = cre_SvcChReq([?megaco_root_termination_id],Parm), + CmdReq = cre_CmdReq({serviceChangeReq, Req}), + Auth = cre_AuthHeader(), + msg_request(Auth, Mid, 9998, ?megaco_null_context_id, [CmdReq]). + + +msg50(Mid, APT) -> + AD = cre_AuditDesc(asn1_NOVALUE, APT), + Req = cre_AuditReq(#megaco_term_id{id = ?A5556},AD), + CmdReq = cre_CmdReq({auditValueRequest, Req}), + msg_request(Mid, 50007, ?megaco_null_context_id, [CmdReq]). + +%% IndAudMediaDescriptor: +msg51(Mid, IATSDorStream) -> + IAMD = cre_IndAudMediaDesc(IATSDorStream), + IAP = cre_IndAudParam(IAMD), + APT = [IAP], + msg50(Mid, APT). + +msg51a() -> + msg51a(?MG2_MID). +msg51a(Mid) -> + PP = cre_IndAudPropertyParm("tdmc/gain"), + PPs = [PP], + IATSD = cre_IndAudTermStateDesc(PPs), + msg51(Mid, IATSD). + +msg51b() -> + msg51b(?MG2_MID). +msg51b(Mid) -> + PP = cre_IndAudPropertyParm("nt/jit"), + PPs = [PP], + IATSD = cre_IndAudTermStateDesc(PPs), + msg51(Mid, IATSD). + +msg51c() -> + msg51c(?MG2_MID). +msg51c(Mid) -> + IATSD = cre_IndAudTermStateDesc([], asn1_NOVALUE, 'NULL'), + msg51(Mid, IATSD). + +msg51d() -> + msg51d(?MG2_MID). +msg51d(Mid) -> + IATSD = cre_IndAudTermStateDesc([], 'NULL', asn1_NOVALUE), + msg51(Mid, IATSD). + +msg51e() -> + msg51e(?MG2_MID). +msg51e(Mid) -> + IALCD = cre_IndAudLocalControlDesc('NULL', asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE), + IASP = cre_IndAudStreamParms(IALCD), + msg51(Mid, IASP). + +msg51f() -> + msg51f(?MG2_MID). +msg51f(Mid) -> + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, 'NULL', + asn1_NOVALUE, asn1_NOVALUE), + IASP = cre_IndAudStreamParms(IALCD), + msg51(Mid, IASP). + +msg51g() -> + msg51g(?MG2_MID). +msg51g(Mid) -> + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, asn1_NOVALUE, + 'NULL', asn1_NOVALUE), + IASP = cre_IndAudStreamParms(IALCD), + msg51(Mid, IASP). + +msg51h() -> + msg51h(?MG2_MID). +msg51h(Mid) -> + Name = "nt/jit", + IAPP = cre_IndAudPropertyParm(Name), + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, asn1_NOVALUE, + asn1_NOVALUE, [IAPP]), + IASP = cre_IndAudStreamParms(IALCD), + SID = 123, + IASD = cre_IndAudStreamDesc(SID, IASP), + msg51(Mid, [IASD]). + + +msg51i() -> + msg51i(?MG2_MID). +msg51i(Mid) -> + Name = "nt/jit", + Name2 = "tdmc/ec", + IAPP = cre_IndAudPropertyParm(Name), + IAPP2 = cre_IndAudPropertyParm(Name2), + IALCD = cre_IndAudLocalControlDesc('NULL', 'NULL', 'NULL', + [IAPP, IAPP2]), + IASP = cre_IndAudStreamParms(IALCD), + SID = 123, + IASD = cre_IndAudStreamDesc(SID, IASP), + msg51(Mid, [IASD]). + + +%% IndAudEventsDescriptor: +msg52() -> + msg52(?MG2_MID). +msg52(Mid) -> + RequestID = 1235, + PkgdName = "tonedet/std", + IAED = cre_IndAudEvsDesc(RequestID, PkgdName), + IAP = cre_IndAudParam(IAED), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudEventBufferDescriptor: +msg53() -> + msg53(?MG2_MID). +msg53(Mid) -> + EN = "tonedet/std", + SID = 1, + IAEBD = cre_IndAudEvBufDesc(EN, SID), + IAP = cre_IndAudParam(IAEBD), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudSignalsDescriptor: +msg54(Mid, Sig) -> + IASD = cre_IndAudSigsDesc(Sig), + IAP = cre_IndAudParam(IASD), + APT = [IAP], + msg50(Mid, APT). + +msg54a() -> + msg54a(?MG2_MID). +msg54a(Mid) -> + SN = "tonegen/pt", + Sig = cre_IndAudSig(SN), + msg54(Mid, Sig). + +msg54b() -> + msg54b(?MG2_MID). +msg54b(Mid) -> + SN = "dg/d0", + Sig = cre_IndAudSig(SN), + msg54(Mid, Sig). + +msg54c() -> + msg54c(?MG2_MID). +msg54c(Mid) -> + SN = "ct/ct", + Sig = cre_IndAudSig(SN), + ID = 4321, + SSL = cre_IndAudSeqSigList(ID, Sig), + msg54(Mid, SSL). + +%% IndAudDigitMapDescriptor: +msg55() -> + msg55(?MG2_MID). +msg55(Mid) -> + DMN = "dialplan00", + IADMD = cre_IndAudDigitMapDesc(DMN), + IAP = cre_IndAudParam(IADMD), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudStatisticsDescriptor: +msg56() -> + msg56(?MG2_MID). +msg56(Mid) -> + SN = "nt/dur", + IASD = cre_IndAudStatsDesc(SN), + IAP = cre_IndAudParam(IASD), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudPackagesDescriptor: +msg57() -> + msg57(?MG2_MID). +msg57(Mid) -> + PN = "al", + PV = 1, + IAPD = cre_IndAudPkgsDesc(PN, PV), + IAP = cre_IndAudParam(IAPD), + APT = [IAP], + msg50(Mid, APT). + +%% Sum it up: +msg58_iaMediaDesc_iap(IATSD) -> + IAMD = cre_IndAudMediaDesc(IATSD), + cre_IndAudParam(IAMD). + +msg58_iaMediaDesc_iap_a() -> + PP = cre_IndAudPropertyParm("tdmc/gain"), + PPs = [PP], + IATSD = cre_IndAudTermStateDesc(PPs), + msg58_iaMediaDesc_iap(IATSD). + +msg58_iaMediaDesc_iap_b() -> + IATSD = cre_IndAudTermStateDesc([], 'NULL', asn1_NOVALUE), + msg58_iaMediaDesc_iap(IATSD). + +msg58_iaEvsDesc_iap() -> + RequestID = 1235, + PkgdName = "tonedet/std", + IAED = cre_IndAudEvsDesc(RequestID, PkgdName), + cre_IndAudParam(IAED). + +msg58_iaEvBufDesc_iap() -> + EN = "tonedet/std", + SID = 1, + IAEBD = cre_IndAudEvBufDesc(EN, SID), + cre_IndAudParam(IAEBD). + +msg58_iaSigsDesc_iap(S) -> + IASD = cre_IndAudSigsDesc(S), + cre_IndAudParam(IASD). + +msg58_iaSigsDesc_iap_a() -> + SN = "tonegen/pt", + Sig = cre_IndAudSig(SN), + msg58_iaSigsDesc_iap(Sig). + +msg58_iaSigsDesc_iap_b() -> + SN = "ct/ct", + Sig = cre_IndAudSig(SN), + ID = 4321, + SSL = cre_IndAudSeqSigList(ID, Sig), + msg58_iaSigsDesc_iap(SSL). + +msg58_iaDigMapDesc_iap() -> + DMN = "dialplan00", + IADMD = cre_IndAudDigitMapDesc(DMN), + cre_IndAudParam(IADMD). + +msg58_iaStatsDesc_iap() -> + SN = "nt/dur", + IASD = cre_IndAudStatsDesc(SN), + cre_IndAudParam(IASD). + +msg58_iaPacksDesc_iap() -> + PN = "al", + PV = 1, + IAPD = cre_IndAudPkgsDesc(PN, PV), + cre_IndAudParam(IAPD). + +msg58a() -> + msg58a(?MG2_MID). +msg58a(Mid) -> + IAMD = msg58_iaMediaDesc_iap_a(), + IAED = msg58_iaEvsDesc_iap(), + IAEBD = msg58_iaEvBufDesc_iap(), + IASiD = msg58_iaSigsDesc_iap_a(), + IADMD = msg58_iaDigMapDesc_iap(), + IAStD = msg58_iaStatsDesc_iap(), + IAPD = msg58_iaPacksDesc_iap(), + APT = [IAMD, IAED, IAEBD, IASiD, IADMD, IAStD, IAPD], + msg50(Mid, APT). + +msg58b() -> + msg58b(?MG2_MID). +msg58b(Mid) -> + IAMD = msg58_iaMediaDesc_iap_b(), + IAED = msg58_iaEvsDesc_iap(), + IAEBD = msg58_iaEvBufDesc_iap(), + IASiD = msg58_iaSigsDesc_iap_b(), + IADMD = msg58_iaDigMapDesc_iap(), + IAStD = msg58_iaStatsDesc_iap(), + IAPD = msg58_iaPacksDesc_iap(), + APT = [IAMD, IAED, IAEBD, IASiD, IADMD, IAStD, IAPD], + msg50(Mid, APT). + + +%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +%% Tests some of the changes in the v2 corr 1 (EmergencyOff and ModemDesc) + +%% Emergency On/Off (optional) tests +msg61(EM) -> + TS = cre_TimeNot("19990729", "22000000"), + Event = cre_ObsEv("al/of",TS), + Desc = cre_ObsEvsDesc(2222,[Event]), + NotReq = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc), + Cmd = ?MSG_LIB:cre_Command(notifyReq, NotReq), + CmdReq = cre_CmdReq(Cmd), + CtxReq = cre_CtxReq(15, EM), + ActReq = ?MSG_LIB:cre_ActionRequest(1, CtxReq, [CmdReq]), + Acts = [ActReq], + TR = ?MSG_LIB:cre_TransactionRequest(9898, Acts), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, ?MG1_MID, [Trans]), + cre_MegacoMessage(Mess). + +msg61a() -> + msg61(false). + +msg61b() -> + msg61(true). + +msg61c() -> + msg61(asn1_NOVALUE). + + +msg62a() -> + MT = ?MSG_LIB:cre_ModemType(v18), + PP = cre_PropParm("c", "IN IP4 $ "), + MD = ?MSG_LIB:cre_ModemDescriptor([MT], [PP]), + AmmDesc = ?MSG_LIB:cre_AmmDescriptor(MD), + TermIDs = [#megaco_term_id{id = ?A4444}], + AmmReq = ?MSG_LIB:cre_AmmRequest(TermIDs, [AmmDesc]), + Cmd = ?MSG_LIB:cre_Command(addReq, AmmReq), + CmdReq = ?MSG_LIB:cre_CommandRequest(Cmd), + ActReq = ?MSG_LIB:cre_ActionRequest(2, [CmdReq]), + Acts = [ActReq], + TR = ?MSG_LIB:cre_TransactionRequest(9898, Acts), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, ?MG1_MID, [Trans]), + cre_MegacoMessage(Mess). + +msg62b() -> + MP = +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 +Transaction = 9898 { + Context = 2 { + Add = 11111111/00000000/00000000 { + Modem[V18] { + tdmc/gain=2 + } + } + } +}", +% MC = +% "!/" ?VERSION_STR " [124.124.124.222]:55555\nT=9898{C=2{A=11111111/00000000/00000000{MD[V18]{tdmc/gain=2}}}}", + list_to_binary(MP). + +%% ActionRequest with various combinations of ContextRequest and +%% ContextAttrAuditRequest +msg71(CR, CAAR) -> + TS1 = cre_TimeNot("19990729", "22000000"), + TS2 = cre_TimeNot("19990729", "22000111"), + Event1 = cre_ObsEv("al/of",TS1), + Event2 = cre_ObsEv("al/on",TS2), + Desc1 = cre_ObsEvsDesc(2222,[Event1]), + Desc2 = cre_ObsEvsDesc(2222,[Event2]), + NR1 = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc1), + NR2 = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc2), + Cmd1 = ?MSG_LIB:cre_Command(notifyReq, NR1), + Cmd2 = ?MSG_LIB:cre_Command(notifyReq, NR2), + CR1 = cre_CmdReq(Cmd1), + CR2 = cre_CmdReq(Cmd2), + ActReq = ?MSG_LIB:cre_ActionRequest(1, CR, CAAR, [CR1, CR2]), + Acts = [ActReq], + TR = ?MSG_LIB:cre_TransactionRequest(9898, Acts), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, ?MG1_MID, [Trans]), + cre_MegacoMessage(Mess). + +msg71a() -> + CR = cre_CtxReq(), + CAAR = cre_CtxAttrAuditReq(), + msg71(CR, CAAR). + +msg71b(CR) -> + CAAR = asn1_NOVALUE, + msg71(CR, CAAR). + +msg71b01() -> + CR = cre_CtxReq(15), + msg71b(CR). + +msg71b02() -> + CR = cre_CtxReq(true), + msg71b(CR). + +msg71b03() -> + CR = cre_CtxReq(false), + msg71b(CR). + +msg71b04() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(Top), + msg71b(CR). + +msg71b05() -> + CR = cre_CtxReq(15, true), + msg71b(CR). + +msg71b06() -> + CR = cre_CtxReq(15, false), + msg71b(CR). + +msg71b07() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, Top), + msg71b(CR). + +msg71b08() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, true, Top), + msg71b(CR). + +msg71b09() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, false, Top), + msg71b(CR). + +msg71b10() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = onewayboth, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, false, Top), + msg71b(CR). + +msg71b11() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = onewayexternal, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, false, Top), + msg71b(CR). + +msg71b12() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, true, Top, true), + msg71b(CR). + +msg71b13() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, true, Top, false), + msg71b(CR). + +msg71b14() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", "2"), + Props = [PP], + CR = cre_CtxReq(15, true, Top, Props), + msg71b(CR). + +msg71b15() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2"], relation, greaterThan), + Props = [PP], + CR = cre_CtxReq(15, true, Top, Props), + msg71b(CR). + +msg71b16() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","10"], range, true), + Props = [PP], + CR = cre_CtxReq(15, true, Top, Props), + msg71b(CR). + +msg71b17() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("nt/jit", ["40","50","50"], sublist, true), + Props = [PP], + CR = cre_CtxReq(15, true, Top, Props), + msg71b(CR). + +msg71b18() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CR = cre_CtxReq(15, true, Top, true, Props), + msg71b(CR). + +msg71b19() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, true, Top, false), + msg71b(CR). + +msg71b20() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CR = cre_CtxReq(15, true, Top, false, Props), + msg71b(CR). + +msg71b21() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CID1 = cre_CtxID(10191), + CID2 = cre_CtxID(10192), + CIDs = [CID1, CID2], + CR = cre_CtxReq(15, true, Top, false, CIDs), + msg71b(CR). + +msg71b22() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CID1 = cre_CtxID(10191), + CID2 = cre_CtxID(10192), + CIDs = [CID1, CID2], + CR = cre_CtxReq(15, true, Top, false, Props, CIDs), + msg71b(CR). + +msg71c(CAAR) -> + CR = asn1_NOVALUE, + msg71(CR, CAAR). + +msg71c01() -> + CAAR = cre_CtxAttrAuditReq('NULL', 'NULL', 'NULL'), + msg71c(CAAR). + +msg71c02() -> + CAAR = cre_CtxAttrAuditReq('NULL', 'NULL', asn1_NOVALUE), + msg71c(CAAR). + +msg71c03() -> + CAAR = cre_CtxAttrAuditReq('NULL', asn1_NOVALUE, 'NULL'), + msg71c(CAAR). + +msg71c04() -> + CAAR = cre_CtxAttrAuditReq(asn1_NOVALUE, 'NULL', 'NULL'), + msg71c(CAAR). + +msg71c05() -> + CAAR = cre_CtxAttrAuditReq(asn1_NOVALUE, asn1_NOVALUE, 'NULL'), + msg71c(CAAR). + +msg71c06() -> + CAAR = cre_CtxAttrAuditReq(asn1_NOVALUE, 'NULL', asn1_NOVALUE), + msg71c(CAAR). + +msg71c07() -> + CAAR = cre_CtxAttrAuditReq('NULL', asn1_NOVALUE, asn1_NOVALUE), + msg71c(CAAR). + +msg71c08() -> + CAAR = cre_CtxAttrAuditReq('NULL', asn1_NOVALUE, 'NULL', 'NULL'), + msg71c(CAAR). + +msg71c09() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + CAAR = cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, CPA), + msg71c(CAAR). + +msg71c10() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + SPrio = 10, + CAAR = cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, CPA, SPrio), + msg71c(CAAR). + +msg71c11() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + SPrio = 10, + SEm = true, + CAAR = cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, CPA, + SPrio, SEm, asn1_NOVALUE, asn1_NOVALUE), + msg71c(CAAR). + +msg71c12() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + SPrio = 10, + SEm = true, + SIeps = false, + CAAR = cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, CPA, + SPrio, SEm, SIeps), + msg71c(CAAR). + +msg71c13() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + SPrio = 10, + SEm = false, + SIeps = true, + SLog = cre_SelectLogic(andAUDITSelect), + CAAR = cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, CPA, + SPrio, SEm, SIeps, SLog), + msg71c(CAAR). + +msg71c14() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + SPrio = 10, + SEm = true, + SIeps = true, + SLog = cre_SelectLogic(orAUDITSelect), + CAAR = cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, CPA, + SPrio, SEm, SIeps, SLog), + msg71c(CAAR). + +msg71c15() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + SPrio = 10, + SLog = cre_SelectLogic(orAUDITSelect), + CAAR = cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, CPA, + SPrio, SLog), + msg71c(CAAR). + +msg71d01() -> + CR = cre_CtxReq(15, true), + CAAR = cre_CtxAttrAuditReq('NULL', 'NULL', 'NULL'), + msg71(CR, CAAR). + +msg71d02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2"], relation, unequalTo), + Props = [PP], + CR = cre_CtxReq(15, true, Top, true, Props), + + CAAR_Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + CAAR = cre_CtxAttrAuditReq(CAAR_Top, Em, Prio, Ieps, CPA), + + msg71(CR, CAAR). + +msg71d03() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2"], relation, unequalTo), + Props = [PP], + CR = cre_CtxReq(15, true, Top, false, Props), + + CAAR_Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + CAAR = cre_CtxAttrAuditReq(CAAR_Top, Em, Prio, Ieps, CPA), + + msg71(CR, CAAR). + +msg71d04() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2"], relation, unequalTo), + Props = [PP], + CID1 = cre_CtxID(10191), + CID2 = cre_CtxID(10192), + CIDs = [CID1, CID2], + CR = cre_CtxReq(15, true, Top, false, Props, CIDs), + + CAAR_Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + SPrio = 10, + SEm = true, + SIeps = true, + SLog = cre_SelectLogic(orAUDITSelect), + CAAR = cre_CtxAttrAuditReq(CAAR_Top, Em, Prio, Ieps, CPA, + SPrio, SEm, SIeps, SLog), + msg71(CR, CAAR). + +msg72(ED, CR) -> + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 124.124.124.222"), + M = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + A = cre_PropParm("a", "a=ptime:30"), + A2 = cre_PropParm("a", "recvonly"), + LD = cre_LocalRemoteDesc([[V, C, M, A, A2]]), + Parms = cre_StreamParmsL(LD), + StreamDesc = cre_StreamDesc(1, Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + CmdRep = [{addReply, Reply}, {addReply, Reply2}], + Action = cre_ActRep(2000, ED, CR, CmdRep), + msg_reply(?MGC_MID, 10003, [Action]). + +msg72a(CR) -> + ED = asn1_NOVALUE, + msg72(ED, CR). + +msg72a01() -> + CR = cre_CtxReq(false), + msg72a(CR). + +msg72a02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(Top), + msg72a(CR). + +msg72a03() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, Top), + msg72a(CR). + +msg72b(CR) -> + EC = ?MSG_LIB:cre_ErrorCode(?megaco_not_ready), + ED = ?MSG_LIB:cre_ErrorDescriptor(EC), + msg72(ED, CR). + +msg72b01() -> + CR = cre_CtxReq(15, false), + msg72b(CR). + +msg72b02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, false, Top), + msg72b(CR). + +msg72b03() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, true, Top, true), + msg72b(CR). + +msg72b04() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, true, Top, false), + msg72b(CR). + +msg72c(CR) -> + EC = ?MSG_LIB:cre_ErrorCode(?megaco_not_ready), + ET = ?MSG_LIB:cre_ErrorText("Just another error string"), + ED = ?MSG_LIB:cre_ErrorDescriptor(EC, ET), + msg72(ED, CR). + +msg72c01() -> + CR = cre_CtxReq(15), + msg72c(CR). + +msg72c02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", "2"), + Props = [PP], + CR = cre_CtxReq(15, true, Top, Props), + msg72c(CR). + +msg72c03() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CR = cre_CtxReq(15, true, Top, true, Props), + msg72c(CR). + +msg72c04() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CR = cre_CtxReq(15, true, Top, false, Props), + msg72c(CR). + + +msg73() -> + Stat1 = cre_StatsParm("rtp/ps"), + Stat2 = cre_StatsParm("nt/os","62300"), + Stat3 = cre_StatsParm("rtp/pr","700"), + Stat4 = cre_StatsParm("nt/or","45100"), + Stat5 = cre_StatsParm("rtp/pl","0.2"), + Stat6 = cre_StatsParm("rtp/jit","20"), + Stat7 = cre_StatsParm("rtp/delay","40"), + Stats = [Stat1, Stat2, Stat3, Stat4, Stat5, Stat6, Stat7], + cre_StatsDesc(Stats). + +%% StatisticsDescriptor in AmmDescriptor +msg73a() -> + StatDesc = msg73(), + AmmDesc = cre_AmmDesc(StatDesc), + TermIDs = [#megaco_term_id{id = ["11111111", "00001111", "00000000"]}], + AmmReq = cre_AmmReq(TermIDs, [AmmDesc]), + Cmd = cre_Cmd(addReq, AmmReq), + CmdReq = cre_CmdReq(Cmd), + CID = cre_CtxID(7301), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(7302), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + + +%% StatisticsDescriptor in IndAudStreamParms +msg73b1() -> + IASD = cre_IndAudStatsDesc("nt/dur"), + cre_IndAudStreamParms(IASD). + +msg73b2(IAMD) -> + IAP = cre_IndAudParam(IAMD), + AD = cre_AuditDesc([IAP]), + TermID = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + AudReq = cre_AuditReq(TermID, AD), + Cmd = cre_Cmd(auditValueRequest, AudReq), + CmdReq = cre_CmdReq(Cmd), + CID = cre_CtxID(7311), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(7312), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg73b01() -> + IASP = msg73b1(), + IAMD = cre_IndAudMediaDesc(IASP), + msg73b2(IAMD). + +msg73b02() -> + IASP = msg73b1(), + SID = cre_StreamID(303), + IASD = cre_IndAudStreamDesc(SID, IASP), + IAMD = cre_IndAudMediaDesc([IASD]), + msg73b2(IAMD). + +%% StatisticsDescriptor in StreamParms +msg73c1() -> + StatDesc = msg73(), + SP = cre_StreamParms(StatDesc), + SID = cre_StreamID(505), + cre_StreamDesc(SID, SP). + +msg73c2(MD) -> + ARP = cre_AuditRetParam(MD), + TA = cre_TermAudit([ARP]), + TermIDs = [#megaco_term_id{id = ["11111111", "00001111", "00000000"]}], + AmmsRep = cre_AmmsReply(TermIDs, TA), + CmdRep = cre_CmdRep(moveReply, AmmsRep), + CID = cre_CtxID(606), + ActRep = cre_ActRep(CID, [CmdRep]), + TransId = cre_TransId(8899), + TransRep = cre_TransRep(TransId, [ActRep]), + Trans = cre_Trans(TransRep), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg73c01() -> + SD = msg73c1(), + MD = cre_MediaDesc(SD), + msg73c2(MD). + +msg73c02() -> + SD = msg73c1(), + MD = cre_MediaDesc([SD]), + msg73c2(MD). + + +%% New Signal (direction and requestID); msg74 +msg74a1(D) -> + Dir = cre_SigDir(D), + cre_Sig("cg/rt", Dir, asn1_NOVALUE). + +msg74a2(D, RID) -> + Dir = cre_SigDir(D), + cre_Sig("cg/rt", Dir, RID). + +msg74a3(D, RID) -> + Name = "al/ri", + SID = cre_StreamID(7401), + ST = cre_SigType(brief), + Dur = 7499, + NC = cre_NotifCompl([onTimeOut,otherReason]), + KA = cre_BOOLEAN(true), + SPL = [], + Dir = cre_SigDir(D), + cre_Sig(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID). + +msg74a4(Sig) -> + SR = cre_SigReq(Sig), + SD = cre_SigsDesc([SR]), + AD = cre_AmmDesc(SD), + TermIDs = [#megaco_term_id{id = ?A4444}], + AR = cre_AmmReq(TermIDs, [AD]), + Cmd = cre_Cmd(modReq, AR), + cre_CmdReq(Cmd). + +msg74a01() -> + Sig = msg74a1(internal), + CR = msg74a4(Sig), + CID = cre_CtxID(7411), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7421), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a02() -> + Sig = msg74a1(both), + CR = msg74a4(Sig), + CID = cre_CtxID(7412), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7422), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a03() -> + RID = cre_ReqID(7433), + Sig = msg74a2(external, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7413), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7423), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a04() -> + RID = cre_ReqID(7434), + Sig = msg74a2(both, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7414), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7424), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a05() -> + RID = cre_ReqID(7435), + Sig = msg74a3(both, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7415), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7425), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a06() -> + RID = cre_ReqID(7436), + Sig = msg74a3(internal, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7416), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7426), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + + + +%% New ServiceChangeParm (serviceChangeIncompleteFlag); msg75 +msg75a(IncFlag) -> + Method = cre_SvcChMethod(restart), + Address = cre_SvcChAddr(portNumber, ?DEFAULT_PORT), + Reason = "901 mg col boot", + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChParm(Method, Address, [Reason], Profile, IncFlag), + TermIDs = [?megaco_root_termination_id], + Req = cre_SvcChReq(TermIDs, Parm), + Cmd = cre_Cmd(serviceChangeReq, Req), + CR = cre_CmdReq(Cmd), + CID = cre_CtxID(7501), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7502), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg75a01() -> + msg75a(asn1_NOVALUE). + +msg75a02() -> + msg75a('NULL'). + + +msg76(IAMD) -> + IAP = cre_IndAudParam(IAMD), + AD = cre_AuditDesc(asn1_NOVALUE, [IAP]), + AR = cre_AuditReq(#megaco_term_id{id = ?A5556}, AD), + CR = cre_CmdReq({auditValueRequest, AR}), + msg_request(?MG2_MID, 50076, ?megaco_null_context_id, [CR]). + +%% IndAudLocalControlDescriptor and IndAudPropertyParm +msg76a(IALCD) when is_record(IALCD, 'IndAudLocalControlDescriptor') -> + IASP = cre_IndAudStreamParms(IALCD), + SID = 123, + IASD = cre_IndAudStreamDesc(SID, IASP), + IAMD = cre_IndAudMediaDesc([IASD]), + msg76(IAMD). + +msg76a01() -> + Name1 = "nt/jit", + IAPP1 = cre_IndAudPropertyParm(Name1), + Name2 = "tdmc/ec", + IAPP2 = cre_IndAudPropertyParm(Name2), + SMS = cre_StreamMode(recvOnly), + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, 'NULL', 'NULL', + [IAPP1, IAPP2], SMS), + msg76a(IALCD). + +msg76a02() -> + Name1 = "tdmc/gain", + PP1 = cre_PropParm("tdmc/gain", "2"), + IAPP1 = cre_IndAudPropertyParm(Name1, PP1), + Name2 = "tdmc/gain", + PP2 = cre_PropParm("tdmc/gain", "3"), + IAPP2 = cre_IndAudPropertyParm(Name2, PP2), + SMS = cre_StreamMode(recvOnly), + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, 'NULL', 'NULL', + [IAPP1, IAPP2], SMS), + msg76a(IALCD). + +%% IndAudTerminationStateDescription + ServiceState +msg76b(IATSD) -> + IAMD = cre_IndAudMediaDesc(IATSD), + msg76(IAMD). + +msg76b01() -> + SSS = cre_ServiceState(outOfSvc), + IATSD = cre_IndAudTermStateDesc([], asn1_NOVALUE, asn1_NOVALUE, SSS), + msg76b(IATSD). + +%% msg76b02() -> +%% PP = cre_PropParm("tdmc/gain", "2"), +%% IAPP = cre_IndAudPropertyParm("nt/jit", PP), +%% IAPPs = [IAPP], +%% SSS = cre_ServiceState(outOfSvc), +%% IATSD = cre_IndAudTermStateDesc(IAPPs, 'NULL', asn1_NOVALUE, SSS), +%% msg76b(IATSD). + +msg77a01() -> + SN = "tonegen/pt", + Sig = cre_IndAudSig(SN, 7701), + msg54(?MG2_MID, Sig). + + +msg78a(Events) -> + EventsDesc = cre_EvsDesc(2223, Events), + Signal = cre_Sig("cg/rt"), + Name = "dialplan00", + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + DigitMapValue = cre_DigitMapValue(Body), + DigMapDesc = cre_DigitMapDesc(Name, DigitMapValue), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, [{signal, Signal}]}, + {digitMapDescriptor, DigMapDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(?MG2_MID, 10001, ?megaco_null_context_id, [CmdReq]). + +msg78a01() -> + Name1 = "al/on", + Strict = cre_EvParm("strict", ["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + Name2 = "al/on", + SID2 = 7801, + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + NB2 = cre_NotifBehav(notifyImmediate, 'NULL'), + RED2 = asn1_NOVALUE, + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB2, RED2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, SID2, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a02() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + Name2 = "al/on", + SID2 = 7802, + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + NB2 = cre_NotifBehav(neverNotify, 'NULL'), + RED2 = asn1_NOVALUE, + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB2, RED2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, SID2, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a03() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + Name2 = "al/on", + SID2 = 7803, + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + RED2 = cre_RegEmbedDesc(), + NB2 = cre_NotifBehav(notifyRegulated, RED2), + REvD2 = asn1_NOVALUE, + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB2, REvD2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, SID2, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a04() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + Name2 = "al/on", + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + SRE2 = cre_SecReqEv("al/on"), + SED2 = cre_SecEvsDesc(7814, [SRE2]), + RED2 = cre_RegEmbedDesc(SED2), + NB2 = cre_NotifBehav(notifyRegulated, RED2), + REvD2 = asn1_NOVALUE, + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB2, REvD2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, 7824, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a05() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + Name2 = "al/on", + SID2 = 7805, + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + SD2 = cre_SigsDesc(), + RED2 = cre_RegEmbedDesc(SD2), + NB2 = cre_NotifBehav(notifyRegulated, RED2), + REvD2 = asn1_NOVALUE, + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB2, REvD2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, SID2, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a06() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + Name2 = "al/on", + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + SRE2 = cre_SecReqEv("al/on"), + SED2 = cre_SecEvsDesc(7816, [SRE2]), + Sig2 = cre_Sig("cg/rt", external, asn1_NOVALUE), + SR2 = cre_SigReq(Sig2), + SRs2 = [SR2], + SD2 = cre_SigsDesc(SRs2), + RED2 = cre_RegEmbedDesc(SED2, SD2), + NB2 = cre_NotifBehav(notifyRegulated, RED2), + REvD2 = asn1_NOVALUE, + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB2, REvD2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, 7826, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a07() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + Name2 = "al/on", + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + SRE2 = cre_SecReqEv("al/on"), + SED2 = cre_SecEvsDesc(7817, [SRE2]), + Sig2 = cre_Sig("cg/rt", external, asn1_NOVALUE), + SR2 = cre_SigReq(Sig2), + SRs2 = [SR2], + SD2 = cre_SigsDesc(SRs2), + RED2 = cre_RegEmbedDesc(SED2, SD2), + NB2 = cre_NotifBehav(notifyRegulated, RED2), + REvD2 = 'NULL', + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB2, REvD2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, 7827, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a08() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + + Name2 = "al/on", + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + + Sig21 = cre_Sig("al/ri", both, asn1_NOVALUE), + SR21 = cre_SigReq(Sig21), + SRs21 = [SR21], + SD21 = cre_SigsDesc(SRs21), + RED21 = cre_RegEmbedDesc(SD21), + NB21 = cre_NotifBehav(notifyRegulated, RED21), + SRA2 = cre_SecReqActs(KA2, EDM2, asn1_NOVALUE, NB21, 'NULL'), + SRE2 = cre_SecReqEv("al/of", 7816, SRA2), + SED2 = cre_SecEvsDesc(7826, [SRE2]), + + Sig22 = cre_Sig("cg/rt", external, asn1_NOVALUE), + SR22 = cre_SigReq(Sig22), + SRs22 = [SR22], + SD22 = cre_SigsDesc(SRs22), + RED22 = cre_RegEmbedDesc(SED2, SD22), + NB22 = cre_NotifBehav(notifyRegulated, RED22), + REvD2 = 'NULL', + + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB22, REvD2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, 7836, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a09() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + + Name2 = "al/on", + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + + SID21 = cre_StreamID(7819), + ST21 = cre_SigType(timeOut), + Dur21 = 7898, + NC21 = cre_NotifCompl([onTimeOut, onInterruptByEvent, otherReason]), + KA21 = cre_BOOLEAN(false), + SPL21 = [], + Dir21 = cre_SigDir(both), + RID21 = cre_ReqID(7829), + + Sig21 = cre_Sig("cg/rt", SID21, ST21, Dur21, NC21, KA21, SPL21, Dir21, + RID21, 7839), + SR21 = cre_SigReq(Sig21), + SRs21 = [SR21], + SD21 = cre_SigsDesc(SRs21), + RED21 = cre_RegEmbedDesc(SD21), + NB21 = cre_NotifBehav(notifyRegulated, RED21), + + SRA2 = cre_SecReqActs(KA2, EDM2, asn1_NOVALUE, NB21, 'NULL'), + SRE2 = cre_SecReqEv("al/of", 7849, SRA2), + SED2 = cre_SecEvsDesc(7859, [SRE2]), + + SID22 = cre_StreamID(7869), + ST22 = cre_SigType(brief), + Dur22 = 17809, + NC22 = cre_NotifCompl([onTimeOut, otherReason]), + KA22 = cre_BOOLEAN(true), + SPL22 = [], + Dir22 = cre_SigDir(external), + RID22 = cre_ReqID(7879), + + Sig22 = cre_Sig("cg/rt", SID22, ST22, Dur22, NC22, KA22, SPL22, Dir22, + RID22, 7889), + SR22 = cre_SigReq(Sig22), + SRs22 = [SR22], + SD22 = cre_SigsDesc(SRs22), + RED22 = cre_RegEmbedDesc(SED2, SD22), + + NB22 = cre_NotifBehav(notifyRegulated, RED22), + REvD2 = 'NULL', + + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB22, REvD2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, 7899, RA2, EPL2), + msg78a([RE1, RE2]). + + +msg79a01() -> + TID1 = #megaco_term_id{id = ?A4444}, + TID2 = #megaco_term_id{id = ?A4445}, + TID3 = #megaco_term_id{id = ?A5555}, + TIDs = cre_TermIDList([TID1, TID2, TID3]), + ErC = cre_ErrCode(?megaco_not_ready), + ErD = cre_ErrDesc(ErC), + ARP1 = cre_AuditRetParam(ErD), + RE = cre_ReqEv("al/of"), + EvD = cre_EvsDesc(7911,[RE]), + ARP2 = cre_AuditRetParam(EvD), + Tks = [mediaToken, digitMapToken, statsToken, packagesToken], + AD = cre_AuditDesc(Tks), + ARP3 = cre_AuditRetParam(AD), + TAR = cre_TermAudit([ARP1, ARP2, ARP3]), + TLAR = cre_TermListAuditRes(TIDs, TAR), + AudR = cre_AuditRep(TLAR), + CR = cre_CmdRep(auditValueReply, AudR), + ActR = cre_ActRep(7921, [CR]), + Acts = [ActR], + msg_reply(?MG2_MID, 7931, Acts). + + +%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +%% Pretty RFC 3525 messages: + +%% Added Reason +rfc3525_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + +rfc3525_msg2() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +%% Removed "," after LocalControl ending "}" +rfc3525_msg3() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 9999 { + Context = - { + Modify = A4444 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive, + tdmc/gain=2, ; in dB, + tdmc/ec=on + } + } + }, + Events = 2222 { + al/of {strict=state} + } + } + } +}". + +%% Removed the outermost "{}" pair (before the Reply token) +rfc3525_msg4() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 9999 { + Context = - { + Modify = A4444 + } +}". + +rfc3525_msg6() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Transaction = 10000 { + Context = - { + Notify = A4444 { + ObservedEvents =2222 { + 19990729T22000000:al/of{init=false} + } + } + } +}". + + +rfc3525_msg7() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 10000 { + Context = - { + Notify = A4444 + } +}". + +rfc3525_msg8() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10001 { + Context = - { + Modify = A4444 { + Events = 2223 { + al/on {strict=state}, + dd/ce {DigitMap=Dialplan0} + }, + Signals {cg/dt}, + DigitMap = Dialplan0 { + (0| 00|[1-7]xxx|8xxxxxxx|fxxxxxxx|exx|91xxxxxxxxxx|9011x.) + } + } + } +}". + +rfc3525_msg9() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10001 { + Context = - { + Modify = A4444 + } +}". + +rfc3525_msg10() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Transaction = 10002 { + Context = - { + Notify = A4444 { + ObservedEvents =2223 { + 19990729T22010001:dd/ce { + ds=\"916135551212\", + Meth=UM + } + } + } + } +}". + + +rfc3525_msg11() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 10002 { + Context = - { + Notify = A4444 + } +}". + +%% Added ? +rfc3525_msg12() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10003 { + Context = $ { + Add = A4444, + Add = $ { + Media { + Stream = 1 { + LocalControl { + Mode = ReceiveOnly, + nt/jit=40 ; in ms + }, + Local { + v=0 c=IN IP4 $ m=audio $ RTP/AVP 4 a=ptime:30 v=0 c=IN IP4 $ m=audio $ RTP/AVP 0 + } + } + } + } + } +}". + +%% Added ? +rfc3525_msg13() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a=recvonly + } ; RTP profile for G.723.1 is 4 + } + } + } + } +}". + +%% +%% Added ? +rfc3525_msg14() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50003 { + Context = $ { + Add = A5555 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive + } + } + }, + Events = 1234 { + al/of {strict=state} + }, + Signals {al/ri} + }, + Add = $ { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive, + nt/jit=40 ; in ms + }, + Local { + v=0 c=IN IP4 $ m=audio $ RTP/AVP 4 a=ptime:30 + }, + Remote { + v=0 c=IN IP4 124.124.124.222 m=audio 2222 RTP/AVP 4 a=ptime:30 + } ; RTP profile for G.723.1 is 4 + } + } + } + } +}". + +%% Added ? +rfc3525_msg15() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50003 { + Context = 5000 { + Add = A5555, + Add = A5556 { + Media { + Stream = 1 { + Local { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 + } ; RTP profile for G723.1 is 4 + } + } + } + } +}". + +%% Added ? +rfc3525_msg16a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10005 { + Context = 2000 { + Modify = A4444 { + Signals {cg/rt} + }, + Modify = A4445 { + Media { + Stream = 1 { + Remote { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 + } ; RTP profile for G723.1 is 4 + } + } + } + } +}". + +rfc3525_msg16b() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10005 { + Context = 2000 { + Modify = A4444, + Modify = A4445 + } +}". + +rfc3525_msg17a() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Transaction = 50005 { + Context = 5000 { + Notify = A5555 { + ObservedEvents = 1234 { + 19990729T22020002:al/of{init=false} + } + } + } +}". + +rfc3525_msg17b() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 50005 { + Context = - { + Notify = A5555 + } +}". + +%% Removed "{ }" after Signals +rfc3525_msg17c() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50006 { + Context = 5000 { + Modify = A5555 { + Events = 1235 { + al/on{strict=state} + }, + Signals ; to turn off ringing + } + } +}". + +rfc3525_msg17d() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50006 { + Context = 5000 { + Modify = A4445 + } +}". + +%% Removed "{ }" after Signals +rfc3525_msg18a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10006 { + Context = 2000 { + Modify = A4445 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive + } + } + } + }, + Modify = A4444 { + Signals + } + } +}". + +rfc3525_msg18b() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10006 { + Context = 2000 { + Modify = A4445, + Modify = A4444 + } +}". + +rfc3525_msg19() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50007 { + Context = - { + AuditValue = A5556 { + Audit { + Media, DigitMap, Events, Signals, Packages, Statistics + } + } + } +}". + +%% Added ? +rfc3525_msg20() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50007 { + Context = - { + AuditValue = A5556 { + Media { + TerminationState { + ServiceStates = InService, + Buffer = OFF + }, + Stream = 1 { + LocalControl { + Mode = SendReceive, + nt/jit=40 + }, + Local { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 a=ptime:30 + }, + Remote { + v=0 o=- 2890844526 2890842807 IN IP4 124.124.124.222 s=- t= 0 0 c=IN IP4 124.124.124.222 m=audio 2222 RTP/AVP 4 a=ptime:30 + } + } + }, + Events, + Signals, + DigitMap, + Packages {nt-1, rtp-1}, + Statistics { + rtp/ps=1200, ; packets sent + nt/os=62300, ; octets sent + rtp/pr=700, ; packets received + nt/or=45100, ; octets received + rtp/pl=0.2, ; % packet loss + rtp/jit=20, + rtp/delay=40 ; avg latency + } + } + } +}". + +rfc3525_msg21a() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Transaction = 50008 { + Context = 5000 { + Notify = A5555 { + ObservedEvents =1235 { + 19990729T24020002:al/on {init=false} + } + } + } +}". + +rfc3525_msg21b() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 50008 { + Context = - { + Notify = A5555 + } +}". + +rfc3525_msg22a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50009 { + Context = 5000 { + Subtract = A5555 { + Audit { + Statistics + } + }, + Subtract = A5556 { + Audit { + Statistics + } + } + } +}". + +%% Added ? +rfc3525_msg22b() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50009 { + Context = 5000 { + Subtract = A5555 { + Statistics { + nt/os=45123, ; Octets Sent + nt/dur=40 ; in seconds + } + }, + Subtract = A5556 { + Statistics { + rtp/ps=1245, ; packets sent + nt/os=62345, ; octets sent + rtp/pr=780, ; packets received + nt/or=45123, ; octets received + rtp/pl=10, ; % packets lost + rtp/jit=27, + rtp/delay=48 ; average latency + } + } + } +}". + +rfc3525_msgs() -> + [ + {msg1, rfc3525_msg1()}, + {msg2, rfc3525_msg2()}, + {msg3, rfc3525_msg3()}, + {msg4, rfc3525_msg4()}, + {msg6, rfc3525_msg6()}, + {msg7, rfc3525_msg7()}, + {msg8, rfc3525_msg8()}, + {msg9, rfc3525_msg9()}, + {msg10, rfc3525_msg10()}, + {msg11, rfc3525_msg11()}, + {msg12, rfc3525_msg12()}, + {msg13, rfc3525_msg13()}, + {msg14, rfc3525_msg14()}, + {msg15, rfc3525_msg15()}, + {msg16a, rfc3525_msg16a()}, + {msg16b, rfc3525_msg16b()}, + {msg17a, rfc3525_msg17a()}, + {msg17b, rfc3525_msg17b()}, + {msg17c, rfc3525_msg17c()}, + {msg17d, rfc3525_msg17d()}, + {msg18a, rfc3525_msg18a()}, + {msg18b, rfc3525_msg18b()}, + {msg19, rfc3525_msg19()}, + {msg20, rfc3525_msg20()}, + {msg21a, rfc3525_msg21a()}, + {msg21b, rfc3525_msg21b()}, + {msg22a, rfc3525_msg22a()}, + {msg22b, rfc3525_msg22b()} + ]. + +rfc3525_msgs_display() -> + Msgs = rfc3525_msgs(), + Fun = fun({Name, Msg}) -> + io:format("~w: ~n~s~n~n", [Name, Msg]) + end, + lists:foreach(Fun, Msgs). + +rfc3525_msgs_test() -> + put(dbg,true), + Res = rfc3525_msgs_test(megaco_pretty_text_encoder, [], 2), + erase(dbg), + io:format("~w~n", [Res]). + +rfc3525_msgs_test(Codec, Config, Ver) -> + io:format("-----------------------------------------" + "~ntesting with" + "~n Codec: ~w" + "~n Config: ~w" + "~n Version: ~w" + "~n", [Codec, Config, Ver]), + Msgs = rfc3525_msgs(), + Test = fun({N,M1}) -> + %% io:format("testing ~w: ", [N]), + io:format("~n*** testing ~w *** ~n~s~n", [N,M1]), + Bin1 = erlang:list_to_binary(M1), + case (catch Codec:decode_message(Config, Ver, Bin1)) of + {ok, M2} -> + %% io:format("d", []), + io:format("decoded:~n~p~n", [M2]), + case (catch Codec:encode_message(Config, Ver, M2)) of + {ok, Bin2} when is_binary(Bin2) -> + %% io:format("e~n", []), + io:format("encode: ~n~s~n", [erlang:binary_to_list(Bin2)]), + {N,ok}; + {ok, M3} -> + %% io:format("e~n", []), + io:format("encode: ~n~s~n", [M3]), + {N,ok}; + E -> + io:format("~n~p~n", [E]), + {N,encode_error} + end; + E -> + io:format("~n~p~n", [E]), + {N,decode_error} + end + end, + [Test(M) || M <- Msgs]. + +%% -------------------------- + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% skip(Reason) -> +%% megaco_codec_test_lib:skip(Reason). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ticket_compact_encode_decode_ok(Msg) -> + ticket_compact_encode_decode_ok(Msg, []). + +ticket_compact_encode_decode_ok(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + ticket_encode_decode_ok(Msg, Codec, Conf). + +ticket_pretty_encode_decode_ok(Msg) -> + ticket_pretty_encode_decode_ok(Msg, []). + +ticket_pretty_encode_decode_ok(Msg, Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_encode_decode_ok(Msg, Codec, Conf). + +ticket_encode_decode_ok(Msg, Codec, Conf0) -> + Conf = [?EC_V3|Conf0], + Encode = fun(M) -> encode_message(Codec, Conf, M) end, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(M1, M2) -> chk_MegacoMessage(M1, M2) end, + megaco_codec_test_lib:expect_encode_decode(Msg, Encode, Decode, Check). + +%% -- + +%% ticket_compact_encode_error(Msg) -> +%% ticket_compact_encode_error(Msg, []). + +%% ticket_compact_encode_error(Msg, Conf) -> +%% Codec = megaco_compact_text_encoder, +%% ticket_encode_error(Msg, Codec, Conf). + +%% ticket_pretty_encode_error(Msg) -> +%% ticket_pretty_encode_error(Msg, []). + +ticket_pretty_encode_error(Msg, Conf) when is_list(Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_encode_error(Msg, Codec, Conf); +ticket_pretty_encode_error(Msg, Check) when is_function(Check) -> + ticket_pretty_encode_error(Msg, [], Check). + +ticket_pretty_encode_error(Msg, Conf, Check) when is_function(Check) -> + Codec = megaco_pretty_text_encoder, + ticket_encode_error(Msg, Codec, Conf, Check). + +ticket_encode_error(Msg, Codec, Conf) when is_list(Conf) -> + Check = fun(_) -> ok end, % Only called when encode failes + ticket_encode_error(Msg, Codec, Conf, Check). + +ticket_encode_error(Msg, Codec, Conf0, Check) -> + Conf = [?EC_V3|Conf0], + Encode = fun(M) -> encode_message(Codec, Conf, M) end, + megaco_codec_test_lib:expect_encode(Msg, Encode, Check). + +%% -- + +ticket_compact_decode_encode_ok(Msg) -> + ticket_compact_decode_encode_ok(Msg, []). + +ticket_compact_decode_encode_ok(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + ticket_decode_encode_ok(Msg, Codec, Conf). + +ticket_pretty_decode_encode_ok(Msg) -> + ticket_pretty_decode_encode_ok(Msg, []). + +ticket_pretty_decode_encode_ok(Msg, Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_decode_encode_ok(Msg, Codec, Conf). + +ticket_decode_encode_ok(Msg, Codec, Conf0) -> + Conf = [?EC_V3|Conf0], + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Encode = fun(M) -> encode_message(Codec, Conf, M) end, + Check = fun(M1, M2) -> chk_MegacoMessage(M1, M2) end, + megaco_codec_test_lib:expect_decode_encode(Msg, Decode, Encode, Check). + +%% -- + +ticket_pretty_decode_encode_only(Msg, Check) -> + ticket_pretty_decode_encode_only(Msg, Check, []). + +ticket_pretty_decode_encode_only(Msg, Check, Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_decode_encode_only(Msg, Codec, Check, Conf). + +ticket_decode_encode_only(Msg, Codec, Check, Conf0) -> + Conf = [?EC_V3|Conf0], + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Encode = fun(M) -> encode_message(Codec, Conf, M) end, + megaco_codec_test_lib:expect_decode_encode_only(Msg, Decode, Encode, + Check). + +%% -- + +ticket_pretty_encode_decode_only(Msg) -> + ticket_pretty_encode_decode_only(Msg, []). + +ticket_pretty_encode_decode_only(Msg, Conf) when is_list(Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_encode_decode_only(Msg, Codec, Conf); +ticket_pretty_encode_decode_only(Msg, Check) when is_function(Check) -> + ticket_pretty_encode_decode_only(Msg, Check, []). + +ticket_pretty_encode_decode_only(Msg, Check, Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_encode_decode_only(Msg, Codec, Check, Conf). + +ticket_encode_decode_only(Msg, Codec, Conf) -> + Check = fun(_) -> ok end, + ticket_encode_decode_only(Msg, Codec, Check, Conf). + +ticket_encode_decode_only(Msg, Codec, Check, Conf0) -> + Conf = [?EC_V3|Conf0], + Encode = fun(M) -> encode_message(Codec, Conf, M) end, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + megaco_codec_test_lib:expect_encode_decode_only(Msg, Encode, Decode, + Check). + +%% -- + +ticket_pretty_decode_only(Msg) -> + ticket_pretty_decode_only(Msg, []). + +ticket_pretty_decode_only(Msg, Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_decode_only(Msg, Codec, Conf). + +ticket_decode_only(Msg, Codec, Conf) -> + Check = fun(_) -> ok end, + ticket_decode_only(Msg, Codec, Check, Conf). + +ticket_decode_only(Msg, Codec, Check, Conf0) -> + Conf = [?EC_V3|Conf0], + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + megaco_codec_test_lib:expect_decode_only(Msg, Decode, Check). + +ticket_check_decode_only_error_reason(R, Check) + when is_list(R) and is_function(Check) -> + case lists:keysearch(reason, 1, R) of + {value, {reason, Reason}} -> + Check(Reason); + false -> + {error, {reason_not_found, R}} + end. + + +%% -- + +ticket_compact_decode_error(Msg) -> + ticket_compact_decode_error(Msg, []). + +ticket_compact_decode_error(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + ticket_decode_error(Msg, Codec, Conf). + +ticket_pretty_decode_error(Msg) -> + ticket_pretty_decode_error(Msg, []). + +ticket_pretty_decode_error(Msg, Conf) when is_list(Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_decode_error(Msg, Codec, Conf); +ticket_pretty_decode_error(Msg, Check) when is_function(Check) -> + ticket_pretty_decode_error(Msg, [], Check). + +ticket_pretty_decode_error(Msg, Conf, Check) -> + Codec = megaco_pretty_text_encoder, + ticket_decode_error(Msg, Codec, Conf, Check). + +ticket_decode_error(Msg, Codec, Conf) -> + Check = fun(X) -> + d("decode error reason: ~n~p~n", [X]), + ok + end, % Only called when decode failes + ticket_decode_error(Msg, Codec, Conf, Check). + +ticket_decode_error(Msg, Codec, Conf0, Check) -> + Conf = [?EC_V3|Conf0], + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + megaco_codec_test_lib:expect_decode(Msg, Decode, Check). + +%% -- + +%% ticket_expect_exec(Instructions, Msg) -> +%% megaco_codec_test_lib:expect_exec(Instructions, Msg). + +%% ticket_expect_instruction(Desc, Cmd, Verify) -> +%% megaco_codec_test_lib:expect_instruction(Desc, Cmd, Verify). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% pretty_decode_message(DynamicDecode, Conf, Bin) -> +%% decode_message(megaco_pretty_text_encoder, DynamicDecode, Conf, Bin). + +%% compact_decode_message(DynamicDecode, Conf, Bin) -> +%% decode_message(megaco_compact_text_encoder, DynamicDecode, Conf, Bin). + +decode_message(Codec, DynamicDecode, Conf, Bin) -> + megaco_codec_test_lib:decode_message(Codec, DynamicDecode, ?VERSION, + Conf, Bin). + +%% pretty_encode_message(Conf, Msg) -> +%% encode_message(megaco_pretty_text_encoder, Conf, Msg). + +%% compact_encode_message(Conf, Msg) -> +%% encode_message(megaco_compact_text_encoder, Conf, Msg). + +encode_message(Codec, Conf, Msg) -> + megaco_codec_test_lib:encode_message(Codec, ?VERSION, Conf, Msg). + +test_msgs(Codec, DynamicDecode, Conf, Msgs) -> + megaco_codec_test_lib:test_msgs(Codec, DynamicDecode, ?VERSION, Conf, + fun chk_MegacoMessage/2, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +chk_MegacoMessage(M1, M2) -> + ?MSG_LIB:chk_MegacoMessage(M1, M2). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +cre_MegacoMessage(Mess) -> + ?MSG_LIB:cre_MegacoMessage(Mess). + +cre_MegacoMessage(Auth, Mess) -> + ?MSG_LIB:cre_MegacoMessage(Auth, Mess). + +cre_MegacoMessage(V, Mid, Body) -> + Mess = ?MSG_LIB:cre_Message(V, Mid, Body), + cre_MegacoMessage(Mess). + +cre_AuthHeader() -> + SecParmIdx = [239, 205, 171, 137], + SeqNum = [18, 52, 86, 120], + AD = [18, 52, 86, 120, 137, 171, 205, 239, 118, 84, 50, 16], + cre_AuthHeader(SecParmIdx, SeqNum, AD). + +cre_AuthHeader(Idx, Num, D) -> + ?MSG_LIB:cre_AuthenticationHeader(Idx, Num, D). + +cre_Msg(Mid, Body) -> + cre_Msg(?VERSION, Mid, Body). + +cre_Msg(V, Mid, Body) -> + ?MSG_LIB:cre_Message(V, Mid, Body). + +cre_TransId(TransId) -> + ?MSG_LIB:cre_TransactionId(TransId). + +cre_Trans(Trans) -> + ?MSG_LIB:cre_Transaction(Trans). + +cre_TransReq(TransId, Actions) -> + ?MSG_LIB:cre_TransactionRequest(TransId, Actions). + +cre_TransRep(TransId, Actions) -> + ?MSG_LIB:cre_TransactionReply(TransId, Actions). + +cre_TransAck(First, Last) -> + ?MSG_LIB:cre_TransactionAck(First, Last). + +cre_ActReq(CtxId, CmdReqs) -> + ?MSG_LIB:cre_ActionRequest(CtxId, CmdReqs). + +cre_ActRep(CtxId, CmdReps) -> + ?MSG_LIB:cre_ActionReply(CtxId, CmdReps). + +cre_ActRep(CtxId, ED, CR, CmdReps) -> + ?MSG_LIB:cre_ActionReply(CtxId, ED, CR, CmdReps). + +cre_CtxReq() -> + ?MSG_LIB:cre_ContextRequest(). + +cre_CtxReq(A) -> + ?MSG_LIB:cre_ContextRequest(A). + +cre_CtxReq(A, B) -> + ?MSG_LIB:cre_ContextRequest(A, B). + +cre_CtxReq(A, B, C) -> + ?MSG_LIB:cre_ContextRequest(A, B, C). + +cre_CtxReq(A, B, C, D) -> + ?MSG_LIB:cre_ContextRequest(A, B, C, D). + +cre_CtxReq(A, B, C, D, E) -> + ?MSG_LIB:cre_ContextRequest(A, B, C, D, E). + +cre_CtxReq(Prio, Em, Top, Ieps, CtxProp, CtxList) -> + ?MSG_LIB:cre_ContextRequest(Prio, Em, Top, Ieps, CtxProp, CtxList). + +cre_CtxAttrAuditReq() -> + ?MSG_LIB:cre_ContextAttrAuditRequest(). + +% cre_CtxAttrAuditReq(A) -> +% ?MSG_LIB:cre_ContextAttrAuditRequest(A). + +% cre_CtxAttrAuditReq(A, B) -> +% ?MSG_LIB:cre_ContextAttrAuditRequest(A, B). + +cre_CtxAttrAuditReq(A, B, C) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(A, B, C). + +cre_CtxAttrAuditReq(A, B, C, D) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(A, B, C, D). + +cre_CtxAttrAuditReq(A, B, C, D, E) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(A, B, C, D, E). + +cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, Ctx, SPrio) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx, SPrio). + +cre_CtxAttrAuditReq(A, B, C, D, E, F, G) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(A, B, C, D, E, F, G). + +cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, Ctx, SPrio, SEm, SIeps) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx, + SPrio, SEm, SIeps). + +cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, Ctx, SPrio, SEm, SIeps, SLog) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx, + SPrio, SEm, SIeps, SLog). + +cre_TopologyRequest(From, To, Dir) -> + ?MSG_LIB:cre_TopologyRequest(From, To, Dir). + +%% Ind Aud related: + +cre_IndAudParam(IAP) -> + ?MSG_LIB:cre_IndAuditParameter(IAP). + +cre_IndAudMediaDesc(D) -> + ?MSG_LIB:cre_IndAudMediaDescriptor(D). + +cre_IndAudStreamDesc(SID, SP) -> + ?MSG_LIB:cre_IndAudStreamDescriptor(SID, SP). + +cre_IndAudStreamParms(LCD) -> + ?MSG_LIB:cre_IndAudStreamParms(LCD). + +cre_IndAudLocalControlDesc(A, B, C, D) -> + ?MSG_LIB:cre_IndAudLocalControlDescriptor(A, B, C, D). + +cre_IndAudLocalControlDesc(SM, RV, RG, PP, SMS) -> + ?MSG_LIB:cre_IndAudLocalControlDescriptor(SM, RV, RG, PP, SMS). + +cre_IndAudPropertyParm(Name) -> + ?MSG_LIB:cre_IndAudPropertyParm(Name). + +cre_IndAudPropertyParm(Name, PP) -> + ?MSG_LIB:cre_IndAudPropertyParm(Name, PP). + +cre_IndAudTermStateDesc(PP) -> + ?MSG_LIB:cre_IndAudTerminationStateDescriptor(PP). + +cre_IndAudTermStateDesc(PP, EBC, SS) -> + ?MSG_LIB:cre_IndAudTerminationStateDescriptor(PP, EBC, SS). + +cre_IndAudTermStateDesc(PP, EBC, SS, SSS) -> + ?MSG_LIB:cre_IndAudTerminationStateDescriptor(PP, EBC, SS, SSS). + +cre_IndAudEvsDesc(RID, PN) + when is_integer(RID) -> + ?MSG_LIB:cre_IndAudEventsDescriptor(RID, PN). + +cre_IndAudEvBufDesc(EN, SID) -> + ?MSG_LIB:cre_IndAudEventBufferDescriptor(EN, SID). + +cre_IndAudSigsDesc(D) -> + ?MSG_LIB:cre_IndAudSignalsDescriptor(D). + +cre_IndAudSig(SN) -> + ?MSG_LIB:cre_IndAudSignal(SN). + +cre_IndAudSig(SN, SigRID) -> + ?MSG_LIB:cre_IndAudSignal(SN, SigRID). + +cre_IndAudSeqSigList(ID, SL) -> + ?MSG_LIB:cre_IndAudSeqSigList(ID, SL). + +cre_IndAudDigitMapDesc(DMN) -> + ?MSG_LIB:cre_IndAudDigitMapDescriptor(DMN). + +cre_IndAudStatsDesc(SN) -> + ?MSG_LIB:cre_IndAudStatisticsDescriptor(SN). + +cre_IndAudPkgsDesc(PN, PV) -> + ?MSG_LIB:cre_IndAudPackagesDescriptor(PN, PV). + +%% Parameter related +cre_PropParm(Name, Val) -> + ?MSG_LIB:cre_PropertyParm(Name, [Val]). + +cre_PropParm(Name, Vals, Tag, EI) -> + ?MSG_LIB:cre_PropertyParm(Name, Vals, Tag, EI). + + +%% Statistics related +cre_StatsDesc(SPs) -> + ?MSG_LIB:cre_StatisticsDescriptor(SPs). + +cre_StatsParm(Name) -> + ?MSG_LIB:cre_StatisticsParameter(Name). + +cre_StatsParm(Name, Val) -> + ?MSG_LIB:cre_StatisticsParameter(Name, [Val]). + + +% Event related +cre_EvParm(Name, Val) -> + ?MSG_LIB:cre_EventParameter(Name, Val). + +cre_ObsEv(Name, Not) -> + ?MSG_LIB:cre_ObservedEvent(Name, Not). +cre_ObsEv(Name, Not, Par) -> + ?MSG_LIB:cre_ObservedEvent(Name, Par, Not). + +cre_ReqEv(Name) -> + ?MSG_LIB:cre_RequestedEvent(Name). +cre_ReqEv(Name, EPL) -> + ?MSG_LIB:cre_RequestedEvent(Name, EPL). +cre_ReqEv(Name, SID, RA, EPL) -> + ?MSG_LIB:cre_RequestedEvent(Name, SID, RA, EPL). + + +cre_ObsEvsDesc(Id, EvList) -> + ?MSG_LIB:cre_ObservedEventsDescriptor(Id, EvList). + +cre_EvsDesc(Id, EvList) -> + ?MSG_LIB:cre_EventsDescriptor(Id, EvList). + + +%% Service change related +cre_SvcChParm(M, A, R, P) -> + ?MSG_LIB:cre_ServiceChangeParm(M, A, P, R). + +cre_SvcChParm(M, A, R, P, IF) -> + ?MSG_LIB:cre_ServiceChangeParm(M, A, asn1_NOVALUE, P, R, asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE, IF). + +cre_SvcChResParm(A, P) -> + ?MSG_LIB:cre_ServiceChangeResParm(A, P). + +cre_SvcChReq(Tids, P) -> + ?MSG_LIB:cre_ServiceChangeRequest(Tids, P). + +cre_SvcChProf(Name, Ver) -> + ?MSG_LIB:cre_ServiceChangeProfile(Name, Ver). + +cre_SvcChAddr(Tag, Val) -> + ?MSG_LIB:cre_ServiceChangeAddress(Tag, Val). + +cre_SvcChMethod(M) -> + ?MSG_LIB:cre_ServiceChangeMethod(M). + +cre_SvcChRep(Tids, Res) -> + ?MSG_LIB:cre_ServiceChangeReply(Tids, Res). + + +%% Stream related +cre_StreamID(Id) -> + ?MSG_LIB:cre_StreamID(Id). + +cre_StreamParms(Lcd) -> + ?MSG_LIB:cre_StreamParms(Lcd). +cre_StreamParms(Lcd, Ld) -> + ?MSG_LIB:cre_StreamParms(Lcd, Ld). +cre_StreamParms(Lcd, Ld, Rd) -> + ?MSG_LIB:cre_StreamParms(Lcd, Ld, Rd). +cre_StreamParmsL(Ld) -> + ?MSG_LIB:cre_StreamParms(asn1_NOVALUE, Ld, asn1_NOVALUE). +cre_StreamParmsR(Rd) -> + ?MSG_LIB:cre_StreamParms(asn1_NOVALUE, asn1_NOVALUE, Rd). + +cre_StreamDesc(Id, P) -> + ?MSG_LIB:cre_StreamDescriptor(Id, P). + + +%% "Local" related +cre_LocalControlDesc(Mode) -> + ?MSG_LIB:cre_LocalControlDescriptor(Mode). +cre_LocalControlDesc(Mode, Parms) -> + ?MSG_LIB:cre_LocalControlDescriptor(Mode, Parms). + +cre_LocalRemoteDesc(Grps) -> + ?MSG_LIB:cre_LocalRemoteDescriptor(Grps). + + +%% DigitMap related +cre_DigitMapDesc() -> + ?MSG_LIB:cre_DigitMapDescriptor(). +cre_DigitMapDesc(NameOrVal) -> + ?MSG_LIB:cre_DigitMapDescriptor(NameOrVal). +cre_DigitMapDesc(Name, Val) -> + ?MSG_LIB:cre_DigitMapDescriptor(Name, Val). + +cre_DigitMapValue(Body) -> + ?MSG_LIB:cre_DigitMapValue(Body). + +cre_DigitMapValue(Body, Start, Short, Long) -> + ?MSG_LIB:cre_DigitMapValue(Start, Short, Long, Body). + +%% Media related +cre_MediaDesc(SD) when is_record(SD, 'StreamDescriptor') -> + cre_MediaDesc([SD]); +cre_MediaDesc(SDs) -> + ?MSG_LIB:cre_MediaDescriptor(SDs). + + +%% Notify related +cre_NotifyReq(Tids, EvsDesc) -> + ?MSG_LIB:cre_NotifyRequest(Tids, EvsDesc). + +cre_NotifyRep(Tids) -> + ?MSG_LIB:cre_NotifyReply(Tids). + + +%% Subtract related +cre_SubReq(Tids, Desc) -> + ?MSG_LIB:cre_SubtractRequest(Tids, Desc). + + +%% Audit related +cre_AuditDesc(Tokens) -> + ?MSG_LIB:cre_AuditDescriptor(Tokens). + +cre_AuditDesc(Tokens, PropertTokens) -> + ?MSG_LIB:cre_AuditDescriptor(Tokens, PropertTokens). + +cre_AuditReq(Tid, Desc) -> + ?MSG_LIB:cre_AuditRequest(Tid, Desc). + +cre_AuditRep(AR) -> + ?MSG_LIB:cre_AuditReply(AR). + +cre_AuditRes(Tid, Res) -> + ?MSG_LIB:cre_AuditResult(Tid, Res). + +cre_TermAudit(ARP) -> + ?MSG_LIB:cre_TerminationAudit(ARP). + +cre_AuditRetParam(D) -> + ?MSG_LIB:cre_AuditReturnParameter(D). + +cre_TermListAuditRes(TIDs, TA) -> + ?MSG_LIB:cre_TermListAuditResult(TIDs, TA). + +%% AMM/AMMS related +cre_AmmDesc(D) -> + ?MSG_LIB:cre_AmmDescriptor(D). + +cre_AmmReq(Tids, Descs) -> + ?MSG_LIB:cre_AmmRequest(Tids, Descs). + +cre_AmmsReply(Tids) -> + ?MSG_LIB:cre_AmmsReply(Tids). +cre_AmmsReply(Tids, Descs) -> + ?MSG_LIB:cre_AmmsReply(Tids, Descs). + + +%% Command related +cre_Cmd(Tag, Req) -> + ?MSG_LIB:cre_Command(Tag, Req). + +cre_CmdReq(Cmd) -> + ?MSG_LIB:cre_CommandRequest(Cmd). + +cre_CmdRep(Tag, Rep) -> + ?MSG_LIB:cre_CommandReply(Tag, Rep). + + +%% Actions related +cre_ReqActs(A) -> + ?MSG_LIB:cre_RequestedActions(A). + +cre_ReqActs(KA, EDM, SE, SD, NB, RED) -> + ?MSG_LIB:cre_RequestedActions(KA, EDM, SE, SD, NB, RED). + +%% cre_SecReqActs() -> +%% ?MSG_LIB:cre_SecondRequestedActions(). + +%% cre_SecReqActs(A) -> +%% ?MSG_LIB:cre_SecondRequestedActions(A). + +cre_SecReqActs(KA, EDM, SD, NB, RED) -> + ?MSG_LIB:cre_SecondRequestedActions(KA, EDM, SD, NB, RED). + +cre_EvDM(Name) when is_list(Name) -> + ?MSG_LIB:cre_EventDM(Name). + +cre_RegEmbedDesc() -> + ?MSG_LIB:cre_RegulatedEmbeddedDescriptor(). + +cre_RegEmbedDesc(D) -> + ?MSG_LIB:cre_RegulatedEmbeddedDescriptor(D). + +cre_RegEmbedDesc(SED, SD) -> + ?MSG_LIB:cre_RegulatedEmbeddedDescriptor(SED, SD). + +%% cre_SecEvsDesc(REDs) -> +%% ?MSG_LIB:cre_SecondEventsDescriptor(REDs). + +cre_SecEvsDesc(RID, REDs) -> + ?MSG_LIB:cre_SecondEventsDescriptor(RID, REDs). + +cre_SecReqEv(N) -> + cre_SecReqEv(N, []). + +cre_SecReqEv(N, EPL) -> + ?MSG_LIB:cre_SecondRequestedEvent(N, EPL). + +cre_SecReqEv(N, SID, EA) when is_list(N) andalso + is_integer(SID) andalso + is_record(EA, 'SecondRequestedActions') -> + cre_SecReqEv(N, SID, EA, []); +cre_SecReqEv(A, B, C) -> + ?MSG_LIB:cre_SecondRequestedEvent(A, B, C). + +cre_SecReqEv(N, SID, EA, EPL) -> + ?MSG_LIB:cre_SecondRequestedEvent(N, SID, EA, EPL). + +%% Signal related +cre_SigsDesc() -> + cre_SigsDesc([]). + +cre_SigsDesc(SRs) -> + ?MSG_LIB:cre_SignalsDescriptor(SRs). + +cre_SigDir(D) -> + ?MSG_LIB:cre_SignalDirection(D). + +cre_Sig(Name) -> + cre_Sig(Name, []). + +cre_Sig(Name, SPL) -> + ?MSG_LIB:cre_Signal(Name, SPL). + +cre_Sig(Name, Dir, RID) -> + cre_Sig(Name, [], Dir, RID). + +cre_Sig(Name, SPL, Dir, RID) -> + cre_Sig(Name, asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE, + asn1_NOVALUE, SPL, Dir, RID). + +cre_Sig(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID) -> + ?MSG_LIB:cre_Signal(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID). + +cre_Sig(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID, ISD) -> + ?MSG_LIB:cre_Signal(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID, ISD). + +cre_SigReq(S) -> + ?MSG_LIB:cre_SignalRequest(S). + +cre_NotifBehav(Tag, Val) -> + ?MSG_LIB:cre_NotifyBehaviour(Tag, Val). + +cre_NotifCompl(NC) -> + ?MSG_LIB:cre_NotifyCompletion(NC). + +cre_SigType(ST) -> + ?MSG_LIB:cre_SignalType(ST). + + +%% Others +cre_ErrCode(EC) -> + ?MSG_LIB:cre_ErrorCode(EC). + +cre_ErrDesc(EC) -> + ?MSG_LIB:cre_ErrorDescriptor(EC). + +cre_TermIDList(TIDs) -> + ?MSG_LIB:cre_TerminationIDList(TIDs). + +cre_ServiceState(SS) -> + ?MSG_LIB:cre_ServiceState(SS). + +cre_StreamMode(SS) -> + ?MSG_LIB:cre_StreamMode(SS). + +cre_SelectLogic(Tag) -> + ?MSG_LIB:cre_SelectLogic(Tag). + +cre_CtxID(CID) -> + ?MSG_LIB:cre_ContextID(CID). + +cre_ReqID(RID) -> + ?MSG_LIB:cre_RequestID(RID). + +cre_TimeNot(D,T) -> + ?MSG_LIB:cre_TimeNotation(D, T). + +cre_PkgsItem(Name, Ver) -> + ?MSG_LIB:cre_PackagesItem(Name, Ver). + +cre_BOOLEAN(B) -> + ?MSG_LIB:cre_BOOLEAN(B). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_init(Config) -> + megaco_codec_flex_lib:init(Config). + +flex_finish(Config) -> + megaco_codec_flex_lib:finish(Config). + +flex_scanner_conf(Config) -> + megaco_codec_flex_lib:scanner_conf(Config). + +%% start_flex_scanner() -> +%% megaco_codec_flex_lib:start(). + +%% stop_flex_scanner(Pid) -> +%% megaco_codec_flex_lib:stop(Pid). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +t(F,A) -> + p(printable(get(severity),trc),trc,F,A). + +d(F,A) -> + p(printable(get(severity),dbg),dbg,F,A). + +%% l(F,A) -> +%% p(printable(get(severity),log),log,F,A). + +e(F,A) -> + p(printable(get(severity),err),err,F,A). + + +printable(trc,_) -> + true; +printable(dbg,trc) -> + false; +printable(dbg,_) -> + true; +printable(log,log) -> + true; +printable(log,err) -> + true; +printable(err,err) -> + true; +printable(_,_) -> + false. + + +p(true,L,F,A) -> + io:format("~s:" ++ F ++ "~n", [image_of(L)|A]); +p(_,_,_,_) -> + ok. + +image_of(trc) -> + "TRC"; +image_of(dbg) -> + "DBG"; +image_of(log) -> + "LOG"; +image_of(err) -> + "ERR"; +image_of(L) -> + io_lib:format("~p",[L]). + diff --git a/lib/megaco/test/megaco_codec_test.erl b/lib/megaco/test/megaco_codec_test.erl new file mode 100644 index 0000000000..d247959cc5 --- /dev/null +++ b/lib/megaco/test/megaco_codec_test.erl @@ -0,0 +1,63 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test application config +%%---------------------------------------------------------------------- + +-module(megaco_codec_test). + +-compile(export_all). + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + +%% Test server callbacks +init_per_testcase(Case, Config) -> + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + megaco_test_lib:fin_per_testcase(Case, Config). + +init() -> + process_flag(trap_exit, true), + megaco_test_lib:flush(). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top test case + +all(suite) -> + [ + codec + ]. + +codec(suite) -> + [{megaco_codec_mini_test, all}, + {megaco_codec_v1_test, all}, + {megaco_codec_v2_test, all}, + {megaco_codec_prev3a_test, all}, + {megaco_codec_prev3b_test, all}, + {megaco_codec_prev3c_test, all}, + {megaco_codec_v3_test, all}]. + diff --git a/lib/megaco/test/megaco_codec_test_lib.erl b/lib/megaco/test/megaco_codec_test_lib.erl new file mode 100644 index 0000000000..66e8a52a24 --- /dev/null +++ b/lib/megaco/test/megaco_codec_test_lib.erl @@ -0,0 +1,1024 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test library module for Megaco/H.248 encode/decode +%%---------------------------------------------------------------------- + +-module(megaco_codec_test_lib). + +%% ---- + +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). +-include("megaco_test_lib.hrl"). + +%% ---- + +-export([ + skip/1, + + display_text_messages/2, display_text_messages/3, + generate_text_messages/4, + test_msgs/6, + + plain_decode_encode/5, + plain_encode_decode/5, + trans_first_encode_decode/5, + actions_first_encode_decode/5, + action_first_encode_decode/5, + + encode_message/4, + decode_message/5, decode_message/6, + + expect_instruction/3, + expect_encode/3, + expect_encode_only/3, + expect_encode_decode/4, + expect_encode_decode_only/4, + expect_decode/3, + expect_decode_only/3, + expect_decode_encode/4, + expect_decode_encode_only/4, + expect_exec/2 + ]). + + +-record(expect_instruction, + { + %% Short description of what this instruction does + description, % string() + + %% The actual instruction + command, % function(Data) -> term() + + %% Verification function of the instruction + verify % function(Res, Data) -> {ok, NewData} | {error, Reason} + } + ). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +display_text_messages(V, Msgs) -> + display_text_messages(V, [], Msgs). + +display_text_messages(_, _, []) -> + ok; +display_text_messages(V, EC, [{Name, Msg, _ED, _Conf}|Msgs]) -> + (catch display_text_message(Name, EC, Msg, V)), + display_text_messages(V, EC, Msgs). + + +display_text_message(Name, EC, Msg, V) when is_tuple(Msg) -> + io:format("~n(Erlang) message ~p:~n~p~n", [Name, Msg]), + case (catch megaco_pretty_text_encoder:encode_message(EC,V,Msg)) of + {'EXIT', _R} -> + io:format("~nPretty encoded: failed (exit)~n", []); + {error, {{deprecated, PWhat}, _}} -> + io:format("~nPretty encoded: deprecated~n~p~n", [PWhat]), + throw(continue); + {error, PReason} -> + io:format("~nPretty encoded: failed (error)~n~p~n", [PReason]), + throw(continue); + {ok, Pretty} -> + io:format("~nPretty encoded:~n~s~n", [binary_to_list(Pretty)]) + end, + case (catch megaco_compact_text_encoder:encode_message(EC,V,Msg)) of + {'EXIT', _} -> + io:format("~nCompact encoded: failed~n", []); + {error, {{deprecated, CWhat}, _}} -> + io:format("~nPretty encoded: deprecated~n~p~n", [CWhat]); + {ok, Compact} -> + io:format("~nCompact encoded:~n~s~n", [binary_to_list(Compact)]) + end; +display_text_message(_, _, _, _) -> + skipping. + +generate_text_messages(DirName, V, EC, Msgs) when is_atom(DirName) -> + generate_text_messages(atom_to_list(DirName), V, EC, Msgs); +generate_text_messages(DirName, V, EC, Msgs) when is_list(DirName) -> + DirPath = filename:join(["/tmp", DirName]), + case file:make_dir(DirPath) of + ok -> + generate_text_messages2(DirPath, V, EC, Msgs); + {error, eexist} -> + generate_text_messages2(DirPath, V, EC, Msgs); + {error, Reason} -> + io:format("Failed creating directory ~s: ~p~n", [DirPath, Reason]), + ok + end. + +generate_text_messages2(_, _, _, []) -> + ok; +generate_text_messages2(Dir, V, EC, [{Name, Msg, _ED, _Conf}|Msgs]) -> + (catch generate_text_message(Dir, Name, EC, Msg, V)), + generate_text_messages2(Dir, V, EC, Msgs). + +generate_text_message(Dir, Name, EC, Msg, V) -> + io:format("~p: ", [Name]), + case (catch megaco_pretty_text_encoder:encode_message(EC,V,Msg)) of + {'EXIT', EReason} -> + io:format("failed encoding [exit]: ~n~p~n", [EReason]), + throw(continue); + {error, {{deprecated, PWhat}, _}} -> + io:format("failed encoding [deprecated]: ~n~p~n", [PWhat]), + throw(continue); + {error, PReason} -> + io:format("failed encoding [error]: ~n~p~n", [PReason]), + throw(continue); + {ok, Pretty} -> + io:format("encoded", []), + FName = filename:flatten([Name, ".txt"]), + Filename = filename:join([Dir, FName]), + case (catch file:open(Filename, [write])) of + {ok, Fd} -> + io:format(Fd, "~s", [binary_to_list(Pretty)]), + io:format(" - written to disk~n", []), + (catch file:close(Fd)), + ok; + {error, OReason} -> + io:format(" - failed writing to disk: " + "~n~p~n~s~n", + [OReason, binary_to_list(Pretty)]), + throw(continue) + end + end. + +test_msgs(Codec, DynamicDecode, Ver, EC, Check, Msgs) + when is_function(Check) andalso is_list(Msgs) -> + io:format("~n", []), + test_msgs(Codec, DynamicDecode, Ver, EC, Check, Msgs, []). + +test_msgs(_Codec, _DD, _Ver, _EC, _Check, [], []) -> + ok; +test_msgs(_Codec, _DD, _Ver, _EC, _Check, [], Errs) -> + ?ERROR(lists:reverse(Errs)); +test_msgs(Codec, DD, Ver, EC, Check, + [{Name, {error, Error}, _ED, _Conf}|Msgs], Acc) -> + io:format("error~n", []), + test_msgs(Codec, DD, Ver, EC, Check, Msgs, [{Name, Error}|Acc]); +test_msgs(Codec, DD, Ver, EC, Check, + [{Name, Msg, ED, Conf}|Msgs], Acc) -> + Dbg = test_msgs_debug(Conf), + put(dbg, Dbg), + io:format("~-16w ", [Name]), + case (catch encode_decode(ED, Check, Codec, DD, Ver, EC, Msg)) of + ok -> + io:format("ok~n", []), + erase(dbg), + test_msgs(Codec, DD, Ver, EC, Check, Msgs, Acc); + Error -> + io:format("error~n", []), + erase(dbg), + test_msgs(Codec, DD, Ver, EC, Check, Msgs, [{Name, Error}|Acc]) + end. + +test_msgs_debug(Conf) -> + case lists:keysearch(dbg, 1, Conf) of + {value, {dbg, true}} -> + true; + _ -> + false + end. + +encode_decode(Func, Check, Codec, DynamicDecode, Ver, EC, Msg1) + when is_function(Func) -> + d("encode_decode -> entry with" + "~n Func: ~p" + "~n Check: ~p" + "~n Codec: ~p" + "~n DynamicDecode: ~p" + "~n Ver: ~p" + "~n EC: ~p", + [Func, Check, Codec, DynamicDecode, Ver, EC]), + case (catch Func(Codec, DynamicDecode, Ver, EC, Msg1)) of + {ok, Msg1} -> + d("encode_decode -> expected result"), + ok; + {ok, Msg2} -> + d("encode_decode -> unexpected result - check"), + case (catch Check(Msg1, Msg2)) of + ok -> + d("encode_decode -> check - ok"), + ok; + {error, Reason} -> + d("encode_decode -> check - error: " + "~n Reason: ~p", [Reason]), + {error, {Reason, Msg1, Msg2}}; + Else -> + d("encode_decode -> check - failed: " + "~n Else: ~p", [Else]), + {error, {invalid_check_result, Else}} + end; + Else -> + d("encode_decode -> failed: " + "~n Else: ~p", [Else]), + Else + end. + + +%% *** plain_encode_decode *** + +plain_encode_decode(Codec, DynamicDecode, Ver, EC, M1) -> + d("plain_encode_decode -> entry with" + "~n Codec: ~p" + "~n DynamicDecode: ~p" + "~n Ver: ~p" + "~n EC: ~p", [Codec, DynamicDecode, Ver, EC]), + case (catch encode_message(Codec, Ver, EC, M1)) of + {ok, Bin} -> + d("plain_encode_decode -> encode - ok"), + decode_message(Codec, DynamicDecode, Ver, EC, Bin, true); + Error -> + d("plain_encode_decode -> encode - failed: " + "~n Error: ~p", [Error]), + Error + end. + + +%% *** plain_decode_encode *** + +plain_decode_encode(Codec, DynamicDecode, Ver, EC, M) when is_list(M) -> + Bin = list_to_binary(M), + plain_decode_encode(Codec, DynamicDecode, Ver, EC, Bin); +plain_decode_encode(Codec, DynamicDecode, Ver, EC, B) when is_binary(B) -> + case (catch decode_message(Codec, DynamicDecode, Ver, EC, B, true)) of + {ok, M} -> + encode_message(Codec, Ver, EC, M); + Error -> + Error + end. + + +%% *** trans_first_encode_decode *** + +trans_first_encode_decode(Codec, DynamicDecode, Ver, EC, M1) -> + d("trans_first_encode_decode -> entry"), + case (catch trans_first_encode_message(Codec, Ver, EC, M1)) of + {ok, Bin} -> + decode_message(Codec, DynamicDecode, Ver, EC, Bin, true); + Error -> + Error + end. + +trans_first_encode_message(Codec, Ver, EC, M1) -> + d("trans_first_encode_message -> entry"), + Mess1 = M1#'MegacoMessage'.mess, + {transactions, Trans1} = Mess1#'Message'.messageBody, + Trans2 = encode_transactions(Codec, Ver, EC, Trans1), + Mess2 = Mess1#'Message'{messageBody = {transactions, Trans2}}, + M2 = M1#'MegacoMessage'{mess = Mess2}, + encode_message(Codec, Ver, EC, M2). + +encode_transactions(Codec, Ver, EC, Trans) when is_list(Trans) -> + d("encode_transactions -> entry"), + [encode_transaction(Codec, Ver, EC, T) || T <- Trans]. + +encode_transaction(Codec, Ver, EC, T) -> + d("encode_transaction -> entry"), + case (catch Codec:encode_transaction(EC, Ver, T)) of + {ok, EncodecTransactions} -> + EncodecTransactions; + Error -> + throw({error, {transaction_encode_failed, Error, T}}) + end. + + +%% *** actions_first_encode_decode *** + +actions_first_encode_decode(Codec, DynamicDecode, Ver, EC, M1) -> + d("actions_first_encode_decode -> entry"), + case (catch actions_first_encode_message(Codec, Ver, EC, M1)) of + {ok, Bin} -> + decode_message(Codec, DynamicDecode, Ver, EC, Bin, true); + Error -> + Error + end. + +actions_first_encode_message(Codec, Ver, EC, M1) -> + d("actions_first_encode_message -> entry"), + Mess1 = M1#'MegacoMessage'.mess, + {transactions, Trans1} = Mess1#'Message'.messageBody, + Trans2 = encode_actions(Codec, Ver, EC, Trans1), + Mess2 = Mess1#'Message'{messageBody = {transactions, Trans2}}, + M2 = M1#'MegacoMessage'{mess = Mess2}, + encode_message(Codec, Ver, EC, M2). + +encode_actions(Codec, Ver, EC, Trans) when is_list(Trans) -> + d("encode_actions -> entry"), + [encode_actions1(Codec, Ver, EC, T) || T <- Trans]. + +encode_actions1(Codec, Ver, EC, {transactionRequest, TR1}) -> + d("encode_actions1 -> entry"), + #'TransactionRequest'{actions = ARs} = TR1, + case (catch encode_action_requests(Codec, Ver, EC, ARs)) of + {ok, EncodedARs} -> + TR2 = TR1#'TransactionRequest'{actions = EncodedARs}, + {transactionRequest, TR2}; + Error -> + throw({error, {actions_encode_failed, Error, TR1}}) + end. + +encode_action_requests(Codec, Ver, EC, ARs) -> + d("encode_action_requests -> entry"), + Codec:encode_action_requests(EC, Ver, ARs). + + +%% *** action_first_encode_decode *** + +action_first_encode_decode(Codec, DynamicDecode, Ver, EC, M1) -> + d("action_first_encode_decode -> entry"), + case (catch action_first_encode_message(Codec, Ver, EC, M1)) of + {ok, Bin} -> + decode_message(Codec, DynamicDecode, Ver, EC, Bin, true); + Error -> + Error + end. + +action_first_encode_message(Codec, Ver, EC, M1) -> + d("action_first_encode_message -> entry"), + Mess1 = M1#'MegacoMessage'.mess, + {transactions, Trans1} = Mess1#'Message'.messageBody, + Trans2 = encode_action(Codec, Ver, EC, Trans1), + Mess2 = Mess1#'Message'{messageBody = {transactions, Trans2}}, + M2 = M1#'MegacoMessage'{mess = Mess2}, + encode_message(Codec, Ver, EC, M2). + +encode_action(Codec, Ver, EC, Trans) when is_list(Trans) -> + d("encode_action -> entry"), + [encode_action1(Codec, Ver, EC, T) || T <- Trans]. + +encode_action1(Codec, Ver, EC, {transactionRequest, TR1}) -> + d("encode_action1 -> entry"), + #'TransactionRequest'{actions = ARs1} = TR1, + ARs2 = [encode_action_request(Codec, Ver, EC, AR) || AR <- ARs1], + TR2 = TR1#'TransactionRequest'{actions = ARs2}, + {transactionRequest, TR2}. + +encode_action_request(Codec, Ver, EC, AR) -> + d("encode_action_request -> entry"), + case (catch Codec:encode_action_request(EC, Ver, AR)) of + {ok, Bin} -> + Bin; + Error -> + throw({error, {encode_action_request_failed, Error, AR}}) + end. + + +encode_message(Codec, Ver, EC, M) -> + d("encode_message -> entry with" + "~n Codec: ~p" + "~n Ver: ~p" + "~n EC: ~p" + "~n M: ~p", [Codec, Ver, EC, M]), +%% case (catch Codec:encode_message(EC, Ver, M)) of +%% {ok, Bin} -> +%% d("encode_message -> encode - ok: " +%% "~n~s", [binary_to_list(Bin)]), +%% {ok, Bin}; +%% Error -> +%% d("encode_message -> encode - failed"), +%% throw({error, {message_encode_failed, Error, M}}) +%% end. + case (catch timer:tc(Codec, encode_message, [EC, Ver, M])) of + {Time, {ok, Bin}} -> + d("encode_message -> encode - ok after ~p: " + "~n~s", [Time, binary_to_list(Bin)]), + {ok, Bin}; + {_Time, Error} -> + d("encode_message -> encode - failed"), + throw({error, {message_encode_failed, Error, M}}) + end. + +decode_message(Codec, Dynamic, Ver, EC, M) -> + decode_message(Codec, Dynamic, Ver, EC, M, false). + +decode_message(Codec, true, _Ver, EC, M, _Timed) -> + d("decode_message -> entry - when using dynamic"), + Codec:decode_message(EC, dynamic, M); +decode_message(Codec, _, Ver, EC, M, false) -> + d("decode_message -> entry with" + "~n Codec: ~p" + "~n Ver: ~p" + "~n EC: ~p", [Codec, Ver, EC]), + Codec:decode_message(EC, Ver, M); +decode_message(Codec, _, Ver, EC, M, true) -> + d("decode_message -> entry with" + "~n Codec: ~p" + "~n Ver: ~p" + "~n EC: ~p", [Codec, Ver, EC]), + {Time, Result} = timer:tc(Codec, decode_message, [EC, Ver, M]), + io:format("~-8w", [Time]), + Result. + + +%% ======================================================================= + +%% ------------------------------------------------------------------ +%% Create an instruction record +%% ------------------------------------------------------------------ + +expect_instruction(Desc, Cmd, Verify) + when is_list(Desc) andalso is_function(Cmd) andalso is_function(Verify) -> + #expect_instruction{description = Desc, + command = Cmd, + verify = Verify}. + + +%% ------------------------------------------------------------------ +%% Function: expect_encode +%% Parameters: Msg -> MegacoMessage +%% Encode -> function/1 +%% Check -> function/1 +%% Description: This function simply encodes, with the Encode fun, +%% and expects this to fail. The failure reason is +%% checked with the Check fun. +%% ------------------------------------------------------------------ + +expect_encode(InitialData, Encode, Check) + when is_function(Encode) andalso is_function(Check) -> + Instructions = + [ + %% Initial encode + expect_instruction( + "Encode (initial) message", + fun(Msg) when is_record(Msg, 'MegacoMessage') -> + (catch Encode(Msg)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({error, Reason}, _) -> + io:format("check error reason ", []), + case (catch Check(Reason)) of + ok -> + {ok, done}; + Error -> + Error + end; + ({ok, Bin}, Msg) when is_binary(Bin) -> + M = binary_to_list(Bin), + {error, {unexpected_encode_success, {M, Msg}}}; + (Crap, _) -> + {error, {unexpected_encode_result, Crap}} + end) + ], + expect_exec(Instructions, InitialData). + + +%% ------------------------------------------------------------------ +%% Function: expect_encode_only +%% Parameters: InitialData -> list() | binary() +%% Encode -> function/1 +%% Check -> function/1 +%% Description: This function simply encodes, with the Encode fun, +%% and expects it to succeed, which is checked by +%% calling the Check fun with the resulting message. +%% ------------------------------------------------------------------ + +expect_encode_only(InitialData, Encode, Check) + when is_function(Encode) andalso is_function(Check) -> + Instructions = + [ + %% Initial encode + expect_instruction( + "Encode (initial) message", + fun(Msg) when is_record(Msg, 'MegacoMessage') -> + (catch Encode(Msg)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Bin}, _Msg) when is_binary(Bin) -> + case (catch Check(Bin)) of + ok -> + {ok, done}; + Error -> + Error + end; + (Crap, _) -> + {error, {unexpected_encode_result, Crap}} + end) + ], + expect_exec(Instructions, InitialData). + + +%% ------------------------------------------------------------------ +%% Function: expect_encode_decode +%% Parameters: InitialData -> MegacoMessage +%% Encode -> function/1 +%% Decode -> function/1 +%% Check -> function/2 +%% Description: This function simply encodes, with the Encode fun, and +%% then decodes, with the Decode fun, the megaco message. +%% The resulting message should be identical, but if it +%% is not, the messages are checked, with the Check fun. +%% ------------------------------------------------------------------ + +expect_encode_decode(InitialData, Encode, Decode, Check) + when is_function(Encode) andalso + is_function(Decode) andalso + is_function(Check) -> + Instructions = + [ + %% Initial encode + expect_instruction( + "Encode (initial) message", + fun(M) when is_record(M, 'MegacoMessage') -> + (catch Encode(M)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Bin}, M) when is_binary(Bin) -> + {ok, {Bin, M}}; + ({error, Reason}, _) -> + {error, {unexpected_encode_failure, Reason}}; + (Crap, _) -> + {error, {unexpected_encode_result, Crap}} + end), + + %% Decode the (encoded) message + expect_instruction( + "Decode message", + fun({Bin, _}) when is_binary(Bin) -> + (catch Decode(Bin)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Msg1}, {_Bin, Msg1}) + when is_record(Msg1, 'MegacoMessage') -> + io:format("messages identical - done ", []), + {ok, done}; + ({ok, Msg2}, {_Bin, Msg1}) -> + io:format("messages not identical - check - ", []), + case (catch Check(Msg1, Msg2)) of + ok -> + io:format("equal ", []), + {ok, done}; + Error -> + io:format("not equal ", []), + io:format("~nError: ~p~n", [Error]), + Error + end; + (Crap, _) -> + {error, {unexpected_decode_result, Crap}} + end) + ], + expect_exec(Instructions, InitialData). + + +%% ------------------------------------------------------------------ +%% Function: expect_encode_decode_only +%% Parameters: InitialData -> MegacoMessage +%% Encode -> function/1 +%% Decode -> function/1 +%% Check -> function/2 +%% Description: This function simply encodes, with the Encode fun, +%% and then decodes, with the Decode fun, the megaco +%% message and expects it to succeed. The resulting +%% message is checked by calling the Check fun with the +%% resulting message. +%% ------------------------------------------------------------------ + +expect_encode_decode_only(InitialData, Encode, Decode, Check) + when is_function(Encode) andalso + is_function(Decode) andalso + is_function(Check) -> + Instructions = + [ + %% Initial encode + expect_instruction( + "Encode (initial) message", + fun(M) when is_record(M, 'MegacoMessage') -> + (catch Encode(M)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Bin}, M) when is_binary(Bin) -> + {ok, {Bin, M}}; + ({error, Reason}, _) -> + {error, {unexpected_encode_failure, Reason}}; + (Crap, _) -> + {error, {unexpected_encode_result, Crap}} + end), + + %% Decode the (encoded) message + expect_instruction( + "Decode message", + fun({Bin, _}) when is_binary(Bin) -> + (catch Decode(Bin)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Msg}, _B) when is_record(Msg, 'MegacoMessage') -> + io:format("decoded - now check ", []), + case (catch Check(Msg)) of + ok -> + {ok, done}; + Error -> + Error + end; + ({error, R}, _) -> + {Line, Mod, Reason} = + case lists:keysearch(reason, 1, R) of + {value, {reason, {L, M, Raw}}} + when is_list(Raw) -> + {L, M, lists:flatten(Raw)}; + {value, {reason, {L, M, Raw}}} -> + {L, M, Raw}; + _ -> + {-1, undefined, R} + end, + Tokens = + case lists:keysearch(token, 1, R) of + {value, {token, T}} -> + T; + _ -> + undefined + end, + {error, {unexpected_decode_failure, + {Mod, Line, Reason, Tokens}}}; + (Crap, _) -> + {error, {unexpected_decode_result, Crap}} + end) + ], + expect_exec(Instructions, InitialData). + + +%% ------------------------------------------------------------------ +%% Function: expect_decode +%% Parameters: InitialData -> list() | binary() +%% Decode -> function/1 +%% Check -> function/1 +%% Description: This function simply decodes, with the Decode fun, +%% and expects this to fail. The failure reason is +%% checked with the Check fun. +%% ------------------------------------------------------------------ + +expect_decode(InitialData, Decode, Check) + when is_list(InitialData) -> + expect_decode(list_to_binary(InitialData), Decode, Check); +expect_decode(InitialData, Decode, Check) + when is_function(Decode) andalso is_function(Check) -> + Instructions = + [ + %% Initial decode + expect_instruction( + "Decode (initial) message", + fun(Bin) when is_binary(Bin) -> + (catch Decode(Bin)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({error, Reason}, _) -> + io:format("check error reason - ", []), + case (catch Check(Reason)) of + ok -> + {ok, done}; + Error -> + Error + end; + ({ok, Msg}, Bin) -> + io:format("unexpected decode success - ", []), + M = binary_to_list(Bin), + {error, {unexpected_decode_success, {Msg, M}}}; + (Crap, _) -> + {error, {unexpected_decode_result, Crap}} + end) + ], + expect_exec(Instructions, InitialData). + + +%% ------------------------------------------------------------------ +%% Function: expect_decode_only +%% Parameters: InitialData -> list() | binary() +%% Decode -> function/1 +%% Check -> function/2 +%% Description: This function simply decodes, with the Decode fun, +%% and expects it to succeed, which is checked by +%% calling the Check fun with the resulting message. +%% ------------------------------------------------------------------ + +expect_decode_only(InitialData, Decode, Check) + when is_list(InitialData) -> + expect_decode_only(list_to_binary(InitialData), Decode, Check); +expect_decode_only(InitialData, Decode, Check) + when is_function(Decode) andalso is_function(Check) -> + Instructions = + [ + %% Initial decode + expect_instruction( + "Decode (initial) message", + fun(B) when is_binary(B) -> + (catch Decode(B)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Msg}, _B) when is_record(Msg, 'MegacoMessage') -> + case (catch Check(Msg)) of + ok -> + {ok, done}; + Error -> + Error + end; + ({error, R}, _) -> + {Line, Mod, Reason} = + case lists:keysearch(reason, 1, R) of + {value, {reason, {L, M, Raw}}} + when is_list(Raw) -> + {L, M, lists:flatten(Raw)}; + {value, {reason, {L, M, Raw}}} -> + {L, M, Raw}; + _ -> + {-1, undefined, R} + end, + Tokens = + case lists:keysearch(token, 1, R) of + {value, {token, T}} -> + T; + _ -> + undefined + end, + {error, {unexpected_decode_failure, + {Mod, Line, Reason, Tokens}}}; + (Crap, _) -> + {error, {unexpected_decode_result, Crap}} + end) + ], + expect_exec(Instructions, InitialData). + + +%% ------------------------------------------------------------------ +%% Function: expect_decode_encode +%% Parameters: InitialData -> list() | binary() +%% Decode -> function/1 +%% Encode -> function/1 +%% Check -> function/2 +%% Description: This function simply decodes, with the Decode fun, +%% and then encodes, with the Encode fun, the megaco +%% message. The resulting binary message should be +%% identical, but if it is not, the messages are +%% decoded again and then if necessary checked, with +%% the Check fun. +%% ------------------------------------------------------------------ + +expect_decode_encode(InitialData, Decode, Encode, Check) + when is_list(InitialData) -> + expect_decode_encode(list_to_binary(InitialData), Decode, Encode, Check); +expect_decode_encode(InitialData, Decode, Encode, Check) + when is_function(Decode) andalso + is_function(Encode) andalso + is_function(Check) -> + Instructions = + [ + %% Initial decode + expect_instruction( + "Decode (initial) message", + fun(B) when is_binary(B) -> + (catch Decode(B)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Msg}, B) when is_record(Msg, 'MegacoMessage') -> + {ok, {Msg, B}}; + ({error, R}, _) -> + {Line, Mod, Reason} = + case lists:keysearch(reason, 1, R) of + {value, {reason, {L, M, Raw}}} + when is_list(Raw) -> + {L, M, lists:flatten(Raw)}; + {value, {reason, {L, M, Raw}}} -> + {L, M, Raw}; + _ -> + {-1, undefined, R} + end, + Tokens = + case lists:keysearch(token, 1, R) of + {value, {token, T}} -> + T; + _ -> + undefined + end, + {error, {unexpected_decode_failure, + {Mod, Line, Reason, Tokens}}}; + (Crap, _) -> + {error, {unexpected_decode_result, Crap}} + end), + + + %% Encode the (decoded) message + expect_instruction( + "Encode message", + fun({Msg, _Bin}) when is_record(Msg, 'MegacoMessage') -> + (catch Encode(Msg)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, B}, {_, B}) -> + io:format("binaries equal - done ", []), + {ok, done}; + ({ok, B}, {Msg, _}) -> + {ok, {Msg, B}}; + ({error, Reason}, _) -> + {error, {unexpected_encode_failure, Reason}}; + (Crap, _) -> + {error, {unexpected_encode_result, Crap}} + end), + + + %% Fallback instruction in case encode produced + %% a binary not equal to the initial + expect_instruction( + "Decode message (if binaries not equal)", + fun(done) -> + done; + ({_Msg, B}) when is_binary(B) -> + (catch Decode(B)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Msg}, {Msg, _Bin}) when is_record(Msg, 'MegacoMessage') -> + io:format("messages identical - done ", []), + {ok, done}; + (done, _) -> + io:format("done ", []), + {ok, done}; + ({ok, Msg2}, {Msg1, _}) -> + io:format("messages not identical - check - ", []), + case (catch Check(Msg1, Msg2)) of + ok -> + io:format("equal ", []), + {ok, done}; + Error -> + io:format("not equal ", []), + Error + end; + ({error, Reason}, _) -> + {error, {unexpected_decode_failure, Reason}}; + (Crap, _) -> + {error, {unexpected_decode_result, Crap}} + end) + ], + expect_exec(Instructions, InitialData). + + +%% ------------------------------------------------------------------ +%% Function: expect_decode_encode_only +%% Parameters: InitialData -> list() | binary() +%% Decode -> function/1 +%% Encode -> function/1 +%% Check -> function/2 +%% Description: This function simply decodes, with the Decode fun, +%% and then encodes, with the Encode fun, the megaco +%% message. The resulting binary message is then checked +%% with the Check fun. +%% ------------------------------------------------------------------ + +expect_decode_encode_only(InitialData, Decode, Encode, Check) + when is_list(InitialData) -> + expect_decode_encode_only(list_to_binary(InitialData), + Decode, Encode, Check); +expect_decode_encode_only(InitialData, Decode, Encode, Check) + when is_function(Decode) andalso + is_function(Encode) andalso + is_function(Check) -> + Instructions = + [ + %% Initial decode + expect_instruction( + "Decode (initial) message", + fun(B) when is_binary(B) -> + (catch Decode(B)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Msg}, B) when is_record(Msg, 'MegacoMessage') -> + {ok, {Msg, B}}; + ({error, R}, _) -> + {Line, Mod, Reason} = + case lists:keysearch(reason, 1, R) of + {value, {reason, {L, M, Raw}}} + when is_list(Raw) -> + {L, M, lists:flatten(Raw)}; + {value, {reason, {L, M, Raw}}} -> + {L, M, Raw}; + _ -> + {-1, undefined, R} + end, + Tokens = + case lists:keysearch(token, 1, R) of + {value, {token, T}} -> + T; + _ -> + undefined + end, + {error, {unexpected_decode_failure, + {Mod, Line, Reason, Tokens}}}; + (Crap, _) -> + {error, {unexpected_decode_result, Crap}} + end), + + + %% Encode the (decoded) message + expect_instruction( + "Encode message", + fun({Msg, _Bin}) when is_record(Msg, 'MegacoMessage') -> + (catch Encode(Msg)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, B2}, {_, B1}) -> + io:format("encode ok - check bins - ", []), + case (catch Check(B1, B2)) of + ok -> + {ok, done}; + Crap -> + {error, {unexpected_encode_check_result, Crap}} + end; + ({error, Reason}, _) -> + {error, {unexpected_encode_failure, Reason}}; + (Crap, _) -> + {error, {unexpected_encode_result, Crap}} + end) + ], + expect_exec(Instructions, InitialData). + + + +%% ------------------------------------------------------------------ +%% Function: expect_exec +%% Parameters: Instructions -> [instruction()] +%% InitialData -> term() +%% Description: This function is the engine in the codec test +%% cases. It executes each instruction in turn. +%% ------------------------------------------------------------------ + +expect_exec(Instructions, InitialData) -> + expect_exec(Instructions, InitialData, 1). + +expect_exec([], _, _) -> + io:format("~n", []), + ok; +expect_exec([#expect_instruction{description = Desc, + command = Cmd, + verify = Verify}|T], Data, Num) -> + io:format("~n Exec command ~w: ~s => ", [Num, Desc]), + case Verify((catch Cmd(Data)), Data) of + {ok, NewData} -> + io:format("ok", []), + expect_exec(T, NewData, Num+1); + {error, Reason} -> + io:format("error", []), + {error, {Num, Desc, Reason}} + end. + +%% ======================================================================= + +skip({What, Why}) when is_atom(What) andalso is_list(Why) -> + Reason = lists:flatten(io_lib:format("~p: ~s", [What, Why])), + exit({skipped, Reason}); +skip({What, Why}) -> + Reason = lists:flatten(io_lib:format("~p: ~p", [What, Why])), + exit({skipped, Reason}); +skip(Reason) when is_list(Reason) -> + exit({skipped, Reason}); +skip(Reason1) -> + Reason2 = lists:flatten(io_lib:format("~p", [Reason1])), + exit({skipped, Reason2}). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% ------------------------------------------------------------------ +%% Internal functions +%% ------------------------------------------------------------------ + + +d(F) -> + d(F, []). + +d(F, A) -> + d(get(dbg), F, A). + +d(true, F, A) -> + io:format("DBG:~w:" ++ F ++ "~n", [?MODULE|A]); +d(_, _, _) -> + ok. + diff --git a/lib/megaco/test/megaco_codec_v1_test.erl b/lib/megaco/test/megaco_codec_v1_test.erl new file mode 100644 index 0000000000..7f2af37282 --- /dev/null +++ b/lib/megaco/test/megaco_codec_v1_test.erl @@ -0,0 +1,7305 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test encoding/decoding (codec) module of Megaco/H.248 v1 +%%---------------------------------------------------------------------- + +-module(megaco_codec_v1_test). + +%% ---- + +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). +-include("megaco_test_lib.hrl"). + +%% ---- + +%% -export([msg/0]). +-export([msgs/0]). +-export([rfc3525_msgs_display/0, rfc3525_msgs_test/0]). + +-export([t/0, t/1]). + +-export([all/1, + + text/1, + + pretty/1, + pretty_test_msgs/1, + + compact/1, + compact_test_msgs/1, + + flex_pretty/1, + flex_pretty_init/1, + flex_pretty_finish/1, + flex_pretty_test_msgs/1, + + flex_compact/1, + flex_compact_init/1, + flex_compact_finish/1, + flex_compact_test_msgs/1, + flex_compact_dm_timers1/1, + flex_compact_dm_timers2/1, + flex_compact_dm_timers3/1, + flex_compact_dm_timers4/1, + flex_compact_dm_timers5/1, + flex_compact_dm_timers6/1, + + binary/1, + + bin/1, + bin_test_msgs/1, + + ber/1, + ber_test_msgs/1, + + ber_bin/1, + ber_bin_test_msgs/1, + + per/1, + per_test_msgs/1, + + per_bin/1, + per_bin_test_msgs/1, + + erl_dist/1, + erl_dist_m/1, + erl_dist_m_test_msgs/1, + + tickets/0, + tickets/1, + + compact_tickets/1, + compact_otp4011_msg1/1, + compact_otp4011_msg2/1, + compact_otp4011_msg3/1, + compact_otp4013_msg1/1, + compact_otp4085_msg1/1, + compact_otp4085_msg2/1, + compact_otp4280_msg1/1, + compact_otp4299_msg1/1, + compact_otp4299_msg2/1, + compact_otp4359_msg1/1, + compact_otp4920_msg0/1, + compact_otp4920_msg1/1, + compact_otp4920_msg2/1, + compact_otp4920_msg3/1, + compact_otp4920_msg4/1, + compact_otp4920_msg5/1, + compact_otp4920_msg6/1, + compact_otp4920_msg7/1, + compact_otp4920_msg8/1, + compact_otp4920_msg9/1, + compact_otp4920_msg10/1, + compact_otp4920_msg11/1, + compact_otp4920_msg12/1, + compact_otp4920_msg20/1, + compact_otp4920_msg21/1, + compact_otp4920_msg22/1, + compact_otp4920_msg23/1, + compact_otp4920_msg24/1, + compact_otp4920_msg25/1, + compact_otp5186_msg01/1, + compact_otp5186_msg02/1, + compact_otp5186_msg03/1, + compact_otp5186_msg04/1, + compact_otp5186_msg05/1, + compact_otp5186_msg06/1, + compact_otp5793_msg01/1, + compact_otp5993_msg01/1, + compact_otp5993_msg02/1, + compact_otp5993_msg03/1, + compact_otp6017_msg01/1, + compact_otp6017_msg02/1, + compact_otp6017_msg03/1, + + flex_compact_tickets/1, + flex_compact_otp7431_msg01a/1, + flex_compact_otp7431_msg01b/1, + flex_compact_otp7431_msg02/1, + flex_compact_otp7431_msg03/1, + flex_compact_otp7431_msg04/1, + flex_compact_otp7431_msg05/1, + flex_compact_otp7431_msg06/1, + flex_compact_otp7431_msg07/1, + + pretty_tickets/1, + pretty_otp4632_msg1/1, + pretty_otp4632_msg2/1, + pretty_otp4632_msg3/1, + pretty_otp4632_msg4/1, + pretty_otp4710_msg1/1, + pretty_otp4710_msg2/1, + pretty_otp4945_msg1/1, + pretty_otp4945_msg2/1, + pretty_otp4945_msg3/1, + pretty_otp4945_msg4/1, + pretty_otp4945_msg5/1, + pretty_otp4945_msg6/1, + pretty_otp4949_msg1/1, + pretty_otp4949_msg2/1, + pretty_otp4949_msg3/1, + pretty_otp5042_msg1/1, + pretty_otp5068_msg1/1, + pretty_otp5085_msg1/1, + pretty_otp5085_msg2/1, + pretty_otp5085_msg3/1, + pretty_otp5085_msg4/1, + pretty_otp5085_msg5/1, + pretty_otp5085_msg6/1, + pretty_otp5085_msg7/1, + pretty_otp5600_msg1/1, + pretty_otp5600_msg2/1, + pretty_otp5601_msg1/1, + pretty_otp5793_msg01/1, + pretty_otp5882_msg01/1, + pretty_otp6490_msg01/1, + pretty_otp6490_msg02/1, + pretty_otp6490_msg03/1, + pretty_otp6490_msg04/1, + pretty_otp6490_msg05/1, + pretty_otp6490_msg06/1, + pretty_otp7671_msg01/1, + pretty_otp7671_msg02/1, + pretty_otp7671_msg03/1, + pretty_otp7671_msg04/1, + pretty_otp7671_msg05/1, + + flex_pretty_tickets/1, + flex_pretty_otp5042_msg1/1, + flex_pretty_otp5085_msg1/1, + flex_pretty_otp5085_msg2/1, + flex_pretty_otp5085_msg3/1, + flex_pretty_otp5085_msg4/1, + flex_pretty_otp5085_msg5/1, + flex_pretty_otp5085_msg6/1, + flex_pretty_otp5085_msg7/1, + flex_pretty_otp5600_msg1/1, + flex_pretty_otp5600_msg2/1, + flex_pretty_otp5601_msg1/1, + flex_pretty_otp5793_msg01/1, + flex_pretty_otp7431_msg01/1, + flex_pretty_otp7431_msg02/1, + flex_pretty_otp7431_msg03/1, + flex_pretty_otp7431_msg04/1, + flex_pretty_otp7431_msg05/1, + flex_pretty_otp7431_msg06/1, + flex_pretty_otp7431_msg07/1, + + init_per_testcase/2, fin_per_testcase/2]). + +-export([display_text_messages/0, generate_text_messages/0]). + + +-export([msg15b/0, msg22f/0]). + +-export([ + %% Decode + profile_decode_compact_text_message/1, + profile_decode_compact_text_messages/0, + prof1/0, prof2/0, + profile_decode_compact_flex_text_message/1, + profile_decode_compact_flex_text_messages/0, + profile_decode_pretty_text_message/1, + profile_decode_pretty_text_messages/0, + profile_decode_pretty_flex_text_message/1, + profile_decode_pretty_flex_text_messages/0, + + %% Encode + profile_encode_compact_text_messages/0, + profile_encode_pretty_text_messages/0 + ]). + + +%% ---- + +-define(V1, v1). +-define(EC, []). +-define(VERSION, 1). +-define(VERSION_STR, "1"). +-define(DEFAULT_PORT, 55555). +-define(MSG_LIB, megaco_test_msg_v1_lib). +-define(MG1_MID_NO_PORT, {ip4Address, + #'IP4Address'{address = [124, 124, 124, 222]}}). +-define(MG1_MID, {ip4Address, #'IP4Address'{address = [124, 124, 124, 222], + portNumber = ?DEFAULT_PORT}}). +-define(MG2_MID, {ip4Address, #'IP4Address'{address = [125, 125, 125, 111], + portNumber = ?DEFAULT_PORT}}). +-define(MG3_MID, {ip6Address, #'IP6Address'{address = [0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 125, 125, 125, 111], + portNumber = ?DEFAULT_PORT}}). +-define(MGC_MID, {ip4Address, #'IP4Address'{address = [123, 123, 123, 4], + portNumber = ?DEFAULT_PORT}}). + +-define(A4444, ["11111111", "00000000", "00000000"]). +-define(A4445, ["11111111", "00000000", "11111111"]). +-define(A5555, ["11111111", "11111111", "00000000"]). +-define(A5556, ["11111111", "11111111", "11111111"]). + + +%% ---- + +display_text_messages() -> + Msgs = + msgs1() ++ + msgs3(), + megaco_codec_test_lib:display_text_messages(?VERSION, Msgs). + + +generate_text_messages() -> + Msgs = + msgs1(), + megaco_codec_test_lib:generate_text_messages(?V1, ?VERSION, ?EC, Msgs). + + +%% ---- + +prof1() -> + megaco_codec_v1_test:profile_decode_compact_text_message(msg10). + +prof2() -> + megaco_codec_v1_test:profile_decode_compact_flex_text_message(msg10). + +%% (catch megaco_codec_v1_test:profile_decode_compact_text_message(msg01a)). +%% (catch megaco_codec_v1_test:profile_decode_compact_text_message(msg01b)). +%% (catch megaco_codec_v1_test:profile_decode_compact_text_message(msg02)). +%% (catch megaco_codec_v1_test:profile_decode_compact_text_message(msg10)). +%% (catch megaco_codec_v1_test:profile_decode_compact_text_message(msg11)). +%% (catch megaco_codec_v1_test:profile_decode_compact_text_message(msg12)). +%% (catch megaco_codec_v1_test:profile_decode_compact_text_message(msg13)). +profile_decode_compact_text_message(MsgTag) when is_atom(MsgTag) -> + Config = [], + Slogan = list_to_atom("decode_compact_v1_" ++ atom_to_list(MsgTag)), + profile_decode_compact_text_message(Slogan, Config, MsgTag). + +profile_decode_compact_flex_text_message(MsgTag) when is_atom(MsgTag) -> + Conf = flex_init([]), + Config = flex_scanner_conf(Conf), + Slogan = list_to_atom("decode_compact_flex_v1_" ++ atom_to_list(MsgTag)), + Res = profile_decode_compact_text_message(Slogan, [Config], MsgTag), + flex_finish(Conf), + Res. + +profile_decode_compact_text_message(Slogan, Config, MsgTag) -> + Codec = megaco_compact_text_encoder, + profile_decode_text_message(Slogan, Codec, Config, MsgTag). + +%% (catch megaco_codec_v1_test:profile_decode_pretty_text_message(msg01a)). +%% (catch megaco_codec_v1_test:profile_decode_pretty_text_message(msg01b)). +%% (catch megaco_codec_v1_test:profile_decode_pretty_text_message(msg02)). +profile_decode_pretty_text_message(MsgTag) when is_atom(MsgTag) -> + Config = [], + Slogan = list_to_atom("decode_pretty_v1_" ++ atom_to_list(MsgTag)), + profile_decode_pretty_text_message(Slogan, Config, MsgTag). + +profile_decode_pretty_flex_text_message(MsgTag) when is_atom(MsgTag) -> + Conf = flex_init([]), + Config = flex_scanner_conf(Conf), + Slogan = list_to_atom("decode_pretty_flex_v1_" ++ atom_to_list(MsgTag)), + Res = profile_decode_pretty_text_message(Slogan, [Config], MsgTag), + flex_finish(Conf), + Res. + +profile_decode_pretty_text_message(Slogan, Config, MsgTag) -> + Codec = megaco_pretty_text_encoder, + profile_decode_text_message(Slogan, Codec, Config, MsgTag). + +profile_decode_text_message(Slogan, Codec, Config, MsgTag) -> + Msgs = msgs1(), + case lists:keysearch(MsgTag, 1, Msgs) of + {value, Msg} -> + [Res] = profile_decode_text_messages(Slogan, Codec, Config, [Msg]), + Res; + false -> + {error, {no_such_message, MsgTag}} + end. + + +%% (catch megaco_codec_v1_test:profile_decode_compact_text_messages()). +profile_decode_compact_text_messages() -> + Config = [], + Slogan = decode_compact_v1, + profile_decode_compact_text_messages(Slogan, Config). + +%% (catch megaco_codec_v1_test:profile_decode_compact_flex_text_messages()). +profile_decode_compact_flex_text_messages() -> + Conf = flex_init([]), + Config = flex_scanner_conf(Conf), + Slogan = decode_compact_flex_v1, + Res = profile_decode_compact_text_messages(Slogan, [Config]), + flex_finish(Conf), + Res. + +profile_decode_compact_text_messages(Slogan, Config) -> + Codec = megaco_compact_text_encoder, + profile_decode_text_messages(Slogan, Codec, Config). + +%% (catch megaco_codec_v1_test:profile_decode_pretty_text_messages()). +profile_decode_pretty_text_messages() -> + Config = [], + Slogan = decode_pretty_v1, + profile_decode_pretty_text_messages(Slogan, Config). + +%% (catch megaco_codec_v1_test:profile_decode_pretty_flex_text_messages()). +profile_decode_pretty_flex_text_messages() -> + Conf = flex_init([]), + Config = flex_scanner_conf(Conf), + Slogan = decode_pretty_flex_v1, + Res = profile_decode_pretty_text_messages(Slogan, [Config]), + flex_finish(Conf), + Res. + + +profile_decode_pretty_text_messages(Slogan, Config) -> + Codec = megaco_pretty_text_encoder, + profile_decode_text_messages(Slogan, Codec, Config). + +profile_decode_text_messages(Slogan, Codec, Config) -> + Msgs = msgs1(), + profile_decode_text_messages(Slogan, Codec, Config, Msgs). + +profile_decode_text_messages(Slogan, Codec, Config, Msgs0) -> + Msgs = [Msg || {_, Msg, _, _} <- Msgs0], + EncodeRes = encode_text_messages(Codec, Config, Msgs, []), + Bins = [Bin || {ok, Bin} <- EncodeRes], + Fun = fun() -> + decode_text_messages(Codec, Config, Bins, []) + end, + %% Make a dry run, just to make sure all modules are loaded: + io:format("make a dry run..~n", []), + (catch Fun()), + io:format("make the run..~n", []), + megaco_profile:profile(Slogan, Fun). + +%% (catch megaco_codec_v1_test:profile_encode_compact_text_messages()). +profile_encode_compact_text_messages() -> + Codec = megaco_compact_text_encoder, + Config = [], + Slogan = encode_compact_v1, + profile_encode_text_messages(Slogan, Codec, Config). + +%% (catch megaco_codec_v1_test:profile_encode_pretty_text_messages()). +profile_encode_pretty_text_messages() -> + Codec = megaco_pretty_text_encoder, + Config = [], + Slogan = encode_pretty_v1, + profile_encode_text_messages(Slogan, Codec, Config). + +profile_encode_text_messages(Slogan, Codec, Config) -> + Msgs = msgs1(), + profile_encode_text_messages(Slogan, Codec, Config, Msgs). + +profile_encode_text_messages(Slogan, Codec, Config, Msgs0) -> + Msgs = [Msg || {_, Msg, _, _} <- Msgs0], + Fun = fun() -> + encode_text_messages(Codec, Config, Msgs, []) + end, + %% Make a dry run, just to make sure all modules are loaded: + io:format("make a dry run...~n", []), + (catch Fun()), + io:format("make the run...~n", []), + megaco_profile:profile(Slogan, Fun). + +encode_text_messages(_Codec, _Config, [], Acc) -> + Acc; +encode_text_messages(Codec, Config, [Msg|Msgs], Acc) -> + Res = Codec:encode_message(Config, ?VERSION, Msg), + encode_text_messages(Codec, Config, Msgs, [Res | Acc]). + +decode_text_messages(_Codec, _Config, [], Acc) -> + Acc; +decode_text_messages(Codec, Config, [Msg|Msgs], Acc) -> + Res = Codec:decode_message(Config, dynamic, Msg), + decode_text_messages(Codec, Config, Msgs, [Res | Acc]). + + +%% ---- + +expand(RootCase) -> + expand([RootCase], []). + +expand([], Acc) -> + lists:flatten(lists:reverse(Acc)); +expand([Case|Cases], Acc) -> + case (catch apply(?MODULE,Case,[suite])) of + [] -> + expand(Cases, [Case|Acc]); + C when is_list(C) -> + expand(Cases, [expand(C, [])|Acc]); + _ -> + expand(Cases, [Case|Acc]) + end. + + +%% ---- + +tickets() -> + Flag = process_flag(trap_exit, true), + Cases = expand(tickets), + Fun = fun(Case) -> + C = init_per_testcase(Case, [{tc_timeout, + timer:minutes(10)}]), + io:format("Eval ~w~n", [Case]), + Result = + case (catch apply(?MODULE, Case, [C])) of + {'EXIT', Reason} -> + io:format("~n~p exited:~n ~p~n", + [Case, Reason]), + {error, {Case, Reason}}; + Res -> + Res + end, + fin_per_testcase(Case, C), + Result + end, + process_flag(trap_exit, Flag), + lists:map(Fun, Cases). + + +%% ---- + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + +init_per_testcase(Case, Config) -> + %% CaseString = io_lib:format("~p", [Case]), + C = + case lists:suffix("time_test", atom_to_list(Case)) of + true -> + [{tc_timeout, timer:minutes(10)}|Config]; + false -> + put(verbosity,trc), + Config + end, + megaco_test_lib:init_per_testcase(Case, C). + +fin_per_testcase(Case, Config) -> + erase(verbosity), + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top test case + +all(suite) -> + [ + text, + binary, + erl_dist, + tickets + ]. + +text(suite) -> + [ + pretty, + flex_pretty, + compact, + flex_compact + ]. + +binary(suite) -> + [ + bin, + ber, + ber_bin, + per, + per_bin + ]. + +erl_dist(suite) -> + [ + erl_dist_m + ]. + +pretty(suite) -> + [ + pretty_test_msgs + ]. + + +compact(suite) -> + [ + compact_test_msgs + ]. + + +flex_pretty(suite) -> + {req, [], + {conf, flex_pretty_init, flex_pretty_cases(), flex_pretty_finish}}. + +flex_pretty_cases() -> + [ + flex_pretty_test_msgs + ]. + + +flex_compact(suite) -> + {req, [], + {conf, flex_compact_init, flex_compact_cases(), flex_compact_finish}}. + +flex_compact_cases() -> + [ + flex_compact_test_msgs, + + flex_compact_dm_timers1, + flex_compact_dm_timers2, + flex_compact_dm_timers3, + flex_compact_dm_timers4, + flex_compact_dm_timers5, + flex_compact_dm_timers6 + ]. + + +bin(suite) -> + [ + bin_test_msgs + ]. + + +ber(suite) -> + [ + ber_test_msgs + ]. + + +ber_bin(suite) -> + [ + ber_bin_test_msgs + ]. + + +per(suite) -> + [ + per_test_msgs + ]. + + +%% Support for per_bin was added to ASN.1 as of version +%% 1.3.2 (R8). And later merged into 1.3.1.3 (R7). These +%% releases are identical (as far as I know). +%% +per_bin(suite) -> + [ + per_bin_test_msgs + ]. + +erl_dist_m(suite) -> + [ + erl_dist_m_test_msgs + ]. + +tickets(suite) -> + [ + compact_tickets, + pretty_tickets, + flex_compact_tickets, + flex_pretty_tickets + ]. + + +compact_tickets(suite) -> + [ + compact_otp4011_msg1, + compact_otp4011_msg2, + compact_otp4011_msg3, + compact_otp4013_msg1, + compact_otp4085_msg1, + compact_otp4085_msg2, + compact_otp4280_msg1, + compact_otp4299_msg1, + compact_otp4299_msg2, + compact_otp4359_msg1, + compact_otp4920_msg0, + compact_otp4920_msg1, + compact_otp4920_msg2, + compact_otp4920_msg3, + compact_otp4920_msg4, + compact_otp4920_msg5, + compact_otp4920_msg6, + compact_otp4920_msg7, + compact_otp4920_msg8, + compact_otp4920_msg9, + compact_otp4920_msg10, + compact_otp4920_msg11, + compact_otp4920_msg12, + compact_otp4920_msg20, + compact_otp4920_msg21, + compact_otp4920_msg22, + compact_otp4920_msg23, + compact_otp4920_msg24, + compact_otp4920_msg25, + compact_otp5186_msg01, + compact_otp5186_msg02, + compact_otp5186_msg03, + compact_otp5186_msg04, + compact_otp5186_msg05, + compact_otp5186_msg06, + compact_otp5793_msg01, + compact_otp5993_msg01, + compact_otp5993_msg02, + compact_otp5993_msg03, + compact_otp6017_msg01, + compact_otp6017_msg02, + compact_otp6017_msg03 + ]. + +flex_compact_tickets(suite) -> + {req, [], + {conf, flex_compact_init, flex_compact_tickets_cases(), + flex_compact_finish}}. + +flex_compact_tickets_cases() -> + [ + flex_compact_otp7431_msg01a, + flex_compact_otp7431_msg01b, + flex_compact_otp7431_msg02, + flex_compact_otp7431_msg03, + flex_compact_otp7431_msg04, + flex_compact_otp7431_msg05, + flex_compact_otp7431_msg06, + flex_compact_otp7431_msg07 + ]. + + +pretty_tickets(suite) -> + [ + pretty_otp4632_msg1, + pretty_otp4632_msg2, + pretty_otp4632_msg3, + pretty_otp4632_msg4, + pretty_otp4710_msg1, + pretty_otp4710_msg2, + pretty_otp4945_msg1, + pretty_otp4945_msg2, + pretty_otp4945_msg3, + pretty_otp4945_msg4, + pretty_otp4945_msg5, + pretty_otp4945_msg6, + pretty_otp4949_msg1, + pretty_otp4949_msg2, + pretty_otp4949_msg3, + pretty_otp5042_msg1, + pretty_otp5068_msg1, + pretty_otp5085_msg1, + pretty_otp5085_msg2, + pretty_otp5085_msg3, + pretty_otp5085_msg4, + pretty_otp5085_msg5, + pretty_otp5085_msg6, + pretty_otp5085_msg7, + pretty_otp5600_msg1, + pretty_otp5600_msg2, + pretty_otp5601_msg1, + pretty_otp5793_msg01, + pretty_otp5882_msg01, + pretty_otp6490_msg01, + pretty_otp6490_msg02, + pretty_otp6490_msg03, + pretty_otp6490_msg04, + pretty_otp6490_msg05, + pretty_otp6490_msg06, + pretty_otp7671_msg01, + pretty_otp7671_msg02, + pretty_otp7671_msg03, + pretty_otp7671_msg04, + pretty_otp7671_msg05 + ]. + +flex_pretty_tickets(suite) -> + {req, [], + {conf, flex_pretty_init, flex_pretty_tickets_cases(), + flex_pretty_finish}}. + +flex_pretty_tickets_cases() -> + [ + flex_pretty_otp5042_msg1, + flex_pretty_otp5085_msg1, + flex_pretty_otp5085_msg2, + flex_pretty_otp5085_msg3, + flex_pretty_otp5085_msg4, + flex_pretty_otp5085_msg5, + flex_pretty_otp5085_msg6, + flex_pretty_otp5085_msg7, + flex_pretty_otp5600_msg1, + flex_pretty_otp5600_msg2, + flex_pretty_otp5601_msg1, + flex_pretty_otp5793_msg01, + flex_pretty_otp7431_msg01, + flex_pretty_otp7431_msg02, + flex_pretty_otp7431_msg03, + flex_pretty_otp7431_msg04, + flex_pretty_otp7431_msg05, + flex_pretty_otp7431_msg06, + flex_pretty_otp7431_msg07 + ]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +pretty_test_msgs(suite) -> + []; +pretty_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1() ++ msgs2() ++ msgs3(), + DynamicDecode = false, + test_msgs(megaco_pretty_text_encoder, DynamicDecode, [], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_pretty_init(Config) -> + flex_init(Config). + +flex_pretty_finish(Config) -> + flex_finish(Config). + + +flex_pretty_test_msgs(suite) -> + []; +flex_pretty_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + %% Msgs = msgs1(), + Msgs = msgs1() ++ msgs2() ++ msgs3(), + Conf = flex_scanner_conf(Config), + DynamicDecode = false, + test_msgs(megaco_pretty_text_encoder, DynamicDecode, [Conf], Msgs). + +flex_pretty_otp5042_msg1(suite) -> + []; +flex_pretty_otp5042_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5042_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp5042_msg1(), + Bin0 = list_to_binary(Msg0), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_pretty_text_encoder, false, [Conf], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {_, _Mod, {not_an_integer, PropertyParm}} -> + exit({not_an_integer, PropertyParm}); + _ -> + io:format("flex_pretty_otp5042_msg1 -> " + "~n Reason: ~w" + "~n", [Reason]), + exit({unexpected_decode_result, Reason}) + end; + {ok, M} -> + t("flex_pretty_otp5042_msg1 -> successfull decode:" + "~n~p", [M]), + ok + end. + + +flex_pretty_otp5085_msg1(suite) -> + []; +flex_pretty_otp5085_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg1(), [Conf]). + +flex_pretty_otp5085_msg2(suite) -> + []; +flex_pretty_otp5085_msg2(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(error, pretty_otp5085_msg2(), [Conf]). + +flex_pretty_otp5085_msg3(suite) -> + []; +flex_pretty_otp5085_msg3(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg3(), [Conf]). + +flex_pretty_otp5085_msg4(suite) -> + []; +flex_pretty_otp5085_msg4(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg4(), [Conf]). + +flex_pretty_otp5085_msg5(suite) -> + []; +flex_pretty_otp5085_msg5(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg5(), [Conf]). + +flex_pretty_otp5085_msg6(suite) -> + []; +flex_pretty_otp5085_msg6(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg6(), [Conf]). + +flex_pretty_otp5085_msg7(suite) -> + []; +flex_pretty_otp5085_msg7(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg7(), [Conf]). + +flex_pretty_otp5600_msg1(suite) -> + []; +flex_pretty_otp5600_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5600_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5600(ok, pretty_otp5600_msg1(), [Conf]). + +flex_pretty_otp5600_msg2(suite) -> + []; +flex_pretty_otp5600_msg2(Config) when is_list(Config) -> + d("flex_pretty_otp5600_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5600(ok, pretty_otp5600_msg2(), [Conf]). + +flex_pretty_otp5601_msg1(suite) -> + []; +flex_pretty_otp5601_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5601_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5601(ok, pretty_otp5601_msg1(), [Conf]). + +flex_pretty_otp5793_msg01(suite) -> + []; +flex_pretty_otp5793_msg01(Config) when is_list(Config) -> + d("flex_pretty_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5793(ok, pretty_otp5793_msg1(), [Conf]). + +flex_pretty_otp7431_msg01(suite) -> + []; +flex_pretty_otp7431_msg01(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(ok, flex_pretty_otp7431_msg1(), [Conf]). + +flex_pretty_otp7431_msg02(suite) -> + []; +flex_pretty_otp7431_msg02(Config) when is_list(Config) -> +%% put(severity,trc), +%% put(dbg,true), + d("flex_pretty_otp7431_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg2(), [Conf]). + +flex_pretty_otp7431_msg03(suite) -> + []; +flex_pretty_otp7431_msg03(Config) when is_list(Config) -> +%% put(severity,trc), +%% put(dbg,true), + d("flex_pretty_otp7431_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg3(), [Conf]). + +flex_pretty_otp7431_msg04(suite) -> + []; +flex_pretty_otp7431_msg04(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg04 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg4(), [Conf]). + +flex_pretty_otp7431_msg05(suite) -> + []; +flex_pretty_otp7431_msg05(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg05 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg5(), [Conf]). + +flex_pretty_otp7431_msg06(suite) -> + []; +flex_pretty_otp7431_msg06(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg06 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg6(), [Conf]). + +flex_pretty_otp7431_msg07(suite) -> + []; +flex_pretty_otp7431_msg07(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg07 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg7(), [Conf]). + +flex_pretty_otp7431(Expected, Msg, Conf) -> + otp7431(Expected, megaco_pretty_text_encoder, Msg, Conf). + +otp7431(Expected, Codec, Msg0, Conf) -> + Bin0 = list_to_binary(Msg0), + case decode_message(Codec, false, Conf, Bin0) of + {ok, _Msg1} when Expected =:= ok -> + io:format(" decoded", []), + ok; + {error, {bad_property_parm, Reason}} when (Expected =:= error) andalso + is_list(Reason) -> + io:format("expected result: ~s", [Reason]), + ok; + Else -> + io:format("unexpected result", []), + exit({unexpected_decode_result, Else}) + end. + + +flex_pretty_otp7431_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a=recvonly + } ; RTP profile for G.723.1 is 4 + } + } + } + } +}". + +flex_pretty_otp7431_msg2() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a= } + } + } + } + } +}". + +flex_pretty_otp7431_msg3() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a } + } + } + } + } +}". + +flex_pretty_otp7431_msg4() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a} + } + } + } + } +}". + +flex_pretty_otp7431_msg5() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { +v= } + } + } + } + } +}". + +flex_pretty_otp7431_msg6() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { +v } + } + } + } + } +}". + +flex_pretty_otp7431_msg7() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { +v} + } + } + } + } +}". + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +compact_test_msgs(suite) -> + []; +compact_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1() ++ msgs2() ++ msgs3(), + DynamicDecode = false, + test_msgs(megaco_compact_text_encoder, DynamicDecode, [], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_compact_init(Config) -> + flex_init(Config). + + +flex_compact_finish(Config) -> + flex_finish(Config). + + +flex_compact_test_msgs(suite) -> + []; +flex_compact_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1() ++ msgs2() ++ msgs3(), + %% Msgs = msgs1(), + Conf = flex_scanner_conf(Config), + DynamicDecode = true, + test_msgs(megaco_compact_text_encoder, DynamicDecode, [Conf], Msgs). + + +flex_compact_dm_timers1(suite) -> + []; +flex_compact_dm_timers1(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("1", "2", "3"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, [Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers1 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers(1,2,3, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers2(suite) -> + []; +flex_compact_dm_timers2(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("02", "03", "04"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, [Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers2 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers(2,3,4, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers3(suite) -> + []; +flex_compact_dm_timers3(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("1", "02", "31"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, [Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers3 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers(1,2,31, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers4(suite) -> + []; +flex_compact_dm_timers4(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("10", "21", "99"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, [Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers4 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers(10,21,99, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers5(suite) -> + []; +flex_compact_dm_timers5(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("99", "23", "11"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, [Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers5 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers(99,23,11, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers6(suite) -> + []; +flex_compact_dm_timers6(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("77", "09", "1"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, [Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers6 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers(77,9,1, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +build_dm_timers_message(T, S, L) -> + M = io_lib:format("!/" ?VERSION_STR " [123.123.123.4]:55555\nT=10001{C=-{MF=11111111/00000000/00000000{E=2223{al/on,dd/ce{DM=dialplan00}},SG{cg/rt},DM=dialplan00{T:~s,S:~s,L:~s,(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)}}}}", [T, S, L]), + lists:flatten(M). + + +verify_dm_timers(T,S,L, #'MegacoMessage'{mess = Mess}) -> + #'Message'{messageBody = Body} = Mess, + case get_dm_timers(Body) of + {T, S, L} -> + ok; + {T1, S1, L1} -> + exit({invalid_timer_values, {{T, S, L}, {T1, S1, L1}}}); + {error, Reason} -> + exit({invalid_timer, {T, S, L, Reason}}) + end. + +get_dm_timers({transactions, T}) when is_list(T) -> + get_dm_timers1(T); +get_dm_timers(Other) -> + {error, {invalid_transactions, Other}}. + +get_dm_timers1([{transactionRequest,T}|Ts]) when is_record(T,'TransactionRequest') -> + case get_dm_timers2(T) of + {ok, Timers} -> + Timers; + _ -> + get_dm_timers1(Ts) + end; +get_dm_timers1([_|Ts]) -> + get_dm_timers1(Ts); +get_dm_timers1([]) -> + {error, {no_timers, 'TransactionRequest'}}. + + +get_dm_timers2(#'TransactionRequest'{actions = Actions}) when is_list(Actions) -> + get_dm_timers3(Actions). + + +get_dm_timers3([#'ActionRequest'{commandRequests = Cmds}|Ars]) when is_list(Cmds) -> + case get_dm_timers4(Cmds) of + {ok, Timers} -> + {ok, Timers}; + _ -> + get_dm_timers3(Ars) + end; +get_dm_timers3([_|Ars]) -> + get_dm_timers3(Ars); +get_dm_timers3([]) -> + {error, {no_timers, 'ActionRequest'}}. + +get_dm_timers4([#'CommandRequest'{command = Cmd}|Cmds]) -> + case get_dm_timers5(Cmd) of + {ok, Timers} -> + {ok, Timers}; + _ -> + get_dm_timers4(Cmds) + end; +get_dm_timers4([_|Cmds]) -> + get_dm_timers4(Cmds); +get_dm_timers4([]) -> + {error, {no_timers, 'CommandRequest'}}. + + +get_dm_timers5({modReq, #'AmmRequest'{descriptors = Descriptors}}) -> + get_dm_timers6(Descriptors); +get_dm_timers5(R) -> + {error, {no_modReq, R}}. + + +get_dm_timers6([{digitMapDescriptor, #'DigitMapDescriptor'{digitMapValue = Val}}|_]) -> + case Val of + #'DigitMapValue'{startTimer = T, + shortTimer = S, + longTimer = L} -> + {ok, {T, S, L}}; + _ -> + {error, no_value_in_dm} + end; +get_dm_timers6([_|Descs]) -> + get_dm_timers6(Descs); +get_dm_timers6([]) -> + {error, {no_timers, descriptors}}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bin_test_msgs(suite) -> + []; +bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(), + DynamicDecode = false, + test_msgs(megaco_binary_encoder, DynamicDecode, [], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ber_test_msgs(suite) -> + []; +ber_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(), + DynamicDecode = false, + test_msgs(megaco_ber_encoder, DynamicDecode, [], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ber_bin_test_msgs(suite) -> + []; +ber_bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(), + DynamicDecode = true, + test_msgs(megaco_ber_bin_encoder, DynamicDecode, [], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +per_test_msgs(suite) -> + []; +per_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(), + DynamicDecode = false, + test_msgs(megaco_per_encoder, DynamicDecode, [], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +per_bin_test_msgs(suite) -> + []; +per_bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1(), + DynamicDecode = false, + test_msgs(megaco_per_bin_encoder, DynamicDecode, [], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +erl_dist_m_test_msgs(suite) -> + []; +erl_dist_m_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1() ++ msgs2() ++ msgs3(), + DynamicDecode = false, + Conf = [megaco_compressed], + test_msgs(megaco_erl_dist_encoder, DynamicDecode, Conf, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +%% Ticket test cases: + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg1(suite) -> + []; +compact_otp4011_msg1(Config) when is_list(Config) -> +% put(severity,trc), +% put(dbg,true), + d("compact_otp4011_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR + " ML T=233350{C=${A=stedevice/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SR}}}}}", + ok = compact_otp4011(M). + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg2(suite) -> + []; +compact_otp4011_msg2(Config) when is_list(Config) -> + d("compact_otp4011_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR + " ML T=233350{C=${A=stedevice/01{M{O{MO=SO,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SR}}}}}", +% put(severity,trc), +% put(dbg,true), + ok = compact_otp4011(M). + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg3(suite) -> + []; +compact_otp4011_msg3(Config) when is_list(Config) -> + d("compact_otp4011_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR + " ML T=233350{C=${A=stedevice/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SO}}}}}", + %% put(severity,trc), + %% put(dbg,true), + ok = compact_otp4011(M). + + +compact_otp4011(M) -> + d("compact_otp4011 -> entry with" + "~n M: '~s'", [M]), + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, _} -> + exit({decoded_erroneous_message,M}); + {error, Error} when is_list(Error) -> % Expected result + d("compact_otp4011 -> expected error result (so far)", []), + case lists:keysearch(reason,1,Error) of + {value, {reason,Reason}} -> + d("compact_otp4011 -> expected error: " + "~n Reason: ~p", [Reason]), + case Reason of + {0, megaco_text_parser_v1, + {do_merge_control_streamParms, [A,B]}} + when is_list(A) andalso is_record(B, 'LocalControlDescriptor') -> + case lists:keysearch(mode,1,A) of + {value, {mode, _Mode}} + when B#'LocalControlDescriptor'.streamMode =/= asn1_NOVALUE -> + d("compact_otp4011 -> expected error",[]), + ok; + Other -> + exit({unexpected_mode_reason, {A,B,Other}}) + end; + Other -> + exit({unexpected_reason, Other}) + end; + + false -> + d("compact_otp4011 -> OUPS, wrong kind of error", []), + exit({unexpected_result, Error}) + end; + Else -> + d("compact_otp4011 -> unexpected decode result: ~p", [Else]), + exit({unexpected_decode_result, Else}) + end. + +%% -------------------------------------------------------------- +%% Note that this decode SHALL fail, because of the misspelled +%% MEGCAO instead of the correct MEGACO. +compact_otp4013_msg1(suite) -> + []; +compact_otp4013_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4013_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "MEGCAO/1 MG1 T=12345678{C=-{SC=root{SV{MT=RS,RE=901}}}}", + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, _} -> + exit({decoded_erroneous_message,M}); + {error, Reason} when is_list(Reason) -> + {value, {reason, no_version_found, _}} = + lists:keysearch(reason, 1, Reason), + {value, {token, [{'SafeChars',_,"megcao/1"}|_]}} = + lists:keysearch(token, 1, Reason), + ok; + Else -> + exit({unexpected_decode_result,Else}) + end. + + + +%% -------------------------------------------------------------- +%% +%% +compact_otp4085_msg1(suite) -> + []; +compact_otp4085_msg1(Config) when is_list(Config) -> + d("compact_otp4085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = compact_otp4085_erroneous_msg(), + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, M} -> + exit({decoded_erroneous_message,M}); + {error, Error} when is_list(Error) -> % Expected result + t("compact_otp4085_msg1 -> decode failed", []), + case lists:keysearch(reason, 1, Error) of + {value, {reason,{999999, Module, Crap}}} -> + t("compact_otp4085_msg1 -> THE ACTUAL ERROR: " + "~n LINE NUMBER: 999999" + "~n Module: ~p" + "~n Crap: ~p", [Module, Crap]), + %% ok; + exit({decode_failed_999999, Module, Crap}); + {value, {reason,{Line, Module, Crap}}} -> + t("compact_otp4085_msg1 -> Expected: " + "~n Line: ~p" + "~n Module: ~p" + "~n Crap: ~p", [Line, Module, Crap]), + ok; + false -> + exit({unexpected_result, Error}) + end; + Else -> + exit({unexpected_decode_result, Else}) + end. + + +%% -------------------------------------------------------------- +%% This test case is just to show that the message used in +%% compact_otp4085_msg1 is actually ok when you add '}' at the end. +compact_otp4085_msg2(suite) -> + []; +compact_otp4085_msg2(Config) when is_list(Config) -> + d("compact_otp4085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M1 = compact_otp4085_erroneous_msg() ++ "}", + Bin = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, M2} -> + l("compact_otp4085_msg1 -> successfull decode" + "~n M2: ~p", [M2]), + ok; + Else -> + e("compact_otp4085_msg1 -> decode error" + "~n Else: ~p", [Else]), + exit({unexpected_decode_result,Else}) + end. + + +%% This message lack the ending parentesis (}). +compact_otp4085_erroneous_msg() -> + M = "!/" + ?VERSION_STR + " ML T=11223342{C=${A=${M{O{MO=SR,RV=OFF,RG=OFF},L{v=0," + "c=ATM NSAP $ ," + "a=eecid:$ ," + "m=audio - AAL1/ATMF -," + "}}},A=stee1181/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=off}}}}", + M. + +%% -------------------------------------------------------------- +%% +%% +compact_otp4280_msg1(suite) -> + []; +compact_otp4280_msg1(Config) when is_list(Config) -> + d("compact_otp4280_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Bin = list_to_binary(compact_otp4280_msg()), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, _Msg} -> + ok; + {error, Error} when is_list(Error) -> + t("compact_otp4280_msg1 -> decode failed", []), + case lists:keysearch(reason, 1, Error) of + {value, {reason,{Line, Module, Reason} = R}} -> + t("compact_otp4280_msg1 -> " + "~n Line: ~w" + "~n Module: ~w" + "~n Reason: ~w", [Line, Module, Reason]), + exit({decode_failed, R}); + false -> + exit({unexpected_result, Error}) + end; + Else -> + exit({unexpected_decode_result, Else}) + end. + +compact_otp4280_msg() -> + M = "!/" + ?VERSION_STR + " mgw1 P=71853646{C=-{AV=root{M{TS{root/maxnumberofcontexts=49500," + "root/maxterminationspercontext=2,root/normalmgexecutiontime=200," + "root/normalmgcexecutiontime=150," + "root/provisionalresponsetimervalue=2000,BF=OFF,SI=IV}}}}}", + M. + + +%% -------------------------------------------------------------- +%% This ticket is about comments in a message +compact_otp4299_msg1(suite) -> + []; +compact_otp4299_msg1(Config) when is_list(Config) -> + d("compact_otp4299_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Bin = list_to_binary(compact_otp4299_msg()), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, _Msg} -> + ok; + + {error, Reason} -> + exit({decode_error, Reason}); + + Else -> + exit({unexpected_decode_result, Else}) + end. + + +%% Same message, but this time decoded using the flex scanner +compact_otp4299_msg2(suite) -> + []; +compact_otp4299_msg2(Config) when is_list(Config) -> + d("compact_otp4299_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + + {Pid, Conf} = compact_otp4299_msg2_init(), + + Bin = list_to_binary(compact_otp4299_msg()), + Res = decode_message(megaco_compact_text_encoder, false, [Conf], Bin), + compact_otp4299_msg2_finish(Pid), + + case Res of + {ok, _Msg} -> + ok; + + {error, Reason} -> + exit({decode_error, Reason}); + + Else -> + exit({unexpected_decode_result, Else}) + end. + + +compact_otp4299_msg2_init() -> + Flag = process_flag(trap_exit, true), + Res = (catch start_flex_scanner()), + process_flag(trap_exit, Flag), + case Res of + {error, Reason} -> + skip(Reason); + {ok, FlexConfig} -> + FlexConfig + end. + +compact_otp4299_msg2_finish(Pid) -> + stop_flex_scanner(Pid). + + +compact_otp4299_msg() -> + M = ";KALLE\n" + "!/" ?VERSION_STR " mg58_1 P=005197711{; YET ANOTHER COMMENT\n" + "C=035146207{A=mg58_1_1_4_1_23/19; BEFORE COMMA\n" + ",; AFTER COMMA\n" + "A=eph58_1/0xA4023371{M{L{\n" + "v=0\n" + "c=ATM NSAP 39.0102.0304.0506.0708.090a.0b58.0100.0000.0000.00\n" + "m=audio - AAL1/ATMF -\n" + "a=eecid:A4023371\n" + "}}; HOBBE\n}; KALLE \"HOBBE \n}}" + ";KALLE\n\n", + M. + + +%% -------------------------------------------------------------- +%% +%% +compact_otp4359_msg1(suite) -> + []; +compact_otp4359_msg1(Config) when is_list(Config) -> + d("compact_otp4359_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Bin = list_to_binary(compact_otp4359_msg()), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, #'MegacoMessage'{mess = Mess}} -> + {transactions, Trans} = Mess#'Message'.messageBody, + case Trans of + [{transactionRequest,#'TransactionRequest'{transactionId = asn1_NOVALUE}}] -> + ok; + _ -> + exit({unexpected_transactions, Trans}) + end; + Else -> + t("compact_otp4359_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +compact_otp4359_msg() -> + M = "!/" ?VERSION_STR " ml2 T={C=${A=${M{O {MO=SR,RG=OFF,RV=OFF}}}}}", + M. + + +%% -------------------------------------------------------------- +%% +%% +compact_otp4920_msg0(suite) -> + []; +compact_otp4920_msg0(Config) when is_list(Config) -> + d("compact_otp4920_msg0 -> entry", []), + ?ACQUIRE_NODES(1, Config), +% put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg0(), true). + +compact_otp4920_msg1(suite) -> + []; +compact_otp4920_msg1(Config) when is_list(Config) -> + d("compact_otp4920_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), +% put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg1(), false). + +compact_otp4920_msg2(suite) -> + []; +compact_otp4920_msg2(Config) when is_list(Config) -> + d("compact_otp4920_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg2(), false). + +compact_otp4920_msg3(suite) -> + []; +compact_otp4920_msg3(Config) when is_list(Config) -> + d("compact_otp4920_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg3(), true). + +compact_otp4920_msg4(suite) -> + []; +compact_otp4920_msg4(Config) when is_list(Config) -> + d("compact_otp4920_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg4(), true). + +compact_otp4920_msg5(suite) -> + []; +compact_otp4920_msg5(Config) when is_list(Config) -> + d("compact_otp4920_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg5(), true). + +compact_otp4920_msg6(suite) -> + []; +compact_otp4920_msg6(Config) when is_list(Config) -> + d("compact_otp4920_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg6(), true). + +compact_otp4920_msg7(suite) -> + []; +compact_otp4920_msg7(Config) when is_list(Config) -> + d("compact_otp4920_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), +% put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg7(), true). + +compact_otp4920_msg8(suite) -> + []; +compact_otp4920_msg8(Config) when is_list(Config) -> + d("compact_otp4920_msg8 -> entry", []), + ?ACQUIRE_NODES(1, Config), +% put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg8(), false). + +compact_otp4920_msg9(suite) -> + []; +compact_otp4920_msg9(Config) when is_list(Config) -> + d("compact_otp4920_msg9 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg9(), false). + +compact_otp4920_msg10(suite) -> + []; +compact_otp4920_msg10(Config) when is_list(Config) -> + d("compact_otp4920_msg10 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg10(), false). + +compact_otp4920_msg11(suite) -> + []; +compact_otp4920_msg11(Config) when is_list(Config) -> + d("compact_otp4920_msg11 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg11(), false). + +compact_otp4920_msg12(suite) -> + []; +compact_otp4920_msg12(Config) when is_list(Config) -> + d("compact_otp4920_msg12 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg12(), true). + +%% Duplicate padding +compact_otp4920_msg20(suite) -> + []; +compact_otp4920_msg20(Config) when is_list(Config) -> + d("compact_otp4920_msg20 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg20(), bad_mid_duplicate_padding). + +%% Length +compact_otp4920_msg21(suite) -> + []; +compact_otp4920_msg21(Config) when is_list(Config) -> + d("compact_otp4920_msg21 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg21(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg22(suite) -> + []; +compact_otp4920_msg22(Config) when is_list(Config) -> + d("compact_otp4920_msg22 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg22(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg23(suite) -> + []; +compact_otp4920_msg23(Config) when is_list(Config) -> + d("compact_otp4920_msg23 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg23(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg24(suite) -> + []; +compact_otp4920_msg24(Config) when is_list(Config) -> + d("compact_otp4920_msg24 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg24(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg25(suite) -> + []; +compact_otp4920_msg25(Config) when is_list(Config) -> + d("compact_otp4920_msg25 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg25(), bad_mid_ip6addr_length). + +compact_otp4920_msg_1(M1, CheckEqual) -> + Bin1 = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, [], Bin1) of + {ok, Msg} -> + io:format(" decoded", []), + case encode_message(megaco_compact_text_encoder, [], Msg) of + {ok, Bin1} -> + io:format(", encoded - equal:", []), + ok; + {ok, Bin2} when CheckEqual =:= true -> + M2 = binary_to_list(Bin2), + io:format(", encoded - not equal:", []), + exit({messages_not_equal, M1, M2}); + {ok, _Bin2} -> + io:format(", encoded:", []), + ok; + Else -> + io:format(", encode failed:", []), + exit({unexpected_encode_result, Else}) + end; + Else -> + io:format("decode failed:", []), + exit({unexpected_decode_result, Else}) + end. + +compact_otp4920_msg_2(M1, ExpectedReason) -> + Bin = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, Msg} -> + io:format("unexpected successfull decode", []), + exit({unexpected_encode_ok, Msg}); + {error, [{reason, {__Line, _Mod, Reason}}|_]} -> + case element(1, Reason) of + ExpectedReason -> + ok; + _ -> + exit({unexpected_decode_error_reason, + ExpectedReason, Reason}) + end; + {error, [{reason, {_Mod, Reason}}|_]} -> + case element(1, Reason) of + ExpectedReason -> + ok; + _ -> + exit({unexpected_decode_error_reason, + ExpectedReason, Reason}) + end; + Else -> + io:format("unexpected decode result", []), + exit({unexpected_decode_result, Else}) + + end. + +compact_otp4920_msg0() -> + M = "!/" ?VERSION_STR " [192.168.30.1]\nT=100{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg1() -> + M = "!/" ?VERSION_STR " [2031:0000:130F:0000:0000:09C0:876A:130B]\nT=101{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg2() -> + M = "!/" ?VERSION_STR " [2031:0:130F:0:0:9C0:876A:130B]\nT=102{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg3() -> + M = "!/" ?VERSION_STR " [2031:0:130F::9C0:876A:130B]\nT=103{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg4() -> + M = "!/" ?VERSION_STR " [::1]\nT=104{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg5() -> + M = "!/" ?VERSION_STR " [::]\nT=105{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg6() -> + M = "!/" ?VERSION_STR " [1::]\nT=106{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg7() -> + M = "!/" ?VERSION_STR " [FEDC:1::]\nT=107{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg8() -> + M = "!/" ?VERSION_STR " [2031:0:130F:0:0:9C0:135.106.19.11]\nT=108{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg9() -> + M = "!/" ?VERSION_STR " [2031:0:130F::9C0:135.106.19.11]\nT=109{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg10() -> + M = "!/" ?VERSION_STR " [::FFFF:192.168.30.1]\nT=110{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg11() -> + M = "!/" ?VERSION_STR " [::192.168.30.1]\nT=111{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg12() -> + M = "!/" ?VERSION_STR " [::C0A8:1E01]\nT=112{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: only one :: allowed +compact_otp4920_msg20() -> + M = "!/" ?VERSION_STR " [2031::130F::9C0]\nT=120{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg21() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:0000:0000:09C0:876A:130B]\nT=121{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg22() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0:130F:0:0:9C0:135.106.19.11]\nT=122{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg23() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:2132:4354::09C0:876A:130B]\nT=123{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg24() -> + M = "!/" ?VERSION_STR " [::2031:FFEE:0000:130F:2132:4354:09C0:876A:130B]\nT=124{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg25() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:2132:4354:09C0:876A:130B::]\nT=125{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + + +compact_otp5186_msg01(suite) -> + []; +compact_otp5186_msg01(Config) when is_list(Config) -> + d("compact_otp5186_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_1(compact_otp5186_msg01(), error, ignore). + +compact_otp5186_msg02(suite) -> + []; +compact_otp5186_msg02(Config) when is_list(Config) -> + d("compact_otp5186_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_1(compact_otp5186_msg02(), ok, ok). + +compact_otp5186_msg03(suite) -> + []; +compact_otp5186_msg03(Config) when is_list(Config) -> + d("compact_otp5186_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg03(), ok, ok). + +compact_otp5186_msg04(suite) -> + []; +compact_otp5186_msg04(Config) when is_list(Config) -> + d("compact_otp5186_msg04 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg04(), ok, ok). + +compact_otp5186_msg05(suite) -> + []; +compact_otp5186_msg05(Config) when is_list(Config) -> + d("compact_otp5186_msg05 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg05(), ok, ok). + +compact_otp5186_msg06(suite) -> + []; +compact_otp5186_msg06(Config) when is_list(Config) -> + d("compact_otp5186_msg06 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg06(), ok, ok). + +compact_otp5186_msg_1(M1, DecodeExpect, EncodeExpect) -> + Bin1 = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, [], Bin1) of + {ok, Msg} when DecodeExpect =:= ok -> + io:format(" decoded", []), + case encode_message(megaco_compact_text_encoder, [], Msg) of + {ok, Bin1} when EncodeExpect =:= ok -> + io:format(", encoded - equal:", []), + ok; + {ok, Bin2} when EncodeExpect =:= ok -> + M2 = binary_to_list(Bin2), + io:format(", encoded - not equal:", []), + exit({messages_not_equal, Msg, M1, M2}); + {ok, Bin3} when EncodeExpect =:= error -> + M3 = binary_to_list(Bin3), + io:format(", unexpected encode:", []), + exit({unexpected_encode_success, Msg, M1, M3}); + _Else when EncodeExpect =:= error -> + io:format(", encode failed ", []), + ok + end; + {ok, Msg} when DecodeExpect =:= error -> + io:format(" decoded", []), + exit({unexpected_decode_success, Msg}); + _Else when DecodeExpect =:= error -> + io:format(" decode failed ", []), + ok; + Else when DecodeExpect =:= ok -> + io:format(" decode failed ", []), + exit({unexpected_decode_result, Else}) + end. + +compact_otp5186_msg_2(Msg1, EncodeExpect, DecodeExpect) -> + case encode_message(megaco_compact_text_encoder, [], Msg1) of + {ok, Bin} when EncodeExpect =:= ok -> + io:format(" encoded", []), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, Msg1} when DecodeExpect =:= ok -> + io:format(", decoded - equal:", []), + ok; + {ok, Msg2} when DecodeExpect =:= ok -> + M = binary_to_list(Bin), + case (catch compact_otp5186_check_megamsg(Msg1, Msg2)) of + ok -> + io:format(", decoded - not equal - ok:", []), + ok; + {'EXIT', Reason} -> + io:format(", decoded - not equal:", []), + exit({messages_not_equal, M, Reason, Msg1, Msg2}) + end; + {ok, Msg3} when DecodeExpect =:= error -> + M = binary_to_list(Bin), + io:format(", decoded:", []), + exit({unexpected_decode_success, M, Msg1, Msg3}); + Else when DecodeExpect =:= ok -> + M = binary_to_list(Bin), + io:format(", decode failed ", []), + exit({unexpected_decode_success, Msg1, M, Else}); + _Else when DecodeExpect =:= error -> + io:format(", decode failed ", []), + ok + end; + {ok, Bin} when EncodeExpect =:= error -> + M = binary_to_list(Bin), + io:format(" encoded", []), + exit({unexpected_encode_success, Msg1, M}); + _Else when EncodeExpect =:= error -> + io:format(" encode failed ", []), + ok; + Else when EncodeExpect =:= ok -> + io:format(" encode failed ", []), + exit({unexpected_encode_result, Else}) + end. + + +%% -- + +compact_otp5186_msg01() -> + "!/1 <mg5>\nP=67111298{C=2699{AV=mg5_ipeph/0x0f0001{}}}". + +compact_otp5186_msg02() -> + "!/1 <mg5>\nP=67111298{C=2699{AV=mg5_ipeph/0x0f0001}}". + +compact_otp5186_msg03() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + 1, + {domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]}, + [ + ] + } + } + } + ] + } + ] + } + } + } + ] + } + } + }. + +compact_otp5186_msg04() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',1,{domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]}, + [ + {emptyDescriptors, + {'AuditDescriptor',asn1_NOVALUE} + } + ] + } + } + } + ] + } + ] + } + } + } + ] + } + } + }. + +compact_otp5186_msg05() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + 1, + {domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {addReply, + {'AmmsReply', + [ + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]} + ], + [ + ] + } + } + ] + } + ] + } + } + } + ] + } + } + }. + +compact_otp5186_msg06() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',1,{domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {addReply, + {'AmmsReply', + [ + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]} + ], + [ + {emptyDescriptors, + {'AuditDescriptor',asn1_NOVALUE} + } + ] + } + } + ] + } + ] + } + } + } + ] + } + } + }. + +%% -- + +compact_otp5186_check_megamsg(M1, M1) -> + ok; +compact_otp5186_check_megamsg(#'MegacoMessage'{authHeader = AH, + mess = M1}, + #'MegacoMessage'{authHeader = AH, + mess = M2}) -> + compact_otp5186_check_mess(M1, M2); +compact_otp5186_check_megamsg(#'MegacoMessage'{authHeader = AH1}, + #'MegacoMessage'{authHeader = AH2}) -> + exit({not_equal, authHeader, AH1, AH2}). + +compact_otp5186_check_mess(M, M) -> + ok; +compact_otp5186_check_mess(#'Message'{version = V, + mId = MId, + messageBody = B1}, + #'Message'{version = V, + mId = MId, + messageBody = B2}) -> + compact_otp5186_check_body(B1, B2); +compact_otp5186_check_mess(#'Message'{version = V, + mId = MId1}, + #'Message'{version = V, + mId = MId2}) -> + exit({not_equal, mId, MId1, MId2}); +compact_otp5186_check_mess(#'Message'{version = V1, + mId = MId}, + #'Message'{version = V2, + mId = MId}) -> + exit({not_equal, version, V1, V2}). + +compact_otp5186_check_body(B, B) -> + ok; +compact_otp5186_check_body({transactions, T1}, {transactions, T2}) -> + compact_otp5186_check_trans(T1, T2); +compact_otp5186_check_body({messageError, E1}, {messageError, E2}) -> + compact_otp5186_check_merr(E1, E2); +compact_otp5186_check_body(B1, B2) -> + exit({not_equal, messageBody, B1, B2}). + +compact_otp5186_check_trans([], []) -> + ok; +compact_otp5186_check_trans([], T2) -> + exit({not_equal, transactions, [], T2}); +compact_otp5186_check_trans(T1, []) -> + exit({not_equal, transactions, T1, []}); +compact_otp5186_check_trans([Tran1|Trans1], [Tran2|Trans2]) -> + compact_otp5186_check_trans(Trans1, Trans2), + compact_otp5186_check_transaction(Tran1, Tran2). + +compact_otp5186_check_merr(ME, ME) -> + ok; +compact_otp5186_check_merr(#'ErrorDescriptor'{errorCode = EC, + errorText = ET1}, + #'ErrorDescriptor'{errorCode = EC, + errorText = ET2}) -> + exit({not_equal, errorText, ET1, ET2}); +compact_otp5186_check_merr(#'ErrorDescriptor'{errorCode = EC1, + errorText = ET}, + #'ErrorDescriptor'{errorCode = EC2, + errorText = ET}) -> + exit({not_equal, errorCode, EC1, EC2}). + +compact_otp5186_check_transaction(T, T) -> + ok; +compact_otp5186_check_transaction({transactionReply, TR1}, + {transactionReply, TR2}) -> + compact_otp5186_check_transRep(TR1, TR2); +compact_otp5186_check_transaction(T1, T2) -> + exit({unexpected_transactions, T1, T2}). + +compact_otp5186_check_transRep(T, T) -> + ok; +compact_otp5186_check_transRep(#'TransactionReply'{transactionId = TId, + immAckRequired = IAR, + transactionResult = TR1}, + #'TransactionReply'{transactionId = TId, + immAckRequired = IAR, + transactionResult = TR2}) -> + compact_otp5186_check_transRes(TR1, TR2); +compact_otp5186_check_transRep(T1, T2) -> + exit({unexpected_transaction_reply, T1, T2}). + +compact_otp5186_check_transRes(TR, TR) -> + ok; +compact_otp5186_check_transRes({actionReplies, AR1}, + {actionReplies, AR2}) -> + compact_otp5186_check_actReps(AR1, AR2); +compact_otp5186_check_transRes(TR1, TR2) -> + exit({unexpected_transaction_result, TR1, TR2}). + +compact_otp5186_check_actReps([], []) -> + ok; +compact_otp5186_check_actReps(AR1, []) -> + exit({not_equal, actionReplies, AR1, []}); +compact_otp5186_check_actReps([], AR2) -> + exit({not_equal, actionReplies, [], AR2}); +compact_otp5186_check_actReps([AR1|ARs1], [AR2|ARs2]) -> + compact_otp5186_check_actRep(AR1, AR2), + compact_otp5186_check_actReps(ARs1, ARs2). + +compact_otp5186_check_actRep(AR, AR) -> + ok; +compact_otp5186_check_actRep(#'ActionReply'{contextId = ID, + errorDescriptor = ED, + contextReply = CtxRep, + commandReply = CmdRep1}, + #'ActionReply'{contextId = ID, + errorDescriptor = ED, + contextReply = CtxRep, + commandReply = CmdRep2}) -> + compact_otp5186_check_cmdReps(CmdRep1, CmdRep2); +compact_otp5186_check_actRep(AR1, AR2) -> + exit({unexpected_actionReply, AR1, AR2}). + +compact_otp5186_check_cmdReps([], []) -> + ok; +compact_otp5186_check_cmdReps(CR1, []) -> + exit({not_equal, commandReplies, CR1, []}); +compact_otp5186_check_cmdReps([], CR2) -> + exit({not_equal, commandReplies, [], CR2}); +compact_otp5186_check_cmdReps([CR1|CRs1], [CR2|CRs2]) -> + compact_otp5186_check_cmdRep(CR1, CR2), + compact_otp5186_check_cmdReps(CRs1, CRs2). + +compact_otp5186_check_cmdRep(CR, CR) -> + ok; +compact_otp5186_check_cmdRep({auditValueReply, AVR1}, + {auditValueReply, AVR2}) -> + compact_otp5186_check_auditReply(AVR1, AVR2); +compact_otp5186_check_cmdRep({addReply, AVR1}, + {addReply, AVR2}) -> + compact_otp5186_check_ammsReply(AVR1, AVR2); +compact_otp5186_check_cmdRep(CR1, CR2) -> + exit({unexpected_commandReply, CR1, CR2}). + +compact_otp5186_check_auditReply(AR, AR) -> + ok; +compact_otp5186_check_auditReply({auditResult, AR1}, + {auditResult, AR2}) -> + compact_otp5186_check_auditRes(AR1, AR2); +compact_otp5186_check_auditReply(AR1, AR2) -> + exit({unexpected_auditReply, AR1, AR2}). + +compact_otp5186_check_ammsReply(AR, AR) -> + ok; +compact_otp5186_check_ammsReply(#'AmmsReply'{terminationID = ID, + terminationAudit = TA1}, + #'AmmsReply'{terminationID = ID, + terminationAudit = TA2}) -> + %% This is just to simplify the test + F = fun(asn1_NOVALUE) -> []; + (E) -> E + end, + compact_otp5186_check_termAudit(F(TA1), F(TA2)); +compact_otp5186_check_ammsReply(AR1, AR2) -> + exit({unexpected_ammsReply, AR1, AR2}). + +compact_otp5186_check_auditRes(AR, AR) -> + ok; +compact_otp5186_check_auditRes(#'AuditResult'{terminationID = ID, + terminationAuditResult = TAR1}, + #'AuditResult'{terminationID = ID, + terminationAuditResult = TAR2}) -> + compact_otp5186_check_termAuditRes(TAR1, TAR2); +compact_otp5186_check_auditRes(AR1, AR2) -> + exit({unexpected_auditResult, AR1, AR2}). + +compact_otp5186_check_termAuditRes([], []) -> + ok; +%% An empty empty descriptor is removed +compact_otp5186_check_termAuditRes([{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE}}|TAR1], []) -> + compact_otp5186_check_termAuditRes(TAR1, []); +compact_otp5186_check_termAuditRes(TAR1, []) -> + exit({not_equal, termAuditRes, TAR1, []}); +%% An empty empty descriptor is removed +compact_otp5186_check_termAuditRes([], [{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE}}|TAR2]) -> + compact_otp5186_check_termAuditRes([], TAR2); +compact_otp5186_check_termAuditRes([], TAR2) -> + exit({not_equal, termAuditRes, [], TAR2}); +compact_otp5186_check_termAuditRes([ARP1|TAR1], [ARP2|TAR2]) -> + compact_otp5186_check_auditRetParm(ARP1, ARP2), + compact_otp5186_check_termAuditRes(TAR1, TAR2). + +compact_otp5186_check_termAudit([], []) -> + ok; +%% An empty empty descriptor is removed +compact_otp5186_check_termAudit([{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE}}|TAR1], []) -> + compact_otp5186_check_termAudit(TAR1, []); +compact_otp5186_check_termAudit(TAR1, []) -> + exit({not_equal, termAudit, TAR1, []}); +%% An empty empty descriptor is removed +compact_otp5186_check_termAudit([], + [{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE}}|TAR2]) -> + compact_otp5186_check_termAudit([], TAR2); +compact_otp5186_check_termAudit([], TAR2) -> + exit({not_equal, termAudit, [], TAR2}); +compact_otp5186_check_termAudit([ARP1|TAR1], [ARP2|TAR2]) -> + compact_otp5186_check_auditRetParm(ARP1, ARP2), + compact_otp5186_check_termAudit(TAR1, TAR2). + +compact_otp5186_check_auditRetParm(ARP, ARP) -> + ok; +compact_otp5186_check_auditRetParm({emptyDescriptors, AD1}, + {emptyDescriptors, AD2}) -> + compact_otp5186_check_auditDesc(AD1, AD2); +compact_otp5186_check_auditRetParm(ARP1, ARP2) -> + exit({unexpected_auditRetParm, ARP1, ARP2}). + +compact_otp5186_check_auditDesc(AD, AD) -> + ok; +compact_otp5186_check_auditDesc(#'AuditDescriptor'{auditToken = L1}, + #'AuditDescriptor'{auditToken = L2}) -> + compact_otp5186_check_auditDesc_auditItems(L1, L2); +compact_otp5186_check_auditDesc(AD1, AD2) -> + exit({unexpected_auditDesc, AD1, AD2}). + +compact_otp5186_check_auditDesc_auditItems([], []) -> + ok; +compact_otp5186_check_auditDesc_auditItems(AI1, []) -> + exit({not_equal, auditItems, AI1, []}); +compact_otp5186_check_auditDesc_auditItems([], AI2) -> + exit({not_equal, auditItems, [], AI2}); +compact_otp5186_check_auditDesc_auditItems([AI1|AIs1], [AI2|AIs2]) -> + compact_otp5186_check_auditDesc_auditItem(AI1, AI2), + compact_otp5186_check_auditDesc_auditItems(AIs1, AIs2). + +compact_otp5186_check_auditDesc_auditItem(AI, AI) -> + ok; +compact_otp5186_check_auditDesc_auditItem(AI1, AI2) -> + exit({not_equal, auditItem, AI1, AI2}). + +compact_otp5793_msg01(suite) -> + []; +compact_otp5793_msg01(Config) when is_list(Config) -> + d("compact_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5793(ok, pretty_otp5793_msg1()). + +compact_otp5793(Expected, Msg) -> + expect_codec(Expected, megaco_compact_text_encoder, Msg, []). + + +%% -------------------------------------------------------------- + +compact_otp5993_msg01(suite) -> + []; +compact_otp5993_msg01(Config) when is_list(Config) -> + d("compact_otp5993_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5993_msg_1(compact_otp5993_msg01(), ok, ok). + +compact_otp5993_msg02(suite) -> + []; +compact_otp5993_msg02(Config) when is_list(Config) -> + d("compact_otp5993_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5993_msg_1(compact_otp5993_msg02(), ok, ok). + +compact_otp5993_msg03(suite) -> + []; +compact_otp5993_msg03(Config) when is_list(Config) -> + d("compact_otp5993_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5993_msg_1(compact_otp5993_msg03(), ok, ok). + +compact_otp5993_msg_1(Msg1, EncodeExpect, DecodeExpect) -> + case encode_message(megaco_compact_text_encoder, [], Msg1) of + {ok, Bin} when EncodeExpect =:= ok -> + io:format(" encoded", []), + %% io:format(" encoded:~n~s~n", [binary_to_list(Bin)]), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, Msg1} when DecodeExpect =:= ok -> + io:format(", decoded - equal:", []), + ok; + {ok, Msg3} when DecodeExpect =:= error -> + M = binary_to_list(Bin), + io:format(", decoded:", []), + exit({unexpected_decode_success, M, Msg1, Msg3}); + Else when DecodeExpect =:= ok -> + M = binary_to_list(Bin), + io:format(", decode failed ", []), + exit({unexpected_decode_failure, Msg1, M, Else}); + _Else when DecodeExpect =:= error -> + io:format(", decode failed ", []), + ok + end; + {ok, Bin} when EncodeExpect =:= error -> + M = binary_to_list(Bin), + io:format(" encoded", []), + exit({unexpected_encode_success, Msg1, M}); + _Else when EncodeExpect =:= error -> + io:format(" encode failed ", []), + ok; + Else when EncodeExpect =:= ok -> + io:format(" encode failed ", []), + exit({unexpected_encode_result, Else}) + end. + +compact_otp5993_msg01() -> + MT = h221, + T = #megaco_term_id{id = ?A4444}, + TL = [T], + MD = #'MuxDescriptor'{muxType = MT, + termList = TL}, + compact_otp5993_msg(MD). + +compact_otp5993_msg02() -> + MT = h223, + T1 = #megaco_term_id{id = ?A4445}, + T2 = #megaco_term_id{id = ?A5556}, + TL = [T1, T2], + MD = #'MuxDescriptor'{muxType = MT, + termList = TL}, + compact_otp5993_msg(MD). + +compact_otp5993_msg(MD) when is_record(MD, 'MuxDescriptor') -> + AmmDesc = {muxDescriptor, MD}, + AmmReq = #'AmmRequest'{terminationID = [hd(MD#'MuxDescriptor'.termList)], + descriptors = [AmmDesc]}, + Cmd = {addReq, AmmReq}, + CmdReq = #'CommandRequest'{command = Cmd}, + ActReq = #'ActionRequest'{contextId = 5993, + commandRequests = [CmdReq]}, + TransReq = #'TransactionRequest'{transactionId = 3995, + actions = [ActReq]}, + Trans = {transactionRequest, TransReq}, + Body = {transactions, [Trans]}, + Msg = #'Message'{version = ?VERSION, + mId = ?MG1_MID, + messageBody = Body}, + #'MegacoMessage'{mess = Msg}. + +compact_otp5993_msg03() -> + T1 = #megaco_term_id{id = ?A4445}, + T2 = #megaco_term_id{id = ?A5556}, + TIDs = [T1, T2], + AudRep = {contextAuditResult, TIDs}, + CmdRep = {auditValueReply, AudRep}, + ActRep = #'ActionReply'{contextId = 5993, + commandReply = [CmdRep]}, + TransRes = {actionReplies, [ActRep]}, + TransRep = #'TransactionReply'{transactionId = 3995, + transactionResult = TransRes}, + Trans = {transactionReply, TransRep}, + Body = {transactions, [Trans]}, + Msg = #'Message'{version = ?VERSION, + mId = ?MG1_MID, + messageBody = Body}, + #'MegacoMessage'{mess = Msg}. + + +%% -------------------------------------------------------------- + +compact_otp6017_msg01(suite) -> + []; +compact_otp6017_msg01(Config) when is_list(Config) -> + d("compact_otp6017_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(0), + ok. + +compact_otp6017_msg02(suite) -> + []; +compact_otp6017_msg02(Config) when is_list(Config) -> + d("compact_otp6017_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(16#FFFFFFFE), + ok. + +compact_otp6017_msg03(suite) -> + []; +compact_otp6017_msg03(Config) when is_list(Config) -> + d("compact_otp6017_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(16#FFFFFFFF), + ok. + +compact_otp6017(BadCID) -> + M = compact_otp6017_msg(BadCID), + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, Msg} -> + exit({unexpected_decode_success, {Msg, M}}); + {error, Reason} when is_list(Reason) -> % Expected result + case lists:keysearch(reason, 1, Reason) of + {value, {reason, {_Line, _Mod, {bad_ContextID, BadCID}}}} -> + io:format(" ~w", [BadCID]), + ok; + {value, {reason, ActualReason}} -> + exit({unexpected_reason, ActualReason}); + false -> + exit({reason_not_found, Reason}) + end; + Crap -> + exit({unexpected_decode_result, Crap}) + end. + + +compact_otp6017_msg(CID) when is_integer(CID) -> + "MEGACO/" ?VERSION_STR " MG1 T=12345678{C=" ++ + integer_to_list(CID) ++ + "{SC=root{SV{MT=RS,RE=901}}}}". + + +%% ============================================================== +%% +%% F l e x C o m p a c t T e s t c a s e s +%% + +flex_compact_otp7431_msg01a(suite) -> + []; +flex_compact_otp7431_msg01a(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg01a -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(ok, flex_compact_otp7431_msg1a(), [Conf]). + +flex_compact_otp7431_msg01b(suite) -> + []; +flex_compact_otp7431_msg01b(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg01b -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(ok, flex_compact_otp7431_msg1b(), [Conf]). + +flex_compact_otp7431_msg02(suite) -> + []; +flex_compact_otp7431_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg02 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg2(), [Conf]). + +flex_compact_otp7431_msg03(suite) -> + []; +flex_compact_otp7431_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg03 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg3(), [Conf]). + +flex_compact_otp7431_msg04(suite) -> + []; +flex_compact_otp7431_msg04(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg04 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg4(), [Conf]). + +flex_compact_otp7431_msg05(suite) -> + []; +flex_compact_otp7431_msg05(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg05 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg5(), [Conf]). + +flex_compact_otp7431_msg06(suite) -> + []; +flex_compact_otp7431_msg06(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg06 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg6(), [Conf]). + +flex_compact_otp7431_msg07(suite) -> + []; +flex_compact_otp7431_msg07(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg07 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg7(), [Conf]). + + +flex_compact_otp7431(Expected, Msg, Conf) -> + otp7431(Expected, megaco_compact_text_encoder, Msg, Conf). + +flex_compact_otp7431_msg1a() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a=recvonly +}}}}}}". + +flex_compact_otp7431_msg1b() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a=recvonly + + + +}}}}}}". + +flex_compact_otp7431_msg2() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a= } +}}}}}". + + +flex_compact_otp7431_msg3() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a } +}}}}}". + + +flex_compact_otp7431_msg4() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a} +}}}}}". + + +flex_compact_otp7431_msg5() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v= } +}}}}}". + + +flex_compact_otp7431_msg6() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v } +}}}}}". + +flex_compact_otp7431_msg7() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v} +}}}}}". + + +%% ============================================================== +%% +%% P r e t t y T e s t c a s e s +%% + +pretty_otp4632_msg1(suite) -> + []; +pretty_otp4632_msg1(Config) when is_list(Config) -> + d("pretty_otp4632_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg1(), + case encode_message(megaco_pretty_text_encoder, [], Msg0) of + {ok, BinMsg} when is_binary(BinMsg) -> + {ok, Msg1} = decode_message(megaco_pretty_text_encoder, false, + [], BinMsg), + ok = chk_MegacoMessage(Msg0,Msg1); + Else -> + t("pretty_otp4632_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4632_msg1() -> + msg4(?MG1_MID_NO_PORT, "901 mg col boot"). + +pretty_otp4632_msg2(suite) -> + []; +pretty_otp4632_msg2(Config) when is_list(Config) -> + d("pretty_otp4632_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg2(), + case encode_message(megaco_pretty_text_encoder, [], Msg0) of + {ok, BinMsg} when is_binary(BinMsg) -> + {ok, Msg1} = decode_message(megaco_pretty_text_encoder, false, + [], BinMsg), + ok = chk_MegacoMessage(Msg0,Msg1); + Else -> + t("pretty_otp4632_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4632_msg2() -> + msg4(?MG1_MID_NO_PORT, "901"). + + +pretty_otp4632_msg3(suite) -> + []; +pretty_otp4632_msg3(Config) when is_list(Config) -> + d("pretty_otp4632_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg3(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, + false, [], Bin0) of + {ok, Msg} when is_record(Msg, 'MegacoMessage') -> + {ok, Bin1} = encode_message(megaco_pretty_text_encoder, [], Msg), + Msg1 = binary_to_list(Bin1), + %% io:format("Msg1:~n~s~n", [Msg1]), + Msg0 = Msg1, + ok; + Else -> + t("pretty_otp4632_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4632_msg3() -> + M = "MEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = \"901\"\n\t\t\t}\n\t\t}\n\t}\n}", + M. + + +pretty_otp4632_msg4(suite) -> + []; +pretty_otp4632_msg4(Config) when is_list(Config) -> + d("pretty_otp4632_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg4(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {ok, Msg} when is_record(Msg, 'MegacoMessage') -> + {ok, Bin1} = encode_message(megaco_pretty_text_encoder, [], Msg), + Msg1 = binary_to_list(Bin1), + %% io:format("Msg1:~n~s~n", [Msg1]), + pretty_otp4632_msg4_chk(Msg0,Msg1); + Else -> + t("pretty_otp4632_msg4 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + + +pretty_otp4632_msg4() -> + M = "MEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = 901\n\t\t\t}\n\t\t}\n\t}\n}", + M. + + +pretty_otp4632_msg4_chk([], []) -> + exit(messages_not_eq); +pretty_otp4632_msg4_chk([], Rest1) -> + exit({messages_not_eq1, Rest1}); +pretty_otp4632_msg4_chk(Rest0, []) -> + exit({messages_not_eq0, Rest0}); +pretty_otp4632_msg4_chk([$R,$e,$a,$s,$o,$n,$ ,$=,$ ,$9,$0,$1|_Rest0], + [$R,$e,$a,$s,$o,$n,$ ,$=,$ ,$",$9,$0,$1,$"|_Rest1]) -> + ok; +pretty_otp4632_msg4_chk([_|Rest0], [_|Rest1]) -> + pretty_otp4632_msg4_chk(Rest0,Rest1). + + +pretty_otp4710_msg1(suite) -> + []; +pretty_otp4710_msg1(Config) when is_list(Config) -> + d("pretty_otp4710_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4710_msg1(), + case encode_message(megaco_pretty_text_encoder, [], Msg0) of + {ok, Bin} when is_binary(Bin) -> + {ok, Msg1} = decode_message(megaco_pretty_text_encoder, false, + [], Bin), + ok = chk_MegacoMessage(Msg0,Msg1); + Else -> + t("pretty_otp4710_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4710_msg1() -> + msg40(). + + +pretty_otp4710_msg2(suite) -> + []; +pretty_otp4710_msg2(Config) when is_list(Config) -> + d("pretty_otp4710_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4710_msg2(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {ok, Msg} when is_record(Msg, 'MegacoMessage') -> + {ok, Bin1} = encode_message(megaco_pretty_text_encoder, [], Msg), + Msg1 = binary_to_list(Bin1), + %% io:format("Msg1:~n~s~n", [Msg1]), + pretty_otp4710_msg2_chk(Msg0,Msg1); + Else -> + t("pretty_otp4710_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4710_msg2() -> + "Authentication = 0xEFCDAB89:0x12345678:0x1234567889ABCDEF76543210\nMEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = \"901 mg col boot\"\n\t\t\t}\n\t\t}\n\t}\n}". + +pretty_otp4710_msg2_chk(Msg,Msg) -> + ok; +pretty_otp4710_msg2_chk( + [$A,$u,$t,$h,$e,$n,$t,$i,$c,$a,$t,$i,$o,$n,$=,$ |Msg0], + [$A,$u,$t,$h,$e,$n,$t,$i,$c,$a,$t,$i,$o,$n,$=,$ |Msg1]) -> + {AH0, Rest0} = pretty_otp4710_msg2_chk_ah(Msg0, []), + {AH1, Rest1} = pretty_otp4710_msg2_chk_ah(Msg1, []), + case AH0 == AH1 of + true -> + exit({message_not_equal, Rest0, Rest1}); + false -> + exit({auth_header_not_equal, AH0, AH1}) + end. + +pretty_otp4710_msg2_chk_ah([], _Acc) -> + exit(no_auth_header_found); +pretty_otp4710_msg2_chk_ah([$M,$E,$G,$A,$C,$O,$/,_|Rest], Acc) -> + {lists:reverse(Acc), Rest}; +pretty_otp4710_msg2_chk_ah([C|R], Acc) -> + pretty_otp4710_msg2_chk_ah(R, [C|Acc]). + + +pretty_otp4945_msg1(suite) -> + []; +pretty_otp4945_msg1(Config) when is_list(Config) -> + d("pretty_otp4945_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg1(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {missing_required_serviceChangeParm, [serviceChangeReason]} -> + ok; + Else -> + t("pretty_otp4945_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + io:format("pretty_otp4945_msg1 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg2(suite) -> + []; +pretty_otp4945_msg2(Config) when is_list(Config) -> + d("pretty_otp4945_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg2(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {missing_required_serviceChangeParm, [serviceChangeMethod]} -> + ok; + Else -> + t("pretty_otp4945_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg2() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg3(suite) -> + []; +pretty_otp4945_msg3(Config) when is_list(Config) -> + d("pretty_otp4945_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg3(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {missing_required_serviceChangeParm, [serviceChangeReason, serviceChangeMethod]} -> + ok; + {missing_required_serviceChangeParm, [serviceChangeMethod, serviceChangeReason]} -> + ok; + Else -> + t("pretty_otp4945_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg3() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg4(suite) -> + []; +pretty_otp4945_msg4(Config) when is_list(Config) -> + d("pretty_otp4945_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg4(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {ok, _} -> + ok; + Else -> + t("pretty_otp4945_msg4 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg4() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg5(suite) -> + []; +pretty_otp4945_msg5(Config) when is_list(Config) -> + d("pretty_otp4945_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg5(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {at_most_once_serviceChangeParm, {profile, _Val1, _Val2}} -> + ok; + Else -> + io:format("pretty_otp4945_msg6 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg5 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg5() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + Profile = ResGW/1, + ServiceChangeAddress = 55555, + Profile = ResGW/2 + } + } + } +}". + + +pretty_otp4945_msg6(suite) -> + []; +pretty_otp4945_msg6(Config) when is_list(Config) -> + d("pretty_otp4945_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg6(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {not_both_address_mgcid_serviceChangeParm, _Val1, _Val2} -> + ok; + Else -> + io:format("pretty_otp4945_msg6 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg6 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg6() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + MgcIdToTry = kalle, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4949_msg1(suite) -> + []; +pretty_otp4949_msg1(Config) when is_list(Config) -> + d("pretty_otp4949_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4949_msg1(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {ok, _} -> + ok; + Else -> + t("pretty_otp4949_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4949_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4949_msg2(suite) -> + []; +pretty_otp4949_msg2(Config) when is_list(Config) -> + d("pretty_otp4949_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4949_msg2(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {at_most_once_servChgReplyParm, {profile, _Val1, _Val2}} -> + ok; + Else -> + io:format("pretty_otp4949_msg2 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4949_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4949_msg2() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Profile = ResGW/1, + ServiceChangeAddress = 55555, + Profile = ResGW/2 + } + } + } +}". + + +pretty_otp4949_msg3(suite) -> + []; +pretty_otp4949_msg3(Config) when is_list(Config) -> + d("pretty_otp4949_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4949_msg3(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {not_both_address_mgcid_servChgReplyParm, _Val1, _Val2} -> + ok; + Else -> + io:format("pretty_otp4949_msg3 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4949_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4949_msg3() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + MgcIdToTry = kalle, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp5042_msg1(suite) -> + []; +pretty_otp5042_msg1(Config) when is_list(Config) -> + d("pretty_otp5042_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp5042_msg1(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {_, _Mod, {not_an_integer, PropertyParm}} -> + exit({not_an_integer, PropertyParm}); + _ -> + io:format("pretty_otp5042_msg1 -> " + "~n Reason: ~w" + "~n", [Reason]), + exit({unexpected_decode_result, Reason}) + end; + {ok, M} -> + t("pretty_otp5042_msg1 -> successfull decode:" + "~n~p", [M]), + ok + end. + +pretty_otp5042_msg1() -> +"MEGACO/" ?VERSION_STR " <CATAPULT>:2944 +Transaction = 102 { +Context = 5 { Notify = MUX/1 { ObservedEvents = 1 { +h245bh/h245msgin { Stream = 1 +, h245enc = +0270020600088175000653401004100403E802E00180018001780680000034301160000700088175010101007A0100020001800001320000C0000219D005027F0070500100040100021080000319D005027F00504001008000041C001250000700088175010000400280010003000880000518AA027F400006850130008011020100000001030002000300040005000006 + } } + } } }". + + +pretty_otp5068_msg1(suite) -> + []; +pretty_otp5068_msg1(Config) when is_list(Config) -> + d("pretty_otp5068_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = pretty_otp5068_msg1(), + case encode_message(megaco_pretty_text_encoder, [], Msg) of + {error, Reason} -> +% io:format("pretty_otp5068_msg1 -> " +% "~n Reason: ~w" +% "~n", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} -> +% io:format("pretty_otp5068_msg1 -> successfull encode:" +% "~n~s~n", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, [], Bin) of + {ok, _} -> +% io:format("pretty_otp5068_msg1 -> ok~n", []), + ok; + Else -> + %% io:format("~npretty_otp5068_msg1 -> ~n~p~n", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + +pretty_otp5068_msg1() -> +{'MegacoMessage', + asn1_NOVALUE, + {'Message', + 2, + {deviceName,[109,103,51,51]}, + {transactions, + [{transactionReply, + {'TransactionReply', + 190, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', %% Comments: Detta upprepas m�nga g�nger + 0, + asn1_NOVALUE, + asn1_NOVALUE, + [{auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false, + [[99,101,100,101,118,49,47,52,47,49,47,49],[51,49]]}, + [{mediaDescriptor, + {'MediaDescriptor', + {'TerminationStateDescriptor', + [], + asn1_NOVALUE, + inSvc}, + asn1_NOVALUE}}]}}}]}]}}}]}}}. + + +pretty_otp5085_msg1(suite) -> + []; +pretty_otp5085_msg1(Config) when is_list(Config) -> + d("pretty_otp5085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg1()). + +pretty_otp5085_msg2(suite) -> + []; +pretty_otp5085_msg2(Config) when is_list(Config) -> + d("pretty_otp5085_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(error, pretty_otp5085_msg2()). + +pretty_otp5085_msg3(suite) -> + []; +pretty_otp5085_msg3(Config) when is_list(Config) -> + d("pretty_otp5085_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg3()). + +pretty_otp5085_msg4(suite) -> + []; +pretty_otp5085_msg4(Config) when is_list(Config) -> + d("pretty_otp5085_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg4()). + +pretty_otp5085_msg5(suite) -> + []; +pretty_otp5085_msg5(Config) when is_list(Config) -> + d("pretty_otp5085_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg5()). + +pretty_otp5085_msg6(suite) -> + []; +pretty_otp5085_msg6(Config) when is_list(Config) -> + d("pretty_otp5085_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg6()). + +pretty_otp5085_msg7(suite) -> + []; +pretty_otp5085_msg7(Config) when is_list(Config) -> + d("pretty_otp5085_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg7()). + +pretty_otp5085(Expected, Msg) -> + pretty_otp5085(Expected, Msg, []). + +pretty_otp5085(Expected, Msg, Conf) -> + t("pretty_otp5085 -> entry with" + "~n Expected: ~p" + "~n Msg: ~p", [Expected, Msg]), + case (catch encode_message(megaco_pretty_text_encoder, Conf, Msg)) of + {error, Reason} when Expected =:= error -> + d("pretty_otp5085 -> encode failed as expected" + "~n Reason: ~w", [Reason]), + ok; + {error, Reason} -> + e("pretty_otp5085 -> encode failed unexpectedly: " + "~n Reason: ~w", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} when Expected =:= error -> + e("pretty_otp5085 -> encode succeded unexpectedly: " + "~n ~w", [binary_to_list(Bin)]), + exit({unexpected_encode_result, binary_to_list(Bin)}); + {ok, Bin} -> + d("pretty_otp5085 -> successfull encode as expected:" + "~n~s", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, Conf, Bin) of + {ok, Msg} -> + d("pretty_otp5085 -> successfull decode~n", []), + ok; + {ok, Msg2} -> + e("pretty_otp5085 -> successfull decode" + " - but not equal", []), + exit({unexpected_decode_result, Msg, Msg2}); + Else -> + e("pretty_otp5085 -> decode failed:~n~p", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + +pretty_otp5085_msg1() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + asn1_NOVALUE, + [] + } + ] + } + } + } + ] + } + } + }. + +pretty_otp5085_msg2() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + asn1_NOVALUE, + [] + } + ] + } + } + } + ] + } + } + }. + +pretty_otp5085_msg3() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + #'ContextRequest'{priority = 3}, + [] + } + ] + } + } + } + ] + } + } + }. + +pretty_otp5085_msg4() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + asn1_NOVALUE, + [{addReply, cre_ammsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_notifyReply([#megaco_term_id{id = ?A5555}])}] + } + ] + } + } + } + ] + } + } + }. + +pretty_otp5085_msg5() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + #'ContextRequest'{priority = 5}, + [{addReply, cre_ammsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_notifyReply([#megaco_term_id{id = ?A5555}])}] + } + ] + } + } + } + ] + } + } + }. + +pretty_otp5085_msg6() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 6}, + [{addReply, cre_ammsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_notifyReply([#megaco_term_id{id = ?A5555}])}] + } + ] + } + } + } + ] + } + } + }. + +pretty_otp5085_msg7() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 7}, + [{notifyReply, cre_notifyReply([#megaco_term_id{id = ?A5555}])}] + } + ] + } + } + } + ] + } + } + }. + + +pretty_otp5600_msg1(suite) -> + []; +pretty_otp5600_msg1(Config) when is_list(Config) -> + d("pretty_otp5600_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5600(ok, pretty_otp5600_msg1()). + +pretty_otp5600_msg2(suite) -> + []; +pretty_otp5600_msg2(Config) when is_list(Config) -> + d("pretty_otp5600_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), +%% put(severity,trc), +%% put(dbg,true), + pretty_otp5600(ok, pretty_otp5600_msg2()). + +pretty_otp5600(Expected, Msg) -> + pretty_otp5600(Expected, Msg, []). + +pretty_otp5600(Expected, Msg, Conf) -> + t("pretty_otp5600 -> entry with" + "~n Expected: ~p" + "~n Msg: ~p", [Expected, Msg]), + case (catch encode_message(megaco_pretty_text_encoder, Conf, Msg)) of + {error, Reason} when Expected =:= error -> + d("pretty_otp5600 -> encode failed as expected" + "~n Reason: ~w", [Reason]), + ok; + {error, Reason} -> + e("pretty_otp5600 -> encode failed unexpectedly: " + "~n Reason: ~w", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} when Expected =:= error -> + e("pretty_otp5600 -> encode succeded unexpectedly: " + "~n ~w", [binary_to_list(Bin)]), + exit({unexpected_encode_result, binary_to_list(Bin)}); + {ok, Bin} -> + d("pretty_otp5600 -> successfull encode as expected:" + "~n~s", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, Conf, Bin) of + {ok, Msg} -> + d("pretty_otp5600 -> successfull decode~n", []), + ok; + {ok, Msg2} -> + e("pretty_otp5600 -> successfull decode" + " - but not equal", []), + exit({unexpected_decode_result, Msg, Msg2}); + Else -> + e("pretty_otp5600 -> decode failed:~n~p", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + +pretty_otp5600_msg1() -> + SRE = #'SecondRequestedEvent'{ pkgdName = "al/on", + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE ] }, + + SIG = { signal, #'Signal'{ signalName = "cg/dt", + sigParList = [] } }, + + RA = #'RequestedActions'{ secondEvent = SED, + signalsDescriptor = [ SIG ] }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + +pretty_otp5600_msg2() -> + SIG = { signal, #'Signal'{ signalName = "cg/dt", + sigParList = [] } }, + + SRA = #'SecondRequestedActions'{ signalsDescriptor = [ SIG ] }, + + SRE = #'SecondRequestedEvent'{ pkgdName = "al/on", + eventAction = SRA, + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE ] }, + + RA = #'RequestedActions'{ secondEvent = SED }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + + +pretty_otp5601_msg1(suite) -> + []; +pretty_otp5601_msg1(Config) when is_list(Config) -> + d("pretty_otp5601_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5601(ok, pretty_otp5601_msg1()). + +pretty_otp5601(Expected, Msg) -> + pretty_otp5601(Expected, Msg, []). + +pretty_otp5601(Expected, Msg, Conf) -> + t("pretty_otp5601 -> entry with" + "~n Expected: ~p" + "~n Msg: ~p", [Expected, Msg]), + case (catch encode_message(megaco_pretty_text_encoder, Conf, Msg)) of + {error, Reason} when Expected =:= error -> + d("pretty_otp5601 -> encode failed as expected" + "~n Reason: ~w", [Reason]), + ok; + {error, Reason} -> + e("pretty_otp5601 -> encode failed unexpectedly: " + "~n Reason: ~w", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} when Expected =:= error -> + e("pretty_otp5601 -> encode succeded unexpectedly: " + "~n ~w", [binary_to_list(Bin)]), + exit({unexpected_encode_result, binary_to_list(Bin)}); + {ok, Bin} -> + d("pretty_otp5601 -> successfull encode as expected:" + "~n~s", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, Conf, Bin) of + {ok, Msg} -> + d("pretty_otp5601 -> successfull decode~n", []), + ok; + {ok, Msg2} -> + e("pretty_otp5601 -> successfull decode" + " - but not equal", []), + exit({unexpected_decode_result, Msg, Msg2}); + Else -> + e("pretty_otp5601 -> decode failed:~n~p", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + +pretty_otp5601_msg1() -> + SRE1 = #'SecondRequestedEvent'{ pkgdName = "al/on", + evParList = [] }, + + SRA = #'SecondRequestedActions'{ eventDM = { digitMapName, "dialllan0" }}, + + SRE2 = #'SecondRequestedEvent'{ pkgdName = "dd/ce", + eventAction = SRA, + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE1, SRE2 ] }, + + RA = #'RequestedActions'{ secondEvent = SED }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + +pretty_otp5793_msg01(suite) -> + []; +pretty_otp5793_msg01(Config) when is_list(Config) -> + d("pretty_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), +% put(severity,trc), +% put(dbg,true), + pretty_otp5793(ok, pretty_otp5793_msg1()). + +pretty_otp5793(Expected, Msg) -> + expect_codec(Expected, megaco_pretty_text_encoder, Msg, []). + +pretty_otp5793(Expected, Msg, Conf) -> + expect_codec(Expected, megaco_pretty_text_encoder, Msg, Conf). + + +pretty_otp5793_msg1() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',2, + {deviceName,"bs_sbg_4/99"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 370, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 3, + asn1_NOVALUE, + asn1_NOVALUE, + [{auditValueReply, + {contextAuditResult, + [{megaco_term_id, + false, + ["ip", + "104", + "1", + "18"]}]}}, + {auditValueReply, + {contextAuditResult, + [{megaco_term_id, + false, + ["ip", + "104", + "2", + "19"]}]}}]}]}}}]}}}. + + +pretty_otp5882_msg01(suite) -> + []; +pretty_otp5882_msg01(Config) when is_list(Config) -> + d("pretty_otp5882_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5882(). + +pretty_otp5882() -> + otp5882(megaco_pretty_text_encoder, []). + +otp5882(Codec, Conf) -> + Msg = pretty_otp5882_msg01(), + case (catch encode_message(Codec, Conf, Msg)) of + {error, {message_encode_failed, {error, {ActualReason, _}}, _}} -> + case ActualReason of + {invalid_LocalControlDescriptor, empty} -> + ok; + _ -> + exit({unexpected_error_actual_reason, ActualReason}) + end; + {error, Reason} -> + exit({unexpected_error_reason, Reason}); + {ok, Bin} -> + exit({unexpected_encode_sucess, binary_to_list(Bin)}) + end. + +pretty_otp5882_msg01() -> + LCD = #'LocalControlDescriptor'{}, % Create illegal LCD + Parms = cre_streamParms(LCD), + StreamDesc = cre_streamDesc(1, Parms), + MediaDesc = cre_mediaDesc(StreamDesc), + AmmReq = cre_ammReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + CmdReq = cre_commandReq({modReq, AmmReq}), + ActReq = #'ActionRequest'{contextId = 5882, + commandRequests = [CmdReq]}, + Actions = [ActReq], + TransReq = #'TransactionRequest'{transactionId = 5882, + actions = Actions}, + Trans = {transactionRequest, TransReq}, + Body = {transactions, [Trans]}, + Mid = ?MG1_MID, + megaco_message(?VERSION, Mid, Body). + + +%% -------------------------------------------------------------- +%% +pretty_otp6490_msg01(suite) -> + []; +pretty_otp6490_msg01(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg01 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg01(), [] ), + %% erase(dbg), + %% erase(severity), + ok. + +pretty_otp6490_msg02(suite) -> + []; +pretty_otp6490_msg02(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg02 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg02(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg03(suite) -> + []; +pretty_otp6490_msg03(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg03 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg03(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg04(suite) -> + []; +pretty_otp6490_msg04(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg04 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg04(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg05(suite) -> + []; +pretty_otp6490_msg05(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg05 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg05(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg06(suite) -> + []; +pretty_otp6490_msg06(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg06 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg06(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490(Msg, Conf) -> + pretty_otp6490(Msg, Conf, ok). + +pretty_otp6490(Msg, Conf, ExpectedEncode) -> + pretty_otp6490(Msg, Conf, ExpectedEncode, ok). + +pretty_otp6490(Msg, Conf, ExpectedEncode, ExpectedDecode) -> + otp6490(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode). + +otp6490(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode) -> + case (catch encode_message(Codec, Conf, Msg)) of + {error, _Reason} when ExpectedEncode =:= error -> + ok; + {error, Reason} when ExpectedEncode =:= ok -> + exit({unexpected_encode_failure, Reason}); + {ok, Bin} when ExpectedEncode =:= error -> + exit({unexpected_encode_success, Msg, binary_to_list(Bin)}); + {ok, Bin} when ExpectedEncode =:= ok -> + case decode_message(Codec, false, Conf, Bin) of + {ok, Msg} when ExpectedDecode == ok -> + ok; + {ok, Msg} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg}); + {ok, Msg2} when ExpectedDecode =:= ok -> + exit({unexpected_decode_result, Msg, Msg2}); + {ok, Msg2} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg, Msg2}); + {error, _Reason} when ExpectedDecode =:= error -> + ok; + {error, Reason} when ExpectedDecode =:= ok -> + exit({unexpected_decode_failure, Msg, Reason}) + end + end. + + +pretty_otp6490_msg(EBD) -> + AmmDesc = ?MSG_LIB:cre_AmmDescriptor(EBD), + AmmReq = cre_ammReq([#megaco_term_id{id = ?A4445}], [AmmDesc]), + CmdReq = cre_commandReq({modReq, AmmReq}), + CID = cre_CtxID(64901), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(64902), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +pretty_otp6490_msg01() -> + EvSpecs = [], % This will result in an error + EBD = EvSpecs, % This is because the lib checks that the size is valid + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg02() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg03() -> + EvPar1 = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + EvPar2 = ?MSG_LIB:cre_EventParameter("kalle", ["anka"]), + EvPar3 = ?MSG_LIB:cre_EventParameter("flippa", ["ur"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar1,EvPar2,EvPar3]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg04() -> + EvPar1 = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + EvPar2 = ?MSG_LIB:cre_EventParameter("kalle", ["anka"]), + EvPar3 = ?MSG_LIB:cre_EventParameter("flippa", ["ur"]), + PkgdName1 = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName1 = ?MSG_LIB:cre_EventName(PkgdName1), + EvSpec1 = ?MSG_LIB:cre_EventSpec(EvName1, [EvPar1,EvPar2,EvPar3]), + EvPar4 = ?MSG_LIB:cre_EventParameter("hej", ["hopp"]), + PkgdName2 = ?MSG_LIB:cre_PkgdName("bar", "b"), + EvName2 = ?MSG_LIB:cre_EventName(PkgdName2), + EvSpec2 = ?MSG_LIB:cre_EventSpec(EvName2, [EvPar4]), + EvSpecs = [EvSpec1,EvSpec2], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg05() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", root), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg06() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName(root, root), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + + +%% -------------------------------------------------------------- +%% + +pretty_otp7671_msg01(suite) -> + []; +pretty_otp7671_msg01(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg01 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg01(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg02(suite) -> + []; +pretty_otp7671_msg02(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg02 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg02(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg03(suite) -> + []; +pretty_otp7671_msg03(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg03 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg03(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg04(suite) -> + []; +pretty_otp7671_msg04(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg04 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg04(), [] , error, ignore), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg05(suite) -> + []; +pretty_otp7671_msg05(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg05 -> entry", []), + Check = fun(M1, M2) -> cmp_otp7671_msg05(M1, M2) end, + ok = pretty_otp7671( pretty_otp7671_msg05(), [] , ok, ok, Check), +%% erase(dbg), +%% erase(severity), + ok. + + +pretty_otp7671(Msg, Conf) -> + pretty_otp7671(Msg, Conf, ok). + +pretty_otp7671(Msg, Conf, ExpectedEncode) -> + pretty_otp7671(Msg, Conf, ExpectedEncode, ok). + +pretty_otp7671(Msg, Conf, ExpectedEncode, ExpectedDecode) -> + otp7671(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode). + +pretty_otp7671(Msg, Conf, ExpectedEncode, ExpectedDecode, Check) -> + otp7671(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode, Check). + +otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode) -> + Check = fun(M1, M2) -> + exit({unexpected_decode_result, M1, M2}) + end, + otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode, Check). + +otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode, Check) -> + case (catch encode_message(Codec, Conf, Msg)) of + {error, _Reason} when ExpectedEncode =:= error -> + ok; + {error, Reason} when ExpectedEncode =:= ok -> + exit({unexpected_encode_failure, Reason}); + {ok, Bin} when ExpectedEncode =:= error -> + exit({unexpected_encode_success, Msg, binary_to_list(Bin)}); + {ok, Bin} when ExpectedEncode =:= ok -> + case decode_message(Codec, false, Conf, Bin) of + {ok, Msg} when ExpectedDecode =:= ok -> + io:format("otp7671 -> decoded:identical~n", []), + ok; + {ok, Msg2} when ExpectedDecode =:= ok -> + Check(Msg, Msg2); + {ok, Msg} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg}); + {ok, Msg2} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg, Msg2}); + {error, _Reason} when ExpectedDecode =:= error -> + ok; + {error, Reason} when ExpectedDecode == ok -> + exit({unexpected_decode_failure, Msg, Reason}) + end + end. + + +pretty_otp7671_msg(DigitMapDesc) -> + AmmReq = cre_ammReq([#megaco_term_id{id = ?A4444}], + [{digitMapDescriptor, DigitMapDesc}]), + CmdReq = cre_commandReq({modReq, AmmReq}), + msg_request(?MGC_MID, 10001, ?megaco_null_context_id, [CmdReq]). + +pretty_otp7671_msg01() -> + Name = "dialplan01", + DigitMapDesc = cre_digitMapDesc(Name), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg02() -> + Name = "dialplan02", + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_digitMapValue(Body), + DigitMapDesc = cre_digitMapDesc(Name, Value), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg03() -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_digitMapValue(Body), + DigitMapDesc = cre_digitMapDesc(Value), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg04() -> + DigitMapDesc = cre_digitMapDesc(asn1_NOVALUE, asn1_NOVALUE), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg05() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',?VERSION, + {domainName,{'DomainName',"tgc",asn1_NOVALUE}}, + {transactions, + [{transactionRequest, + {'TransactionRequest',12582952, + [{'ActionRequest',0,asn1_NOVALUE,asn1_NOVALUE, + [{'CommandRequest', + {modReq, + {'AmmRequest', + [{megaco_term_id,false,["root"]}], + [{digitMapDescriptor, + {'DigitMapDescriptor',"dialplan1", + {'DigitMapValue',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,[]}}}]}}, + asn1_NOVALUE,asn1_NOVALUE}]}]}}]}}}. + +cmp_otp7671_msg05(#'MegacoMessage'{authHeader = asn1_NOVALUE, + mess = M1}, + #'MegacoMessage'{authHeader = asn1_NOVALUE, + mess = M2}) -> + #'Message'{messageBody = Body1} = M1, + #'Message'{messageBody = Body2} = M2, + {transactions, Trans1} = Body1, + {transactions, Trans2} = Body2, + [{transactionRequest, TR1}] = Trans1, + [{transactionRequest, TR2}] = Trans2, + #'TransactionRequest'{actions = Acts1} = TR1, + #'TransactionRequest'{actions = Acts2} = TR2, + [#'ActionRequest'{commandRequests = CR1}] = Acts1, + [#'ActionRequest'{commandRequests = CR2}] = Acts2, + [#'CommandRequest'{command = Cmd1}] = CR1, + [#'CommandRequest'{command = Cmd2}] = CR2, + {modReq, #'AmmRequest'{descriptors = Descs1}} = Cmd1, + {modReq, #'AmmRequest'{descriptors = Descs2}} = Cmd2, + [{digitMapDescriptor, + #'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value1}}] = Descs1, + [{digitMapDescriptor, + #'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value2}}] = Descs2, + #'DigitMapValue'{startTimer = asn1_NOVALUE, + shortTimer = asn1_NOVALUE, + longTimer = asn1_NOVALUE, + digitMapBody = []} = Value1, + asn1_NOVALUE = Value2, + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +expect_codec(Expect, Codec, Msg, Conf) -> + t("expect_codec -> entry with" + "~n Expect: ~p" + "~n Msg: ~p", [Expect, Msg]), + case (catch encode_message(Codec, Conf, Msg)) of + {error, _Reason} when Expect =:= error -> + d("expect_codec -> encode failed as expected" + "~n _Reason: ~w", [_Reason]), + ok; + {error, Reason} -> + e("expect_codec -> encode failed unexpectedly: " + "~n Reason: ~w", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} when Expect =:= error -> + e("expect_codec -> encode succeded unexpectedly: " + "~n ~w", [binary_to_list(Bin)]), + exit({unexpected_encode_result, binary_to_list(Bin)}); + {ok, Bin} -> + d("expect_codec -> successfull encode as expected:" + "~n~s", [binary_to_list(Bin)]), + case (catch decode_message(Codec, false, Conf, Bin)) of + {ok, Msg} -> + d("expect_codec -> successfull decode~n", []), + ok; + {ok, Msg2} -> + e("expect_codec -> successfull decode" + " - but not equal", []), + chk_MegacoMessage(Msg, Msg2); + %% exit({unexpected_decode_result, Msg, Msg2}); + Else -> + e("expect_codec -> decode failed:~n~p", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + e("expect_codec -> encode failed:~n~p", [Else]), + exit({unexpected_encode_result, Else}) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +msgs() -> + Msgs = msgs1() ++ msgs2() ++ msgs3(), + [M || {_, M, _, _} <- Msgs]. + +msgs1() -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [ + {msg01a, msg1a(), Plain, [{dbg,false}]}, + {msg01b, msg1b(), Plain, [{dbg,false}]}, + {msg02, msg2(), Plain, [{dbg,false}]}, + {msg03, msg3(), Plain, [{dbg,false}]}, + {msg04, msg4(), Plain, [{dbg,false}]}, + {msg05, msg5(), Plain, [{dbg,false}]}, + {msg06a, msg6a(), Plain, [{dbg,false}]}, + {msg06b, msg6b(), Plain, [{dbg,false}]}, + {msg07, msg7(), Plain, [{dbg,false}]}, + {msg08a, msg8a(), Plain, [{dbg,false}]}, + {msg08b, msg8b(), Plain, [{dbg,false}]}, + {msg09, msg9(), Plain, [{dbg,false}]}, + {msg10, msg10(), Plain, [{dbg,false}]}, + {msg11, msg11(), Plain, [{dbg,false}]}, + {msg12, msg12(), Plain, [{dbg,false}]}, + {msg13, msg13(), Plain, [{dbg,false}]}, + {msg14, msg14(), Plain, [{dbg,false}]}, + {msg15, msg15(), Plain, [{dbg,false}]}, + {msg16, msg16(), Plain, [{dbg,false}]}, + {msg17, msg17(), Plain, [{dbg,false}]}, + {msg18, msg18(), Plain, [{dbg,false}]}, + {msg19, msg19(), Plain, [{dbg,false}]}, + {msg20, msg20(), Plain, [{dbg,false}]}, + {msg21, msg21(), Plain, [{dbg,false}]}, + {msg22a, msg22a(), Plain, [{dbg,false}]}, + {msg22b, msg22b(), Plain, [{dbg,false}]}, + {msg22c, msg22c(), Plain, [{dbg,false}]}, + {msg22d, msg22d(), Plain, [{dbg,false}]}, + {msg22e, msg22e(), Plain, [{dbg,false}]}, + {msg22f, msg22f(), Plain, [{dbg,false}]}, + {msg23a, msg23a(), Plain, [{dbg,false}]}, + {msg23b, msg23b(), Plain, [{dbg,false}]}, + {msg23c, msg23c(), Plain, [{dbg,false}]}, + {msg23d, msg23d(), Plain, [{dbg,false}]}, + {msg24, msg24(), Plain, [{dbg,false}]}, + {msg25, msg25(), Plain, [{dbg,false}]}, + {msg30a, msg30a(), Plain, [{dbg,false}]}, + {msg30b, msg30b(), Plain, [{dbg,false}]}, + {msg30c, msg30c(), Plain, [{dbg,false}]}, + {msg30d, msg30d(), Plain, [{dbg,false}]} + ]. + +msgs2() -> + TransFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:trans_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + ActionsFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:actions_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + ActionFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:action_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + [ + {msg01a_tf, msg1a(), TransFirst, [{dbg,false}]}, + {msg02_tf, msg2(), TransFirst, [{dbg,false}]}, + {msg10_tf, msg10(), TransFirst, [{dbg,false}]}, + {msg11_tf, msg11(), TransFirst, [{dbg,false}]}, + {msg23d_tf, msg23d(), TransFirst, [{dbg,false}]}, + {msg30b_tf, msg30b(), TransFirst, [{dbg,false}]}, + {msg30c_tf, msg30c(), TransFirst, [{dbg,false}]}, + {msg01a_asf, msg1a(), ActionsFirst, [{dbg,false}]}, + {msg02_asf, msg2(), ActionsFirst, [{dbg,false}]}, + {msg10_asf, msg10(), ActionsFirst, [{dbg,false}]}, + {msg23d_asf, msg23d(), ActionsFirst, [{dbg,false}]}, + {msg01a_af, msg1a(), ActionFirst, [{dbg,false}]}, + {msg02_af, msg2(), ActionFirst, [{dbg,false}]}, + {msg10_af, msg10(), ActionFirst, [{dbg,false}]}, + {msg23d_af, msg23d(), ActionFirst, [{dbg,false}]} + ]. + + +msgs3() -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [{msgs3_name(Name), rfc3525_decode(M), Plain, [{dbg, false}]} || + {Name, M} <- rfc3525_msgs()]. + +msgs3_name(N) -> + list_to_atom("rfc3525_" ++ atom_to_list(N)). + +rfc3525_decode(M) when is_list(M) -> + rfc3525_decode(list_to_binary(M)); +rfc3525_decode(M) when is_binary(M) -> + case (catch decode_message(megaco_pretty_text_encoder, false, [], M)) of + {ok, Msg} -> + Msg; + Error -> + {error, {rfc3525_decode_error, Error}} + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +msg_actions([], Actions) -> + lists:reverse(Actions); +msg_actions([{CtxId, CmdReqs}|ActionInfo], Actions) -> + Action = #'ActionRequest'{contextId = CtxId, + commandRequests = CmdReqs}, + msg_actions(ActionInfo, [Action|Actions]). + +megaco_trans_req([], Transactions) -> + {transactions, lists:reverse(Transactions)}; +megaco_trans_req([{TransId, ActionInfo}|TransInfo], Transactions) -> + Actions = msg_actions(ActionInfo, []), + TransReq = {transactionRequest, + #'TransactionRequest'{transactionId = TransId, + actions = Actions}}, + megaco_trans_req(TransInfo, [TransReq|Transactions]). + +megaco_message(Version, Mid, Body) -> + #'MegacoMessage'{mess = #'Message'{version = Version, + mId = Mid, + messageBody = Body}}. + +megaco_message(Auth, Version, Mid, Body) -> + #'MegacoMessage'{authHeader = Auth, + mess = #'Message'{version = Version, + mId = Mid, + messageBody = Body}}. + +msg_request(Mid, TransInfo) -> + TransReq = megaco_trans_req(TransInfo, []), + megaco_message(1, Mid, TransReq). + +msg_request(Mid, TransId, ContextId, CmdReq) when is_list(CmdReq) -> + Actions = [#'ActionRequest'{contextId = ContextId, + commandRequests = CmdReq}], + Req = {transactions, + [{transactionRequest, + #'TransactionRequest'{transactionId = TransId, + actions = Actions}}]}, + megaco_message(?VERSION, Mid, Req). + +msg_request(Auth, Mid, TransId, ContextId, CmdReq) when is_list(CmdReq) -> + Actions = [#'ActionRequest'{contextId = ContextId, + commandRequests = CmdReq}], + Req = {transactions, + [{transactionRequest, + #'TransactionRequest'{transactionId = TransId, + actions = Actions}}]}, + megaco_message(Auth, ?VERSION, Mid, Req). + +msg_reply(Mid, TransId, ContextId, CmdReply) when is_list(CmdReply) -> + ReplyData = [{ContextId, CmdReply}], + msg_replies(Mid, TransId, ReplyData). + +msg_replies(Mid, TransId, ReplyData) when is_list(ReplyData) -> + Actions = [cre_actionReply(ContextId, CmdReply) || + {ContextId, CmdReply} <- ReplyData], + Req = {transactions, + [{transactionReply, cre_transactionReply(TransId, Actions)}]}, + cre_megacoMessage(?VERSION, Mid, Req). + + +msg_ack(Mid, [Range|_] = Ranges) when is_tuple(Range) -> + msg_ack(Mid, [Ranges]); + +msg_ack(Mid, Ranges) -> + %% TRAs = make_tras(Ranges, []), + TRAs = make_tras(Ranges), + Req = {transactions, TRAs}, + cre_megacoMessage(?VERSION, Mid, Req). + +make_tras(TRARanges) -> + F = fun(R) -> {transactionResponseAck, make_tra(R)} end, + lists:map(F, TRARanges). + +make_tra(Ranges) -> + F = fun({F,L}) -> cre_transactionAck(F,L) end, + lists:map(F, Ranges). + + +%% ------------------------------------------------------------------------- + + +msg1(Mid, Tid) -> + Gain = cre_propertyParm("tdmc/gain", "2"), + Ec = cre_propertyParm("tdmc/ec", "g165"), + LCD = cre_localControlDesc(sendRecv,[Gain, Ec]), + V = cre_propertyParm("v", "0"), + %% C = cre_propertyParm("c", "IN IP4 $ "), + C = cre_propertyParm("c", [$I,$N,$ ,$I,$P,$4,$ ,$$,$ ]), + M = cre_propertyParm("m", "audio $ RTP/AVP 0"), + A = cre_propertyParm("a", "fmtp:PCMU VAD=X-NNVAD"), + LD = cre_localRemoteDesc([[V, C, M, A]]), + Parms = cre_streamParms(LCD,LD), + StreamDesc = cre_streamDesc(1,Parms), + MediaDesc = cre_mediaDesc(StreamDesc), + ReqEvent = cre_requestedEvent("al/of"), + EventsDesc = cre_eventsDesc(2222,[ReqEvent]), + AmmReq = cre_ammReq([#megaco_term_id{id = Tid}], + [{mediaDescriptor, MediaDesc}, + {eventsDescriptor, EventsDesc}]), + CmdReq = cre_commandReq({modReq, AmmReq}), + msg_request(Mid, 9999, ?megaco_null_context_id, [CmdReq]). + + +msg1a() -> + msg1a(?MGC_MID). +msg1a(Mid) -> + msg1(Mid, ?A4444). + +msg1b() -> + msg1b(?MGC_MID). +msg1b(Mid) -> + msg1(Mid, ?A4445). + + +%% -------------------------- + + +msg2() -> + msg2(?MGC_MID). +msg2(Mid) -> + msg2(Mid, ?A4444). +msg2(Mid, Tid) -> + Gain = cre_propertyParm("tdmc/gain", "2"), + Ec = cre_propertyParm("tdmc/ec", "g165"), + LCD = cre_localControlDesc(sendRecv,[Gain, Ec]), + V = cre_propertyParm("v", "0"), + %% C = cre_propertyParm("c", "IN IP4 $ "), + C = cre_propertyParm("c", [$I,$N,$ ,$I,$P,$4,$ ,$$,$ ]), + M = cre_propertyParm("m", "audio $ RTP/AVP 0"), + A = cre_propertyParm("a", "fmtp:PCMU VAD=X-NNVAD"), + LD = cre_localRemoteDesc([[V, C, M, A]]), + Parms = cre_streamParms(LCD,LD), + StreamDesc = cre_streamDesc(1,Parms), + MediaDesc = cre_mediaDesc(StreamDesc), + EventParm = cre_eventParm("strict",["exact"]), + ReqEvent = cre_requestedEvent("al/of", [EventParm]), + EventsDesc = cre_eventsDesc(2222,[ReqEvent]), + AmmReq = cre_ammReq([#megaco_term_id{id = Tid}], + [{mediaDescriptor, MediaDesc}, + {eventsDescriptor, EventsDesc}]), + CmdReq = cre_commandReq({modReq, AmmReq}), + msg_request(Mid, 9999, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg3() -> + msg3(?MG1_MID). +msg3(Mid) -> + TimeStamp = cre_timeNotation("19990729", "22000000"), + Event = cre_observedEvent("al/of",TimeStamp), + Desc = cre_observedEventsDesc(2222,[Event]), + NotifyReq = cre_notifyReq([#megaco_term_id{id = ?A4444}],Desc), + CmdReq = cre_commandReq({notifyReq, NotifyReq}), + msg_request(Mid, 10000, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg4() -> + msg4(?MG1_MID_NO_PORT, "901 mg col boot"). +msg4(Mid, Reason) when is_list(Reason) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_serviceChangeProf("resgw",1), + Parm = cre_serviceChangeParm(restart,Address,[Reason],Profile), + Req = cre_serviceChangeReq([?megaco_root_termination_id],Parm), + CmdReq = cre_commandReq({serviceChangeReq, Req}), + msg_request(Mid, 9998, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg5() -> + msg5(?MGC_MID). +msg5(Mid) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_serviceChangeProf("resgw",1), + Parm = cre_serviceChangeResParm(Address,Profile), + Reply = cre_serviceChangeReply([?megaco_root_termination_id], + {serviceChangeResParms,Parm}), + msg_reply(Mid, 9998, ?megaco_null_context_id, + [{serviceChangeReply, Reply}]). + + +%% -------------------------- + +msg6(Mid, Tid) -> + Reply = cre_ammsReply([#megaco_term_id{id = Tid}]), + msg_reply(Mid, 9999, ?megaco_null_context_id, [{modReply, Reply}]). + +msg6a() -> + msg6a(?MG1_MID). +msg6a(Mid) -> + msg6(Mid, ?A4444). + +msg6b() -> + msg6b(?MG2_MID). +msg6b(Mid) -> + msg6(Mid, ?A5555). + + +%% -------------------------- + +msg7() -> + msg7(?MGC_MID). +msg7(Mid) -> + Reply = cre_notifyReply([#megaco_term_id{id = ?A4444}]), + msg_reply(Mid, 10000, ?megaco_null_context_id, [{notifyReply, Reply}]). + + +%% -------------------------- + +msg8(Mid, DigitMapValue) -> + Strict = cre_eventParm("strict",["state"]), + On = cre_requestedEvent("al/on", [Strict]), + Name = "dialplan00", + Action = cre_requestedActions(Name), + Ce = cre_requestedEvent("dd/ce", Action), + EventsDesc = cre_eventsDesc(2223,[On, Ce]), + Signal = cre_signal("cg/rt"), + DigMapDesc = cre_digitMapDesc(Name, DigitMapValue), + AmmReq = cre_ammReq([#megaco_term_id{id = ?A4444}], + [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, [{signal, Signal}]}, + {digitMapDescriptor, DigMapDesc}]), + CmdReq = cre_commandReq({modReq, AmmReq}), + msg_request(Mid, 10001, ?megaco_null_context_id, [CmdReq]). + +msg8a() -> + msg8a(?MGC_MID). +msg8a(Mid) -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_digitMapValue(Body), + msg8(Mid, Value). + +msg8b() -> + msg8b(?MGC_MID). +msg8b(Mid) -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_digitMapValue(Body, 1, 23, 99), + msg8(Mid, Value). + + +%% -------------------------- + +msg9() -> + msg9(?MG1_MID). +msg9(Mid) -> + TimeStamp = cre_timeNotation("19990729","22010001"), + Parm = cre_eventParm("ds",["916135551212"]), + Event = cre_observedEvent("dd/ce",TimeStamp,[Parm]), + Desc = cre_observedEventsDesc(2223,[Event]), + NotifyReq = cre_notifyReq([#megaco_term_id{id = ?A4444}], Desc), + CmdReq = cre_commandReq({notifyReq, NotifyReq}), + msg_request(Mid, 10002, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg10() -> + msg10(?MGC_MID). +msg10(Mid) -> + AmmReq = cre_ammReq([#megaco_term_id{id = ?A4444}],[]), + CmdReq = cre_commandReq({addReq, AmmReq}), + Jit = cre_propertyParm("nt/jit", "40"), + LCD = cre_localControlDesc(recvOnly,[Jit]), + V = cre_propertyParm("v", "0"), + C = cre_propertyParm("c", "IN IP4 $ "), + M = cre_propertyParm("m", "audio $ RTP/AVP 4"), + A = cre_propertyParm("a", "ptime:30"), + V2 = cre_propertyParm("v", "0"), + C2 = cre_propertyParm("c", "IN IP4 $ "), + M2 = cre_propertyParm("m", "audio $ RTP/AVP 0"), + LD = cre_localRemoteDesc([[V, C, M, A], [V2, C2, M2]]), + Parms = cre_streamParms(LCD, LD), + StreamDesc = cre_streamDesc(1,Parms), + MediaDesc = cre_mediaDesc(StreamDesc), + ChooseTid = #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}, + AmmReq2 = cre_ammReq([ChooseTid],[{mediaDescriptor, MediaDesc}]), + CmdReq2 = cre_commandReq({addReq, AmmReq2}), + msg_request(Mid, 10003, ?megaco_choose_context_id, [CmdReq, CmdReq2]). + + +msg11() -> + msg11(?MG1_MID). +msg11(Mid) -> + V = cre_propertyParm("v", "0"), + C = cre_propertyParm("c", "IN IP4 124.124.124.222"), + M = cre_propertyParm("m", "audio 2222 RTP/AVP 4"), + A = cre_propertyParm("a", "ptime:30"), + A2 = cre_propertyParm("a", "recvonly"), + LD = cre_localRemoteDesc([[V, C, M, A, A2]]), + Parms = cre_streamParmsL(LD), + StreamDesc = cre_streamDesc(1, Parms), + MediaDesc = cre_mediaDesc(StreamDesc), + Reply = cre_ammsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_ammsReply([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + msg_reply(Mid, 10003, 2000, [{addReply, Reply}, {addReply, Reply2}]). + + +%% -------------------------- + +msg12() -> + msg12(?MGC_MID). +msg12(Mid) -> + LCD = cre_localControlDesc(sendRecv), + Parms = cre_streamParms(LCD), + StreamDesc = cre_streamDesc(1,Parms), + MediaDesc = cre_mediaDesc(StreamDesc), + Signal = cre_signal("al/ri"), + Descs = [{mediaDescriptor, MediaDesc}, + {signalsDescriptor, [{signal, Signal}]}], + AmmReq = cre_ammReq([#megaco_term_id{id = ?A5555}], Descs), + CmdReq = cre_commandReq({addReq, AmmReq}), + Jit = cre_propertyParm("nt/jit", "40"), + LCD2 = cre_localControlDesc(sendRecv, [Jit]), + V = cre_propertyParm("v", "0"), + C = cre_propertyParm("c", "IN IP4 $ "), + M = cre_propertyParm("m", "audio $ RTP/AVP 4"), + A = cre_propertyParm("a", "ptime:30"), + LD2 = cre_localRemoteDesc([[V, C, M, A]]), + V2 = cre_propertyParm("v", "0"), + C2 = cre_propertyParm("c", "IN IP4 124.124.124.222"), + M2 = cre_propertyParm("m", "audio 2222 RTP/AVP 4"), + RD2 = cre_localRemoteDesc([[V2, C2, M2]]), + Parms2 = cre_streamParms(LCD2,LD2,RD2), + StreamDesc2 = cre_streamDesc(1,Parms2), + MediaDesc2 = cre_mediaDesc(StreamDesc2), + ChooseTid = #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}, + AmmReq2 = cre_ammReq([ChooseTid],[{mediaDescriptor, MediaDesc2}]), + CmdReq2 = cre_commandReq({addReq, AmmReq2}), + msg_request(Mid, 50003, ?megaco_choose_context_id, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg13() -> + msg13(?MG2_MID). +msg13(Mid) -> + V = cre_propertyParm("v", "0"), + C = cre_propertyParm("c", "IN IP4 125.125.125.111"), + M = cre_propertyParm("m", "audio 1111 RTP/AVP 4"), + LD = cre_localRemoteDesc([[V, C, M]]), + Parms = cre_streamParmsL(LD), + StreamDesc = cre_streamDesc(1,Parms), + MediaDesc = cre_mediaDesc(StreamDesc), + Reply = cre_ammsReply([#megaco_term_id{id = ?A5556}], + [{mediaDescriptor, MediaDesc}]), + msg_reply(Mid, 50003, 5000, [{addReply, Reply}]). + + +%% -------------------------- + +msg14() -> + msg14(?MGC_MID). +msg14(Mid) -> + Signal = cre_signal("cg/rt"), + AmmReq1 = cre_ammReq([#megaco_term_id{id = ?A4444}], + [{signalsDescriptor, [{signal, Signal}]}]), + CmdReq1 = cre_commandReq({modReq, AmmReq1}), + + Gain = cre_propertyParm("tdmc/gain", "2"), + Ec = cre_propertyParm("tdmc/ec", "g165"), + LCD = cre_localControlDesc(sendRecv, [Gain, Ec]), + Parms2 = cre_streamParms(LCD), + StreamDesc2 = cre_streamDesc(1,Parms2), + MediaDesc2 = cre_mediaDesc(StreamDesc2), + AmmReq2 = cre_ammReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc2}]), + CmdReq2 = cre_commandReq({modReq, AmmReq2}), + + V = cre_propertyParm("v", "0"), + C = cre_propertyParm("c", "IN IP4 125.125.125.111"), + M = cre_propertyParm("m", "audio 1111 RTP/AVP 4"), + RD = cre_localRemoteDesc([[V, C, M]]), + Parms3 = cre_streamParmsR(RD), + StreamDesc3 = cre_streamDesc(1,Parms3), + MediaDesc3 = cre_mediaDesc(StreamDesc3), + AmmReq3 = cre_ammReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc3}]), + CmdReq3 = cre_commandReq({modReq, AmmReq3}), + msg_request(Mid, 10005, 2000, [CmdReq1, CmdReq2, CmdReq3]). + + +%% -------------------------- + +msg15() -> + msg15(?MG1_MID). +msg15(Mid) -> + Reply = cre_ammsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_ammsReply([#megaco_term_id{id = ?A4445}]), + msg_reply(Mid, 10005, 2000, [{modReply, Reply}, {modReply, Reply2}]). + + +msg15b() -> + msg15b(?MG1_MID). + +msg15b(Mid) -> + %% We reuse the amms reply stuff + Reply1 = cre_ammsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_ammsReply([#megaco_term_id{id = ?A4445}]), + ActionReplyData = + [{modReply, Reply1}, {modReply, Reply2}], + ReplyData = + [{2001, ActionReplyData}, + {2002, ActionReplyData}, + {2003, ActionReplyData}, + {2004, ActionReplyData}, + {2005, ActionReplyData}, + {2006, ActionReplyData}, + {2007, ActionReplyData}, + {2008, ActionReplyData}, + {2009, ActionReplyData}, + {2010, ActionReplyData}, + {2011, ActionReplyData}, + {2012, ActionReplyData}, + {2013, ActionReplyData}, + {2014, ActionReplyData}, + {2015, ActionReplyData}, + {2016, ActionReplyData}, + {2017, ActionReplyData}, + {2018, ActionReplyData}, + {2019, ActionReplyData}, + {2020, ActionReplyData}, + {2021, ActionReplyData}, + {2022, ActionReplyData}, + {2023, ActionReplyData}, + {2024, ActionReplyData}, + {2025, ActionReplyData}, + {2026, ActionReplyData}, + {2027, ActionReplyData}, + {2028, ActionReplyData}, + {2029, ActionReplyData}, + {2030, ActionReplyData}, + {2031, ActionReplyData}], + msg_replies(Mid, 10005, ReplyData). + + +%% -------------------------- + +msg16() -> + msg16(?MG2_MID). +msg16(Mid) -> + TimeStamp = cre_timeNotation("19990729","22020002"), + Event = cre_observedEvent("al/of",TimeStamp), + Desc = cre_observedEventsDesc(1234,[Event]), + NotifyReq = cre_notifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq = cre_commandReq({notifyReq, NotifyReq}), + msg_request(Mid, 50005, 5000, [CmdReq]). + + +%% -------------------------- + +msg17() -> + msg17(?MGC_MID). +msg17(Mid) -> + Reply = cre_notifyReply([#megaco_term_id{id = ?A5555}]), + msg_reply(Mid, 50005, ?megaco_null_context_id, [{notifyReply, Reply}]). + + +%% -------------------------- + +msg18() -> + msg18(?MGC_MID). +msg18(Mid) -> + On = cre_requestedEvent("al/on"), + EventsDesc = cre_eventsDesc(1235,[On]), + AmmReq = cre_ammReq([#megaco_term_id{id = ?A5555}], + [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, []}]), + CmdReq = cre_commandReq({modReq, AmmReq}), + msg_request(Mid, 50006, 5000, [CmdReq]). + + +%% -------------------------- + +msg19() -> + msg19(?MG2_MID). +msg19(Mid) -> + Reply = cre_ammsReply([#megaco_term_id{id = ?A4445}]), + msg_reply(Mid, 50006, 5000, [{modReply, Reply}]). + + +%% -------------------------- + +msg20() -> + msg20(?MGC_MID). +msg20(Mid) -> + LCD = cre_localControlDesc(sendRecv), + Parms = cre_streamParms(LCD), + StreamDesc = cre_streamDesc(1,Parms), + MediaDesc = cre_mediaDesc(StreamDesc), + AmmReq = cre_ammReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + CmdReq = cre_commandReq({modReq, AmmReq}), + AmmReq2 = cre_ammReq([#megaco_term_id{id = ?A4444}], + [{signalsDescriptor, []}]), + CmdReq2 = cre_commandReq({modReq, AmmReq2}), + msg_request(Mid, 10006, 2000, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg21() -> + msg21(?MGC_MID). +msg21(Mid) -> + Tokens = [mediaToken, eventsToken, signalsToken, + digitMapToken, statsToken, packagesToken], + AuditDesc = cre_auditDesc(Tokens), + Req = cre_auditReq(#megaco_term_id{id = ?A5556},AuditDesc), + CmdReq = cre_commandReq({auditValueRequest, Req}), + msg_request(Mid, 50007, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg22a() -> + msg22(1). + +msg22b() -> + msg22(10). + +msg22c() -> + msg22(25). + +msg22d() -> + msg22(50). + +msg22e() -> + msg22(75). + +msg22f() -> + msg22(100). + +msg22(N) -> + msg22(?MG2_MID, N). +msg22(Mid, N) -> + Jit = cre_propertyParm("nt/jit", "40"), + LCD = cre_localControlDesc(sendRecv,[Jit]), + LDV = cre_propertyParm("v", "0"), + LDC = cre_propertyParm("c", "IN IP4 125.125.125.111"), + LDM = cre_propertyParm("m", "audio 1111 RTP/AVP 4"), + LDA = cre_propertyParm("a", "ptime:30"), + LD = cre_localRemoteDesc([[LDV, LDC, LDM, LDA]]), + RDV = cre_propertyParm("v", "0"), + RDC = cre_propertyParm("c", "IN IP4 124.124.124.222"), + RDM = cre_propertyParm("m", "audio 2222 RTP/AVP 4"), + RDA = cre_propertyParm("a", "ptime:30"), + RD = cre_localRemoteDesc([[RDV, RDC, RDM, RDA]]), + StreamParms = cre_streamParms(LCD,LD,RD), + StreamDesc = cre_streamDesc(1,StreamParms), + Media = cre_mediaDesc(StreamDesc), + PackagesItem = cre_packagesItem("nt",1), + PackagesItem2 = cre_packagesItem("rtp",1), + Stat = cre_statisticsParm("rtp/ps","1200"), + Stat2 = cre_statisticsParm("nt/os","62300"), + Stat3 = cre_statisticsParm("rtp/pr","700"), + Stat4 = cre_statisticsParm("nt/or","45100"), + Stat5 = cre_statisticsParm("rtp/pl","0.2"), + Stat6 = cre_statisticsParm("rtp/jit","20"), + Stat7 = cre_statisticsParm("rtp/delay","40"), + Statistics = [Stat, Stat2, Stat3, Stat4, Stat5, Stat6, Stat7], + Audits = [{mediaDescriptor, Media}, + {packagesDescriptor, [PackagesItem, PackagesItem2]}, + {statisticsDescriptor, Statistics}], + Reply = {auditResult, + cre_auditRes(#megaco_term_id{id = ?A5556},Audits)}, + msg_reply(Mid, 50007, ?megaco_null_context_id, + lists:duplicate(N,{auditValueReply, Reply})). +%% msg_reply(Mid, 50007, ?megaco_null_context_id, +%% lists.duplicate([{auditValueReply, Reply}]). + + +%% -------------------------- + +msg23a() -> + msg23a(?MG2_MID). +msg23a(Mid) -> + TimeStamp = cre_timeNotation("19990729","24020002"), + Event = cre_observedEvent("al/on",TimeStamp), + Desc = cre_observedEventsDesc(1235,[Event]), + NotifyReq = cre_notifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq = cre_commandReq({notifyReq, NotifyReq}), + msg_request(Mid, 50008, 5000, [CmdReq]). + + +msg23b() -> + msg23b(?MG2_MID). +msg23b(Mid) -> + TimeStamp = cre_timeNotation("19990729","24020002"), + Event = cre_observedEvent("al/on",TimeStamp), + Desc = cre_observedEventsDesc(1235,[Event]), + NotifyReq1 = cre_notifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_commandReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_notifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_commandReq({notifyReq, NotifyReq2}), + ActionInfo = [{5000, [CmdReq1]}, {5001, [CmdReq2]}], + TransInfo = [{50008, ActionInfo}], + msg_request(Mid, TransInfo). + + +msg23c() -> + msg23c(?MG2_MID). +msg23c(Mid) -> + TimeStamp = cre_timeNotation("19990729","24020002"), + Event = cre_observedEvent("al/on",TimeStamp), + Desc = cre_observedEventsDesc(1235,[Event]), + NotifyReq1 = cre_notifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_commandReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_notifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_commandReq({notifyReq, NotifyReq2}), + ActionInfo1 = [{5000, [CmdReq1]}], + ActionInfo2 = [{5001, [CmdReq2]}], + TransInfo = [{50008, ActionInfo1}, {50009, ActionInfo2}], + msg_request(Mid, TransInfo). + + +msg23d() -> + msg23d(?MG2_MID). +msg23d(Mid) -> + TimeStamp = cre_timeNotation("19990729","24020002"), + Event = cre_observedEvent("al/on",TimeStamp), + Desc = cre_observedEventsDesc(1235,[Event]), + NotifyReq1 = cre_notifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_commandReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_notifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_commandReq({notifyReq, NotifyReq2}), + NotifyReq3 = cre_notifyReq([#megaco_term_id{id = ?A4444}],Desc), + CmdReq3 = cre_commandReq({notifyReq, NotifyReq3}), + NotifyReq4 = cre_notifyReq([#megaco_term_id{id = ?A4445}],Desc), + CmdReq4 = cre_commandReq({notifyReq, NotifyReq4}), + ActionInfo1 = [{5000, [CmdReq1]}, {5001, [CmdReq2]}], + ActionInfo2 = [{5003, [CmdReq3]}, {5004, [CmdReq4]}], + TransInfo = [{50008, ActionInfo1}, {50009, ActionInfo2}], + msg_request(Mid, TransInfo). + + +%% -------------------------- + +msg24() -> + msg24(?MGC_MID). +msg24(Mid) -> + AuditDesc = cre_auditDesc([statsToken]), + SubReq = cre_subtractReq([#megaco_term_id{id = ?A5555}], AuditDesc), + SubReq2 = cre_subtractReq([#megaco_term_id{id = ?A5556}], AuditDesc), + CmdReq = cre_commandReq({subtractReq, SubReq}), + CmdReq2 = cre_commandReq({subtractReq, SubReq2}), + msg_request(Mid, 50009, 5000, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg25() -> + msg25(?MG2_MID). +msg25(Mid) -> + Stat11 = cre_statisticsParm("nt/os","45123"), + Stat12 = cre_statisticsParm("nt/dur", "40"), + Stats1 = [Stat11, Stat12], + Reply1 = cre_ammsReply([#megaco_term_id{id = ?A5555}], + [{statisticsDescriptor, Stats1}]), + Stat21 = cre_statisticsParm("rtp/ps","1245"), + Stat22 = cre_statisticsParm("nt/os", "62345"), + Stat23 = cre_statisticsParm("rtp/pr", "780"), + Stat24 = cre_statisticsParm("nt/or", "45123"), + Stat25 = cre_statisticsParm("rtp/pl", "10"), + Stat26 = cre_statisticsParm("rtp/jit", "27"), + Stat27 = cre_statisticsParm("rtp/delay","48"), + Stats2 = [Stat21, Stat22, Stat23, Stat24, Stat25, Stat26, Stat27], + Reply2 = cre_ammsReply([#megaco_term_id{id = ?A5556}], + [{statisticsDescriptor, Stats2}]), + msg_reply(Mid, 50009, 5000, + [{subtractReply, Reply1}, {subtractReply, Reply2}]). + + +msg30a() -> + msg_ack(?MG2_MID, [{9,9}]). + +msg30b() -> + msg_ack(?MG2_MID, [{9,13}]). + +msg30c() -> + msg_ack(?MG2_MID, + [{9,13}, {15,15}, {33,40}, {50,60}, {70,80}, {85,90}, + {101,105},{109,119},{121,130},{140,160},{170,175},{180,189}, + {201,205},{209,219},{221,230},{240,260},{270,275},{280,289}, + {301,305},{309,319},{321,330},{340,360},{370,375},{380,389}, + {401,405},{409,419},{421,430},{440,460},{470,475},{480,489}, + {501,505},{509,519},{521,530},{540,560},{570,575},{580,589} + ]). + +%% Don't think this will be used by the megaco stack, but since it +%% seem's to be a valid construction... +msg30d() -> + msg_ack(?MG2_MID, + [[{9,13}, {15,15}, {33,40}, {50,60}, {70,80}, {85,90}], + [{101,105},{109,119},{121,130},{140,160},{170,175},{180,189}], + [{201,205},{209,219},{221,230},{240,260},{270,275},{280,289}], + [{301,305},{309,319},{321,330},{340,360},{370,375},{380,389}], + [{401,405},{409,419},{421,430},{440,460},{470,475},{480,489}], + [{501,505},{509,519},{521,530},{540,560},{570,575},{580,589}] + ]). + + + +msg40() -> + msg40(?MG1_MID_NO_PORT, "901 mg col boot"). +msg40(Mid, Reason) when is_list(Reason) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_serviceChangeProf("resgw",1), + Parm = cre_serviceChangeParm(restart,Address,[Reason],Profile), + Req = cre_serviceChangeReq([?megaco_root_termination_id],Parm), + CmdReq = cre_commandReq({serviceChangeReq, Req}), + Auth = cre_authHeader(), + msg_request(Auth, Mid, 9998, ?megaco_null_context_id, [CmdReq]). + + +%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +%% Pretty RFC 3525 messages: + +%% Added Reason +rfc3525_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + +rfc3525_msg2() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +%% Removed "," after LocalControl ending "}" +rfc3525_msg3() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 9999 { + Context = - { + Modify = A4444 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive, + tdmc/gain=2, ; in dB, + tdmc/ec=on + } + } + }, + Events = 2222 { + al/of {strict=state} + } + } + } +}". + +%% Removed the outermost "{}" pair (before the Reply token) +rfc3525_msg4() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 9999 { + Context = - { + Modify = A4444 + } +}". + +rfc3525_msg6() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Transaction = 10000 { + Context = - { + Notify = A4444 { + ObservedEvents =2222 { + 19990729T22000000:al/of{init=false} + } + } + } +}". + + +rfc3525_msg7() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 10000 { + Context = - { + Notify = A4444 + } +}". + +rfc3525_msg8() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10001 { + Context = - { + Modify = A4444 { + Events = 2223 { + al/on {strict=state}, + dd/ce {DigitMap=Dialplan0} + }, + Signals {cg/dt}, + DigitMap = Dialplan0 { + (0| 00|[1-7]xxx|8xxxxxxx|fxxxxxxx|exx|91xxxxxxxxxx|9011x.) + } + } + } +}". + +rfc3525_msg9() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10001 { + Context = - { + Modify = A4444 + } +}". + +rfc3525_msg10() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Transaction = 10002 { + Context = - { + Notify = A4444 { + ObservedEvents =2223 { + 19990729T22010001:dd/ce { + ds=\"916135551212\", + Meth=UM + } + } + } + } +}". + + +rfc3525_msg11() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 10002 { + Context = - { + Notify = A4444 + } +}". + +%% Added ? +rfc3525_msg12() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10003 { + Context = $ { + Add = A4444, + Add = $ { + Media { + Stream = 1 { + LocalControl { + Mode = ReceiveOnly, + nt/jit=40 ; in ms + }, + Local { + v=0 c=IN IP4 $ m=audio $ RTP/AVP 4 a=ptime:30 v=0 c=IN IP4 $ m=audio $ RTP/AVP 0 + } + } + } + } + } +}". + +%% Added ? +rfc3525_msg13() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a=recvonly + } ; RTP profile for G.723.1 is 4 + } + } + } + } +}". + +%% +%% Added ? +rfc3525_msg14() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50003 { + Context = $ { + Add = A5555 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive + } + } + }, + Events = 1234 { + al/of {strict=state} + }, + Signals {al/ri} + }, + Add = $ { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive, + nt/jit=40 ; in ms + }, + Local { + v=0 c=IN IP4 $ m=audio $ RTP/AVP 4 a=ptime:30 + }, + Remote { + v=0 c=IN IP4 124.124.124.222 m=audio 2222 RTP/AVP 4 a=ptime:30 + } ; RTP profile for G.723.1 is 4 + } + } + } + } +}". + +%% Added ? +rfc3525_msg15() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50003 { + Context = 5000 { + Add = A5555, + Add = A5556 { + Media { + Stream = 1 { + Local { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 + } ; RTP profile for G723.1 is 4 + } + } + } + } +}". + +%% Added ? +rfc3525_msg16a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10005 { + Context = 2000 { + Modify = A4444 { + Signals {cg/rt} + }, + Modify = A4445 { + Media { + Stream = 1 { + Remote { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 + } ; RTP profile for G723.1 is 4 + } + } + } + } +}". + +rfc3525_msg16b() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10005 { + Context = 2000 { + Modify = A4444, + Modify = A4445 + } +}". + +rfc3525_msg17a() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Transaction = 50005 { + Context = 5000 { + Notify = A5555 { + ObservedEvents = 1234 { + 19990729T22020002:al/of{init=false} + } + } + } +}". + +rfc3525_msg17b() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 50005 { + Context = - { + Notify = A5555 + } +}". + +%% Removed "{ }" after Signals +rfc3525_msg17c() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50006 { + Context = 5000 { + Modify = A5555 { + Events = 1235 { + al/on{strict=state} + }, + Signals ; to turn off ringing + } + } +}". + +rfc3525_msg17d() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50006 { + Context = 5000 { + Modify = A4445 + } +}". + +%% Removed "{ }" after Signals +rfc3525_msg18a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10006 { + Context = 2000 { + Modify = A4445 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive + } + } + } + }, + Modify = A4444 { + Signals + } + } +}". + +rfc3525_msg18b() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10006 { + Context = 2000 { + Modify = A4445, + Modify = A4444 + } +}". + +rfc3525_msg19() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50007 { + Context = - { + AuditValue = A5556 { + Audit { + Media, DigitMap, Events, Signals, Packages, Statistics + } + } + } +}". + +%% Added ? +rfc3525_msg20() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50007 { + Context = - { + AuditValue = A5556 { + Media { + TerminationState { + ServiceStates = InService, + Buffer = OFF + }, + Stream = 1 { + LocalControl { + Mode = SendReceive, + nt/jit=40 + }, + Local { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 a=ptime:30 + }, + Remote { + v=0 o=- 2890844526 2890842807 IN IP4 124.124.124.222 s=- t= 0 0 c=IN IP4 124.124.124.222 m=audio 2222 RTP/AVP 4 a=ptime:30 + } + } + }, + Events, + Signals, + DigitMap, + Packages {nt-1, rtp-1}, + Statistics { + rtp/ps=1200, ; packets sent + nt/os=62300, ; octets sent + rtp/pr=700, ; packets received + nt/or=45100, ; octets received + rtp/pl=0.2, ; % packet loss + rtp/jit=20, + rtp/delay=40 ; avg latency + } + } + } +}". + +rfc3525_msg21a() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Transaction = 50008 { + Context = 5000 { + Notify = A5555 { + ObservedEvents =1235 { + 19990729T24020002:al/on {init=false} + } + } + } +}". + +rfc3525_msg21b() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 50008 { + Context = - { + Notify = A5555 + } +}". + +rfc3525_msg22a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50009 { + Context = 5000 { + Subtract = A5555 { + Audit { + Statistics + } + }, + Subtract = A5556 { + Audit { + Statistics + } + } + } +}". + +%% Added ? +rfc3525_msg22b() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50009 { + Context = 5000 { + Subtract = A5555 { + Statistics { + nt/os=45123, ; Octets Sent + nt/dur=40 ; in seconds + } + }, + Subtract = A5556 { + Statistics { + rtp/ps=1245, ; packets sent + nt/os=62345, ; octets sent + rtp/pr=780, ; packets received + nt/or=45123, ; octets received + rtp/pl=10, ; % packets lost + rtp/jit=27, + rtp/delay=48 ; average latency + } + } + } +}". + + +rfc3525_msgs() -> + [ + {msg1, rfc3525_msg1()}, + {msg2, rfc3525_msg2()}, + {msg3, rfc3525_msg3()}, + {msg4, rfc3525_msg4()}, + {msg6, rfc3525_msg6()}, + {msg7, rfc3525_msg7()}, + {msg8, rfc3525_msg8()}, + {msg9, rfc3525_msg9()}, + {msg10, rfc3525_msg10()}, + {msg11, rfc3525_msg11()}, + {msg12, rfc3525_msg12()}, + {msg13, rfc3525_msg13()}, + {msg14, rfc3525_msg14()}, + {msg15, rfc3525_msg15()}, + {msg16a, rfc3525_msg16a()}, + {msg16b, rfc3525_msg16b()}, + {msg17a, rfc3525_msg17a()}, + {msg17b, rfc3525_msg17b()}, + {msg17c, rfc3525_msg17c()}, + {msg17d, rfc3525_msg17d()}, + {msg18a, rfc3525_msg18a()}, + {msg18b, rfc3525_msg18b()}, + {msg19, rfc3525_msg19()}, + {msg20, rfc3525_msg20()}, + {msg21a, rfc3525_msg21a()}, + {msg21b, rfc3525_msg21b()}, + {msg22a, rfc3525_msg22a()}, + {msg22b, rfc3525_msg22b()} + ]. + + +rfc3525_msgs_display() -> + Msgs = rfc3525_msgs(), + Fun = fun({Name, Msg}) -> + io:format("~w: ~n~s~n~n", [Name, Msg]) + end, + lists:foreach(Fun, Msgs). + +rfc3525_msgs_test() -> + put(dbg,true), + Res = rfc3525_msgs_test(megaco_pretty_text_encoder, [], 1), + erase(dbg), + io:format("~w~n", [Res]). + +rfc3525_msgs_test(Codec, Config, Ver) -> + io:format("-----------------------------------------" + "~ntesting with" + "~n Codec: ~w" + "~n Config: ~w" + "~n Version: ~w" + "~n", [Codec, Config, Ver]), + Msgs = rfc3525_msgs(), + Test = fun({N,M1}) -> + %% io:format("testing ~w: ", [N]), + io:format("~n*** testing ~w *** ~n~s~n", [N,M1]), + Bin1 = erlang:list_to_binary(M1), + case (catch Codec:decode_message(Config, Ver, Bin1)) of + {ok, M2} -> + %% io:format("d", []), + io:format("decoded:~n~p~n", [M2]), + case (catch Codec:encode_message(Config, Ver, M2)) of + {ok, Bin2} when is_binary(Bin2) -> + %% io:format("e~n", []), + io:format("encode: ~n~s~n", [erlang:binary_to_list(Bin2)]), + {N,ok}; + {ok, M3} -> + %% io:format("e~n", []), + io:format("encode: ~n~s~n", [M3]), + {N,ok}; + E -> + io:format("~n~p~n", [E]), + {N,encode_error} + end; + E -> + io:format("~n~p~n", [E]), + {N,decode_error} + end + end, + [Test(M) || M <- Msgs]. + +%% -------------------------- + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +skip(Reason) -> + megaco_codec_test_lib:skip(Reason). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +decode_message(Codec, DynamicDecode, Conf, Bin) -> + megaco_codec_test_lib:decode_message(Codec, DynamicDecode, ?VERSION, + Conf, Bin). +encode_message(Codec, Conf, Msg) -> + megaco_codec_test_lib:encode_message(Codec, ?VERSION, Conf, Msg). + +test_msgs(Codec, DynamicDecode, Conf, Msgs) -> + megaco_codec_test_lib:test_msgs(Codec, DynamicDecode, ?VERSION, Conf, + fun chk_MegacoMessage/2, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +chk_MegacoMessage(M,M) when is_record(M,'MegacoMessage') -> + ok; +chk_MegacoMessage(#'MegacoMessage'{authHeader = Auth1, + mess = Mess1}, + #'MegacoMessage'{authHeader = Auth2, + mess = Mess2}) -> + chk_opt_AuthenticationHeader(Auth1,Auth2), + chk_Message(Mess1,Mess2), + ok; +chk_MegacoMessage(M1, M2) -> + wrong_type({'MegacoMessage', M1, M2}). + +chk_opt_AuthenticationHeader(A,A) -> + ok; +chk_opt_AuthenticationHeader(A1,A2) -> + not_equal({auth,A1,A2}). + +chk_Message(M,M) when is_record(M,'Message') -> + ok; +chk_Message(#'Message'{version = Version1, + mId = MID1, + messageBody = Body1}, + #'Message'{version = Version2, + mId = MID2, + messageBody = Body2}) -> + chk_version(Version1,Version2), + chk_MId(MID1,MID2), + chk_messageBody(Body1,Body2), + ok; +chk_Message(M1,M2) -> + wrong_type({'Message',M1,M2}). + + +chk_version(V,V) when is_integer(V) -> + ok; +chk_version(V1,V2) when is_integer(V1) andalso is_integer(V2) -> + not_equal({version,V1,V2}); +chk_version(V1,V2) -> + wrong_type({integer,V1,V2}). + + +chk_MId(M,M) -> + {equal,mid}; +chk_MId({Tag,M1},{Tag,M2}) -> + Res = chk_MId(Tag,M1,M2), + equal(Res); +chk_MId(M1,M2) -> + not_equal({mid,M1,M2}). + +chk_MId(ip4Address,M1,M2) -> chk_IP4Address(M1, M2); +chk_MId(ip6Address,M1,M2) -> chk_IP6Address(M1, M2); +chk_MId(domainName,M1,M2) -> chk_DomainName(M1, M2); +chk_MId(deviceName,M1,M2) -> chk_PathName(M1, M2); +chk_MId(mtpAddress,M1,M2) -> chk_mtpAddress(M1, M2); +chk_MId(Tag,M1,M2) -> + wrong_type({invalid_tag,Tag,M1,M2}). + + +chk_IP4Address(M, M) -> + ok; +chk_IP4Address(M1, M2) -> + not_equal({ip4Address,M1,M2}). + +chk_IP6Address(M, M) -> + ok; +chk_IP6Address(M1, M2) -> + not_equal({ip6Address,M1,M2}). + +chk_DomainName(D, D) when is_record(D,'DomainName') -> + ok; +chk_DomainName(#'DomainName'{name = Name1, + portNumber = Port1}, + #'DomainName'{name = Name2, + portNumber = Port2}) -> + chk_DomainName_name(Name1,Name2), + chk_DomainName_opt_portNumber(Port1,Port2), + equal('DomainName'); +chk_DomainName(D1,D2) -> + wrong_type({'DomainName',D1,D2}). + +chk_DomainName_name(N,N) when is_list(N) -> + ok; +chk_DomainName_name(N1,N2) when is_list(N1) andalso is_list(N2) -> + not_equal({'DomainName',name,N1,N2}); +chk_DomainName_name(N1,N2) -> + wrong_type({'DomainName',name,N1,N2}). + +chk_DomainName_opt_portNumber(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_DomainName_opt_portNumber(P,P) + when is_integer(P) andalso (P >= 0) -> + ok; +chk_DomainName_opt_portNumber(P1,P2) + when (is_integer(P1) andalso (P1 >= 0) andalso + is_integer(P2) andalso (P2 >= 0)) -> + not_equal({'DomainName',portNumber,P1,P2}); +chk_DomainName_opt_portNumber(P1,P2) -> + wrong_type({'DomainName',portNumber,P1,P2}). + + +chk_PathName(P, P) -> + ok; +chk_PathName(P1, P2) -> + not_equal({pathname,P1,P2}). + +chk_mtpAddress(M, M) -> + ok; +chk_mtpAddress(M1, M2) -> + not_equal({mtpAddress, M1, M2}). + + +chk_messageBody({messageError, B}, + {messageError, B}) when is_record(B,'ErrorDescriptor') -> + ok; +chk_messageBody({messageError,B1},{messageError,B2}) -> + chk_ErrorDescriptor(B1,B2), + equal({messageBody, messageError}); +chk_messageBody({transactions,T},{transactions,T}) when is_list(T) -> + ok; +chk_messageBody({transactions,T1},{transactions,T2}) -> + chk_transactions(T1,T2), + ok; +chk_messageBody(B1,B2) -> + wrong_type({messageBody,B1,B2}). + + +chk_transactions(T,T) when is_list(T) -> + ok; +chk_transactions(T1,T2) + when is_list(T1) andalso is_list(T2) andalso (length(T1) =:= length(T2)) -> + chk_transactions1(T1,T2); +chk_transactions(T1,T2) + when is_list(T1) andalso is_list(T2) -> + not_equal({transactions, T1, T2}); +chk_transactions(T1, T2) -> + wrong_type({transactions,T1,T2}). + +chk_transactions1([],[]) -> + equal(transactions); +chk_transactions1([T|Ts1],[T|Ts2]) -> + chk_transactions1(Ts1,Ts2); +chk_transactions1([T1|_Ts1],[T2|_Ts2]) -> + chk_transaction(T1,T2), + ok. + +chk_transaction(T,T) -> + ok; +chk_transaction({transactionRequest,T1},{transactionRequest,T2}) -> + chk_transactionRequest(T1,T2), + ok; +chk_transaction({transactionPending,T1},{transactionPending,T2}) -> + chk_transactionPending(T1,T2), + equal({transactionPending,T1,T2}); +chk_transaction({transactionReply,T1},{transactionReply,T2}) -> + chk_transactionReply(T1,T2), + equal({transactionReply,T1,T2}); +chk_transaction({transactionResponseAck,T1},{transactionResponseAck,T2}) -> + chk_transactionAck(T1,T2), + equal({transactionResponseAck,T1,T2}); +chk_transaction({Tag1,_T1},{Tag2,_T2}) -> + wrong_type({transaction_tag,Tag1,Tag2}). + + +chk_transactionRequest(T,T) when is_record(T,'TransactionRequest') -> + ok; +chk_transactionRequest(T1,T2) when is_record(T1,'TransactionRequest') andalso + is_record(T2,'TransactionRequest') -> + chk_transactionId(T1#'TransactionRequest'.transactionId, + T2#'TransactionRequest'.transactionId), + chk_actionRequests(T1#'TransactionRequest'.actions, + T2#'TransactionRequest'.actions), + ok; +chk_transactionRequest(T1,T2) -> + wrong_type({transactionRequest,T1,T2}). + + +chk_transactionPending(T,T) when is_record(T,'TransactionPending') -> + ok; +chk_transactionPending(#'TransactionPending'{transactionId = Id1}, + #'TransactionPending'{transactionId = Id2}) -> + chk_transactionId(Id1,Id2), + equal(transactionPending); +chk_transactionPending(T1,T2) -> + wrong_type({transactionPending,T1,T2}). + +chk_transactionReply(T,T) when is_record(T,'TransactionReply') -> + ok; +chk_transactionReply(#'TransactionReply'{transactionId = Id1, + immAckRequired = ImmAck1, + transactionResult = TransRes1}, + #'TransactionReply'{transactionId = Id2, + immAckRequired = ImmAck2, + transactionResult = TransRes2}) -> + chk_transactionId(Id1,Id2), + ImmAck1 = ImmAck2, + chk_transactionReply_transactionResult(TransRes1,TransRes2), + equal(transactionReply); +chk_transactionReply(T1,T2) -> + wrong_type({transactionReply,T1,T2}). + +chk_transactionReply_transactionResult(R,R) -> + ok; +chk_transactionReply_transactionResult(R1,R2) -> + not_equal({transactionReply_transactionResult,R1,R2}). + +chk_transactionAck(T,T) when is_record(T,'TransactionAck') -> + ok; +chk_transactionAck(#'TransactionAck'{firstAck = F1, + lastAck = L1}, + #'TransactionAck'{firstAck = F2, + lastAck = L2}) -> + chk_transactionId(F1,F2), + chk_opt_transactionId(L1,L2), + equal('TransactionAck'); +chk_transactionAck(T1,T2) -> + wrong_type({transactionAck,T1,T2}). + + +chk_actionRequests(A,A) when is_list(A) andalso (length(A) =:= 0) -> + ok; +chk_actionRequests(A,A) when is_list(A) -> + case hd(A) of + A when is_record(A,'ActionRequest') -> + ok; + Else -> + wrong_type({'ActionRequest',Else}) + end; +chk_actionRequests(A1,A2) + when is_list(A1) andalso is_list(A2) andalso (length(A1) =:= length(A2)) -> + chk_actionRequests1(A1,A2); +chk_actionRequests(A1,A2) -> + wrong_type({actionRequests,A1,A2}). + +chk_actionRequests1([],[]) -> + equal(actionRequests); +chk_actionRequests1([A|As1],[A|As2]) when is_record(A,'ActionRequest') -> + chk_actionRequests1(As1,As2); +chk_actionRequests1([A1|_As1],[A2|_As2]) -> + chk_actionRequest(A1,A2), + ok. + +chk_actionRequest(A,A) when is_record(A,'ActionRequest') -> + ok; +chk_actionRequest(#'ActionRequest'{contextId = Id1, + contextRequest = Req1, + contextAttrAuditReq = AuditReq1, + commandRequests = CmdReqs1}, + #'ActionRequest'{contextId = Id2, + contextRequest = Req2, + contextAttrAuditReq = AuditReq2, + commandRequests = CmdReqs2}) -> + t("chk_actionRequest -> entry with" + "~n CmdReqs1: ~p" + "~n CmdReqs2: ~p",[CmdReqs1,CmdReqs2]), + chk_contextId(Id1,Id2), + chk_opt_contextRequest(Req1,Req2), + chk_opt_contextAttrAuditReq(AuditReq1,AuditReq2), + chk_commandRequests(CmdReqs1,CmdReqs2), + ok. + +chk_contextId(Id,Id) when is_integer(Id) -> + ok; +chk_contextId(Id1,Id2) when is_integer(Id1) andalso is_integer(Id2) -> + not_equal({contextId,Id1,Id2}); +chk_contextId(Id1,Id2) -> + wrong_type({contextId,Id1,Id2}). + +chk_opt_contextRequest(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_contextRequest(R,R) when is_record(R,'ContextRequest') -> + ok; +chk_opt_contextRequest(#'ContextRequest'{priority = Prio1, + emergency = Em1, + topologyReq = TopReq1} = C1, + #'ContextRequest'{priority = Prio2, + emergency = Em2, + topologyReq = TopReq2} = C2) -> + chk_contextRequest_priority(Prio1,Prio2), + chk_contextRequest_emergency(Em1,Em2), + chk_topologyRequest(TopReq1,TopReq2), + equal({'ContextRequest',C1,C2}). + +chk_contextRequest_priority(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_contextRequest_priority(P,P) when is_integer(P) -> + ok; +chk_contextRequest_priority(P1,P2) when is_integer(P1) andalso is_integer(P2) -> + not_equal({contextRequest_priority,P1,P2}); +chk_contextRequest_priority(P1,P2) -> + wrong_type({contextRequest_priority,P1,P2}). + +chk_contextRequest_emergency(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_contextRequest_emergency(true,true) -> + ok; +chk_contextRequest_emergency(false,false) -> + ok; +chk_contextRequest_emergency(E1,E2) -> + not_equal({contextRequest_emergency,E1,E2}). + +chk_topologyRequest(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_topologyRequest(T,T) when is_record(T,'TopologyRequest') -> + ok; +chk_topologyRequest(#'TopologyRequest'{terminationFrom = F1, + terminationTo = T1, + topologyDirection = D1} = T1, + #'TopologyRequest'{terminationFrom = F2, + terminationTo = T2, + topologyDirection = D2} = T2) -> + chk_terminationId(F1,F2), + chk_terminationId(T1,T2), + chk_topologyRequest_topologyDirection(D1,D2), + equal({'TopologyRequest',D1,D2}). + +chk_topologyRequest_topologyDirection(bothway,bothway) -> + ok; +chk_topologyRequest_topologyDirection(isolate,isolate) -> + ok; +chk_topologyRequest_topologyDirection(oneway,oneway) -> + ok; +chk_topologyRequest_topologyDirection(D1,D2) -> + not_equal({topologyRequest_topologyDirection, D1, D2}). + +chk_opt_contextAttrAuditReq(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_opt_contextAttrAuditReq(R,R) when is_record(R,'ContextAttrAuditRequest') -> + ok; +chk_opt_contextAttrAuditReq(#'ContextAttrAuditRequest'{topology = T1, + emergency = E1, + priority = P1} = R1, + #'ContextAttrAuditRequest'{topology = T2, + emergency = E2, + priority = P2} = R2) -> + T1 = T2, + E1 = E2, + P1 = P2, + equal({'ContextAttrAuditRequest',R1,R2}). + +chk_commandRequests(C1,C2) + when is_list(C1) andalso is_list(C2) andalso (length(C1) =:= length(C2)) -> + t("chk_commandRequests -> entry with" + "~n C1: ~p" + "~n C2: ~p", [C1, C2]), + chk_commandRequests1(C1,C2); +chk_commandRequests(C1,C2) -> + t("chk_commandRequests -> entry",[]), + wrong_type({commandRequests,C1,C2}). + +chk_commandRequests1([],[]) -> + ok; +chk_commandRequests1([C1|Cs1],[C2|Cs2]) -> + chk_commandRequest(C1,C2), + chk_commandRequests1(Cs1,Cs2). + +chk_commandRequest(C,C) when is_record(C,'CommandRequest') -> + ok; +chk_commandRequest(#'CommandRequest'{command = Cmd1, + optional = O1, + wildcardReturn = W1}, + #'CommandRequest'{command = Cmd2, + optional = O2, + wildcardReturn = W2}) -> + t("chk_commandRequest -> entry with" + "~n C1: ~p" + "~n C2: ~p", [Cmd1, Cmd2]), + chk_commandRequest_command(Cmd1,Cmd2), + O1 = O2, + W1 = W2, + ok; +chk_commandRequest(C1,C2) -> + wrong_type({commandRequest,C1,C2}). + +chk_commandRequest_command({addReq,C1},{addReq,C2}) -> + chk_AmmRequest(C1,C2); +chk_commandRequest_command({moveReq,C1},{moveReq,C2}) -> + chk_AmmRequest(C1,C2); +chk_commandRequest_command({modReq,C1},{modReq,C2}) -> + chk_AmmRequest(C1,C2); +chk_commandRequest_command({subtractReq,C1},{subtractReq,C2}) -> + chk_SubtractRequest(C1,C2); +chk_commandRequest_command({auditCapRequest,C1},{auditCapRequest,C2}) -> + chk_AuditRequest(C1,C2); +chk_commandRequest_command({auditValueRequest,C1},{auditValueRequest,C2}) -> + chk_AuditRequest(C1,C2); +chk_commandRequest_command({notifyReq,C1},{notifyReq,C2}) -> + chk_NotifyRequest(C1,C2); +chk_commandRequest_command({serviceChangeReq,C1},{serviceChangeReq,C2}) -> + chk_ServiceChangeRequest(C1,C2); +chk_commandRequest_command(C1,C2) -> + wrong_type({commandRequest_command,C1,C2}). + + +chk_AmmRequest(R,R) when is_record(R,'AmmRequest') -> + ok; +chk_AmmRequest(#'AmmRequest'{terminationID = Tids1, + descriptors = D1}, + #'AmmRequest'{terminationID = Tids2, + descriptors = D2}) -> + chk_terminationIds(Tids1,Tids2), + chk_AmmRequest_descriptors(D1,D2), + ok; +chk_AmmRequest(R1,R2) -> + wrong_type({'AmmRequest',R1,R2}). + +chk_AmmRequest_descriptors([],[]) -> + ok; +chk_AmmRequest_descriptors(D1,D2) + when is_list(D1) andalso is_list(D2) andalso (length(D1) =:= length(D2)) -> + chk_AmmRequest_descriptors1(D1,D2); +chk_AmmRequest_descriptors(D1,D2) -> + wrong_type({ammRequest_descriptors,D1,D2}). + +chk_AmmRequest_descriptors1([],[]) -> + ok; +chk_AmmRequest_descriptors1([D1|Ds1],[D2|Ds2]) -> + chk_AmmRequest_descriptor(D1,D2), + chk_AmmRequest_descriptors1(Ds1,Ds2). + +chk_AmmRequest_descriptor({mediaDescriptor,D1},{mediaDescriptor,D2}) -> + chk_MediaDescriptor(D1,D2); +chk_AmmRequest_descriptor({modemDescriptor,D1},{modemDescriptor,D2}) -> + chk_ModemDescriptor(D1,D2); +chk_AmmRequest_descriptor({muxDescriptor,D1},{muxDescriptor,D2}) -> + chk_MuxDescriptor(D1,D2); +chk_AmmRequest_descriptor({eventsDescriptor,D1},{eventsDescriptor,D2}) -> + chk_EventsDescriptor(D1,D2); +chk_AmmRequest_descriptor({eventBufferDescriptor,D1},{eventBufferDescriptor,D2}) -> + chk_EventBufferDescriptor(D1,D2); +chk_AmmRequest_descriptor({signalsDescriptor,D1},{signalsDescriptor,D2}) -> + chk_SignalsDescriptor(D1,D2); +chk_AmmRequest_descriptor({digitMapDescriptor,D1},{digitMapDescriptor,D2}) -> + chk_DigitMapDescriptor(D1,D2); +chk_AmmRequest_descriptor({auditDescriptor,D1},{auditDescriptor,D2}) -> + chk_AuditDescriptor(D1,D2); +chk_AmmRequest_descriptor({Tag1,_D1},{Tag2,_D2}) -> + wrong_type({ammRequest_descriptor_tag,Tag1,Tag2}). + + +chk_SubtractRequest(R,R) when is_record(R,'SubtractRequest') -> + ok; +chk_SubtractRequest(#'SubtractRequest'{terminationID = Tids1, + auditDescriptor = D1} = R1, + #'SubtractRequest'{terminationID = Tids2, + auditDescriptor = D2} = R2) -> + chk_terminationIds(Tids1, Tids2), + chk_opt_AuditDescriptor(D1, D2), + equal({'SubtractRequest',R1,R2}); +chk_SubtractRequest(R1,R2) -> + wrong_type({'SubtractRequest',R1,R2}). + + +chk_AuditRequest(R,R) when is_record(R,'AuditRequest') -> + ok; +chk_AuditRequest(#'AuditRequest'{terminationID = Tid1, + auditDescriptor = D1} = R1, + #'AuditRequest'{terminationID = Tid2, + auditDescriptor = D2} = R2) -> + chk_terminationId(Tid1,Tid2), + chk_AuditDescriptor(D1,D2), + equal({'AuditRequest',R1,R2}); +chk_AuditRequest(R1,R2) -> + wrong_type({'AuditRequest',R1,R2}). + + +chk_NotifyRequest(R,R) when is_record(R,'NotifyRequest') -> + ok; +chk_NotifyRequest(#'NotifyRequest'{terminationID = Tids1, + observedEventsDescriptor = ObsDesc1, + errorDescriptor = ErrDesc1} = R1, + #'NotifyRequest'{terminationID = Tids2, + observedEventsDescriptor = ObsDesc2, + errorDescriptor = ErrDesc2} = R2) -> + chk_terminationIds(Tids1,Tids2), + chk_ObservedEventsDescriptor(ObsDesc1,ObsDesc2), + chk_opt_ErrorDescriptor(ErrDesc1,ErrDesc2), + equal({'NotifyRequest',R1,R2}); +chk_NotifyRequest(R1,R2) -> + wrong_type({'NotifyRequest',R1,R2}). + + +chk_ServiceChangeRequest(R,R) when is_record(R,'ServiceChangeRequest') -> + ok; +chk_ServiceChangeRequest(#'ServiceChangeRequest'{terminationID = Tids1, + serviceChangeParms = P1} = R1, + #'ServiceChangeRequest'{terminationID = Tids2, + serviceChangeParms = P2} = R2) -> + chk_terminationIds(Tids1,Tids2), + chk_ServiceChangeParm(P1,P2), + equal({'ServiceChangeRequest',R1,R2}); +chk_ServiceChangeRequest(R1,R2) -> + wrong_type({'ServiceChangeRequest',R1,R2}). + + +chk_MediaDescriptor(D, D) when is_record(D,'MediaDescriptor') -> + ok; +chk_MediaDescriptor(#'MediaDescriptor'{termStateDescr = Tsd1, + streams = S1} = D1, + #'MediaDescriptor'{termStateDescr = Tsd2, + streams = S2} = D2) -> +%% io:format("chk_MediaDescriptor -> entry with" +%% "~n Tsd1: ~p" +%% "~n Tsd2: ~p" +%% "~n S1: ~p" +%% "~n S2: ~p" +%% "~n", [Tsd1, Tsd2, S1, S2]), + chk_MediaDescriptor_tsd(Tsd1, Tsd2), + chk_MediaDescriptor_streams(S1, S2), + equal({'MediaDescriptor',D1,D2}); +chk_MediaDescriptor(D1,D2) -> + wrong_type({'MediaDescriptor',D1,D2}). + +chk_MediaDescriptor_tsd(D, D) -> + ok; +chk_MediaDescriptor_tsd(D1, D2) -> + not_equal({termStateDescr, D1, D2}). + +chk_MediaDescriptor_streams({oneStream, S}, {oneStream, S}) -> + ok; +chk_MediaDescriptor_streams({oneStream, S1}, {oneStream, S2}) -> + not_equal({oneStream, S1, S2}); +chk_MediaDescriptor_streams({multiStream, MS}, {multiStream, MS}) -> + ok; +chk_MediaDescriptor_streams({multiStream, MS1}, {multiStream, MS2}) -> + chk_StreamDescriptors(MS1, MS2); +chk_MediaDescriptor_streams(S1, S2) -> + not_equal({streams, S1, S2}). + +chk_StreamDescriptors([], []) -> + ok; +chk_StreamDescriptors([SD1|MS1], [SD2|MS2]) -> + chk_StreamDescriptor(SD1, SD2), + chk_StreamDescriptors(MS1, MS2). + +chk_StreamDescriptor(SD, SD) when is_record(SD, 'StreamDescriptor') -> + ok; +chk_StreamDescriptor(#'StreamDescriptor'{streamID = SID1, + streamParms = SP1} = SD1, + #'StreamDescriptor'{streamID = SID2, + streamParms = SP2} = SD2) -> + SID1 = SID2, + chk_StreamParms(SP1, SP2), + equal({'StreamDescriptor',SD1, SD2}); +chk_StreamDescriptor(SD1, SD2) -> + wrong_type({'StreamDescriptor',SD1,SD2}). + + +chk_StreamParms(SP, SP) when is_record(SP, 'StreamParms') -> + ok; +chk_StreamParms(#'StreamParms'{localControlDescriptor = LCD1, + localDescriptor = LD1, + remoteDescriptor = RD1} = SP1, + #'StreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2} = SP2) -> + LCD1 = LCD2, + LD1 = LD2, + RD1 = RD2, + equal({'StreamParms', SP1, SP2}); +chk_StreamParms(SP1, SP2) -> + wrong_type({'StreamDescriptor', SP1, SP2}). + +chk_ModemDescriptor(D,D) when is_record(D,'ModemDescriptor') -> + ok; +chk_ModemDescriptor(#'ModemDescriptor'{mtl = T1, + mpl = P1} = D1, + #'ModemDescriptor'{mtl = T2, + mpl = P2} = D2) -> + T1 = T2, + P1 = P2, + equal({'ModemDescriptor',D1,D2}); +chk_ModemDescriptor(D1,D2) -> + wrong_type({'ModemDescriptor',D1,D2}). + +chk_MuxDescriptor(D,D) when is_record(D,'MuxDescriptor') -> + ok; +chk_MuxDescriptor(#'MuxDescriptor'{muxType = T1, + termList = I1} = D1, + #'MuxDescriptor'{muxType = T2, + termList = I2} = D2) -> + T1 = T2, + I1 = I2, + equal({'MuxDescriptor',D1,D2}); +chk_MuxDescriptor(D1,D2) -> + wrong_type({'MuxDescriptor',D1,D2}). + +chk_EventsDescriptor(D,D) when is_record(D,'EventsDescriptor') -> + ok; +chk_EventsDescriptor(#'EventsDescriptor'{requestID = I1, + eventList = E1} = D1, + #'EventsDescriptor'{requestID = I2, + eventList = E2} = D2) -> + I1 = I2, + E1 = E2, + equal({'EventsDescriptor',D1,D2}); +chk_EventsDescriptor(D1,D2) -> + wrong_type({'EventsDescriptor',D1,D2}). + +chk_EventBufferDescriptor(D1,D2) + when is_list(D1) andalso is_list(D2) andalso (length(D1) =:= length(D2)) -> + chk_EventBufferDescriptor1(D1,D2); +chk_EventBufferDescriptor(D1,D2) -> + wrong_type({eventBufferDescriptor,D1,D2}). + +chk_EventBufferDescriptor1([],[]) -> + ok; +chk_EventBufferDescriptor1([ES1|D1],[ES2|D2]) -> + chk_EventSpec(ES1,ES2), + chk_EventBufferDescriptor1(D1,D2). + +chk_EventSpec(ES,ES) when is_record(ES,'EventSpec') -> + ok; +chk_EventSpec(#'EventSpec'{eventName = N1, + streamID = I1, + eventParList = P1} = ES1, + #'EventSpec'{eventName = N2, + streamID = I2, + eventParList = P2} = ES2) -> + N1 = N2, + chk_opt_StreamId(I1,I2), + chk_EventParameters(P1,P2), + equal({'EventSpec',ES1,ES2}); +chk_EventSpec(ES1,ES2) -> + wrong_type({'EventSpec',ES1,ES2}). + + +chk_opt_ErrorDescriptor(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_opt_ErrorDescriptor(E1,E2) -> + chk_ErrorDescriptor(E1,E2). + +chk_ErrorDescriptor(E,E) when is_record(E,'ErrorDescriptor') -> + ok; +chk_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code1, + errorText = Text1} = E1, + #'ErrorDescriptor'{errorCode = Code2, + errorText = Text2} = E2) -> + chk_ErrorCode(Code1,Code2), + chk_opt_ErrorText(Text1,Text2), + equal({'ErrorDescriptor',E1,E2}); +chk_ErrorDescriptor(E1,E2) -> + wrong_type({'ErrorDescriptor',E1,E2}). + +chk_ErrorCode(C,C) when is_integer(C) -> + ok; +chk_ErrorCode(C1,C2) when is_integer(C1) andalso is_integer(C2) -> + not_equal({errorCode,C1,C2}); +chk_ErrorCode(C1,C2) -> + throw({wrong_type,{errorCode,C1,C2}}). + +chk_opt_ErrorText(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_opt_ErrorText(T,T) when is_list(T) -> + ok; +chk_opt_ErrorText(T1,T2) when is_list(T1) andalso is_list(T2) -> + not_equal({errorText,T1,T2}); +chk_opt_ErrorText(T1,T2) -> + wrong_type({errorText,T1,T2}). + + +chk_SignalsDescriptor(D1,D2) + when is_list(D1) andalso is_list(D2) andalso (length(D1) =:= length(D2)) -> + chk_SignalsDescriptor1(D1,D2); +chk_SignalsDescriptor(D1,D2) -> + wrong_type({signalsDescriptor,D1,D2}). + +chk_SignalsDescriptor1([],[]) -> + ok; +chk_SignalsDescriptor1([S1|D1],[S2|D2]) -> + chk_SignalRequest(S1,S2), + chk_SignalsDescriptor1(D1,D2). + +chk_SignalRequest({signal,S1},{signal,S2}) -> + chk_Signal(S1,S2); +chk_SignalRequest({seqSigList,S1},{seqSigList,S2}) -> + chk_SeqSignalList(S1,S2); +chk_SignalRequest(R1,R2) -> + wrong_type({signalRequest,R1,R2}). + +chk_SeqSignalList(S,S) when is_record(S,'SeqSigList') -> + ok; +chk_SeqSignalList(#'SeqSigList'{id = Id1, + signalList = SigList1} = S1, + #'SeqSigList'{id = Id2, + signalList = SigList2} = S2) -> + Id1 = Id2, + chk_Signals(SigList1,SigList2), + equal({'SeqSigList',S1,S2}); +chk_SeqSignalList(S1,S2) -> + wrong_type({'SeqSigList',S1,S2}). + + +chk_Signals([],[]) -> + ok; +chk_Signals([Sig1|Sigs1],[Sig2|Sigs2]) -> + chk_Signal(Sig1,Sig2), + chk_Signals(Sigs1,Sigs2). + + +chk_Signal(S,S) when is_record(S,'Signal') -> + ok; +chk_Signal(#'Signal'{signalName = N1, + streamID = I1, + sigType = T1, + duration = D1, + notifyCompletion = C1, + keepActive = K1, + sigParList = P1} = S1, + #'Signal'{signalName = N2, + streamID = I2, + sigType = T2, + duration = D2, + notifyCompletion = C2, + keepActive = K2, + sigParList = P2} = S2) -> + N1 = N2, + chk_opt_StreamId(I1,I2), + chk_opt_SignalType(T1,T2), + chk_opt_duration(D1,D2), + chk_opt_NotifyCompletion(C1,C2), + chk_opt_keepAlive(K1,K2), + chk_sigParameters(P1,P2), + equal({'Signal',S1,S2}); +chk_Signal(S1,S2) -> + wrong_type({'Signal',S1,S2}). + +chk_DigitMapDescriptor(D,D) when is_record(D,'DigitMapDescriptor') -> + ok; +chk_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = N1, + digitMapValue = V1}, + #'DigitMapDescriptor'{digitMapName = N2, + digitMapValue = V2}) -> + chk_opt_digitMapName(N1,N2), + chk_opt_digitMapValue(V1,V2), + ok; +chk_DigitMapDescriptor(D1,D2) -> + wrong_type({'DigitMapDescriptor',D1,D2}). + +chk_opt_digitMapName(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_opt_digitMapName(N1,N2) -> + chk_digitMapName(N1,N2). + +chk_digitMapName(N,N) -> + ok; +chk_digitMapName(N1,N2) -> + not_equal({digitMapName,N1,N2}). + +chk_opt_digitMapValue(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_opt_digitMapValue(V1,V2) -> + chk_digitMapValue(V1,V2). + +chk_digitMapValue(V,V) when is_record(V,'DigitMapValue') -> + ok; +chk_digitMapValue(#'DigitMapValue'{digitMapBody = Body1, + startTimer = Start1, + shortTimer = Short1, + longTimer = Long1}, + #'DigitMapValue'{digitMapBody = Body2, + startTimer = Start2, + shortTimer = Short2, + longTimer = Long2}) -> + chk_digitMapValue_digitMapBody(Body1,Body2), % Could contain trailing '\n', ... + chk_opt_timer(Start1,Start2), + chk_opt_timer(Short1,Short2), + chk_opt_timer(Long1,Long2), + ok; +chk_digitMapValue(V1,V2) -> + wrong_type({digitMapValue,V1,V2}). + +chk_digitMapValue_digitMapBody(B,B) when is_list(B) -> + ok; +chk_digitMapValue_digitMapBody(B1, B2) + when is_list(B1) andalso is_list(B2) andalso (length(B1) > length(B2)) -> + case string:str(B2, B1) of + 0 -> + ok; + _ -> + not_equal({digitMapValue_digitMapBody,B1,B2}) + end; +chk_digitMapValue_digitMapBody(B1, B2) + when is_list(B1) andalso is_list(B2) andalso (length(B1) < length(B2)) -> + case string:str(B1, B2) of + 0 -> + ok; + _ -> + not_equal({digitMapValue_digitMapBody,B1,B2}) + end; +chk_digitMapValue_digitMapBody(B1,B2) when is_list(B1) andalso is_list(B2) -> + not_equal({digitMapValue_digitMapBody,B1,B2}); +chk_digitMapValue_digitMapBody(B1,B2) -> + wrong_type({digitMapValue_digitMapBody,B1,B2}). + + +chk_opt_AuditDescriptor(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_opt_AuditDescriptor(D1,D2) -> + chk_AuditDescriptor(D1,D2). + +chk_AuditDescriptor(D,D) when is_record(D,'AuditDescriptor') -> + ok; +chk_AuditDescriptor(#'AuditDescriptor'{auditToken = T1} = D1, + #'AuditDescriptor'{auditToken = T2} = D2) -> + chk_opt_auditToken(T1,T2), + equal({'AuditDescriptor',D1,D2}); +chk_AuditDescriptor(D1,D2) -> + wrong_type({'AuditDescriptor',D1,D2}). + +chk_opt_auditToken(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_opt_auditToken(T1,T2) -> + chk_auditToken(T1,T2). + +chk_auditToken(T1,T2) + when is_list(T1) andalso is_list(T2) andalso (length(T1) =:= length(T2)) -> + chk_auditToken1(T1,T2); +chk_auditToken(T1,T2) -> + wrong_type({auditToken,T1,T2}). + +chk_auditToken1([],[]) -> + ok; +chk_auditToken1([H1|T1],[H2|T2]) -> + chk_auditToken2(H1,H2), + chk_auditToken1(T1,T2). + +chk_auditToken2(muxToken,muxToken) -> + ok; +chk_auditToken2(modemToken,modemToken) -> + ok; +chk_auditToken2(mediaToken,mediaToken) -> + ok; +chk_auditToken2(eventsToken,eventsToken) -> + ok; +chk_auditToken2(signalsToken,signalsToken) -> + ok; +chk_auditToken2(digitMapToken,digitMapToken) -> + ok; +chk_auditToken2(statsToken,statsToken) -> + ok; +chk_auditToken2(observedEventsToken,observedEventsToken) -> + ok; +chk_auditToken2(packagesToken,packagesToken) -> + ok; +chk_auditToken2(eventBufferToken,eventBufferToken) -> + ok; +chk_auditToken2(T1,T2) when is_atom(T1) andalso is_atom(T2) -> + not_equal({auditToken,T1,T2}); +chk_auditToken2(T1,T2) -> + wrong_type({auditToken,T1,T2}). + +chk_ObservedEventsDescriptor(D,D) + when is_record(D,'ObservedEventsDescriptor') -> + ok; +chk_ObservedEventsDescriptor( + #'ObservedEventsDescriptor'{requestId = Id1, + observedEventLst = E1} = D1, + #'ObservedEventsDescriptor'{requestId = Id2, + observedEventLst = E2} = D2) -> + Id1 = Id2, + chk_ObservedEvents(E1,E2), + equal({'ObservedEventsDescriptor',D1,D2}); +chk_ObservedEventsDescriptor(D1,D2) -> + wrong_type({'ObservedEventsDescriptor',D1,D2}). + + +chk_ObservedEvents(E1,E2) + when is_list(E1) andalso is_list(E2) andalso (length(E1) =:= length(E2)) -> + chk_ObservedEvents1(E1,E2); +chk_ObservedEvents(E1,E2) -> + wrong_type({observedEvents,E1,E2}). + + +chk_ObservedEvents1([],[]) -> + ok; +chk_ObservedEvents1([Ev1|Evs1],[Ev2|Evs2]) -> + chk_ObservedEvent(Ev1,Ev2), + chk_ObservedEvents1(Evs1,Evs2). + +chk_ObservedEvent(#'ObservedEvent'{eventName = N1, + streamID = I1, + eventParList = P1, + timeNotation = T1} = E1, + #'ObservedEvent'{eventName = N2, + streamID = I2, + eventParList = P2, + timeNotation = T2} = E2) -> + N1 = N2, + chk_opt_StreamId(I1,I2), + chk_EventParameters(P1,P2), + chk_opt_TimeNotation(T1,T2), + equal({'ObservedEvent',E1,E2}); +chk_ObservedEvent(E1,E2) -> + wrong_type({'ObservedEvent',E1,E2}). + + +chk_opt_TimeNotation(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_opt_TimeNotation(T1,T2) -> + chk_TimeNotation(T1,T2). + +chk_TimeNotation(T,T) when is_record(T,'TimeNotation') -> + ok; +chk_TimeNotation(#'TimeNotation'{date = Date1, + time = Time1} = T1, + #'TimeNotation'{date = Date2, + time = Time2} = T2) -> + Date1 = Date2, + Time1 = Time2, + equal({'TimeNotation',T1,T2}); +chk_TimeNotation(T1,T2) -> + wrong_type({'TimeNotation',T1,T2}). + + +chk_opt_timer(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_opt_timer(T1,T2) -> + chk_timer(T1,T2). + +chk_timer(T,T) when is_integer(T) -> + {equal,timer}; +chk_timer(T1,T2) when is_integer(T1) andalso is_integer(T2) -> + throw({not_equal,{timer,T1,T2}}); +chk_timer(T1,T2) -> + throw({wrong_type,{timer,T1,T2}}). + + +chk_opt_SignalType(asn1_NOVALUE,asn1_NOVALUE) -> + {equal,signalType}; +chk_opt_SignalType(T1,T2) -> + chk_SignalType(T1,T2). + +chk_SignalType(brief,brief) -> + {equal,signalType}; +chk_SignalType(onOffonOff,onOffonOff) -> + {equal,signalType}; +chk_SignalType(timeOut,timeOut) -> + {equal,signalType}; +chk_SignalType(T1,T2) -> + throw({wrong_type,{signalType,T1,T2}}). + + +chk_opt_duration(asn1_NOVALUE,asn1_NOVALUE) -> + {equal,duration}; +chk_opt_duration(D1,D2) -> + chk_duration(D1,D2). + +chk_duration(D,D) when is_integer(D) -> + {equal,duration}; +chk_duration(D1,D2) when is_integer(D1) andalso is_integer(D2) -> + throw({not_equal,{duration,D1,D2}}); +chk_duration(D1,D2) -> + throw({wrong_type,{duration,D1,D2}}). + + +chk_opt_NotifyCompletion(asn1_NOVALUE,asn1_NOVALUE) -> + {equal,notifyCompletion}; +chk_opt_NotifyCompletion(N1,N2) -> + chk_NotifyCompletion(N1,N2). + +chk_NotifyCompletion([],[]) -> + {equal,notifyCompletion}; +chk_NotifyCompletion([Item1|Items1],[Item2|Items2]) -> + chk_NotifyCompletion1(Item1,Item2), + chk_NotifyCompletion(Items1,Items2); +chk_NotifyCompletion(C1,C2) -> + throw({wrong_type,{notifyCompletion,C1,C2}}). + +chk_NotifyCompletion1(onTimeOut,onTimeOut) -> + {equal,notifyCompletion_part}; +chk_NotifyCompletion1(onInterruptByEvent,onInterruptByEvent) -> + {equal,notifyCompletion_part}; +chk_NotifyCompletion1(onInterruptByNewSignalDescr,onInterruptByNewSignalDescr) -> + {equal,notifyCompletion_part}; +chk_NotifyCompletion1(otherReason,otherReason) -> + {equal,notifyCompletion_part}; +chk_NotifyCompletion1(C1,C2) -> + throw({wrong_type,{notifyCompletion_part,C1,C2}}). + + +chk_opt_keepAlive(asn1_NOVALUE,asn1_NOVALUE) -> + {equal,keepAlive}; +chk_opt_keepAlive(K1,K2) -> + chk_keepAlive(K1,K2). + +chk_keepAlive(true,true) -> + ok; +chk_keepAlive(false,false) -> + ok; +chk_keepAlive(K1,K2) -> + wrong_type({keepAlive,K1,K2}). + + +chk_ServiceChangeParm(P,P) when is_record(P,'ServiceChangeParm') -> + ok; +chk_ServiceChangeParm(#'ServiceChangeParm'{serviceChangeMethod = M1, + serviceChangeAddress = A1, + serviceChangeVersion = V1, + serviceChangeProfile = P1, + serviceChangeReason = R1, + serviceChangeDelay = D1, + serviceChangeMgcId = Mid1, + timeStamp = T1} = P1, + #'ServiceChangeParm'{serviceChangeMethod = M2, + serviceChangeAddress = A2, + serviceChangeVersion = V2, + serviceChangeProfile = P2, + serviceChangeReason = R2, + serviceChangeDelay = D2, + serviceChangeMgcId = Mid2, + timeStamp = T2} = P2) -> + M1 = M2, + A1 = A2, + V1 = V2, + P1 = P2, + R1 = R2, + D1 = D2, + Mid1 = Mid2, + T1 = T2, + equal({'ServiceChangeParm',P1,P2}); +chk_ServiceChangeParm(P1,P2) -> + wrong_type({'ServiceChangeParm',P1,P2}). + + +chk_sigParameters(S1,S2) + when is_list(S1) andalso is_list(S2) andalso (length(S1) =:= length(S2)) -> + chk_sigParameters1(S1,S2); +chk_sigParameters(S1,S2) -> + wrong_type({sigParameters,S1,S2}). + +chk_sigParameters1([],[]) -> + ok; +chk_sigParameters1([H1|T1],[H2|T2]) -> + chk_sigParameter(H1,H2), + chk_sigParameters1(T1,T2); +chk_sigParameters1(P1,P2) -> + wrong_type({sigParameters,P1,P2}). + +chk_sigParameter(#'SigParameter'{sigParameterName = N1, + value = V1, + extraInfo = E1}, + #'SigParameter'{sigParameterName = N2, + value = V2, + extraInfo = E2}) -> + N1 = N2, + chk_Value(V1,V2), + chk_opt_extraInfo(E1,E2), + ok; +chk_sigParameter(P1,P2) -> + wrong_type({'SigParameter',P1,P2}). + + +chk_opt_StreamId(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_opt_StreamId(I1,I2) -> + chk_StreamId(I1,I2). + +chk_StreamId(I,I) when is_integer(I) -> + ok; +chk_StreamId(I1,I2) when is_integer(I1) andalso is_integer(I2) -> + not_equal({streamId,I1,I2}); +chk_StreamId(I1,I2) -> + wrong_type({streamId,I1,I2}). + + +chk_EventParameters(EP1,EP2) + when is_list(EP1) andalso is_list(EP2) andalso (length(EP1) =:= length(EP2)) -> + chk_EventParameters1(EP1,EP2); +chk_EventParameters(EP1,EP2) -> + wrong_type({eventParameters,EP1,EP2}). + +chk_EventParameters1([],[]) -> + ok; +chk_EventParameters1([EP1|EPS1],[EP2|EPS2]) -> + chk_EventParameter(EP1,EP2), + chk_EventParameters1(EPS1,EPS2). + +chk_EventParameter(EP,EP) when is_record(EP,'EventParameter') -> + ok; +chk_EventParameter(#'EventParameter'{eventParameterName = N1, + value = V1, + extraInfo = E1} = EP1, + #'EventParameter'{eventParameterName = N2, + value = V2, + extraInfo = E2} = EP2) -> + N1 = N2, + chk_Value(V1,V2), + chk_opt_extraInfo(E1,E2), + equal({'EventParameter',EP1,EP2}); +chk_EventParameter(EP1,EP2) -> + wrong_type({'EventParameter',EP1,EP2}). + + +chk_Value(V,V) when is_list(V) -> + chk_Value(V); +chk_Value(V1,V2) + when is_list(V1) andalso is_list(V2) andalso (length(V1) =:= length(V2)) -> + chk_Value1(V1,V2); +chk_Value(V1,V2) -> + wrong_type({value,V1,V2}). + +chk_Value([]) -> + ok; +chk_Value([H|T]) when is_list(H) -> + chk_Value(T); +chk_Value([H|_T]) -> + wrong_type({value_part,H}). + +chk_Value1([],[]) -> + ok; +chk_Value1([H|T1],[H|T2]) when is_list(H) -> + chk_Value1(T1,T2); +chk_Value1([H|_T1],[H|_T2]) -> + wrong_type({value_part,H}); +chk_Value1([H1|_T1],[H2|_T2]) when is_list(H1) andalso is_list(H2) -> + not_equal({value_part,H1,H2}); +chk_Value1(V1,V2) -> + wrong_type({value,V1,V2}). + + +chk_opt_extraInfo(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_opt_extraInfo(E1,E2) -> + chk_extraInfo(E1,E2). + +chk_extraInfo({relation,greaterThan},{relation,greaterThan}) -> + ok; +chk_extraInfo({relation,smallerThan},{relation,smallerThan}) -> + ok; +chk_extraInfo({relation,unequalTo},{relation,unequalTo}) -> + ok; +chk_extraInfo({range,true},{range,true}) -> + ok; +chk_extraInfo({range,false},{range,false}) -> + ok; +chk_extraInfo({sublist,true},{sublist,true}) -> + ok; +chk_extraInfo({sublist,false},{sublist,false}) -> + ok; +chk_extraInfo(E1,E2) -> + wrong_type({extraInfo,E1,E2}). + + +chk_opt_transactionId(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_opt_transactionId(Id1,Id2) -> + chk_transactionId(Id1,Id2). + +chk_transactionId(Id,Id) when is_integer(Id) -> + ok; +chk_transactionId(Id1,Id2) when is_integer(Id1) andalso is_integer(Id2) -> + not_equal({transactionId,Id1,Id2}); +chk_transactionId(Id1,Id2) -> + wrong_type({transactionId,Id1,Id2}). + + +chk_terminationIds(Tids1,Tids2) + when is_list(Tids1) andalso is_list(Tids2) andalso (length(Tids1) =:= length(Tids2)) -> + chk_terminationIds1(Tids1,Tids2); +chk_terminationIds(Tids1,Tids2) -> + wrong_type({terminationIds,Tids1,Tids2}). + +chk_terminationIds1([],[]) -> + ok; +chk_terminationIds1([Tid1|Tids1],[Tid2|Tids2]) -> + chk_terminationId(Tid1,Tid2), + chk_terminationIds1(Tids1,Tids2). + +chk_terminationId(Id,Id) when is_record(Id,'TerminationID') -> + ok; +chk_terminationId(Id,Id) when is_record(Id,megaco_term_id) -> + ok; +chk_terminationId(#'TerminationID'{wildcard = W1, + id = I1} = Tid1, + #'TerminationID'{wildcard = W2, + id = I2} = Tid2) -> + chk_terminationId_wildcard(W1,W2), + chk_terminationId_id(I1,I2), + equal({'TerminationID',Tid1,Tid2}); +chk_terminationId(#megaco_term_id{contains_wildcards = W1, + id = I1} = Tid1, + #megaco_term_id{contains_wildcards = W2, + id = I2} = Tid2) -> + chk_terminationId_wildcard(W1,W2), + chk_terminationId_id(I1,I2), + equal({megaco_term_id,Tid1,Tid2}); +chk_terminationId(Tid1,Tid2) -> + wrong_type({terminationId,Tid1,Tid2}). + +chk_terminationId_wildcard(W,W) -> + ok; +chk_terminationId_wildcard(W1,W2) -> + not_equal({terminationId_wildcard,W1,W2}). + +chk_terminationId_id(I,I) -> + ok; +chk_terminationId_id(I1,I2) -> + not_equal({terminationId_id,I1,I2}). + + +equal(What) -> + error({equal, What}). + +not_equal(What) -> + error({not_equal, What}). + +wrong_type(What) -> + error({wrong_type, What}). + +error(Reason) -> + throw({error, Reason}). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +cre_MegacoMessage(Mess) -> + ?MSG_LIB:cre_MegacoMessage(Mess). + +cre_megacoMessage(V, Mid, Body) -> + #'MegacoMessage'{mess = #'Message'{version = V, + mId = Mid, + messageBody = Body}}. + +cre_Msg(Mid, Body) -> + cre_Msg(?VERSION, Mid, Body). + +cre_Msg(V, Mid, Body) -> + ?MSG_LIB:cre_Message(V, Mid, Body). + +cre_authHeader() -> + SecParmIdx = [239, 205, 171, 137], + SeqNum = [18, 52, 86, 120], + AD = [18, 52, 86, 120, 137, 171, 205, 239, 118, 84, 50, 16], + cre_authHeader(SecParmIdx, SeqNum, AD). + +cre_authHeader(Idx, Num, D) -> + #'AuthenticationHeader'{secParmIndex = Idx, + seqNum = Num, + ad = D}. + +cre_TransId(TransId) -> + ?MSG_LIB:cre_TransactionId(TransId). + +cre_Trans(Trans) -> + ?MSG_LIB:cre_Transaction(Trans). + +cre_TransReq(TransId, Actions) -> + ?MSG_LIB:cre_TransactionRequest(TransId, Actions). + +cre_transactionReply(TransId, Actions) -> + #'TransactionReply'{transactionId = TransId, + transactionResult = {actionReplies, Actions}}. + +cre_transactionAck(Serial, Serial) -> + #'TransactionAck'{firstAck = Serial}; +cre_transactionAck(First, Last) -> + #'TransactionAck'{firstAck = First, lastAck = Last}. + +cre_ActReq(CtxId, CmdReqs) -> + ?MSG_LIB:cre_ActionRequest(CtxId, CmdReqs). + +cre_actionReply(CtxId, CmdReply) -> + #'ActionReply'{contextId = CtxId, + commandReply = CmdReply}. + +cre_CtxID(Id) -> + ?MSG_LIB:cre_ContextID(Id). + +%% Parameter related +cre_propertyParm(Name, Val) -> + #'PropertyParm'{name = Name, value = [Val]}. + + +%% Statistics related +cre_statisticsParm(Name, Val) -> + #'StatisticsParameter'{statName = Name, statValue = [Val]}. + + +% Event related +cre_eventParm(Name, Val) -> + #'EventParameter'{eventParameterName = Name, value = Val}. + +cre_observedEvent(Name, Not) -> + #'ObservedEvent'{eventName = Name, timeNotation = Not}. +cre_observedEvent(Name, Not, Par) -> + #'ObservedEvent'{eventName = Name, timeNotation = Not, eventParList = Par}. + +cre_requestedEvent(Name) -> + #'RequestedEvent'{pkgdName = Name}. +cre_requestedEvent(Name, ParList) when is_list(ParList) -> + #'RequestedEvent'{pkgdName = Name, evParList = ParList}; +cre_requestedEvent(Name, Action) when is_tuple(Action) -> + #'RequestedEvent'{pkgdName = Name, eventAction = Action}. + + +cre_observedEventsDesc(Id, EvList) -> + #'ObservedEventsDescriptor'{requestId = Id, observedEventLst = EvList}. + +cre_eventsDesc(Id, EvList) -> + #'EventsDescriptor'{requestID = Id, eventList = EvList}. + + +%% Service change related +cre_serviceChangeParm(M,A,R,P) -> + #'ServiceChangeParm'{serviceChangeMethod = M, serviceChangeAddress = A, + serviceChangeReason = R, serviceChangeProfile = P}. + +cre_serviceChangeResParm(A,P) -> + #'ServiceChangeResParm'{serviceChangeAddress = A, + serviceChangeProfile = P}. + +cre_serviceChangeReq(Tid, P) -> + #'ServiceChangeRequest'{terminationID = Tid, serviceChangeParms = P}. + +cre_serviceChangeProf(Name, Ver) when is_list(Name) andalso is_integer(Ver) -> + #'ServiceChangeProfile'{profileName = Name, version = Ver}. + +cre_serviceChangeReply(Tid, Res) -> + #'ServiceChangeReply'{terminationID = Tid, serviceChangeResult = Res}. + + +%% Stream related +cre_streamParms(Lcd) -> + #'StreamParms'{localControlDescriptor = Lcd}. +cre_streamParms(Lcd, Ld) -> + #'StreamParms'{localControlDescriptor = Lcd, localDescriptor = Ld}. +cre_streamParms(Lcd, Ld, Rd) -> + #'StreamParms'{localControlDescriptor = Lcd, + localDescriptor = Ld, + remoteDescriptor = Rd}. +cre_streamParmsL(Ld) -> + #'StreamParms'{localDescriptor = Ld}. +cre_streamParmsR(Rd) -> + #'StreamParms'{remoteDescriptor = Rd}. + +cre_streamDesc(Id, P) -> + #'StreamDescriptor'{streamID = Id, streamParms = P}. + + +%% "Local" related +cre_localControlDesc(Mode) -> + #'LocalControlDescriptor'{streamMode = Mode}. +cre_localControlDesc(Mode, Parms) -> + #'LocalControlDescriptor'{streamMode = Mode, propertyParms = Parms }. + +cre_localRemoteDesc(Grps) -> + #'LocalRemoteDescriptor'{propGrps = Grps}. + + +%% DigitMap related +cre_digitMapDesc(Value) when is_record(Value, 'DigitMapValue') -> + #'DigitMapDescriptor'{digitMapValue = Value}; +cre_digitMapDesc(Name) -> + #'DigitMapDescriptor'{digitMapName = Name}. + +cre_digitMapDesc(Name, Val) -> + #'DigitMapDescriptor'{digitMapName = Name, digitMapValue = Val}. + +cre_digitMapValue(Body) -> + #'DigitMapValue'{digitMapBody = Body}. + +cre_digitMapValue(Body, Start, Short, Long) -> + #'DigitMapValue'{startTimer = Start, + shortTimer = Short, + longTimer = Long, + digitMapBody = Body}. + +%% Media related +cre_mediaDesc(StreamDesc) -> + #'MediaDescriptor'{streams = {multiStream, [StreamDesc]}}. + + +%% Notify related +cre_notifyReq(Tid, EvsDesc) -> + #'NotifyRequest'{terminationID = Tid, observedEventsDescriptor = EvsDesc}. + +cre_notifyReply(Tid) -> + #'NotifyReply'{terminationID = Tid}. + + +%% Subtract related +cre_subtractReq(Tid, Desc) -> + #'SubtractRequest'{terminationID = Tid, auditDescriptor = Desc}. + + +%% Audit related +cre_auditDesc(Tokens) -> + #'AuditDescriptor'{auditToken = Tokens}. + +cre_auditReq(Tid, Desc) -> + #'AuditRequest'{terminationID = Tid, auditDescriptor = Desc}. + +cre_auditRes(Tid, Res) -> + #'AuditResult'{terminationID = Tid, terminationAuditResult = Res}. + + +%% AMM/AMMS related +cre_ammReq(Tid, Descs) -> + #'AmmRequest'{terminationID = Tid, descriptors = Descs}. + +cre_ammsReply(Tid) -> + #'AmmsReply'{terminationID = Tid}. +cre_ammsReply(Tid, Descs) -> + #'AmmsReply'{terminationID = Tid, terminationAudit = Descs}. + + +%% Command related +cre_commandReq(Cmd) -> + #'CommandRequest'{command = Cmd}. + + +%% Actions related +cre_requestedActions(DmName) -> + #'RequestedActions'{eventDM = {digitMapName, DmName}}. + + +%% Signal related +cre_signal(Name) -> + #'Signal'{signalName = Name}. + + +%% Others +cre_timeNotation(D,T) -> + #'TimeNotation'{date = D, time = T}. + +cre_packagesItem(_Name, _Ver) -> + #'PackagesItem'{packageName = "nt", packageVersion = 1}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_init(Config) -> + megaco_codec_flex_lib:init(Config). + +flex_finish(Config) -> + megaco_codec_flex_lib:finish(Config). + +flex_scanner_conf(Config) -> + megaco_codec_flex_lib:scanner_conf(Config). + +start_flex_scanner() -> + megaco_codec_flex_lib:start(). + +stop_flex_scanner(Pid) -> + megaco_codec_flex_lib:stop(Pid). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +t(F,A) -> + p(printable(get(severity),trc),trc,F,A). + +d(F,A) -> + p(printable(get(severity),dbg),dbg,F,A). + +l(F,A) -> + p(printable(get(severity),log),log,F,A). + +e(F,A) -> + p(printable(get(severity),err),err,F,A). + + +printable(trc,_) -> + true; +printable(dbg,trc) -> + false; +printable(dbg,_) -> + true; +printable(log,log) -> + true; +printable(log,err) -> + true; +printable(err,err) -> + true; +printable(_,_) -> + false. + + +p(true,L,F,A) -> + io:format("~s: " ++ F ++ "~n", [image_of(L)|A]); +p(_,_,_,_) -> + ok. + +image_of(trc) -> + "T"; +image_of(dbg) -> + "D"; +image_of(log) -> + "L"; +image_of(err) -> + "E"; +image_of(L) -> + io_lib:format("~p",[L]). + + diff --git a/lib/megaco/test/megaco_codec_v2_test.erl b/lib/megaco/test/megaco_codec_v2_test.erl new file mode 100644 index 0000000000..1df1c6c93b --- /dev/null +++ b/lib/megaco/test/megaco_codec_v2_test.erl @@ -0,0 +1,6992 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test encoding/decoding (codec) module of Megaco/H.248 +%%---------------------------------------------------------------------- + +-module(megaco_codec_v2_test). + +%% ---- + +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v2.hrl"). +-include("megaco_test_lib.hrl"). + +%% ---- + +-export([msgs/0]). +-export([rfc3525_msgs_display/0, rfc3525_msgs_test/0]). + +-export([t/0, t/1]). + +-export([all/1, + + text/1, + + pretty/1, + pretty_test_msgs/1, + + compact/1, + compact_test_msgs/1, + + flex_pretty/1, + flex_pretty_init/1, + flex_pretty_finish/1, + flex_pretty_test_msgs/1, + + flex_compact/1, + flex_compact_init/1, + flex_compact_finish/1, + flex_compact_test_msgs/1, + + flex_compact_dm_timers1/1, + flex_compact_dm_timers2/1, + flex_compact_dm_timers3/1, + flex_compact_dm_timers4/1, + flex_compact_dm_timers5/1, + flex_compact_dm_timers6/1, + flex_compact_dm_timers7/1, + flex_compact_dm_timers8/1, + + binary/1, + + bin/1, + bin_test_msgs/1, + + ber/1, + ber_test_msgs/1, + + ber_bin/1, + ber_bin_test_msgs/1, + + per/1, + per_test_msgs/1, + + per_bin/1, + per_bin_test_msgs/1, + + erl_dist/1, + erl_dist_m/1, + erl_dist_m_test_msgs/1, + + tickets/0, + tickets/1, + + compact_tickets/1, + compact_otp4011_msg1/1, + compact_otp4011_msg2/1, + compact_otp4011_msg3/1, + compact_otp4013_msg1/1, + compact_otp4085_msg1/1, + compact_otp4085_msg2/1, + compact_otp4280_msg1/1, + compact_otp4299_msg1/1, + compact_otp4299_msg2/1, + compact_otp4359_msg1/1, + compact_otp4920_msg0/1, + compact_otp4920_msg1/1, + compact_otp4920_msg2/1, + compact_otp4920_msg3/1, + compact_otp4920_msg4/1, + compact_otp4920_msg5/1, + compact_otp4920_msg6/1, + compact_otp4920_msg7/1, + compact_otp4920_msg8/1, + compact_otp4920_msg9/1, + compact_otp4920_msg10/1, + compact_otp4920_msg11/1, + compact_otp4920_msg12/1, + compact_otp4920_msg20/1, + compact_otp4920_msg21/1, + compact_otp4920_msg22/1, + compact_otp4920_msg23/1, + compact_otp4920_msg24/1, + compact_otp4920_msg25/1, + compact_otp5186_msg01/1, + compact_otp5186_msg02/1, + compact_otp5186_msg03/1, + compact_otp5186_msg04/1, + compact_otp5186_msg05/1, + compact_otp5186_msg06/1, + compact_otp5290_msg01/1, + compact_otp5290_msg02/1, + compact_otp5793_msg01/1, + compact_otp5993_msg01/1, + compact_otp5993_msg02/1, + compact_otp5993_msg03/1, + compact_otp6017_msg01/1, + compact_otp6017_msg02/1, + compact_otp6017_msg03/1, + compact_otp7138_msg01/1, + compact_otp7138_msg02/1, + compact_otp7457_msg01/1, + compact_otp7457_msg02/1, + compact_otp7457_msg03/1, + compact_otp7534_msg01/1, + compact_otp7576_msg01/1, + compact_otp7671_msg01/1, + + flex_compact_tickets/1, + flex_compact_otp7138_msg01/1, + flex_compact_otp7138_msg02/1, + flex_compact_otp7431_msg01/1, + flex_compact_otp7431_msg02/1, + flex_compact_otp7431_msg03/1, + flex_compact_otp7431_msg04/1, + flex_compact_otp7431_msg05/1, + flex_compact_otp7431_msg06/1, + flex_compact_otp7431_msg07/1, + flex_compact_otp7457_msg01/1, + flex_compact_otp7457_msg02/1, + flex_compact_otp7457_msg03/1, + flex_compact_otp7534_msg01/1, + flex_compact_otp7573_msg01/1, + flex_compact_otp7576_msg01/1, + + pretty_tickets/1, + pretty_otp4632_msg1/1, + pretty_otp4632_msg2/1, + pretty_otp4632_msg3/1, + pretty_otp4632_msg4/1, + pretty_otp4710_msg1/1, + pretty_otp4710_msg2/1, + pretty_otp4945_msg1/1, + pretty_otp4945_msg2/1, + pretty_otp4945_msg3/1, + pretty_otp4945_msg4/1, + pretty_otp4945_msg5/1, + pretty_otp4945_msg6/1, + pretty_otp4949_msg1/1, + pretty_otp4949_msg2/1, + pretty_otp4949_msg3/1, + pretty_otp5042_msg1/1, + pretty_otp5068_msg1/1, + pretty_otp5085_msg1/1, + pretty_otp5085_msg2/1, + pretty_otp5085_msg3/1, + pretty_otp5085_msg4/1, + pretty_otp5085_msg5/1, + pretty_otp5085_msg6/1, + pretty_otp5085_msg7/1, + pretty_otp5600_msg1/1, + pretty_otp5600_msg2/1, + pretty_otp5601_msg1/1, + pretty_otp5793_msg01/1, + pretty_otp5882_msg01/1, + pretty_otp6490_msg01/1, + pretty_otp6490_msg02/1, + pretty_otp6490_msg03/1, + pretty_otp6490_msg04/1, + pretty_otp6490_msg05/1, + pretty_otp6490_msg06/1, + pretty_otp7249_msg01/1, + pretty_otp7671_msg01/1, + pretty_otp7671_msg02/1, + pretty_otp7671_msg03/1, + pretty_otp7671_msg04/1, + pretty_otp7671_msg05/1, + + flex_pretty_tickets/1, + flex_pretty_otp5042_msg1/1, + flex_pretty_otp5085_msg1/1, + flex_pretty_otp5085_msg2/1, + flex_pretty_otp5085_msg3/1, + flex_pretty_otp5085_msg4/1, + flex_pretty_otp5085_msg5/1, + flex_pretty_otp5085_msg6/1, + flex_pretty_otp5085_msg7/1, + flex_pretty_otp5600_msg1/1, + flex_pretty_otp5600_msg2/1, + flex_pretty_otp5601_msg1/1, + flex_pretty_otp5793_msg01/1, + flex_pretty_otp7431_msg01/1, + flex_pretty_otp7431_msg02/1, + flex_pretty_otp7431_msg03/1, + flex_pretty_otp7431_msg04/1, + flex_pretty_otp7431_msg05/1, + flex_pretty_otp7431_msg06/1, + flex_pretty_otp7431_msg07/1, + + init_per_testcase/2, fin_per_testcase/2]). + +-export([display_text_messages/0, generate_text_messages/0]). + +-export([ + %% Decode + profile_decode_compact_text_message/1, + profile_decode_compact_text_messages/0, + profile_decode_compact_flex_text_messages/0, + profile_decode_pretty_text_message/1, + profile_decode_pretty_text_messages/0, + profile_decode_pretty_flex_text_messages/0, + + %% Encode + profile_encode_compact_text_messages/0, + profile_encode_pretty_text_messages/0 + ]). + + +%% ---- + +-define(V2, v2). +-define(EC, []). +-define(VERSION, 2). +-define(VERSION_STR, "2"). +-define(MSG_LIB, megaco_test_msg_v2_lib). +-define(DEFAULT_PORT, 55555). +-define(MG1_MID_NO_PORT, {ip4Address, + #'IP4Address'{address = [124, 124, 124, 222]}}). +-define(MG1_MID, {ip4Address, #'IP4Address'{address = [124, 124, 124, 222], + portNumber = ?DEFAULT_PORT}}). +-define(MG2_MID, {ip4Address, #'IP4Address'{address = [125, 125, 125, 111], + portNumber = ?DEFAULT_PORT}}). +-define(MGC_MID, {ip4Address, #'IP4Address'{address = [123, 123, 123, 4], + portNumber = ?DEFAULT_PORT}}). + +-define(A4444, ["11111111", "00000000", "00000000"]). +-define(A4445, ["11111111", "00000000", "11111111"]). +-define(A5555, ["11111111", "11111111", "00000000"]). +-define(A5556, ["11111111", "11111111", "11111111"]). + + +%% ---- + +display_text_messages() -> + Msgs = + msgs4() ++ + msgs5(), + megaco_codec_test_lib:display_text_messages(?VERSION, Msgs). + + +generate_text_messages() -> + Msgs = + msgs4() ++ + msgs5(), + megaco_codec_test_lib:generate_text_messages(?V2, ?VERSION, ?EC, Msgs). + + +%% ---- + +%% (catch megaco_codec_v2_test:profile_decode_compact_text_message(msg51a)). +%% (catch megaco_codec_v2_test:profile_decode_compact_text_message(msg51b)). +%% (catch megaco_codec_v2_test:profile_decode_compact_text_message(msg52)). +%% (catch megaco_codec_v2_test:profile_decode_compact_text_message(msg53)). +%% (catch megaco_codec_v2_test:profile_decode_compact_text_message(msg54a)). +%% (catch megaco_codec_v2_test:profile_decode_compact_text_message(msg58a)). +%% (catch megaco_codec_v2_test:profile_decode_compact_text_message(msg58b)). +%% (catch megaco_codec_v2_test:profile_decode_compact_text_message(msg61a)). +profile_decode_compact_text_message(MsgTag) -> + Codec = megaco_compact_text_encoder, + Config = [], + profile_decode_text_message(Codec, Config, MsgTag). + +%% (catch megaco_codec_v2_test:profile_decode_pretty_text_message(msg51a)). +%% (catch megaco_codec_v2_test:profile_decode_pretty_text_message(msg51b)). +%% (catch megaco_codec_v2_test:profile_decode_pretty_text_message(msg52)). +profile_decode_pretty_text_message(MsgTag) -> + Codec = megaco_pretty_text_encoder, + Config = [], + profile_decode_text_message(Codec, Config, MsgTag). + +profile_decode_text_message(Codec, Config, MsgTag) -> + Msgs = msgs4() ++ msgs5(), + case lists:keysearch(MsgTag, 1, Msgs) of + {value, Msg} -> + profile_decode_text_messages(Codec, Config, [Msg]); + false -> + {error, {no_such_message, MsgTag}} + end. + + +%% (catch megaco_codec_v2_test:profile_decode_compact_text_messages()). +profile_decode_compact_text_messages() -> + Config = [], + Slogan = decode_compact_v2, + profile_decode_compact_text_messages(Slogan, Config). + +%% (catch megaco_codec_v2_test:profile_decode_compact_flex_text_messages()). +profile_decode_compact_flex_text_messages() -> + Conf = flex_init([]), + Config = flex_scanner_conf(Conf), + Slogan = decode_compact_flex_v2, + Res = profile_decode_compact_text_messages(Slogan, [Config]), + flex_finish(Conf), + Res. + +profile_decode_compact_text_messages(Slogan, Config) -> + Codec = megaco_compact_text_encoder, + profile_decode_text_messages(Slogan, Codec, Config). + +%% (catch megaco_codec_v2_test:profile_decode_pretty_text_messages()). +profile_decode_pretty_text_messages() -> + Config = [], + Slogan = decode_pretty_v2, + profile_decode_pretty_text_messages(Slogan, Config). + +%% (catch megaco_codec_v2_test:profile_decode_pretty_flex_text_messages()). +profile_decode_pretty_flex_text_messages() -> + Conf = flex_init([]), + Config = flex_scanner_conf(Conf), + Slogan = decode_pretty_flex_v2, + Res = profile_decode_pretty_text_messages(Slogan, [Config]), + flex_finish(Conf), + Res. + +profile_decode_pretty_text_messages(Slogan, Config) -> + Codec = megaco_pretty_text_encoder, + profile_decode_text_messages(Slogan, Codec, Config). + +profile_decode_text_messages(Slogan, Codec, Config) -> + Msgs = msgs4() ++ msgs5(), + profile_decode_text_messages(Slogan, Codec, Config, Msgs). + +profile_decode_text_messages(Slogan, Codec, Config, Msgs0) -> + Msgs = [Msg || {_, Msg, _, _} <- Msgs0], + EncodeRes = encode_text_messages(Codec, Config, Msgs, []), + Bins = [Bin || {ok, Bin} <- EncodeRes], + Fun = fun() -> + decode_text_messages(Codec, Config, Bins, []) + end, + %% Make a dry run, just to make sure all modules are loaded: + io:format("make a dry run..~n", []), + (catch Fun()), + io:format("make the run..~n", []), + megaco_profile:profile(Slogan, Fun). + +%% (catch megaco_codec_v2_test:profile_encode_compact_text_messages()). +profile_encode_compact_text_messages() -> + Codec = megaco_compact_text_encoder, + Config = [], + Slogan = encode_compact_v2, + profile_encode_text_messages(Slogan, Codec, Config). + +%% (catch megaco_codec_v2_test:profile_encode_pretty_text_messages()). +profile_encode_pretty_text_messages() -> + Codec = megaco_pretty_text_encoder, + Config = [], + Slogan = encode_pretty_v2, + profile_encode_text_messages(Slogan, Codec, Config). + +profile_encode_text_messages(Slogan, Codec, Config) -> + Msgs = msgs4() ++ msgs5(), + profile_encode_text_messages(Slogan, Codec, Config, Msgs). + +profile_encode_text_messages(Slogan, Codec, Config, Msgs0) -> + Msgs = [Msg || {_, Msg, _, _} <- Msgs0], + Fun = fun() -> + encode_text_messages(Codec, Config, Msgs, []) + end, + %% Make a dry run, just to make sure all modules are loaded: + io:format("make a dry run...~n", []), + (catch Fun()), + io:format("make the run...~n", []), + megaco_profile:profile(Slogan, Fun). + +encode_text_messages(_Codec, _Config, [], Acc) -> + Acc; +encode_text_messages(Codec, Config, [Msg|Msgs], Acc) -> + Res = Codec:encode_message(Config, ?VERSION, Msg), + encode_text_messages(Codec, Config, Msgs, [Res | Acc]). + +decode_text_messages(_Codec, _Config, [], Acc) -> + Acc; +decode_text_messages(Codec, Config, [Msg|Msgs], Acc) -> + Res = Codec:decode_message(Config, dynamic, Msg), + decode_text_messages(Codec, Config, Msgs, [Res | Acc]). + + +%% ---- + + +expand(RootCase) -> + expand([RootCase], []). + +expand([], Acc) -> + lists:flatten(lists:reverse(Acc)); +expand([Case|Cases], Acc) -> + case (catch apply(?MODULE,Case,[suite])) of + [] -> + expand(Cases, [Case|Acc]); + C when is_list(C) -> + expand(Cases, [expand(C, [])|Acc]); + _ -> + expand(Cases, [Case|Acc]) + end. + + +%% ---- + +tickets() -> + Flag = process_flag(trap_exit, true), + Cases = expand(tickets), + Fun = fun(Case) -> + C = init_per_testcase(Case, [{tc_timeout, + timer:minutes(10)}]), + io:format("Eval ~w~n", [Case]), + Result = + case (catch apply(?MODULE, Case, [C])) of + {'EXIT', Reason} -> + io:format("~n~p exited:~n ~p~n", + [Case, Reason]), + {error, {Case, Reason}}; + Res -> + Res + end, + fin_per_testcase(Case, C), + Result + end, + process_flag(trap_exit, Flag), + lists:map(Fun, Cases). + + +%% ---- + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + +init_per_testcase(Case, Config) -> + %% CaseString = io_lib:format("~p", [Case]), + C = + case lists:suffix("time_test", atom_to_list(Case)) of + true -> + [{tc_timeout, timer:minutes(10)}|Config]; + false -> + put(verbosity,trc), + Config + end, + megaco_test_lib:init_per_testcase(Case, C). + +fin_per_testcase(Case, Config) -> + erase(verbosity), + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top test case + +all(suite) -> + [ + text, + binary, + erl_dist, + tickets + ]. + +text(suite) -> + [ + pretty, + flex_pretty, + compact, + flex_compact + ]. + +binary(suite) -> + [ + bin, + ber, + ber_bin, + per, + per_bin + ]. + +erl_dist(suite) -> + [ + erl_dist_m + ]. + +pretty(suite) -> + [ + pretty_test_msgs + ]. + + +compact(suite) -> + [ + compact_test_msgs + ]. + + +flex_pretty(suite) -> + {req, [], + {conf, flex_pretty_init, flex_pretty_cases(), flex_pretty_finish}}. + +flex_pretty_cases() -> + [ + flex_pretty_test_msgs + ]. + +flex_compact(suite) -> + {req, [], + {conf, flex_compact_init, flex_compact_cases(), flex_compact_finish}}. + +flex_compact_cases() -> + [ + flex_compact_test_msgs, + flex_compact_dm_timers1, + flex_compact_dm_timers2, + flex_compact_dm_timers3, + flex_compact_dm_timers4, + flex_compact_dm_timers5, + flex_compact_dm_timers6, + flex_compact_dm_timers7, + flex_compact_dm_timers8 + ]. + + +bin(suite) -> + [ + bin_test_msgs + ]. + + +ber(suite) -> + [ + ber_test_msgs + ]. + + +ber_bin(suite) -> + [ + ber_bin_test_msgs + ]. + + +per(suite) -> + [ + per_test_msgs + ]. + + +%% Support for per_bin was added to ASN.1 as of version +%% 1.3.2 (R8). And later merged into 1.3.1.3 (R7). These +%% releases are identical (as far as I know). +%% +per_bin(suite) -> + [ + per_bin_test_msgs + ]. + + +erl_dist_m(suite) -> + [ + erl_dist_m_test_msgs + ]. + +tickets(suite) -> + [ + compact_tickets, + pretty_tickets, + flex_compact_tickets, + flex_pretty_tickets + ]. + + +compact_tickets(suite) -> + [ + compact_otp4011_msg1, + compact_otp4011_msg2, + compact_otp4011_msg3, + compact_otp4013_msg1, + compact_otp4085_msg1, + compact_otp4085_msg2, + compact_otp4280_msg1, + compact_otp4299_msg1, + compact_otp4299_msg2, + compact_otp4359_msg1, + compact_otp4920_msg0, + compact_otp4920_msg1, + compact_otp4920_msg2, + compact_otp4920_msg3, + compact_otp4920_msg4, + compact_otp4920_msg5, + compact_otp4920_msg6, + compact_otp4920_msg7, + compact_otp4920_msg8, + compact_otp4920_msg9, + compact_otp4920_msg10, + compact_otp4920_msg11, + compact_otp4920_msg12, + compact_otp4920_msg20, + compact_otp4920_msg21, + compact_otp4920_msg22, + compact_otp4920_msg23, + compact_otp4920_msg24, + compact_otp4920_msg25, + compact_otp5186_msg01, + compact_otp5186_msg02, + compact_otp5186_msg03, + compact_otp5186_msg04, + compact_otp5186_msg05, + compact_otp5186_msg06, + compact_otp5290_msg01, + compact_otp5290_msg02, + compact_otp5793_msg01, + compact_otp5993_msg01, + compact_otp5993_msg02, + compact_otp5993_msg03, + compact_otp6017_msg01, + compact_otp6017_msg02, + compact_otp6017_msg03, + compact_otp7138_msg01, + compact_otp7138_msg02, + compact_otp7457_msg01, + compact_otp7457_msg02, + compact_otp7457_msg03, + compact_otp7534_msg01, + compact_otp7576_msg01, + compact_otp7671_msg01 + ]. + +flex_compact_tickets(suite) -> + {req, [], + {conf, flex_compact_init, flex_compact_tickets_cases(), + flex_compact_finish}}. + +flex_compact_tickets_cases() -> + [ + flex_compact_otp7138_msg01, + flex_compact_otp7138_msg02, + flex_compact_otp7431_msg01, + flex_compact_otp7431_msg02, + flex_compact_otp7431_msg03, + flex_compact_otp7431_msg04, + flex_compact_otp7431_msg05, + flex_compact_otp7431_msg06, + flex_compact_otp7431_msg07, + flex_compact_otp7138_msg02, + flex_compact_otp7457_msg01, + flex_compact_otp7457_msg02, + flex_compact_otp7457_msg03, + flex_compact_otp7534_msg01, + flex_compact_otp7573_msg01, + flex_compact_otp7576_msg01 + ]. + +pretty_tickets(suite) -> + [ + pretty_otp4632_msg1, + pretty_otp4632_msg2, + pretty_otp4632_msg3, + pretty_otp4632_msg4, + pretty_otp4710_msg1, + pretty_otp4710_msg2, + pretty_otp4945_msg1, + pretty_otp4945_msg2, + pretty_otp4945_msg3, + pretty_otp4945_msg4, + pretty_otp4945_msg5, + pretty_otp4945_msg6, + pretty_otp4949_msg1, + pretty_otp4949_msg2, + pretty_otp4949_msg3, + pretty_otp5042_msg1, + pretty_otp5068_msg1, + pretty_otp5085_msg1, + pretty_otp5085_msg2, + pretty_otp5085_msg3, + pretty_otp5085_msg4, + pretty_otp5085_msg5, + pretty_otp5085_msg6, + pretty_otp5085_msg7, + pretty_otp5600_msg1, + pretty_otp5600_msg2, + pretty_otp5601_msg1, + pretty_otp5793_msg01, + pretty_otp5882_msg01, + pretty_otp6490_msg01, + pretty_otp6490_msg02, + pretty_otp6490_msg03, + pretty_otp6490_msg04, + pretty_otp6490_msg05, + pretty_otp6490_msg06, + pretty_otp7249_msg01, + pretty_otp7671_msg01, + pretty_otp7671_msg02, + pretty_otp7671_msg03, + pretty_otp7671_msg04, + pretty_otp7671_msg05 + ]. + +flex_pretty_tickets(suite) -> + {req, [], + {conf, flex_pretty_init, flex_pretty_tickets_cases(), + flex_pretty_finish}}. + +flex_pretty_tickets_cases() -> + [ + flex_pretty_otp5042_msg1, + flex_pretty_otp5085_msg1, + flex_pretty_otp5085_msg2, + flex_pretty_otp5085_msg3, + flex_pretty_otp5085_msg4, + flex_pretty_otp5085_msg5, + flex_pretty_otp5085_msg6, + flex_pretty_otp5085_msg7, + flex_pretty_otp5600_msg1, + flex_pretty_otp5600_msg2, + flex_pretty_otp5601_msg1, + flex_pretty_otp5793_msg01, + flex_pretty_otp7431_msg01, + flex_pretty_otp7431_msg02, + flex_pretty_otp7431_msg03, + flex_pretty_otp7431_msg04, + flex_pretty_otp7431_msg05, + flex_pretty_otp7431_msg06, + flex_pretty_otp7431_msg07 + ]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +pretty_test_msgs(suite) -> + []; +pretty_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1() ++ msgs2() ++ msgs3() ++ msgs4() ++ msgs5(), + %% Msgs = msgs5(), + DynamicDecode = false, + test_msgs(megaco_pretty_text_encoder, DynamicDecode, [], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_pretty_init(Config) -> + flex_init(Config). + +flex_pretty_finish(Config) -> + flex_finish(Config). + + +flex_pretty_test_msgs(suite) -> + []; +flex_pretty_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1() ++ msgs2() ++ msgs3() ++ msgs4(), + Conf = flex_scanner_conf(Config), + DynamicDecode = false, + test_msgs(megaco_pretty_text_encoder, DynamicDecode, [Conf], Msgs). + + +flex_pretty_otp5042_msg1(suite) -> + []; +flex_pretty_otp5042_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5042_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp5042_msg1(), + Bin0 = list_to_binary(Msg0), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_pretty_text_encoder, false, [Conf], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {_, _Mod, {bad_timeStamp, TimeStamp}} -> + exit({bad_timeStamp, TimeStamp}); + _ -> + io:format("flex_pretty_otp5042_msg1 -> " + "~n Reason: ~w" + "~n", [Reason]), + exit({unexpected_decode_result, Reason}) + end; + {ok, M} -> + t("flex_pretty_otp5042_msg1 -> successfull decode:" + "~n~p", [M]), + ok + end. + + +flex_pretty_otp5085_msg1(suite) -> + []; +flex_pretty_otp5085_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg1(), [Conf]). + +flex_pretty_otp5085_msg2(suite) -> + []; +flex_pretty_otp5085_msg2(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(error, pretty_otp5085_msg2(), [Conf]). + +flex_pretty_otp5085_msg3(suite) -> + []; +flex_pretty_otp5085_msg3(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg3(), [Conf]). + +flex_pretty_otp5085_msg4(suite) -> + []; +flex_pretty_otp5085_msg4(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg4(), [Conf]). + +flex_pretty_otp5085_msg5(suite) -> + []; +flex_pretty_otp5085_msg5(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg5(), [Conf]). + +flex_pretty_otp5085_msg6(suite) -> + []; +flex_pretty_otp5085_msg6(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg6(), [Conf]). + +flex_pretty_otp5085_msg7(suite) -> + []; +flex_pretty_otp5085_msg7(Config) when is_list(Config) -> + d("flex_pretty_otp5085_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5085(ok, pretty_otp5085_msg7(), [Conf]). + +flex_pretty_otp5600_msg1(suite) -> + []; +flex_pretty_otp5600_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5600_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5600(ok, pretty_otp5600_msg1(), [Conf]). + +flex_pretty_otp5600_msg2(suite) -> + []; +flex_pretty_otp5600_msg2(Config) when is_list(Config) -> + d("flex_pretty_otp5600_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5600(ok, pretty_otp5600_msg2(), [Conf]). + +flex_pretty_otp5601_msg1(suite) -> + []; +flex_pretty_otp5601_msg1(Config) when is_list(Config) -> + d("flex_pretty_otp5601_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5601(ok, pretty_otp5601_msg1(), [Conf]). + +flex_pretty_otp5793_msg01(suite) -> + []; +flex_pretty_otp5793_msg01(Config) when is_list(Config) -> + d("flex_pretty_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + pretty_otp5793(ok, pretty_otp5793_msg1(), [Conf]). + + +flex_pretty_otp7431_msg01(suite) -> + []; +flex_pretty_otp7431_msg01(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(ok, flex_pretty_otp7431_msg1(), [Conf]). + +flex_pretty_otp7431_msg02(suite) -> + []; +flex_pretty_otp7431_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp7431_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg2(), [Conf]). + +flex_pretty_otp7431_msg03(suite) -> + []; +flex_pretty_otp7431_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp7431_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg3(), [Conf]). + +flex_pretty_otp7431_msg04(suite) -> + []; +flex_pretty_otp7431_msg04(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg04 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg4(), [Conf]). + +flex_pretty_otp7431_msg05(suite) -> + []; +flex_pretty_otp7431_msg05(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg05 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg5(), [Conf]). + +flex_pretty_otp7431_msg06(suite) -> + []; +flex_pretty_otp7431_msg06(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg06 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg6(), [Conf]). + +flex_pretty_otp7431_msg07(suite) -> + []; +flex_pretty_otp7431_msg07(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg07 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg7(), [Conf]). + +flex_pretty_otp7431(Expected, Msg, Conf) -> + otp7431(Expected, megaco_pretty_text_encoder, Msg, Conf). + +otp7431(Expected, Codec, Msg0, Conf) -> + Bin0 = list_to_binary(Msg0), + case decode_message(Codec, false, Conf, Bin0) of + {ok, _Msg1} when Expected =:= ok -> + io:format(" decoded", []); + {error, {bad_property_parm, Reason}} when (Expected =:= error) andalso + is_list(Reason) -> + io:format("expected result: ~s", [Reason]), + ok; + Else -> + io:format("unexpected result", []), + exit({unexpected_decode_result, Else}) + end. + + +flex_pretty_otp7431_msg1() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a=recvonly + } ; RTP profile for G.723.1 is 4 + } + } + } + } + }". + +flex_pretty_otp7431_msg2() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a= } + } + } + } + } + }". + +flex_pretty_otp7431_msg3() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a } + } + } + } + } + }". + +flex_pretty_otp7431_msg4() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a} + } + } + } + } + }". + +flex_pretty_otp7431_msg5() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v= } + } + } + } + } + }". + +flex_pretty_otp7431_msg6() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v } + } + } + } + } + }". + +flex_pretty_otp7431_msg7() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v} + } + } + } + } + }". + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +compact_test_msgs(suite) -> + []; +compact_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1() ++ msgs2() ++ msgs3() ++ msgs4(), + DynamicDecode = false, + test_msgs(megaco_compact_text_encoder, DynamicDecode, [], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_compact_init(Config) -> + flex_init(Config). + +flex_compact_finish(Config) -> + flex_finish(Config). + + +flex_compact_test_msgs(suite) -> + []; +flex_compact_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1() ++ msgs2() ++ msgs3() ++ msgs4(), + Conf = flex_scanner_conf(Config), + DynamicDecode = true, + test_msgs(megaco_compact_text_encoder, DynamicDecode, [Conf], Msgs). + + +flex_compact_dm_timers1(suite) -> + []; +flex_compact_dm_timers1(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("1", "2", "3"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, [Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers1 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({1,2,3}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers2(suite) -> + []; +flex_compact_dm_timers2(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("02", "03", "04"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, [Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers2 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({2,3,4}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers3(suite) -> + []; +flex_compact_dm_timers3(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("1", "02", "31"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, [Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers3 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({1,2,31}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers4(suite) -> + []; +flex_compact_dm_timers4(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("10", "21", "99"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, [Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers4 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({10,21,99}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers5(suite) -> + []; +flex_compact_dm_timers5(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("99", "23", "11"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, [Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers5 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({99,23,11}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers6(suite) -> + []; +flex_compact_dm_timers6(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("77", "09", "1"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, [Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers6 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({77,9,1}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers7(suite) -> + []; +flex_compact_dm_timers7(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("77", "09", "1", "99"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, [Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers7 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({77,9,1,99}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers8(suite) -> + []; +flex_compact_dm_timers8(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("01", "09", "01", "02"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, [Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers8 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({1,9,1,2}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +build_dm_timers_message(T, S, L) -> + TMRs = lists:flatten(io_lib:format("T:~s,S:~s,L:~s", [T, S, L])), + build_dm_timers_message(TMRs). + +build_dm_timers_message(T, S, L, Z) -> + TMRs = lists:flatten(io_lib:format("T:~s,S:~s,L:~s,Z:~s", [T, S, L,Z])), + build_dm_timers_message(TMRs). + +build_dm_timers_message(TMRs) -> + M = io_lib:format("!/" ?VERSION_STR " [123.123.123.4]:55555\nT=10001{C=-{MF=11111111/00000000/00000000{E=2223{al/on,dd/ce{DM=dialplan00}},SG{cg/rt},DM=dialplan00{~s,(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)}}}}", [TMRs]), + lists:flatten(M). + + +verify_dm_timers(TMRs, #'MegacoMessage'{mess = Mess}) -> + #'Message'{messageBody = Body} = Mess, + case get_dm_timers(Body) of + {error, Reason} -> + exit({invalid_timer, {TMRs, Reason}}); + TMRs -> + ok; + TMRs1 -> + exit({invalid_timer_values, {TMRs, TMRs1}}) + end. + +get_dm_timers({transactions, T}) when is_list(T) -> + get_dm_timers1(T); +get_dm_timers(Other) -> + {error, {invalid_transactions, Other}}. + +get_dm_timers1([{transactionRequest,T}|Ts]) + when is_record(T,'TransactionRequest') -> + case get_dm_timers2(T) of + {ok, Timers} -> + Timers; + _ -> + get_dm_timers1(Ts) + end; +get_dm_timers1([_|Ts]) -> + get_dm_timers1(Ts); +get_dm_timers1([]) -> + {error, {no_timers, 'TransactionRequest'}}. + + +get_dm_timers2(#'TransactionRequest'{actions = Actions}) when is_list(Actions) -> + get_dm_timers3(Actions). + + +get_dm_timers3([#'ActionRequest'{commandRequests = Cmds}|Ars]) when is_list(Cmds) -> + case get_dm_timers4(Cmds) of + {ok, Timers} -> + {ok, Timers}; + _ -> + get_dm_timers3(Ars) + end; +get_dm_timers3([_|Ars]) -> + get_dm_timers3(Ars); +get_dm_timers3([]) -> + {error, {no_timers, 'ActionRequest'}}. + +get_dm_timers4([#'CommandRequest'{command = Cmd}|Cmds]) -> + case get_dm_timers5(Cmd) of + {ok, Timers} -> + {ok, Timers}; + _ -> + get_dm_timers4(Cmds) + end; +get_dm_timers4([_|Cmds]) -> + get_dm_timers4(Cmds); +get_dm_timers4([]) -> + {error, {no_timers, 'CommandRequest'}}. + + +get_dm_timers5({modReq, #'AmmRequest'{descriptors = Descriptors}}) -> + get_dm_timers6(Descriptors); +get_dm_timers5(R) -> + {error, {no_modReq, R}}. + + +get_dm_timers6([{digitMapDescriptor, #'DigitMapDescriptor'{digitMapValue = Val}}|_]) -> + case Val of + #'DigitMapValue'{startTimer = T, + shortTimer = S, + longTimer = L, + durationTimer = asn1_NOVALUE} -> + {ok, {T, S, L}}; + #'DigitMapValue'{startTimer = T, + shortTimer = S, + longTimer = L, + durationTimer = Z} -> + {ok, {T, S, L, Z}}; + _ -> + {error, no_value_in_dm} + end; +get_dm_timers6([_|Descs]) -> + get_dm_timers6(Descs); +get_dm_timers6([]) -> + {error, {no_timers, descriptors}}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bin_test_msgs(suite) -> + []; +bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1() ++ msgs4(), + DynamicDecode = false, + test_msgs(megaco_binary_encoder, DynamicDecode, [], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ber_test_msgs(suite) -> + []; +ber_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1() ++ msgs4(), + DynamicDecode = false, + test_msgs(megaco_ber_encoder, DynamicDecode, [], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ber_bin_test_msgs(suite) -> + []; +ber_bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1() ++ msgs4(), + DynamicDecode = true, + test_msgs(megaco_ber_bin_encoder, DynamicDecode, [], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +per_test_msgs(suite) -> + []; +per_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1() ++ msgs4(), + DynamicDecode = false, + test_msgs(megaco_per_encoder, DynamicDecode, [], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +per_bin_test_msgs(suite) -> + []; +per_bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1() ++ msgs4(), + DynamicDecode = false, + test_msgs(megaco_per_bin_encoder, DynamicDecode, [], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +erl_dist_m_test_msgs(suite) -> + []; +erl_dist_m_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = msgs1() ++ msgs2() ++ msgs3() ++ msgs4(), + DynamicDecode = false, + Conf = [megaco_compressed], + test_msgs(megaco_erl_dist_encoder, DynamicDecode, Conf, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +%% Ticket test cases: + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg1(suite) -> + []; +compact_otp4011_msg1(Config) when is_list(Config) -> +% put(severity,trc), +% put(dbg,true), + d("compact_otp4011_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR " ML T=233350{C=${A=stedevice/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SR}}}}}", + ok = compact_otp4011(M), +% erase(severity), +% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg2(suite) -> + []; +compact_otp4011_msg2(Config) when is_list(Config) -> + d("compact_otp4011_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR " ML T=233350{C=${A=stedevice/01{M{O{MO=SO,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SR}}}}}", +% put(severity,trc), +% put(dbg,true), + ok = compact_otp4011(M). + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg3(suite) -> + []; +compact_otp4011_msg3(Config) when is_list(Config) -> + d("compact_otp4011_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR " ML T=233350{C=${A=stedevice/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SO}}}}}", +% put(severity,trc), +% put(dbg,true), + ok = compact_otp4011(M). + + +compact_otp4011(M) -> + d("compact_otp4011 -> entry with" + "~n M: '~s'", [M]), + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, _} -> + exit({decoded_erroneous_message,M}); + {error, Error} when is_list(Error) -> % Expected result + d("compact_otp4011 -> expected error result (so far)", []), + case lists:keysearch(reason,1,Error) of + {value, {reason,Reason}} -> + d("compact_otp4011 -> expected error: " + "~n Reason: ~p", [Reason]), + case Reason of + {0, megaco_text_parser_v2, + {do_merge_control_streamParms, [A,B]}} + when is_list(A) andalso is_record(B, 'LocalControlDescriptor') -> + case lists:keysearch(mode,1,A) of + {value, {mode, Mode}} + when B#'LocalControlDescriptor'.streamMode /= asn1_NOVALUE -> + d("compact_otp4011 -> " + "expected error [~w]",[Mode]), + ok; + Other -> + exit({unexpected_mode_reason, {A,B,Other}}) + end; + Other -> + exit({unexpected_reason, Other}) + end; + + false -> + d("compact_otp4011 -> OUPS, wrong kind of error", []), + exit({unexpected_result, Error}) + end; + Else -> + d("compact_otp4011 -> unexpected decode result: ~p", [Else]), + exit({unexpected_decode_result, Else}) + end. + + +%% -------------------------------------------------------------- +%% Note that this decode SHALL fail, because of the misspelled +%% MEGCAO instead of the correct MEGACO. +compact_otp4013_msg1(suite) -> + []; +compact_otp4013_msg1(Config) when is_list(Config) -> + d("compact_otp4013_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "MEGCAO/2 MG1 T=12345678{C=-{SC=root{SV{MT=RS,RE=901}}}}", + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, _} -> + exit({decoded_erroneous_message,M}); + {error, Reason} when is_list(Reason) -> + {value, {reason, no_version_found, _}} = + lists:keysearch(reason, 1, Reason), + {value, {token, [{'SafeChars',_,"megcao/2"}|_]}} = + lists:keysearch(token, 1, Reason), + ok; + Else -> + exit({unexpected_decode_result,Else}) + end. + + + +%% -------------------------------------------------------------- +%% +%% +compact_otp4085_msg1(suite) -> + []; +compact_otp4085_msg1(Config) when is_list(Config) -> + d("compact_otp4085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = compact_otp4085_erroneous_msg(), + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, M} -> + exit({decoded_erroneous_message,M}); + {error, Error} when is_list(Error) -> % Expected result + t("compact_otp4085_msg1 -> decode failed", []), + case lists:keysearch(reason, 1, Error) of + {value, {reason,{999999, Module, Crap}}} -> + t("compact_otp4085_msg1 -> THE ACTUAL ERROR: " + "~n LINE NUMBER: 999999" + "~n Module: ~p" + "~n Crap: ~p", [Module, Crap]), + %% ok; + exit({decode_failed_999999, Module, Crap}); + {value, {reason,{Line, Module, Crap}}} -> + t("compact_otp4085_msg1 -> Expected: " + "~n Line: ~p" + "~n Module: ~p" + "~n Crap: ~p", [Line, Module, Crap]), + ok; + false -> + exit({unexpected_result, Error}) + end; + Else -> + exit({unexpected_decode_result, Else}) + end. + + +%% -------------------------------------------------------------- +%% This test case is just to show that the message used in +%% compact_otp4085_msg1 is actually ok when you add '}' at the end. +compact_otp4085_msg2(suite) -> + []; +compact_otp4085_msg2(Config) when is_list(Config) -> + d("compact_otp4085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M1 = compact_otp4085_erroneous_msg() ++ "}", + Bin = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, M2} -> + l("compact_otp4085_msg1 -> successfull decode" + "~n M2: ~p", [M2]), + ok; + Else -> + e("compact_otp4085_msg1 -> decode error" + "~n Else: ~p", [Else]), + exit({unexpected_decode_result,Else}) + end. + + +%% This message lack the ending parentesis (}). +compact_otp4085_erroneous_msg() -> + M = "!/" + ?VERSION_STR + " ML T=11223342{C=${A=${M{O{MO=SR,RV=OFF,RG=OFF},L{v=0," + "c=ATM NSAP $ ," + "a=eecid:$ ," + "m=audio - AAL1/ATMF -," + "}}},A=stee1181/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=off}}}}", + M. + +%% -------------------------------------------------------------- +%% +%% +compact_otp4280_msg1(suite) -> + []; +compact_otp4280_msg1(Config) when is_list(Config) -> + d("compact_otp4280_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Bin = list_to_binary(compact_otp4280_msg()), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, _Msg} -> + ok; + {error, Error} when is_list(Error) -> + t("compact_otp4280_msg1 -> decode failed", []), + case lists:keysearch(reason, 1, Error) of + {value, {reason,{Line, Module, Reason} = R}} -> + t("compact_otp4280_msg1 -> " + "~n Line: ~w" + "~n Module: ~w" + "~n Reason: ~w", [Line, Module, Reason]), + exit({decode_failed, R}); + false -> + exit({unexpected_result, Error}) + end; + Else -> + exit({unexpected_decode_result, Else}) + end. + +compact_otp4280_msg() -> + M = "!/" + ?VERSION_STR + " mgw1 P=71853646{C=-{AV=root{M{TS{root/maxnumberofcontexts=49500," + "root/maxterminationspercontext=2,root/normalmgexecutiontime=200," + "root/normalmgcexecutiontime=150," + "root/provisionalresponsetimervalue=2000,BF=OFF,SI=IV}}}}}", + M. + + +%% -------------------------------------------------------------- +%% This ticket is about comments in a message +compact_otp4299_msg1(suite) -> + []; +compact_otp4299_msg1(Config) when is_list(Config) -> + d("compact_otp4299_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Bin = list_to_binary(compact_otp4299_msg()), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, _Msg} -> + ok; + + {error, Reason} -> + exit({decode_error, Reason}); + + Else -> + exit({unexpected_decode_result, Else}) + end. + + +%% Same message, but this time decoded using the flex scanner +compact_otp4299_msg2(suite) -> + []; +compact_otp4299_msg2(Config) when is_list(Config) -> + d("compact_otp4299_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + + {Pid, Conf} = compact_otp4299_msg2_init(), + + Bin = list_to_binary(compact_otp4299_msg()), + Res = decode_message(megaco_compact_text_encoder, false, [Conf], Bin), + compact_otp4299_msg2_finish(Pid), + + case Res of + {ok, _Msg} -> + ok; + + {error, Reason} -> + exit({decode_error, Reason}); + + Else -> + exit({unexpected_decode_result, Else}) + end. + + +compact_otp4299_msg2_init() -> + Flag = process_flag(trap_exit, true), + Res = (catch start_flex_scanner()), + process_flag(trap_exit, Flag), + case Res of + {error, Reason} -> + skip(Reason); + {ok, FlexConfig} -> + FlexConfig + end. + +compact_otp4299_msg2_finish(Pid) -> + stop_flex_scanner(Pid). + + +compact_otp4299_msg() -> + M = ";KALLE\n" + "!/" + ?VERSION_STR + " mg58_1 P=005197711{; YET ANOTHER COMMENT\n" + "C=035146207{A=mg58_1_1_4_1_23/19; BEFORE COMMA\n" + ",; AFTER COMMA\n" + "A=eph58_1/0xA4023371{M{L{\n" + "v=0\n" + "c=ATM NSAP 39.0102.0304.0506.0708.090a.0b58.0100.0000.0000.00\n" + "m=audio - AAL1/ATMF -\n" + "a=eecid:A4023371\n" + "}}; HOBBE\n}; KALLE \"HOBBE \n}}" + ";KALLE\n\n", + M. + + +%% -------------------------------------------------------------- +%% +%% +compact_otp4359_msg1(suite) -> + []; +compact_otp4359_msg1(Config) when is_list(Config) -> + d("compact_otp4359_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Bin = list_to_binary(compact_otp4359_msg()), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, #'MegacoMessage'{mess = Mess}} -> + {transactions, Trans} = Mess#'Message'.messageBody, + case Trans of + [{transactionRequest,#'TransactionRequest'{transactionId = asn1_NOVALUE}}] -> + ok; + _ -> + exit({unexpected_transactions, Trans}) + end; + Else -> + t("compact_otp4359_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +compact_otp4359_msg() -> + M = "!/" ?VERSION_STR " ml2 T={C=${A=${M{O {MO=SR,RG=OFF,RV=OFF}}}}}", + M. + + +%% -------------------------------------------------------------- +%% +%% +compact_otp4920_msg0(suite) -> + []; +compact_otp4920_msg0(Config) when is_list(Config) -> + d("compact_otp4920_msg0 -> entry", []), + ?ACQUIRE_NODES(1, Config), + % put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg0(), true). + +compact_otp4920_msg1(suite) -> + []; +compact_otp4920_msg1(Config) when is_list(Config) -> + d("compact_otp4920_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + % put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg1(), false). + +compact_otp4920_msg2(suite) -> + []; +compact_otp4920_msg2(Config) when is_list(Config) -> + d("compact_otp4920_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg2(), false). + +compact_otp4920_msg3(suite) -> + []; +compact_otp4920_msg3(Config) when is_list(Config) -> + d("compact_otp4920_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg3(), true). + +compact_otp4920_msg4(suite) -> + []; +compact_otp4920_msg4(Config) when is_list(Config) -> + d("compact_otp4920_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg4(), true). + +compact_otp4920_msg5(suite) -> + []; +compact_otp4920_msg5(Config) when is_list(Config) -> + d("compact_otp4920_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg5(), true). + +compact_otp4920_msg6(suite) -> + []; +compact_otp4920_msg6(Config) when is_list(Config) -> + d("compact_otp4920_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg6(), true). + +compact_otp4920_msg7(suite) -> + []; +compact_otp4920_msg7(Config) when is_list(Config) -> + d("compact_otp4920_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + % put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg7(), true). + +compact_otp4920_msg8(suite) -> + []; +compact_otp4920_msg8(Config) when is_list(Config) -> + d("compact_otp4920_msg8 -> entry", []), + ?ACQUIRE_NODES(1, Config), + % put(dbg,true), + compact_otp4920_msg_1(compact_otp4920_msg8(), false). + +compact_otp4920_msg9(suite) -> + []; +compact_otp4920_msg9(Config) when is_list(Config) -> + d("compact_otp4920_msg9 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg9(), false). + +compact_otp4920_msg10(suite) -> + []; +compact_otp4920_msg10(Config) when is_list(Config) -> + d("compact_otp4920_msg10 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg10(), false). + +compact_otp4920_msg11(suite) -> + []; +compact_otp4920_msg11(Config) when is_list(Config) -> + d("compact_otp4920_msg11 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg11(), false). + +compact_otp4920_msg12(suite) -> + []; +compact_otp4920_msg12(Config) when is_list(Config) -> + d("compact_otp4920_msg12 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_1(compact_otp4920_msg12(), true). + +%% Duplicate padding +compact_otp4920_msg20(suite) -> + []; +compact_otp4920_msg20(Config) when is_list(Config) -> + d("compact_otp4920_msg20 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg20(), bad_mid_duplicate_padding). + +%% Length +compact_otp4920_msg21(suite) -> + []; +compact_otp4920_msg21(Config) when is_list(Config) -> + d("compact_otp4920_msg21 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg21(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg22(suite) -> + []; +compact_otp4920_msg22(Config) when is_list(Config) -> + d("compact_otp4920_msg22 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg22(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg23(suite) -> + []; +compact_otp4920_msg23(Config) when is_list(Config) -> + d("compact_otp4920_msg23 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg23(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg24(suite) -> + []; +compact_otp4920_msg24(Config) when is_list(Config) -> + d("compact_otp4920_msg24 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg24(), bad_mid_ip6addr_length). + +%% Length +compact_otp4920_msg25(suite) -> + []; +compact_otp4920_msg25(Config) when is_list(Config) -> + d("compact_otp4920_msg25 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp4920_msg_2(compact_otp4920_msg25(), bad_mid_ip6addr_length). + +compact_otp4920_msg_1(M1, CheckEqual) -> + Bin1 = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, [], Bin1) of + {ok, Msg} -> + io:format(" decoded", []), + case encode_message(megaco_compact_text_encoder, [], Msg) of + {ok, Bin1} -> + io:format(", encoded - equal:", []), + ok; + {ok, Bin2} when is_binary(Bin2) andalso (CheckEqual =:= true) -> + M2 = binary_to_list(Bin2), + io:format(", encoded - not equal:", []), + exit({messages_not_equal, M1, M2}); + {ok, _} -> + io:format(", encoded:", []), + ok; + Else -> + io:format(", encode failed:", []), + exit({unexpected_encode_result, Else}) + end; + Else -> + io:format("decode failed:", []), + exit({unexpected_decode_result, Else}) + end. + +compact_otp4920_msg_2(M1, ExpectedReason) -> + Bin = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, Msg} -> + io:format("unexpected successfull decode", []), + exit({unexpected_encode_ok, Msg}); + {error, [{reason, {__Line, _Mod, Reason}}|_]} -> + case element(1, Reason) of + ExpectedReason -> + ok; + _ -> + exit({unexpected_decode_error_reason, + ExpectedReason, Reason}) + end; + {error, [{reason, {_Mod, Reason}}|_]} -> + case element(1, Reason) of + ExpectedReason -> + ok; + _ -> + exit({unexpected_decode_error_reason, + ExpectedReason, Reason}) + end; + Else -> + io:format("unexpected decode result", []), + exit({unexpected_decode_result, Else}) + + end. + +compact_otp4920_msg0() -> + M = "!/" ?VERSION_STR " [192.168.30.1]\nT=100{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg1() -> + M = "!/" ?VERSION_STR " [2031:0000:130F:0000:0000:09C0:876A:130B]\nT=101{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg2() -> + M = "!/" ?VERSION_STR " [2031:0:130F:0:0:9C0:876A:130B]\nT=102{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg3() -> + M = "!/" ?VERSION_STR " [2031:0:130F::9C0:876A:130B]\nT=103{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg4() -> + M = "!/" ?VERSION_STR " [::1]\nT=104{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg5() -> + M = "!/" ?VERSION_STR " [::]\nT=105{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg6() -> + M = "!/" ?VERSION_STR " [1::]\nT=106{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg7() -> + M = "!/" ?VERSION_STR " [FEDC:1::]\nT=107{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg8() -> + M = "!/" ?VERSION_STR " [2031:0:130F:0:0:9C0:135.106.19.11]\nT=108{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg9() -> + M = "!/" ?VERSION_STR " [2031:0:130F::9C0:135.106.19.11]\nT=109{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg10() -> + M = "!/" ?VERSION_STR " [::FFFF:192.168.30.1]\nT=110{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg11() -> + M = "!/" ?VERSION_STR " [::192.168.30.1]\nT=111{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg12() -> + M = "!/" ?VERSION_STR " [::C0A8:1E01]\nT=112{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: only one :: allowed +compact_otp4920_msg20() -> + M = "!/" ?VERSION_STR " [2031::130F::9C0]\nT=120{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg21() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:0000:0000:09C0:876A:130B]\nT=121{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg22() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0:130F:0:0:9C0:135.106.19.11]\nT=122{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg23() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:2132:4354::09C0:876A:130B]\nT=123{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg24() -> + M = "!/" ?VERSION_STR " [::2031:FFEE:0000:130F:2132:4354:09C0:876A:130B]\nT=124{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg25() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:2132:4354:09C0:876A:130B::]\nT=125{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + + +compact_otp5186_msg01(suite) -> + []; +compact_otp5186_msg01(Config) when is_list(Config) -> + d("compact_otp5186_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_1(compact_otp5186_msg01(), error, ignore). + +compact_otp5186_msg02(suite) -> + []; +compact_otp5186_msg02(Config) when is_list(Config) -> + d("compact_otp5186_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_1(compact_otp5186_msg02(), ok, ok). + +compact_otp5186_msg03(suite) -> + []; +compact_otp5186_msg03(Config) when is_list(Config) -> + d("compact_otp5186_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg03(), ok, ok). + +compact_otp5186_msg04(suite) -> + []; +compact_otp5186_msg04(Config) when is_list(Config) -> + d("compact_otp5186_msg04 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg04(), ok, ok). + +compact_otp5186_msg05(suite) -> + []; +compact_otp5186_msg05(Config) when is_list(Config) -> + d("compact_otp5186_msg05 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg05(), ok, ok). + +compact_otp5186_msg06(suite) -> + []; +compact_otp5186_msg06(Config) when is_list(Config) -> + d("compact_otp5186_msg06 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5186_msg_2(compact_otp5186_msg06(), ok, ok). + +compact_otp5186_msg_1(M1, DecodeExpect, EncodeExpect) -> + Bin1 = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, [], Bin1) of + {ok, Msg} when DecodeExpect == ok -> + io:format(" decoded", []), + case encode_message(megaco_compact_text_encoder, [], Msg) of + {ok, Bin1} when EncodeExpect == ok -> + io:format(", encoded - equal:", []), + ok; + {ok, Bin2} when EncodeExpect == ok -> + M2 = binary_to_list(Bin2), + io:format(", encoded - not equal:", []), + exit({messages_not_equal, Msg, M1, M2}); + {ok, Bin3} when EncodeExpect == error -> + M3 = binary_to_list(Bin3), + io:format(", unexpected encode:", []), + exit({unexpected_encode_success, Msg, M1, M3}); + _Else when EncodeExpect == error -> + io:format(", encode failed ", []), + ok + end; + {ok, Msg} when DecodeExpect == error -> + io:format(" decoded", []), + exit({unexpected_decode_success, Msg}); + _Else when DecodeExpect == error -> + io:format(" decode failed ", []), + ok; + Else when DecodeExpect == ok -> + io:format(" decode failed ", []), + exit({unexpected_decode_result, Else}) + end. + +compact_otp5186_msg_2(Msg1, EncodeExpect, DecodeExpect) -> + case encode_message(megaco_compact_text_encoder, [], Msg1) of + {ok, Bin} when EncodeExpect == ok -> + io:format(" encoded", []), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, Msg1} when DecodeExpect == ok -> + io:format(", decoded - equal:", []), + ok; + {ok, Msg2} when DecodeExpect == ok -> + M = binary_to_list(Bin), + case (catch compact_otp5186_check_megamsg(Msg1, Msg2)) of + ok -> + io:format(", decoded - not equal - ok:", []), + ok; + {'EXIT', Reason} -> + io:format(", decoded - not equal:", []), + exit({messages_not_equal, M, Reason, Msg1, Msg2}) + end; + {ok, Msg3} when DecodeExpect == error -> + M = binary_to_list(Bin), + io:format(", decoded:", []), + exit({unexpected_decode_success, M, Msg1, Msg3}); + Else when DecodeExpect == ok -> + M = binary_to_list(Bin), + io:format(", decode failed ", []), + exit({unexpected_decode_success, Msg1, M, Else}); + _Else when DecodeExpect == error -> + io:format(", decode failed ", []), + ok + end; + {ok, Bin} when EncodeExpect == error -> + M = binary_to_list(Bin), + io:format(" encoded", []), + exit({unexpected_encode_success, Msg1, M}); + _Else when EncodeExpect == error -> + io:format(" encode failed ", []), + ok; + Else when EncodeExpect == ok -> + io:format(" encode failed ", []), + exit({unexpected_encode_result, Else}) + end. + + +%% -- + +compact_otp5186_msg01() -> + "!/2 <mg5>\nP=67111298{C=2699{AV=mg5_ipeph/0x0f0001{}}}". + +compact_otp5186_msg02() -> + "!/2 <mg5>\nP=67111298{C=2699{AV=mg5_ipeph/0x0f0001}}". + +compact_otp5186_msg03() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + 2, + {domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]}, + [ + ] + } + } + } + ] + } + ] + } + } + } + ] + } + } + }. + +compact_otp5186_msg04() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',2,{domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]}, + [ + {emptyDescriptors, + {'AuditDescriptor',asn1_NOVALUE,asn1_NOVALUE} + } + ] + } + } + } + ] + } + ] + } + } + } + ] + } + } + }. + +compact_otp5186_msg05() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + 2, + {domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {addReply, + {'AmmsReply', + [ + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]} + ], + [ + ] + } + } + ] + } + ] + } + } + } + ] + } + } + }. + +compact_otp5186_msg06() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',2,{domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {addReply, + {'AmmsReply', + [ + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]} + ], + [ + {emptyDescriptors, + {'AuditDescriptor',asn1_NOVALUE,asn1_NOVALUE} + } + ] + } + } + ] + } + ] + } + } + } + ] + } + } + }. + +%% -- + +compact_otp5186_check_megamsg(M1, M1) -> + ok; +compact_otp5186_check_megamsg(#'MegacoMessage'{authHeader = AH, + mess = M1}, + #'MegacoMessage'{authHeader = AH, + mess = M2}) -> + compact_otp5186_check_mess(M1, M2); +compact_otp5186_check_megamsg(#'MegacoMessage'{authHeader = AH1}, + #'MegacoMessage'{authHeader = AH2}) -> + exit({not_equal, authHeader, AH1, AH2}). + +compact_otp5186_check_mess(M, M) -> + ok; +compact_otp5186_check_mess(#'Message'{version = V, + mId = MId, + messageBody = B1}, + #'Message'{version = V, + mId = MId, + messageBody = B2}) -> + compact_otp5186_check_body(B1, B2); +compact_otp5186_check_mess(#'Message'{version = V, + mId = MId1}, + #'Message'{version = V, + mId = MId2}) -> + exit({not_equal, mId, MId1, MId2}); +compact_otp5186_check_mess(#'Message'{version = V1, + mId = MId}, + #'Message'{version = V2, + mId = MId}) -> + exit({not_equal, version, V1, V2}). + +compact_otp5186_check_body(B, B) -> + ok; +compact_otp5186_check_body({transactions, T1}, {transactions, T2}) -> + compact_otp5186_check_trans(T1, T2); +compact_otp5186_check_body({messageError, E1}, {messageError, E2}) -> + compact_otp5186_check_merr(E1, E2); +compact_otp5186_check_body(B1, B2) -> + exit({not_equal, messageBody, B1, B2}). + +compact_otp5186_check_trans([], []) -> + ok; +compact_otp5186_check_trans([], T2) -> + exit({not_equal, transactions, [], T2}); +compact_otp5186_check_trans(T1, []) -> + exit({not_equal, transactions, T1, []}); +compact_otp5186_check_trans([Tran1|Trans1], [Tran2|Trans2]) -> + compact_otp5186_check_trans(Trans1, Trans2), + compact_otp5186_check_transaction(Tran1, Tran2). + +compact_otp5186_check_merr(ME, ME) -> + ok; +compact_otp5186_check_merr(#'ErrorDescriptor'{errorCode = EC, + errorText = ET1}, + #'ErrorDescriptor'{errorCode = EC, + errorText = ET2}) -> + exit({not_equal, errorText, ET1, ET2}); +compact_otp5186_check_merr(#'ErrorDescriptor'{errorCode = EC1, + errorText = ET}, + #'ErrorDescriptor'{errorCode = EC2, + errorText = ET}) -> + exit({not_equal, errorCode, EC1, EC2}). + +compact_otp5186_check_transaction(T, T) -> + ok; +compact_otp5186_check_transaction({transactionReply, TR1}, + {transactionReply, TR2}) -> + compact_otp5186_check_transRep(TR1, TR2); +compact_otp5186_check_transaction(T1, T2) -> + exit({unexpected_transactions, T1, T2}). + +compact_otp5186_check_transRep(T, T) -> + ok; +compact_otp5186_check_transRep(#'TransactionReply'{transactionId = TId, + immAckRequired = IAR, + transactionResult = TR1}, + #'TransactionReply'{transactionId = TId, + immAckRequired = IAR, + transactionResult = TR2}) -> + compact_otp5186_check_transRes(TR1, TR2); +compact_otp5186_check_transRep(T1, T2) -> + exit({unexpected_transaction_reply, T1, T2}). + +compact_otp5186_check_transRes(TR, TR) -> + ok; +compact_otp5186_check_transRes({actionReplies, AR1}, + {actionReplies, AR2}) -> + compact_otp5186_check_actReps(AR1, AR2); +compact_otp5186_check_transRes(TR1, TR2) -> + exit({unexpected_transaction_result, TR1, TR2}). + +compact_otp5186_check_actReps([], []) -> + ok; +compact_otp5186_check_actReps(AR1, []) -> + exit({not_equal, actionReplies, AR1, []}); +compact_otp5186_check_actReps([], AR2) -> + exit({not_equal, actionReplies, [], AR2}); +compact_otp5186_check_actReps([AR1|ARs1], [AR2|ARs2]) -> + compact_otp5186_check_actRep(AR1, AR2), + compact_otp5186_check_actReps(ARs1, ARs2). + +compact_otp5186_check_actRep(AR, AR) -> + ok; +compact_otp5186_check_actRep(#'ActionReply'{contextId = ID, + errorDescriptor = ED, + contextReply = CtxRep, + commandReply = CmdRep1}, + #'ActionReply'{contextId = ID, + errorDescriptor = ED, + contextReply = CtxRep, + commandReply = CmdRep2}) -> + compact_otp5186_check_cmdReps(CmdRep1, CmdRep2); +compact_otp5186_check_actRep(AR1, AR2) -> + exit({unexpected_actionReply, AR1, AR2}). + +compact_otp5186_check_cmdReps([], []) -> + ok; +compact_otp5186_check_cmdReps(CR1, []) -> + exit({not_equal, commandReplies, CR1, []}); +compact_otp5186_check_cmdReps([], CR2) -> + exit({not_equal, commandReplies, [], CR2}); +compact_otp5186_check_cmdReps([CR1|CRs1], [CR2|CRs2]) -> + compact_otp5186_check_cmdRep(CR1, CR2), + compact_otp5186_check_cmdReps(CRs1, CRs2). + +compact_otp5186_check_cmdRep(CR, CR) -> + ok; +compact_otp5186_check_cmdRep({auditValueReply, AVR1}, + {auditValueReply, AVR2}) -> + compact_otp5186_check_auditReply(AVR1, AVR2); +compact_otp5186_check_cmdRep({addReply, AVR1}, + {addReply, AVR2}) -> + compact_otp5186_check_ammsReply(AVR1, AVR2); +compact_otp5186_check_cmdRep(CR1, CR2) -> + exit({unexpected_commandReply, CR1, CR2}). + +compact_otp5186_check_auditReply(AR, AR) -> + ok; +compact_otp5186_check_auditReply({auditResult, AR1}, + {auditResult, AR2}) -> + compact_otp5186_check_auditRes(AR1, AR2); +compact_otp5186_check_auditReply(AR1, AR2) -> + exit({unexpected_auditReply, AR1, AR2}). + +compact_otp5186_check_ammsReply(AR, AR) -> + ok; +compact_otp5186_check_ammsReply(#'AmmsReply'{terminationID = ID, + terminationAudit = TA1}, + #'AmmsReply'{terminationID = ID, + terminationAudit = TA2}) -> + %% This is just to simplify the test + F = fun(asn1_NOVALUE) -> []; + (E) -> E + end, + compact_otp5186_check_termAudit(F(TA1), F(TA2)); +compact_otp5186_check_ammsReply(AR1, AR2) -> + exit({unexpected_ammsReply, AR1, AR2}). + +compact_otp5186_check_auditRes(AR, AR) -> + ok; +compact_otp5186_check_auditRes(#'AuditResult'{terminationID = ID, + terminationAuditResult = TAR1}, + #'AuditResult'{terminationID = ID, + terminationAuditResult = TAR2}) -> + compact_otp5186_check_termAuditRes(TAR1, TAR2); +compact_otp5186_check_auditRes(AR1, AR2) -> + exit({unexpected_auditResult, AR1, AR2}). + +compact_otp5186_check_termAuditRes([], []) -> + ok; +%% An empty empty descriptor is removed +compact_otp5186_check_termAuditRes([{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = asn1_NOVALUE}}|TAR1], []) -> + compact_otp5186_check_termAuditRes(TAR1, []); +compact_otp5186_check_termAuditRes(TAR1, []) -> + exit({not_equal, termAuditRes, TAR1, []}); +%% An empty empty descriptor is removed +compact_otp5186_check_termAuditRes([], [{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = asn1_NOVALUE}}|TAR2]) -> + compact_otp5186_check_termAuditRes([], TAR2); +compact_otp5186_check_termAuditRes([], TAR2) -> + exit({not_equal, termAuditRes, [], TAR2}); +compact_otp5186_check_termAuditRes([ARP1|TAR1], [ARP2|TAR2]) -> + compact_otp5186_check_auditRetParm(ARP1, ARP2), + compact_otp5186_check_termAuditRes(TAR1, TAR2). + +compact_otp5186_check_termAudit([], []) -> + ok; +%% An empty empty descriptor is removed +compact_otp5186_check_termAudit([{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = asn1_NOVALUE}}|TAR1], []) -> + compact_otp5186_check_termAudit(TAR1, []); +compact_otp5186_check_termAudit(TAR1, []) -> + exit({not_equal, termAudit, TAR1, []}); +%% An empty empty descriptor is removed +compact_otp5186_check_termAudit([], + [{emptyDescriptors, + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = asn1_NOVALUE}}|TAR2]) -> + compact_otp5186_check_termAudit([], TAR2); +compact_otp5186_check_termAudit([], TAR2) -> + exit({not_equal, termAudit, [], TAR2}); +compact_otp5186_check_termAudit([ARP1|TAR1], [ARP2|TAR2]) -> + compact_otp5186_check_auditRetParm(ARP1, ARP2), + compact_otp5186_check_termAudit(TAR1, TAR2). + +compact_otp5186_check_auditRetParm(ARP, ARP) -> + ok; +compact_otp5186_check_auditRetParm({emptyDescriptors, AD1}, + {emptyDescriptors, AD2}) -> + compact_otp5186_check_auditDesc(AD1, AD2); +compact_otp5186_check_auditRetParm(ARP1, ARP2) -> + exit({unexpected_auditRetParm, ARP1, ARP2}). + +compact_otp5186_check_auditDesc(AD, AD) -> + ok; +compact_otp5186_check_auditDesc(#'AuditDescriptor'{auditToken = L1, + auditPropertyToken = asn1_NOVALUE}, + #'AuditDescriptor'{auditToken = L2, + auditPropertyToken = asn1_NOVALUE}) -> + compact_otp5186_check_auditDesc_auditItems(L1, L2); +compact_otp5186_check_auditDesc(#'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = APT1}, + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = APT2}) -> + compact_otp5186_check_auditDesc_apt(APT1, APT2); +compact_otp5186_check_auditDesc(AD1, AD2) -> + exit({unexpected_auditDesc, AD1, AD2}). + +compact_otp5186_check_auditDesc_auditItems([], []) -> + ok; +compact_otp5186_check_auditDesc_auditItems(AI1, []) -> + exit({not_equal, auditItems, AI1, []}); +compact_otp5186_check_auditDesc_auditItems([], AI2) -> + exit({not_equal, auditItems, [], AI2}); +compact_otp5186_check_auditDesc_auditItems([AI1|AIs1], [AI2|AIs2]) -> + compact_otp5186_check_auditDesc_auditItem(AI1, AI2), + compact_otp5186_check_auditDesc_auditItems(AIs1, AIs2). + +compact_otp5186_check_auditDesc_auditItem(AI, AI) -> + ok; +compact_otp5186_check_auditDesc_auditItem(AI1, AI2) -> + exit({not_equal, auditItem, AI1, AI2}). + +compact_otp5186_check_auditDesc_apt(APT, APT) -> + ok; +compact_otp5186_check_auditDesc_apt(APT1, APT2) -> + exit({not_equal, auditPropertyToken, APT1, APT2}). + + + +%% -------------------------------------------------------------- + +compact_otp5290_msg01(suite) -> + []; +compact_otp5290_msg01(Config) when is_list(Config) -> + d("compact_otp5290_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5290_msg_1(compact_otp5290_msg01(), ok, ok). + +compact_otp5290_msg02(suite) -> + []; +compact_otp5290_msg02(Config) when is_list(Config) -> + d("compact_otp5290_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5290_msg_1(compact_otp5290_msg02(), error, ignore). + +compact_otp5290_msg_1(M1, DecodeExpect, EncodeExpect) -> + Bin1 = list_to_binary(M1), + case decode_message(megaco_compact_text_encoder, false, [], Bin1) of + {ok, Msg} when DecodeExpect == ok -> + io:format(" decoded", []), + case encode_message(megaco_compact_text_encoder, [], Msg) of + {ok, Bin1} when EncodeExpect == ok -> + io:format(", encoded - equal:", []), + ok; + {ok, Bin2} when EncodeExpect == ok -> + M2 = binary_to_list(Bin2), + io:format(", encoded - not equal:", []), + exit({messages_not_equal, Msg, M1, M2}); + {ok, Bin3} when EncodeExpect == error -> + M3 = binary_to_list(Bin3), + io:format(", unexpected encode:", []), + exit({unexpected_encode_success, Msg, M3}); + _ when EncodeExpect == error -> + io:format(", encode failed ", []), + ok + end; + {ok, Msg} when DecodeExpect == error -> + io:format(" decoded", []), + exit({unexpected_decode_success, Msg}); + _Else when DecodeExpect == error -> + io:format(" decode failed ", []), + ok; + Else when DecodeExpect == ok -> + io:format(" decode failed ", []), + exit({unexpected_decode_result, Else}) + end. + +compact_otp5290_msg01() -> + "!/" ?VERSION_STR " <ml>\nT=12345678{C=*{CA{TP,PR}}}". + +compact_otp5290_msg02() -> + "!/" ?VERSION_STR " <ml>\nT=12345678{C=*{CA{TP,PR,TP}}}". + + +compact_otp5793_msg01(suite) -> + []; +compact_otp5793_msg01(Config) when is_list(Config) -> + d("compact_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5793(ok, pretty_otp5793_msg1()). + +compact_otp5793(Expected, Msg) -> + expect_codec(Expected, megaco_compact_text_encoder, Msg, []). + + +%% -------------------------------------------------------------- + +compact_otp5993_msg01(suite) -> + []; +compact_otp5993_msg01(Config) when is_list(Config) -> + d("compact_otp5993_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5993(ok, compact_otp5993_msg01()). + +compact_otp5993_msg02(suite) -> + []; +compact_otp5993_msg02(Config) when is_list(Config) -> + d("compact_otp5993_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5993(ok, compact_otp5993_msg02()). + +compact_otp5993_msg03(suite) -> + []; +compact_otp5993_msg03(Config) when is_list(Config) -> + d("compact_otp5993_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + compact_otp5993(ok, compact_otp5993_msg03()). + +compact_otp5993(Expected, Msg) -> + expect_codec(Expected, megaco_compact_text_encoder, Msg, []). + +compact_otp5993_msg01() -> + MT = h221, + T = #megaco_term_id{id = ?A4444}, + TL = [T], + MD = #'MuxDescriptor'{muxType = MT, + termList = TL}, + compact_otp5993_msg(MD). + +compact_otp5993_msg02() -> + MT = h223, + T1 = #megaco_term_id{id = ?A4445}, + T2 = #megaco_term_id{id = ?A5556}, + TL = [T1, T2], + MD = #'MuxDescriptor'{muxType = MT, + termList = TL}, + compact_otp5993_msg(MD). + +compact_otp5993_msg(MD) when is_record(MD, 'MuxDescriptor') -> + AmmDesc = {muxDescriptor, MD}, + AmmReq = #'AmmRequest'{terminationID = [hd(MD#'MuxDescriptor'.termList)], + descriptors = [AmmDesc]}, + Cmd = {addReq, AmmReq}, + CmdReq = #'CommandRequest'{command = Cmd}, + ActReq = #'ActionRequest'{contextId = 5993, + commandRequests = [CmdReq]}, + TransReq = #'TransactionRequest'{transactionId = 3995, + actions = [ActReq]}, + Trans = {transactionRequest, TransReq}, + Body = {transactions, [Trans]}, + Msg = #'Message'{version = ?VERSION, + mId = ?MG1_MID, + messageBody = Body}, + #'MegacoMessage'{mess = Msg}. + +compact_otp5993_msg03() -> + T1 = #megaco_term_id{id = ?A4445}, + T2 = #megaco_term_id{id = ?A5556}, + TIDs = [T1, T2], + AudRep = {contextAuditResult, TIDs}, + CmdRep = {auditValueReply, AudRep}, + ActRep = #'ActionReply'{contextId = 5993, + commandReply = [CmdRep]}, + TransRes = {actionReplies, [ActRep]}, + TransRep = #'TransactionReply'{transactionId = 3995, + transactionResult = TransRes}, + Trans = {transactionReply, TransRep}, + Body = {transactions, [Trans]}, + Msg = #'Message'{version = ?VERSION, + mId = ?MG1_MID, + messageBody = Body}, + #'MegacoMessage'{mess = Msg}. + + +%% -------------------------------------------------------------- + +compact_otp6017_msg01(suite) -> + []; +compact_otp6017_msg01(Config) when is_list(Config) -> + d("compact_otp6017_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(0), + ok. + +compact_otp6017_msg02(suite) -> + []; +compact_otp6017_msg02(Config) when is_list(Config) -> + d("compact_otp6017_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(16#FFFFFFFE), + ok. + +compact_otp6017_msg03(suite) -> + []; +compact_otp6017_msg03(Config) when is_list(Config) -> + d("compact_otp6017_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(16#FFFFFFFF), + ok. + +compact_otp6017(BadCID) -> + M = compact_otp6017_msg(BadCID), + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, [], Bin) of + {ok, Msg} -> + exit({unexpected_decode_success, {Msg, M}}); + {error, Reason} when is_list(Reason) -> % Expected result + case lists:keysearch(reason, 1, Reason) of + {value, {reason, {_Line, _Mod, {bad_ContextID, BadCID}}}} -> + io:format(" ~w", [BadCID]), + ok; + {value, {reason, ActualReason}} -> + exit({unexpected_reason, ActualReason}); + false -> + exit({reason_not_found, Reason}) + end; + Crap -> + exit({unexpected_decode_result, Crap}) + end. + +compact_otp6017_msg(CID) when is_integer(CID) -> + "MEGACO/" ?VERSION_STR " MG1 T=12345678{C=" ++ + integer_to_list(CID) ++ + "{SC=root{SV{MT=RS,RE=901}}}}". + + +%% -------------------------------------------------------------- + +compact_otp7138_msg01(suite) -> + []; +compact_otp7138_msg01(Config) when is_list(Config) -> +%% put(dbg, true), +%% put(severity, trc), + d("compact_otp7138_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = compact_otp7138_msg01(), + EC = [], + ok = compact_otp7138(EC, Msg), + ok. + +compact_otp7138_msg02(suite) -> + []; +compact_otp7138_msg02(Config) when is_list(Config) -> +%% put(dbg, true), +%% put(severity, trc), + d("compact_otp7138_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = compact_otp7138_msg02(), + EC = [], + ok = compact_otp7138(EC, Msg), + ok. + +compact_otp7138_msg01() -> + <<"!/2 <gw>\nT=1111{C=1{N=mgw2dev1/1{OE=16777985{ctyp/dtone{dtt=CT}}}}}">>. + +compact_otp7138_msg02() -> + <<"!/2 <gw>\nT=1111{C=1{N=mgw2dev1/1{OE=16777985{ctyp/dtone{dtt=\"CT\"}}}}}">>. + +compact_otp7138(EC, BinMsg) -> + d("compact_otp7138 -> " + "~n ~p", [binary_to_list(BinMsg)]), + Codec = megaco_compact_text_encoder, + case decode_message(Codec, false, EC, BinMsg) of + {ok, Msg} -> + case encode_message(Codec, EC, Msg) of + {ok, BinMsg} -> + d("compact_otp7138 -> encode successfull: " + "~n ~p", [binary_to_list(BinMsg)]), + ok; + {ok, BinMsg2} -> + d("compact_otp7138 -> encode successfull but result differ: " + "~n ~p", [binary_to_list(BinMsg2)]), + ok; + {error, Reason} -> + e("encode failed: ~p", [Reason]), + {error, Reason} + end; + {error, Reason} -> + e("decode failed: ~p", [Reason]), + {error, Reason} + end. + + +compact_otp7457_msg01(suite) -> + []; +compact_otp7457_msg01(Config) when is_list(Config) -> + put(dbg, true), + put(severity, trc), + d("compact_otp7457_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = compact_otp7457_msg01(), + EC = [], + ok = compact_otp7457(EC, Msg), + ok. + +compact_otp7457_msg02(suite) -> + []; +compact_otp7457_msg02(Config) when is_list(Config) -> + put(dbg, true), + put(severity, trc), + d("compact_otp7457_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = compact_otp7457_msg02(), + EC = [], + ok = compact_otp7457(EC, Msg), + ok. + +compact_otp7457_msg03(suite) -> + []; +compact_otp7457_msg03(Config) when is_list(Config) -> + put(dbg, true), + put(severity, trc), + d("compact_otp7457_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = compact_otp7457_msg03(), + EC = [], + ok = compact_otp7457(EC, Msg), + ok. + +compact_otp7457_msg01() -> + <<"!/2 <mg1>\nT=15{C=-{SC=tdm12/1/1/*{SV{MT=RS,RE=900}}}}\n">>. + +compact_otp7457_msg02() -> + <<"!/2 <mg1>\nT=15{C=-{O-SC=tdm12/1/1/*{SV{MT=RS,RE=900}}}}\n">>. + +compact_otp7457_msg03() -> + <<"!/2 <mg1>\nT=15{C=-{W-SC=tdm12/1/1/*{SV{MT=RS,RE=900}}}}\n">>. + +compact_otp7457(EC, BinMsg) -> + d("compact_otp7457 -> " + "~n ~p", [binary_to_list(BinMsg)]), + Codec = megaco_compact_text_encoder, + case decode_message(Codec, false, EC, BinMsg) of + {ok, Msg} -> + case encode_message(Codec, EC, Msg) of + {ok, BinMsg} -> + d("compact_otp7457 -> encode successfull: " + "~n ~p", [binary_to_list(BinMsg)]), + ok; + {ok, BinMsg2} -> + d("compact_otp7457 -> " + "encode successfull but result differ: " + "~n ~p", [binary_to_list(BinMsg2)]), + ok; + {error, Reason} -> + e("encode failed: ~p", [Reason]), + {error, Reason} + end; + {error, Reason} -> + e("decode failed: ~p", [Reason]), + {error, Reason} + end. + +compact_otp7534_msg01(suite) -> + []; +compact_otp7534_msg01(Config) when is_list(Config) -> + put(dbg, true), + put(severity, trc), + d("compact_otp7534_msg01 -> entry", []), + Msg = otp7534_msg01(), + compact_otp7534([], Msg). + + +compact_otp7576_msg01(suite) -> + []; +compact_otp7576_msg01(Config) when is_list(Config) -> +%% put(dbg, true), +%% put(severity, trc), + d("compact_otp7576_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = compact_otp7576_msg01(), + EC = [], + ok = compact_otp7576(EC, Msg), + ok. + +compact_otp7576_msg01() -> + M = "!/" + ?VERSION_STR + "[130.100.144.37]:2944\nT=10032{C=${tp{*,*,is,st=1},pr=6,a=rtp/2/${m{st=1{o{mo=so,rv=ON},l{ +v=0 +c=IN IP4 $ +m=audio $ RTP/AVP 0 +b=AS:64 +a=rtpmap:0 PCMU/8000 +}}},e=1{G/CAUSE}},a=rtp/2/${m{st=1{o{mo=rc,rv=ON},l{ +v=0 +c=IN IP4 $ +m=audio $ RTP/AVP 0 +b=AS:64 +a=rtpmap:0 PCMU/8000 +},r{ +v=0 +c=IN IP4 130.100.126.77 +m=audio 8014 RTP/AVP 0 +b=AS:64 +a=rtpmap:0 PCMU/8000 +}}},e=1{G/CAUSE}}}}", + list_to_binary(M). + +compact_otp7576(EC, BinMsg) -> + d("compact_otp7576 -> " + "~n ~p", [binary_to_list(BinMsg)]), + Codec = megaco_compact_text_encoder, + case decode_message(Codec, false, EC, BinMsg) of + {ok, Msg} -> + case encode_message(Codec, EC, Msg) of + {ok, BinMsg} -> + d("compact_otp7138 -> encode successfull: " + "~n ~p", [binary_to_list(BinMsg)]), + ok; + {ok, BinMsg2} -> + d("compact_otp7138 -> encode successfull but result differ: " + "~n ~p", [binary_to_list(BinMsg2)]), + case decode_message(Codec, false, EC, BinMsg2) of + {ok, Msg} -> + d("compact_otp7138 -> " + "extra verification decode ok", []), + ok; + {ok, Msg2} -> + e("verification decode generated other message: " + "~n Msg: ~p" + "~n Msg2: ~p", [Msg, Msg2]), + {error, {verification_decode, Msg, Msg2}} + end; + {error, Reason} -> + e("encode failed: ~p", [Reason]), + {error, Reason} + end; + {error, Reason} -> + e("decode failed: ~p", [Reason]), + {error, Reason} + end. + + +%% -------------------------------------------------------------- +%% + +compact_otp7671_msg01(suite) -> + []; +compact_otp7671_msg01(Config) when is_list(Config) -> + put(severity, trc), + put(dbg, true), + d("compact_otp7671_msg01 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = compact_otp7671( compact_otp7671_msg01(), [] ), + erase(dbg), + erase(severity), + ok. + +compact_otp7671(Msg, Conf) -> + compact_otp7671(Msg, Conf, ok). + +compact_otp7671(Msg, Conf, ExpectedEncode) -> + compact_otp7671(Msg, Conf, ExpectedEncode, ok). + +compact_otp7671(Msg, Conf, ExpectedEncode, ExpectedDecode) -> + otp7671(Msg, megaco_compact_text_encoder, Conf, + ExpectedEncode, ExpectedDecode). + +%% "!/" ?VERSION_STR " <ml>\nT=172047781{C=-{MF=root{DM=DmName}}}", +compact_otp7671_msg01() -> + pretty_otp7671_msg01(). + + +%% ============================================================== +%% +%% F l e x C o m p a c t T e s t c a s e s +%% + +flex_compact_otp7138_msg01(suite) -> + []; +flex_compact_otp7138_msg01(Config) when is_list(Config) -> + %% put(dbg, true), + %% put(severity, trc), + d("flex_compact_otp7138_msg01 -> entry", []), + Msg = compact_otp7138_msg01(), + Conf = flex_scanner_conf(Config), + compact_otp7138([Conf], Msg). + +flex_compact_otp7138_msg02(suite) -> + []; +flex_compact_otp7138_msg02(Config) when is_list(Config) -> + %% put(dbg, true), + %% put(severity, trc), + d("flex_compact_otp7138_msg02 -> entry", []), + Msg = compact_otp7138_msg02(), + Conf = flex_scanner_conf(Config), + compact_otp7138([Conf], Msg). + + +flex_compact_otp7431_msg01(suite) -> + []; +flex_compact_otp7431_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg01 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(ok, flex_compact_otp7431_msg1(), [Conf]). + +flex_compact_otp7431_msg02(suite) -> + []; +flex_compact_otp7431_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg02 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg2(), [Conf]). + +flex_compact_otp7431_msg03(suite) -> + []; +flex_compact_otp7431_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg03 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg3(), [Conf]). + +flex_compact_otp7431_msg04(suite) -> + []; +flex_compact_otp7431_msg04(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg04 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg4(), [Conf]). + +flex_compact_otp7431_msg05(suite) -> + []; +flex_compact_otp7431_msg05(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg05 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg5(), [Conf]). + +flex_compact_otp7431_msg06(suite) -> + []; +flex_compact_otp7431_msg06(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg06 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg6(), [Conf]). + +flex_compact_otp7431_msg07(suite) -> + []; +flex_compact_otp7431_msg07(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg07 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg7(), [Conf]). + + +flex_compact_otp7431(Expected, Msg, Conf) -> + otp7431(Expected, megaco_compact_text_encoder, Msg, Conf). + +flex_compact_otp7431_msg1() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a=recvonly +}}}}}}". + +flex_compact_otp7431_msg2() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a= } +}}}}}". + + +flex_compact_otp7431_msg3() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a } +}}}}}". + + +flex_compact_otp7431_msg4() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a} +}}}}}". + + +flex_compact_otp7431_msg5() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v= } +}}}}}". + + +flex_compact_otp7431_msg6() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v } +}}}}}". + +flex_compact_otp7431_msg7() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v} +}}}}}". + +flex_compact_otp7457_msg01(suite) -> + []; +flex_compact_otp7457_msg01(Config) when is_list(Config) -> + put(dbg, true), + put(severity, trc), + d("flex_compact_otp7457_msg01 -> entry", []), + Msg = compact_otp7457_msg01(), + Conf = flex_scanner_conf(Config), + compact_otp7457([Conf], Msg). + +flex_compact_otp7457_msg02(suite) -> + []; +flex_compact_otp7457_msg02(Config) when is_list(Config) -> + put(dbg, true), + put(severity, trc), + d("flex_compact_otp7457_msg02 -> entry", []), + Msg = compact_otp7457_msg02(), + Conf = flex_scanner_conf(Config), + compact_otp7457([Conf], Msg). + +flex_compact_otp7457_msg03(suite) -> + []; +flex_compact_otp7457_msg03(Config) when is_list(Config) -> + put(dbg, true), + put(severity, trc), + d("flex_compact_otp7457_msg03 -> entry", []), + Msg = compact_otp7457_msg03(), + Conf = flex_scanner_conf(Config), + compact_otp7457([Conf], Msg). + +flex_compact_otp7534_msg01(suite) -> + []; +flex_compact_otp7534_msg01(Config) when is_list(Config) -> + put(dbg, true), + put(severity, trc), + d("flex_compact_otp7534_msg01 -> entry", []), + Msg = otp7534_msg01(), + Conf = flex_scanner_conf(Config), + compact_otp7534([Conf], Msg). + +otp7534_msg01() -> + <<"!/2 bgwch3_1\nP=62916991{C=-{AV=root{M{TS{ipra/ar=[interconnect,interconnect1,internal],SI=IV}},PG{root-2,ocp-1,it-1,nt-1,rtp-1,gm-1,ds-1,tman-1,xnq-1}}}}">>. + +compact_otp7534(EC, BinMsg) -> + Codec = megaco_compact_text_encoder, + otp7534(Codec, EC, BinMsg). + +otp7534(Codec, EC, BinMsg) -> + d("otp7534 -> " + "~n Codec: ~p" + "~n ~p", [Codec, binary_to_list(BinMsg)]), + case decode_message(Codec, false, EC, BinMsg) of + {ok, Msg} -> + case encode_message(Codec, EC, Msg) of + {ok, BinMsg} -> + d("otp7457 -> encode successfull: " + "~n ~p", [binary_to_list(BinMsg)]), + ok; + {ok, BinMsg2} -> + d("otp7457 -> " + "encode successfull but result differ: " + "~n ~p", [binary_to_list(BinMsg2)]), + ok; + {error, Reason} -> + e("encode failed: ~p", [Reason]), + {error, Reason} + end; + {error, Reason} -> + e("decode failed: ~p", [Reason]), + {error, Reason} + end. + + +flex_compact_otp7573_msg01(suite) -> + []; +flex_compact_otp7573_msg01(Config) when is_list(Config) -> + put(dbg, true), + put(severity, trc), + d("flex_compact_otp7573_msg01 -> entry", []), + Msg = otp7573_msg01(), + Conf = flex_scanner_conf(Config), + compact_otp7573([Conf], Msg). + +otp7573_msg01() -> + <<"!/2 <aa>\nP=37775561{C=-{AV=root{M{TS{root/maxnumberofcontexts=16000,root/maxterminationspercontext=2,root/normalmgexecutiontime=3000,root/normalmgcexecutiontime=3000,root/mgprovisionalresponsetimervalue=2000,root/mgcprovisionalresponsetimervalue=2000,root/mgcoriginatedpendinglimit=5,root/mgoriginatedpendinglimit=5,ipra/ar=[\"\"],SI=IV}},PG{root-2,ocp-1,it-1,nt-1,rtp-1,gm-1,ds-1,tman-1,xnq-1,ipra-1}}}}">>. + +compact_otp7573(EC, BinMsg) -> + Codec = megaco_compact_text_encoder, + otp7573(Codec, EC, BinMsg). + +otp7573(Codec, EC, BinMsg) -> + d("otp7573 -> " + "~n Codec: ~p" + "~n ~p", [Codec, binary_to_list(BinMsg)]), + case decode_message(Codec, false, EC, BinMsg) of + {ok, Msg} -> + case encode_message(Codec, EC, Msg) of + {ok, BinMsg} -> + d("otp7573 -> encode successfull: " + "~n ~p", [binary_to_list(BinMsg)]), + ok; + {ok, BinMsg2} -> + d("otp7573 -> " + "encode successfull but result differ: " + "~n ~p", [binary_to_list(BinMsg2)]), + ok; + {error, Reason} -> + e("encode failed: ~p", [Reason]), + {error, Reason} + end; + {error, Reason} -> + e("decode failed: ~p", [Reason]), + {error, Reason} + end. + + +flex_compact_otp7576_msg01(suite) -> + []; +flex_compact_otp7576_msg01(Config) when is_list(Config) -> +%% put(dbg, true), +%% put(severity, trc), + d("flex_compact_otp7576_msg01 -> entry", []), + Msg = compact_otp7576_msg01(), + Conf = flex_scanner_conf(Config), + compact_otp7576([Conf], Msg). + + +%% ============================================================== +%% +%% P r e t t y T e s t c a s e s +%% + +pretty_otp4632_msg1(suite) -> + []; +pretty_otp4632_msg1(Config) when is_list(Config) -> + d("pretty_otp4632_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg1(), + case encode_message(megaco_pretty_text_encoder, [], Msg0) of + {ok, BinMsg} when is_binary(BinMsg) -> + {ok, Msg1} = decode_message(megaco_pretty_text_encoder, false, + [], BinMsg), + ok = chk_MegacoMessage(Msg0, Msg1); + Else -> + t("pretty_otp4632_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4632_msg1() -> + msg4(?MG1_MID_NO_PORT, "901 mg col boot"). + +pretty_otp4632_msg2(suite) -> + []; +pretty_otp4632_msg2(Config) when is_list(Config) -> + d("pretty_otp4632_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg2(), + case encode_message(megaco_pretty_text_encoder, [], Msg0) of + {ok, BinMsg} when is_binary(BinMsg) -> + {ok, Msg1} = decode_message(megaco_pretty_text_encoder, false, + [], BinMsg), + ok = chk_MegacoMessage(Msg0,Msg1); + Else -> + t("pretty_otp4632_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4632_msg2() -> + msg4(?MG1_MID_NO_PORT, "901"). + + +pretty_otp4632_msg3(suite) -> + []; +pretty_otp4632_msg3(Config) when is_list(Config) -> + d("pretty_otp4632_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg3(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, + false, [], Bin0) of + {ok, Msg} when is_record(Msg, 'MegacoMessage') -> + {ok, Bin1} = encode_message(megaco_pretty_text_encoder, [], Msg), + Msg1 = binary_to_list(Bin1), + %% io:format("Msg1:~n~s~n", [Msg1]), + Msg0 = Msg1, + ok; + Else -> + t("pretty_otp4632_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4632_msg3() -> + M = "MEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = \"901\"\n\t\t\t}\n\t\t}\n\t}\n}", + M. + + +pretty_otp4632_msg4(suite) -> + []; +pretty_otp4632_msg4(Config) when is_list(Config) -> + d("pretty_otp4632_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4632_msg4(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {ok, Msg} when is_record(Msg, 'MegacoMessage') -> + {ok, Bin1} = encode_message(megaco_pretty_text_encoder, [], Msg), + Msg1 = binary_to_list(Bin1), + %% io:format("Msg1:~n~s~n", [Msg1]), + pretty_otp4632_msg4_chk(Msg0,Msg1); + Else -> + t("pretty_otp4632_msg4 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + + +pretty_otp4632_msg4() -> + M = "MEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = 901\n\t\t\t}\n\t\t}\n\t}\n}", + M. + + +pretty_otp4632_msg4_chk([], []) -> + exit(messages_not_eq); +pretty_otp4632_msg4_chk([], Rest1) -> + exit({messages_not_eq1, Rest1}); +pretty_otp4632_msg4_chk(Rest0, []) -> + exit({messages_not_eq0, Rest0}); +pretty_otp4632_msg4_chk([$R,$e,$a,$s,$o,$n,$ ,$=,$ ,$9,$0,$1|_Rest0], + [$R,$e,$a,$s,$o,$n,$ ,$=,$ ,$",$9,$0,$1,$"|_Rest1]) -> + ok; +pretty_otp4632_msg4_chk([_|Rest0], [_|Rest1]) -> + pretty_otp4632_msg4_chk(Rest0,Rest1). + + +pretty_otp4710_msg1(suite) -> + []; +pretty_otp4710_msg1(Config) when is_list(Config) -> + d("pretty_otp4710_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4710_msg1(), + case encode_message(megaco_pretty_text_encoder, [], Msg0) of + {ok, Bin} when is_binary(Bin) -> + {ok, Msg1} = decode_message(megaco_pretty_text_encoder, false, + [], Bin), + ok = chk_MegacoMessage(Msg0,Msg1); + Else -> + t("pretty_otp4710_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4710_msg1() -> + msg40(). + + +pretty_otp4710_msg2(suite) -> + []; +pretty_otp4710_msg2(Config) when is_list(Config) -> + d("pretty_otp4710_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4710_msg2(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {ok, Msg} when is_record(Msg, 'MegacoMessage') -> + {ok, Bin1} = encode_message(megaco_pretty_text_encoder, [], Msg), + Msg1 = binary_to_list(Bin1), + %% io:format("Msg1:~n~s~n", [Msg1]), + pretty_otp4710_msg2_chk(Msg0,Msg1); + Else -> + t("pretty_otp4710_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4710_msg2() -> + "Authentication = 0xEFCDAB89:0x12345678:0x1234567889ABCDEF76543210\nMEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = \"901 mg col boot\"\n\t\t\t}\n\t\t}\n\t}\n}". + +pretty_otp4710_msg2_chk(Msg,Msg) -> + ok; +pretty_otp4710_msg2_chk( + [$A,$u,$t,$h,$e,$n,$t,$i,$c,$a,$t,$i,$o,$n,$=,$ |Msg0], + [$A,$u,$t,$h,$e,$n,$t,$i,$c,$a,$t,$i,$o,$n,$=,$ |Msg1]) -> + {AH0, Rest0} = pretty_otp4710_msg2_chk_ah(Msg0, []), + {AH1, Rest1} = pretty_otp4710_msg2_chk_ah(Msg1, []), + case AH0 == AH1 of + true -> + exit({message_not_equal, Rest0, Rest1}); + false -> + exit({auth_header_not_equal, AH0, AH1}) + end. + +pretty_otp4710_msg2_chk_ah([], _Acc) -> + exit(no_auth_header_found); +pretty_otp4710_msg2_chk_ah([$M,$E,$G,$A,$C,$O,$/,_|Rest], Acc) -> + {lists:reverse(Acc), Rest}; +pretty_otp4710_msg2_chk_ah([C|R], Acc) -> + pretty_otp4710_msg2_chk_ah(R, [C|Acc]). + + +pretty_otp4945_msg1(suite) -> + []; +pretty_otp4945_msg1(Config) when is_list(Config) -> + d("pretty_otp4945_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg1(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {missing_required_serviceChangeParm, [serviceChangeReason]} -> + ok; + Else -> + t("pretty_otp4945_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + io:format("pretty_otp4945_msg1 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg2(suite) -> + []; +pretty_otp4945_msg2(Config) when is_list(Config) -> + d("pretty_otp4945_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg2(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {missing_required_serviceChangeParm, [serviceChangeMethod]} -> + ok; + Else -> + t("pretty_otp4945_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg2() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg3(suite) -> + []; +pretty_otp4945_msg3(Config) when is_list(Config) -> + d("pretty_otp4945_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg3(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {missing_required_serviceChangeParm, [serviceChangeReason, serviceChangeMethod]} -> + ok; + {missing_required_serviceChangeParm, [serviceChangeMethod, serviceChangeReason]} -> + ok; + Else -> + t("pretty_otp4945_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg3() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg4(suite) -> + []; +pretty_otp4945_msg4(Config) when is_list(Config) -> + d("pretty_otp4945_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg4(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {ok, _} -> + ok; + Else -> + t("pretty_otp4945_msg4 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg4() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg5(suite) -> + []; +pretty_otp4945_msg5(Config) when is_list(Config) -> + d("pretty_otp4945_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg5(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {at_most_once_serviceChangeParm, {profile, _Val1, _Val2}} -> + ok; + Else -> + io:format("pretty_otp4945_msg6 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg5 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg5() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + Profile = ResGW/1, + ServiceChangeAddress = 55555, + Profile = ResGW/2 + } + } + } +}". + + +pretty_otp4945_msg6(suite) -> + []; +pretty_otp4945_msg6(Config) when is_list(Config) -> + d("pretty_otp4945_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4945_msg6(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {not_both_address_mgcid_serviceChangeParm, _Val1, _Val2} -> + ok; + Else -> + io:format("pretty_otp4945_msg6 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4945_msg6 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4945_msg6() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + MgcIdToTry = kalle, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4949_msg1(suite) -> + []; +pretty_otp4949_msg1(Config) when is_list(Config) -> + d("pretty_otp4949_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4949_msg1(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {ok, _} -> + ok; + Else -> + t("pretty_otp4949_msg1 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4949_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4949_msg2(suite) -> + []; +pretty_otp4949_msg2(Config) when is_list(Config) -> + d("pretty_otp4949_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4949_msg2(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {at_most_once_servChgReplyParm, {profile, _Val1, _Val2}} -> + ok; + Else -> + io:format("pretty_otp4949_msg2 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4949_msg2 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4949_msg2() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Profile = ResGW/1, + ServiceChangeAddress = 55555, + Profile = ResGW/2 + } + } + } +}". + + +pretty_otp4949_msg3(suite) -> + []; +pretty_otp4949_msg3(Config) when is_list(Config) -> + d("pretty_otp4949_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp4949_msg3(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {not_both_address_mgcid_servChgReplyParm, _Val1, _Val2} -> + ok; + Else -> + io:format("pretty_otp4949_msg3 -> " + "~n Else: ~w" + "~n", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + t("pretty_otp4949_msg3 -> " + "~n Else: ~w", [Else]), + exit({unexpected_decode_result, Else}) + end. + +pretty_otp4949_msg3() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + MgcIdToTry = kalle, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp5042_msg1(suite) -> + []; +pretty_otp5042_msg1(Config) when is_list(Config) -> + d("pretty_otp5042_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg0 = pretty_otp5042_msg1(), + Bin0 = list_to_binary(Msg0), + case decode_message(megaco_pretty_text_encoder, false, [], Bin0) of + {error, [{reason, Reason}|_]} -> + case Reason of + {_, _Mod, {bad_timeStamp, TimeStamp}} -> + exit({bad_timeStamp, TimeStamp}); + _ -> + io:format("pretty_otp5042_msg1 -> " + "~n Reason: ~w" + "~n", [Reason]), + exit({unexpected_decode_result, Reason}) + end; + {ok, M} -> + t("pretty_otp5042_msg1 -> successfull decode:" + "~n~p", [M]), + ok + end. + +pretty_otp5042_msg1() -> +"MEGACO/" ?VERSION_STR " <CATAPULT>:2944 +Transaction = 102 { +Context = 5 { Notify = MUX/1 { ObservedEvents = 1 { +h245bh/h245msgin { Stream = 1 +, h245enc = +0270020600088175000653401004100403E802E00180018001780680000034301160000700088175010101007A0100020001800001320000C0000219D005027F0070500100040100021080000319D005027F00504001008000041C001250000700088175010000400280010003000880000518AA027F400006850130008011020100000001030002000300040005000006 + } } + } } }". + + +pretty_otp5068_msg1(suite) -> + []; +pretty_otp5068_msg1(Config) when is_list(Config) -> + d("pretty_otp5068_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = pretty_otp5068_msg1(), + case encode_message(megaco_pretty_text_encoder, [], Msg) of + {error, Reason} -> +% io:format("pretty_otp5068_msg1 -> " +% "~n Reason: ~w" +% "~n", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} -> +% io:format("pretty_otp5068_msg1 -> successfull encode:" +% "~n~s~n", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, [], Bin) of + {ok, _} -> +% io:format("pretty_otp5068_msg1 -> ok~n", []), + ok; + Else -> +% io:format("pretty_otp5068_msg1 -> ~n~p~n", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + +pretty_otp5068_msg1() -> +{'MegacoMessage', + asn1_NOVALUE, + {'Message', + 2, + {deviceName,[109,103,51,51]}, + {transactions, + [{transactionReply, + {'TransactionReply', + 190, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', %% Comments: Detta upprepas m�nga g�nger + 0, + asn1_NOVALUE, + asn1_NOVALUE, + [{auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false, + [[99,101,100,101,118,49,47,52,47,49,47,49],[51,49]]}, + [{mediaDescriptor, + {'MediaDescriptor', + {'TerminationStateDescriptor', + [], + asn1_NOVALUE, + inSvc}, + asn1_NOVALUE}}]}}}]}]}}}]}}}. + + + +pretty_otp5085_msg1(suite) -> + []; +pretty_otp5085_msg1(Config) when is_list(Config) -> + d("pretty_otp5085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg1()). + +pretty_otp5085_msg2(suite) -> + []; +pretty_otp5085_msg2(Config) when is_list(Config) -> + d("pretty_otp5085_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(error, pretty_otp5085_msg2()). + +pretty_otp5085_msg3(suite) -> + []; +pretty_otp5085_msg3(Config) when is_list(Config) -> + d("pretty_otp5085_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg3()). + +pretty_otp5085_msg4(suite) -> + []; +pretty_otp5085_msg4(Config) when is_list(Config) -> + d("pretty_otp5085_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg4()). + +pretty_otp5085_msg5(suite) -> + []; +pretty_otp5085_msg5(Config) when is_list(Config) -> + d("pretty_otp5085_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg5()). + +pretty_otp5085_msg6(suite) -> + []; +pretty_otp5085_msg6(Config) when is_list(Config) -> + d("pretty_otp5085_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg6()). + +pretty_otp5085_msg7(suite) -> + []; +pretty_otp5085_msg7(Config) when is_list(Config) -> + d("pretty_otp5085_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + pretty_otp5085(ok, pretty_otp5085_msg7()). + +pretty_otp5085(Expected, Msg) -> + pretty_otp5085(Expected, Msg, []). + +pretty_otp5085(Expected, Msg, Conf) -> + t("pretty_otp5085 -> entry with" + "~n Expected: ~p" + "~n Msg: ~p", [Expected, Msg]), + case (catch encode_message(megaco_pretty_text_encoder, Conf, Msg)) of + {error, Reason} when Expected == error -> + d("pretty_otp5085 -> encode failed as expected" + "~n Reason: ~w", [Reason]), + ok; + {error, Reason} -> + e("pretty_otp5085 -> encode failed unexpectedly: " + "~n Reason: ~w", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} when Expected == error -> + e("pretty_otp5085 -> encode succeded unexpectedly: " + "~n ~w", [binary_to_list(Bin)]), + exit({unexpected_encode_result, binary_to_list(Bin)}); + {ok, Bin} -> + d("pretty_otp5085 -> successfull encode as expected:" + "~n~s", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, Conf, Bin) of + {ok, Msg} -> + d("pretty_otp5085 -> successfull decode~n", []), + ok; + {ok, Msg2} -> + e("pretty_otp5085 -> successfull decode" + " - but not equal", []), + exit({unexpected_decode_result, Msg, Msg2}); + Else -> + e("pretty_otp5085 -> decode failed:~n~p", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + +pretty_otp5085_msg1() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + asn1_NOVALUE, + [] + } + ] + } + } + } + ] + } + } + }. + +pretty_otp5085_msg2() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + asn1_NOVALUE, + [] + } + ] + } + } + } + ] + } + } + }. + +pretty_otp5085_msg3() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + #'ContextRequest'{priority = 3}, + [] + } + ] + } + } + } + ] + } + } + }. + +pretty_otp5085_msg4() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + asn1_NOVALUE, + [{addReply, cre_AmmsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + } + } + } + ] + } + } + }. + +pretty_otp5085_msg5() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + #'ContextRequest'{priority = 5}, + [{addReply, cre_AmmsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + } + } + } + ] + } + } + }. + +pretty_otp5085_msg6() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 6}, + [{addReply, cre_AmmsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + } + } + } + ] + } + } + }. + +pretty_otp5085_msg7() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 7}, + [{notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + } + } + } + ] + } + } + }. + + + +pretty_otp5600_msg1(suite) -> + []; +pretty_otp5600_msg1(Config) when is_list(Config) -> + d("pretty_otp5600_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5600(ok, pretty_otp5600_msg1()). + +pretty_otp5600_msg2(suite) -> + []; +pretty_otp5600_msg2(Config) when is_list(Config) -> + d("pretty_otp5600_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5600(ok, pretty_otp5600_msg2()). + +pretty_otp5600(Expected, Msg) -> + pretty_otp5600(Expected, Msg, []). + +pretty_otp5600(Expected, Msg, Conf) -> + t("pretty_otp5600 -> entry with" + "~n Expected: ~p" + "~n Msg: ~p", [Expected, Msg]), + case (catch encode_message(megaco_pretty_text_encoder, Conf, Msg)) of + {error, Reason} when Expected == error -> + d("pretty_otp5600 -> encode failed as expected" + "~n Reason: ~w", [Reason]), + ok; + {error, Reason} -> + e("pretty_otp5600 -> encode failed unexpectedly: " + "~n Reason: ~w", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} when Expected == error -> + e("pretty_otp5600 -> encode succeded unexpectedly: " + "~n ~w", [binary_to_list(Bin)]), + exit({unexpected_encode_result, binary_to_list(Bin)}); + {ok, Bin} -> + d("pretty_otp5600 -> successfull encode as expected:" + "~n~s", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, Conf, Bin) of + {ok, Msg} -> + d("pretty_otp5600 -> successfull decode~n", []), + ok; + {ok, Msg2} -> + e("pretty_otp5600 -> successfull decode" + " - but not equal", []), + exit({unexpected_decode_result, Msg, Msg2}); + Else -> + e("pretty_otp5600 -> decode failed:~n~p", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + + +pretty_otp5600_msg1() -> + SRE = #'SecondRequestedEvent'{ pkgdName = "al/on", + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE ] }, + + SIG = { signal, #'Signal'{ signalName = "cg/dt", + sigParList = [] } }, + + RA = #'RequestedActions'{ secondEvent = SED, + signalsDescriptor = [ SIG ] }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + + +pretty_otp5600_msg2() -> + SIG = { signal, #'Signal'{ signalName = "cg/dt", + sigParList = [] } }, + + SRA = #'SecondRequestedActions'{ signalsDescriptor = [ SIG ] }, + + SRE = #'SecondRequestedEvent'{ pkgdName = "al/on", + eventAction = SRA, + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE ] }, + + RA = #'RequestedActions'{ secondEvent = SED }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + + +pretty_otp5601_msg1(suite) -> + []; +pretty_otp5601_msg1(Config) when is_list(Config) -> + d("pretty_otp5601_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5601(ok, pretty_otp5601_msg1()). + +pretty_otp5601(Expected, Msg) -> + pretty_otp5601(Expected, Msg, []). + +pretty_otp5601(Expected, Msg, Conf) -> + t("pretty_otp5601 -> entry with" + "~n Expected: ~p" + "~n Msg: ~p", [Expected, Msg]), + case (catch encode_message(megaco_pretty_text_encoder, Conf, Msg)) of + {error, Reason} when Expected == error -> + d("pretty_otp5601 -> encode failed as expected" + "~n Reason: ~w", [Reason]), + ok; + {error, Reason} -> + e("pretty_otp5601 -> encode failed unexpectedly: " + "~n Reason: ~w", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} when Expected == error -> + e("pretty_otp5601 -> encode succeded unexpectedly: " + "~n ~w", [binary_to_list(Bin)]), + exit({unexpected_encode_result, binary_to_list(Bin)}); + {ok, Bin} -> + d("pretty_otp5601 -> successfull encode as expected:" + "~n~s", [binary_to_list(Bin)]), + case decode_message(megaco_pretty_text_encoder, false, Conf, Bin) of + {ok, Msg} -> + d("pretty_otp5601 -> successfull decode~n", []), + ok; + {ok, Msg2} -> + e("pretty_otp5601 -> successfull decode" + " - but not equal", []), + exit({unexpected_decode_result, Msg, Msg2}); + Else -> + e("pretty_otp5601 -> decode failed:~n~p", [Else]), + exit({unexpected_decode_result, Else}) + end + end. + +pretty_otp5601_msg1() -> + SRE1 = #'SecondRequestedEvent'{ pkgdName = "al/on", + evParList = [] }, + + SRA = #'SecondRequestedActions'{ eventDM = { digitMapName, "dialllan0" }}, + + SRE2 = #'SecondRequestedEvent'{ pkgdName = "dd/ce", + eventAction = SRA, + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE1, SRE2 ] }, + + RA = #'RequestedActions'{ secondEvent = SED }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + + +pretty_otp5793_msg01(suite) -> + []; +pretty_otp5793_msg01(Config) when is_list(Config) -> + d("pretty_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), +%% put(severity,trc), +%% put(dbg,true), + pretty_otp5793(ok, pretty_otp5793_msg1()). + +pretty_otp5793(Expected, Msg) -> + expect_codec(Expected, megaco_pretty_text_encoder, Msg, []). + +pretty_otp5793(Expected, Msg, Conf) -> + expect_codec(Expected, megaco_pretty_text_encoder, Msg, Conf). + + +pretty_otp5793_msg1() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',2, + {deviceName,"bs_sbg_4/99"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 370, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 3, + asn1_NOVALUE, + asn1_NOVALUE, + [{auditValueReply, + {contextAuditResult, + [{megaco_term_id, + false, + ["ip", + "104", + "1", + "18"]}]}}, + {auditValueReply, + {contextAuditResult, + [{megaco_term_id, + false, + ["ip", + "104", + "2", + "19"]}]}}]}]}}}]}}}. + + +pretty_otp5882_msg01(suite) -> + []; +pretty_otp5882_msg01(Config) when is_list(Config) -> + d("pretty_otp5882_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% put(severity,trc), + %% put(dbg,true), + pretty_otp5882(). + +pretty_otp5882() -> + otp5882(megaco_pretty_text_encoder, []). + +otp5882(Codec, Conf) -> + Msg = pretty_otp5882_msg01(), + case (catch encode_message(Codec, Conf, Msg)) of + {error, {message_encode_failed, {error, {ActualReason, _}}, _}} -> + case ActualReason of + {invalid_LocalControlDescriptor, empty} -> + ok; + _ -> + exit({unexpected_error_actual_reason, ActualReason}) + end; + {error, Reason} -> + exit({unexpected_error_reason, Reason}); + {ok, Bin} -> + exit({unexpected_encode_sucess, binary_to_list(Bin)}) + end. + +pretty_otp5882_msg01() -> + LCD = #'LocalControlDescriptor'{}, % Create illegal LCD + Parms = ?MSG_LIB:cre_StreamParms(LCD), + StreamDesc = ?MSG_LIB:cre_StreamDescriptor(1, Parms), + MediaDesc = ?MSG_LIB:cre_MediaDescriptor([StreamDesc]), + AmmReq = ?MSG_LIB:cre_AmmRequest([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + Cmd = ?MSG_LIB:cre_Command(modReq, AmmReq), + CmdReq = ?MSG_LIB:cre_CommandRequest(Cmd), + CID = ?MSG_LIB:cre_ContextID(5882), + ActReq = ?MSG_LIB:cre_ActionRequest(CID, [CmdReq]), + Actions = [ActReq], + TransId = ?MSG_LIB:cre_TransactionId(7302), + TransReq = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TransReq), + Mid = ?MG1_MID, + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + ?MSG_LIB:cre_MegacoMessage(Mess). + + +%% -------------------------------------------------------------- +%% +pretty_otp6490_msg01(suite) -> + []; +pretty_otp6490_msg01(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg01 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg01(), [] ), + %% erase(dbg), + %% erase(severity), + ok. + +pretty_otp6490_msg02(suite) -> + []; +pretty_otp6490_msg02(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg02 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg02(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg03(suite) -> + []; +pretty_otp6490_msg03(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg03 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg03(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg04(suite) -> + []; +pretty_otp6490_msg04(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg04 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg04(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg05(suite) -> + []; +pretty_otp6490_msg05(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg05 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg05(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg06(suite) -> + []; +pretty_otp6490_msg06(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg06 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp6490( pretty_otp6490_msg06(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490(Msg, Conf) -> + pretty_otp6490(Msg, Conf, ok). + +pretty_otp6490(Msg, Conf, ExpectedEncode) -> + pretty_otp6490(Msg, Conf, ExpectedEncode, ok). + +pretty_otp6490(Msg, Conf, ExpectedEncode, ExpectedDecode) -> + otp6490(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode). + +otp6490(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode) -> + case (catch encode_message(Codec, Conf, Msg)) of + {error, _Reason} when ExpectedEncode == error -> + ok; + {error, Reason} when ExpectedEncode == ok -> + exit({unexpected_encode_failure, Reason}); + {ok, Bin} when ExpectedEncode == error -> + exit({unexpected_encode_success, Msg, binary_to_list(Bin)}); + {ok, Bin} when ExpectedEncode == ok -> + case decode_message(Codec, false, Conf, Bin) of + {ok, Msg} when ExpectedDecode == ok -> + ok; + {ok, Msg} when ExpectedDecode == error -> + exit({unexpected_decode_success, Msg}); + {ok, Msg2} when ExpectedDecode == ok -> + exit({unexpected_decode_result, Msg, Msg2}); + {ok, Msg2} when ExpectedDecode == error -> + exit({unexpected_decode_success, Msg, Msg2}); + {error, _Reason} when ExpectedDecode == error -> + ok; + {error, Reason} when ExpectedDecode == ok -> + exit({unexpected_decode_failure, Msg, Reason}) + end + end. + + +pretty_otp6490_msg(EBD) -> + AmmDesc = ?MSG_LIB:cre_AmmDescriptor(EBD), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4445}], [AmmDesc]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + CID = cre_CtxID(64901), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(64902), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +pretty_otp6490_msg01() -> + EvSpecs = [], % This will result in an error + EBD = EvSpecs, % This is because the lib checks that the size is valid + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg02() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg03() -> + EvPar1 = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + EvPar2 = ?MSG_LIB:cre_EventParameter("kalle", ["anka"]), + EvPar3 = ?MSG_LIB:cre_EventParameter("flippa", ["ur"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar1,EvPar2,EvPar3]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg04() -> + EvPar1 = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + EvPar2 = ?MSG_LIB:cre_EventParameter("kalle", ["anka"]), + EvPar3 = ?MSG_LIB:cre_EventParameter("flippa", ["ur"]), + PkgdName1 = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName1 = ?MSG_LIB:cre_EventName(PkgdName1), + EvSpec1 = ?MSG_LIB:cre_EventSpec(EvName1, [EvPar1,EvPar2,EvPar3]), + EvPar4 = ?MSG_LIB:cre_EventParameter("hej", ["hopp"]), + PkgdName2 = ?MSG_LIB:cre_PkgdName("bar", "b"), + EvName2 = ?MSG_LIB:cre_EventName(PkgdName2), + EvSpec2 = ?MSG_LIB:cre_EventSpec(EvName2, [EvPar4]), + EvSpecs = [EvSpec1,EvSpec2], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg05() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", root), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg06() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName(root, root), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + + +%% -------------------------------------------------------------- +%% +pretty_otp7249_msg01(suite) -> + []; +pretty_otp7249_msg01(doc) -> + "Ticket OTP-7249 has really nothing to to with just version 2 " + "although the test message is version 2. Instead the decode " + "is actually done by the mini decoder, which is where the bug " + "manifests itself. The bug is in effect located in the (plain) " + "text scanner. "; +pretty_otp7249_msg01(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp7249_msg01 -> entry", []), + ok = pretty_otp7249( pretty_otp7249_msg01() ), + %% erase(dbg), + %% erase(severity), + ok. + + +pretty_otp7249_msg01() -> + "MEGACO/2 <AGW95_DCT_2_DPNSS>\r\nTransaction = 500017 { \r\nContext = - { ServiceChange = ROOT { Services { \r\nMethod = Disconnected, Reason = 900, 20070116T15233997 } \r\n } } } \r\n". + +pretty_otp7249(EncodedMsg) -> + Codec = megaco_pretty_text_encoder, + Conf = [], + Bin = list_to_binary(EncodedMsg), + case decode_mini_message(Codec, Conf, Bin) of + {ok, Msg} when is_record(Msg, 'MegacoMessage') -> + %% io:format("Msg: ~n~p" + %% "~n", [Msg]), + ok; + {error, Reason} -> + exit({unexpected_decode_failure, EncodedMsg, Reason}) + end. + + + +%% -------------------------------------------------------------- +%% + +pretty_otp7671_msg01(suite) -> + []; +pretty_otp7671_msg01(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg01 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg01(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg02(suite) -> + []; +pretty_otp7671_msg02(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg02 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg02(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg03(suite) -> + []; +pretty_otp7671_msg03(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg03 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg03(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg04(suite) -> + []; +pretty_otp7671_msg04(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg04 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg04(), [] , error, ignore), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg05(suite) -> + []; +pretty_otp7671_msg05(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg05 -> entry", []), + Check = fun(M1, M2) -> cmp_otp7671_msg05(M1, M2) end, + ok = pretty_otp7671( pretty_otp7671_msg05(), [] , ok, ok, Check), +%% erase(dbg), +%% erase(severity), + ok. + + +pretty_otp7671(Msg, Conf) -> + pretty_otp7671(Msg, Conf, ok). + +pretty_otp7671(Msg, Conf, ExpectedEncode) -> + pretty_otp7671(Msg, Conf, ExpectedEncode, ok). + +pretty_otp7671(Msg, Conf, ExpectedEncode, ExpectedDecode) -> + otp7671(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode). + +pretty_otp7671(Msg, Conf, ExpectedEncode, ExpectedDecode, Check) -> + otp7671(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode, Check). + +otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode) -> + Check = fun(M1, M2) -> + exit({unexpected_decode_result, M1, M2}) + end, + otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode, Check). + +otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode, Check) + when is_function(Check) -> + case (catch encode_message(Codec, Conf, Msg)) of + {error, _Reason} when ExpectedEncode =:= error -> + ok; + {error, Reason} when ExpectedEncode =:= ok -> + exit({unexpected_encode_failure, Reason}); + {ok, Bin} when ExpectedEncode =:= error -> + exit({unexpected_encode_success, Msg, binary_to_list(Bin)}); + {ok, Bin} when ExpectedEncode =:= ok -> + case decode_message(Codec, false, Conf, Bin) of + {ok, Msg} when ExpectedDecode =:= ok -> + ok; + {ok, Msg2} when ExpectedDecode =:= ok -> + Check(Msg, Msg2); + {ok, Msg} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg}); + {ok, Msg2} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg, Msg2}); + {error, _Reason} when ExpectedDecode =:= error -> + ok; + {error, Reason} when ExpectedDecode == ok -> + exit({unexpected_decode_failure, Msg, Reason}) + end + end. + + +pretty_otp7671_msg(DigitMapDesc) -> + AmmReq = cre_AmmReq([#megaco_term_id{id = ["root"]}], + [{digitMapDescriptor, DigitMapDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(?MGC_MID, 10001, ?megaco_null_context_id, [CmdReq]). + +pretty_otp7671_msg01() -> + Name = "dialplan01", + DigitMapDesc = cre_DigitMapDesc(Name), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg02() -> + Name = "dialplan02", + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body), + DigitMapDesc = cre_DigitMapDesc(Name, Value), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg03() -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body), + DigitMapDesc = cre_DigitMapDesc(Value), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg04() -> + DigitMapDesc = cre_DigitMapDesc(), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg05() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',?VERSION, + {domainName,{'DomainName',"tgc",asn1_NOVALUE}}, + {transactions, + [{transactionRequest, + {'TransactionRequest',12582952, + [{'ActionRequest',0,asn1_NOVALUE,asn1_NOVALUE, + [{'CommandRequest', + {modReq, + {'AmmRequest', + [{megaco_term_id,false,["root"]}], + [{digitMapDescriptor, + {'DigitMapDescriptor',"dialplan1", + {'DigitMapValue',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,[], + asn1_NOVALUE}}}]}}, + asn1_NOVALUE,asn1_NOVALUE}]}]}}]}}}. + +cmp_otp7671_msg05(#'MegacoMessage'{authHeader = asn1_NOVALUE, + mess = M1}, + #'MegacoMessage'{authHeader = asn1_NOVALUE, + mess = M2}) -> + #'Message'{messageBody = Body1} = M1, + #'Message'{messageBody = Body2} = M2, + {transactions, Trans1} = Body1, + {transactions, Trans2} = Body2, + [{transactionRequest, TR1}] = Trans1, + [{transactionRequest, TR2}] = Trans2, + #'TransactionRequest'{actions = Acts1} = TR1, + #'TransactionRequest'{actions = Acts2} = TR2, + [#'ActionRequest'{commandRequests = CR1}] = Acts1, + [#'ActionRequest'{commandRequests = CR2}] = Acts2, + [#'CommandRequest'{command = Cmd1}] = CR1, + [#'CommandRequest'{command = Cmd2}] = CR2, + {modReq, #'AmmRequest'{descriptors = Descs1}} = Cmd1, + {modReq, #'AmmRequest'{descriptors = Descs2}} = Cmd2, + [{digitMapDescriptor, + #'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value1}}] = Descs1, + [{digitMapDescriptor, + #'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value2}}] = Descs2, + #'DigitMapValue'{startTimer = asn1_NOVALUE, + shortTimer = asn1_NOVALUE, + longTimer = asn1_NOVALUE, + digitMapBody = [], + durationTimer = asn1_NOVALUE} = Value1, + asn1_NOVALUE = Value2, + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +expect_codec(Expect, Codec, Msg, Conf) -> + t("expect_codec -> entry with" + "~n Expect: ~p" + "~n Msg: ~p", [Expect, Msg]), + case (catch encode_message(Codec, Conf, Msg)) of + {error, _Reason} when Expect == error -> + d("expect_codec -> encode failed as expected" + "~n _Reason: ~w", [_Reason]), + ok; + {error, Reason} -> + e("expect_codec -> encode failed unexpectedly: " + "~n Reason: ~w", [Reason]), + exit({unexpected_encode_result, Reason}); + {ok, Bin} when Expect == error -> + e("expect_codec -> encode succeded unexpectedly: " + "~n ~w", [binary_to_list(Bin)]), + exit({unexpected_encode_result, binary_to_list(Bin)}); + {ok, Bin} -> + d("expect_codec -> successfull encode as expected:" + "~n~s", [binary_to_list(Bin)]), + case (catch decode_message(Codec, false, Conf, Bin)) of + {ok, Msg} -> + d("expect_codec -> successfull decode~n", []), + ok; + {ok, Msg2} -> + e("expect_codec -> successfull decode" + " - but not equal", []), + chk_MegacoMessage(Msg, Msg2); + %% exit({unexpected_decode_result, Msg, Msg2}); + Else -> + e("expect_codec -> decode failed:~n~p", [Else]), + exit({unexpected_decode_result, Else}) + end; + Else -> + e("expect_codec -> encode failed:~n~p", [Else]), + exit({unexpected_encode_result, Else}) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +msgs() -> + Msgs = msgs1() ++ msgs2() ++ msgs3() ++ msgs4(), + [M || {_, M, _, _} <- Msgs]. + +msgs1() -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [ + {msg01a, msg1a(), Plain, [{dbg,false}]}, + {msg01b, msg1b(), Plain, [{dbg,false}]}, + {msg02, msg2(), Plain, [{dbg,false}]}, + {msg03, msg3(), Plain, [{dbg,false}]}, + {msg04, msg4(), Plain, [{dbg,false}]}, + {msg05, msg5(), Plain, [{dbg,false}]}, + {msg06a, msg6a(), Plain, [{dbg,false}]}, + {msg06b, msg6b(), Plain, [{dbg,false}]}, + {msg07, msg7(), Plain, [{dbg,false}]}, + {msg08a, msg8a(), Plain, [{dbg,false}]}, + {msg08b, msg8b(), Plain, [{dbg,false}]}, + {msg09, msg9(), Plain, [{dbg,false}]}, + {msg10, msg10(), Plain, [{dbg,false}]}, + {msg11, msg11(), Plain, [{dbg,false}]}, + {msg12, msg12(), Plain, [{dbg,false}]}, + {msg13, msg13(), Plain, [{dbg,false}]}, + {msg14, msg14(), Plain, [{dbg,false}]}, + {msg15, msg15(), Plain, [{dbg,false}]}, + {msg16, msg16(), Plain, [{dbg,false}]}, + {msg17, msg17(), Plain, [{dbg,false}]}, + {msg18, msg18(), Plain, [{dbg,false}]}, + {msg19, msg19(), Plain, [{dbg,false}]}, + {msg20, msg20(), Plain, [{dbg,false}]}, + {msg21, msg21(), Plain, [{dbg,false}]}, + {msg22a, msg22a(), Plain, [{dbg,false}]}, + {msg22b, msg22b(), Plain, [{dbg,false}]}, + {msg22c, msg22c(), Plain, [{dbg,false}]}, + {msg22d, msg22d(), Plain, [{dbg,false}]}, + {msg22e, msg22e(), Plain, [{dbg,false}]}, + {msg22f, msg22f(), Plain, [{dbg,false}]}, + {msg23a, msg23a(), Plain, [{dbg,false}]}, + {msg23b, msg23b(), Plain, [{dbg,false}]}, + {msg23c, msg23c(), Plain, [{dbg,false}]}, + {msg23d, msg23d(), Plain, [{dbg,false}]}, + {msg24, msg24(), Plain, [{dbg,false}]}, + {msg25, msg25(), Plain, [{dbg,false}]}, + {msg30a, msg30a(), Plain, [{dbg,false}]}, + {msg30b, msg30b(), Plain, [{dbg,false}]}, + {msg30c, msg30c(), Plain, [{dbg,false}]}, + {msg30d, msg30d(), Plain, [{dbg,false}]} + ]. + + +msgs2() -> + TransFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:trans_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + ActionsFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:actions_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + ActionFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:action_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + [ + {msg01a_tf, msg1a(), TransFirst, [{dbg,false}]}, + {msg02_tf, msg2(), TransFirst, [{dbg,false}]}, + {msg10_tf, msg10(), TransFirst, [{dbg,false}]}, + {msg11_tf, msg11(), TransFirst, [{dbg,false}]}, + {msg23d_tf, msg23d(), TransFirst, [{dbg,false}]}, + {msg30b_tf, msg30b(), TransFirst, [{dbg,false}]}, + {msg30c_tf, msg30c(), TransFirst, [{dbg,false}]}, + {msg01a_asf, msg1a(), ActionsFirst, [{dbg,false}]}, + {msg02_asf, msg2(), ActionsFirst, [{dbg,false}]}, + {msg10_asf, msg10(), ActionsFirst, [{dbg,false}]}, + {msg23d_asf, msg23d(), ActionsFirst, [{dbg,false}]}, + {msg01a_af, msg1a(), ActionFirst, [{dbg,false}]}, + {msg02_af, msg2(), ActionFirst, [{dbg,false}]}, + {msg10_af, msg10(), ActionFirst, [{dbg,false}]}, + {msg23d_af, msg23d(), ActionFirst, [{dbg,false}]} + ]. + + +msgs3() -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [{msgs3_name(Name), rfc3525_decode(M), Plain, [{dbg, false}]} || + {Name, M} <- rfc3525_msgs()]. + +msgs3_name(N) -> + list_to_atom("rfc3525_" ++ atom_to_list(N)). + +rfc3525_decode(M) when is_list(M) -> + rfc3525_decode(list_to_binary(M)); +rfc3525_decode(M) when is_binary(M) -> + case (catch decode_message(megaco_pretty_text_encoder, false, [], M)) of + {ok, Msg} -> + Msg; + Error -> + {error, {rfc3525_decode_error, Error}} + end. + + +msgs4() -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [ + {msg51a, msg51a(), Plain, [{dbg, false}]}, + {msg51b, msg51b(), Plain, [{dbg, false}]}, + {msg51c, msg51c(), Plain, [{dbg, false}]}, + {msg51d, msg51d(), Plain, [{dbg, false}]}, + {msg51e, msg51e(), Plain, [{dbg, false}]}, + {msg51f, msg51f(), Plain, [{dbg, false}]}, + {msg51g, msg51g(), Plain, [{dbg, false}]}, + {msg51h, msg51h(), Plain, [{dbg, false}]}, + {msg51i, msg51i(), Plain, [{dbg, false}]}, + {msg52, msg52(), Plain, [{dbg, false}]}, + {msg53, msg53(), Plain, [{dbg, false}]}, + {msg54a, msg54a(), Plain, [{dbg, false}]}, + {msg54b, msg54b(), Plain, [{dbg, false}]}, + {msg54c, msg54c(), Plain, [{dbg, false}]}, + {msg55, msg55(), Plain, [{dbg, false}]}, + {msg56, msg56(), Plain, [{dbg, false}]}, + {msg57, msg57(), Plain, [{dbg, false}]}, + {msg58a, msg58a(), Plain, [{dbg, false}]}, + {msg58b, msg58b(), Plain, [{dbg, false}]} + ]. + + +msgs5() -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + + PlainEDFail = + fun(Codec, DD, Ver, EC, M) -> + Res = + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M), + case Res of + {error, {message_encode_failed, Reason, _M}} -> + case Reason of + {error, {{deprecated, _}, _}} -> + ok; + _ -> + Res + end; + _ -> + Res + end + end, + + PlainDE = + fun(Codec, _DD, Ver, EC, B) -> + Res = + megaco_codec_test_lib:decode_message(Codec, false, Ver, + EC, B), + case Res of + {ok, M} -> + #'MegacoMessage'{mess = Mess} = M, + #'Message'{messageBody = {transactions, TRs}} = Mess, + [{transactionRequest, TR}] = TRs, + #'TransactionRequest'{actions = Actions} = TR, + [Action] = Actions, + #'ActionRequest'{commandRequests = CmdReqs} = Action, + [CmdReq] = CmdReqs, + #'CommandRequest'{command = Cmd} = CmdReq, + {addReq,AmmReq} = Cmd, + #'AmmRequest'{descriptors = []} = AmmReq, + ok; + _ -> + Res + end + end, + + [ + {msg61a, msg61a(), Plain, [{dbg, false}]}, + {msg61b, msg61b(), Plain, [{dbg, false}]}, + {msg61c, msg61c(), Plain, [{dbg, false}]}, + {msg62a, msg62a(), PlainEDFail, [{dbg, false}]}, + {msg62b, msg62b(), PlainDE, [{dbg, false}]} + ]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +msg_actions([], Actions) -> + lists:reverse(Actions); +msg_actions([{CtxId, CmdReqs}|ActionInfo], Actions) -> + Action = ?MSG_LIB:cre_ActionRequest(CtxId,CmdReqs), + msg_actions(ActionInfo, [Action|Actions]). + +megaco_trans_req([], Transactions) -> + {transactions, lists:reverse(Transactions)}; +megaco_trans_req([{TransId, ActionInfo}|TransInfo], Transactions) -> + Actions = msg_actions(ActionInfo, []), + TR = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + megaco_trans_req(TransInfo, [Trans|Transactions]). + +megaco_message(Version, Mid, Body) -> + Mess = ?MSG_LIB:cre_Message(Version, Mid, Body), + ?MSG_LIB:cre_MegacoMessage(Mess). + +msg_request(Mid, TransInfo) -> + TransReq = megaco_trans_req(TransInfo, []), + megaco_message(?VERSION, Mid, TransReq). + +msg_request(Mid, TransId, ContextId, CmdReq) -> + Action = ?MSG_LIB:cre_ActionRequest(ContextId, CmdReq), + Actions = [Action], + TR = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + ?MSG_LIB:cre_MegacoMessage(Mess). + +msg_request(Auth, Mid, TransId, ContextId, CmdReq) -> + Action = ?MSG_LIB:cre_ActionRequest(ContextId, CmdReq), + Actions = [Action], + TR = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + ?MSG_LIB:cre_MegacoMessage(Auth, Mess). + +msg_reply(Mid, TransId, ContextId, CmdReply) -> + Action = cre_ActRep(ContextId, CmdReply), + Actions = [Action], + TR = cre_TransRep(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + ?MSG_LIB:cre_MegacoMessage(Mess). + +msg_ack(Mid, [Range|_] = Ranges) when is_tuple(Range) -> + msg_ack(Mid, [Ranges]); + +msg_ack(Mid, Ranges) -> + %% TRAs = make_tras(Ranges, []), + TRAs = make_tras(Ranges), + Req = {transactions, TRAs}, + cre_MegacoMessage(?VERSION, Mid, Req). + +make_tras(TRARanges) -> + F = fun(R) -> {transactionResponseAck, make_tra(R)} end, + lists:map(F, TRARanges). + +make_tra(Ranges) -> + F = fun({F,L}) -> cre_TransAck(F,L) end, + lists:map(F, Ranges). + + +%% ------------------------------------------------------------------------- + + +msg1(Mid, Tid) -> + Gain = cre_PropParm("tdmc/gain", "2"), + Ec = cre_PropParm("tdmc/ec", "g165"), + LCD = cre_LocalControlDesc(sendRecv,[Gain, Ec]), + V = cre_PropParm("v", "0"), + %% C = cre_PropParm("c", "IN IP4 $ "), + C = cre_PropParm("c", [$I,$N,$ ,$I,$P,$4,$ ,$$,$ ]), + M = cre_PropParm("m", "audio $ RTP/AVP 0"), + A = cre_PropParm("a", "fmtp:PCMU VAD=X-NNVAD"), + LD = cre_LocalRemoteDesc([[V, C, M, A]]), + Parms = cre_StreamParms(LCD,LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + ReqEvent = cre_ReqedEv("al/of"), + EventsDesc = cre_EvsDesc(2222,[ReqEvent]), + AmmReq = cre_AmmReq([#megaco_term_id{id = Tid}], + [{mediaDescriptor, MediaDesc}, + {eventsDescriptor, EventsDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 9999, ?megaco_null_context_id, [CmdReq]). + +msg1a() -> + msg1a(?MGC_MID). +msg1a(Mid) -> + msg1(Mid, ?A4444). + +msg1b() -> + msg1b(?MGC_MID). +msg1b(Mid) -> + msg1(Mid, ?A4445). + + +%% -------------------------- + + +msg2() -> + msg2(?MGC_MID). +msg2(Mid) -> + msg2(Mid, ?A4444). +msg2(Mid, Tid) -> + Gain = cre_PropParm("tdmc/gain", "2"), + Ec = cre_PropParm("tdmc/ec", "g165"), + LCD = cre_LocalControlDesc(sendRecv,[Gain, Ec]), + V = cre_PropParm("v", "0"), + %% C = cre_PropParm("c", "IN IP4 $ "), + C = cre_PropParm("c", [$I,$N,$ ,$I,$P,$4,$ ,$$,$ ]), + M = cre_PropParm("m", "audio $ RTP/AVP 0"), + A = cre_PropParm("a", "fmtp:PCMU VAD=X-NNVAD"), + LD = cre_LocalRemoteDesc([[V, C, M, A]]), + Parms = cre_StreamParms(LCD,LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + EventParm = cre_EvParm("strict",["exact"]), + ReqEvent = cre_ReqedEv("al/of", [EventParm]), + EventsDesc = cre_EvsDesc(2222,[ReqEvent]), + AmmReq = cre_AmmReq([#megaco_term_id{id = Tid}], + [{mediaDescriptor, MediaDesc}, + {eventsDescriptor, EventsDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 9999, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg3() -> + msg3(?MG1_MID). +msg3(Mid) -> + TimeStamp = cre_TimeNot("19990729", "22000000"), + Event = cre_ObsEv("al/of",TimeStamp), + Desc = cre_ObsEvsDesc(2222,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 10000, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg4() -> + msg4(?MG1_MID_NO_PORT, "901 mg col boot"). +msg4(Mid, Reason) when is_list(Reason) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChParm(restart,Address,[Reason],Profile), + Req = cre_SvcChReq([?megaco_root_termination_id],Parm), + CmdReq = cre_CmdReq({serviceChangeReq, Req}), + msg_request(Mid, 9998, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg5() -> + msg5(?MGC_MID). +msg5(Mid) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChResParm(Address,Profile), + Reply = cre_SvcChRep([?megaco_root_termination_id], + {serviceChangeResParms,Parm}), + msg_reply(Mid, 9998, ?megaco_null_context_id, + [{serviceChangeReply, Reply}]). + + +%% -------------------------- + +msg6(Mid, Tid) -> + Reply = cre_AmmsReply([#megaco_term_id{id = Tid}]), + msg_reply(Mid, 9999, ?megaco_null_context_id, [{modReply, Reply}]). + +msg6a() -> + msg6a(?MG1_MID). +msg6a(Mid) -> + msg6(Mid, ?A4444). + +msg6b() -> + msg6b(?MG2_MID). +msg6b(Mid) -> + msg6(Mid, ?A5555). + + +%% -------------------------- + +msg7() -> + msg7(?MGC_MID). +msg7(Mid) -> + Reply = cre_NotifyRep([#megaco_term_id{id = ?A4444}]), + msg_reply(Mid, 10000, ?megaco_null_context_id, [{notifyReply, Reply}]). + + +%% -------------------------- + +msg8(Mid, DigitMapValue) -> + Strict = cre_EvParm("strict",["state"]), + On = cre_ReqedEv("al/on", [Strict]), + Name = "dialplan00", + Action = cre_ReqedActs(Name), + Ce = cre_ReqedEv("dd/ce", Action), + EventsDesc = cre_EvsDesc(2223,[On, Ce]), + Signal = cre_Sig("cg/rt"), + DigMapDesc = cre_DigitMapDesc(Name, DigitMapValue), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, [{signal, Signal}]}, + {digitMapDescriptor, DigMapDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 10001, ?megaco_null_context_id, [CmdReq]). + +msg8a() -> + msg8a(?MGC_MID). +msg8a(Mid) -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body), + msg8(Mid, Value). + +msg8b() -> + msg8b(?MGC_MID). +msg8b(Mid) -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body, 1, 23, 99), + msg8(Mid, Value). + + +%% -------------------------- + +msg9() -> + msg9(?MG1_MID). +msg9(Mid) -> + TimeStamp = cre_TimeNot("19990729","22010001"), + Parm = cre_EvParm("ds",["916135551212"]), + Event = cre_ObsEv("dd/ce",TimeStamp,[Parm]), + Desc = cre_ObsEvsDesc(2223,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A4444}], Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 10002, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg10() -> + msg10(?MGC_MID). +msg10(Mid) -> + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}],[]), + CmdReq = cre_CmdReq({addReq, AmmReq}), + Jit = cre_PropParm("nt/jit", "40"), + LCD = cre_LocalControlDesc(recvOnly,[Jit]), + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 $ "), + M = cre_PropParm("m", "audio $ RTP/AVP 4"), + A = cre_PropParm("a", "ptime:30"), + V2 = cre_PropParm("v", "0"), + C2 = cre_PropParm("c", "IN IP4 $ "), + M2 = cre_PropParm("m", "audio $ RTP/AVP 0"), + LD = cre_LocalRemoteDesc([[V, C, M, A], [V2, C2, M2]]), + Parms = cre_StreamParms(LCD, LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + ChooseTid = #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}, + AmmReq2 = cre_AmmReq([ChooseTid],[{mediaDescriptor, MediaDesc}]), + CmdReq2 = cre_CmdReq({addReq, AmmReq2}), + msg_request(Mid, 10003, ?megaco_choose_context_id, [CmdReq, CmdReq2]). + + +msg11() -> + msg11(?MG1_MID). +msg11(Mid) -> + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 124.124.124.222"), + M = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + A = cre_PropParm("a", "ptime:30"), + A2 = cre_PropParm("a", "recvonly"), + LD = cre_LocalRemoteDesc([[V, C, M, A, A2]]), + Parms = cre_StreamParmsL(LD), + StreamDesc = cre_StreamDesc(1, Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + msg_reply(Mid, 10003, 2000, [{addReply, Reply}, {addReply, Reply2}]). + + +%% -------------------------- + +msg12() -> + msg12(?MGC_MID). +msg12(Mid) -> + LCD = cre_LocalControlDesc(sendRecv), + Parms = cre_StreamParms(LCD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Signal = cre_Sig("al/ri"), + Descs = [{mediaDescriptor, MediaDesc}, + {signalsDescriptor, [{signal, Signal}]}], + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A5555}], Descs), + CmdReq = cre_CmdReq({addReq, AmmReq}), + Jit = cre_PropParm("nt/jit", "40"), + LCD2 = cre_LocalControlDesc(sendRecv, [Jit]), + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 $ "), + M = cre_PropParm("m", "audio $ RTP/AVP 4"), + A = cre_PropParm("a", "ptime:30"), + LD2 = cre_LocalRemoteDesc([[V, C, M, A]]), + V2 = cre_PropParm("v", "0"), + C2 = cre_PropParm("c", "IN IP4 124.124.124.222"), + M2 = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + RD2 = cre_LocalRemoteDesc([[V2, C2, M2]]), + Parms2 = cre_StreamParms(LCD2,LD2,RD2), + StreamDesc2 = cre_StreamDesc(1,Parms2), + MediaDesc2 = cre_MediaDesc(StreamDesc2), + ChooseTid = #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}, + AmmReq2 = cre_AmmReq([ChooseTid],[{mediaDescriptor, MediaDesc2}]), + CmdReq2 = cre_CmdReq({addReq, AmmReq2}), + msg_request(Mid, 50003, ?megaco_choose_context_id, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg13() -> + msg13(?MG2_MID). +msg13(Mid) -> + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 125.125.125.111"), + M = cre_PropParm("m", "audio 1111 RTP/AVP 4"), + LD = cre_LocalRemoteDesc([[V, C, M]]), + Parms = cre_StreamParmsL(LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Reply = cre_AmmsReply([#megaco_term_id{id = ?A5556}], + [{mediaDescriptor, MediaDesc}]), + msg_reply(Mid, 50003, 5000, [{addReply, Reply}]). + + +%% -------------------------- + +msg14() -> + msg14(?MGC_MID). +msg14(Mid) -> + %% Cmd 1) + Signal = cre_Sig("cg/rt"), + AmmReq1 = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{signalsDescriptor, [{signal, Signal}]}]), + CmdReq1 = cre_CmdReq({modReq, AmmReq1}), + + %% Cmd 2) + Gain = cre_PropParm("tdmc/gain", "2"), + Ec = cre_PropParm("tdmc/ec", "g165"), + LCD = cre_LocalControlDesc(sendRecv, [Gain, Ec]), + Parms2 = cre_StreamParms(LCD), + StreamDesc2 = cre_StreamDesc(1,Parms2), + MediaDesc2 = cre_MediaDesc(StreamDesc2), + AmmReq2 = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc2}]), + CmdReq2 = cre_CmdReq({modReq, AmmReq2}), + + %% Cmd 3) + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 125.125.125.111"), + M = cre_PropParm("m", "audio 1111 RTP/AVP 4"), + RD = cre_LocalRemoteDesc([[V, C, M]]), + Parms3 = cre_StreamParmsR(RD), + StreamDesc3 = cre_StreamDesc(2,Parms3), + MediaDesc3 = cre_MediaDesc(StreamDesc3), + AmmReq3 = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc3}]), + CmdReq3 = cre_CmdReq({modReq, AmmReq3}), + msg_request(Mid, 10005, 2000, [CmdReq1, CmdReq2, CmdReq3]). + + +%% -------------------------- + +msg15() -> + msg15(?MG1_MID). +msg15(Mid) -> + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A4445}]), + msg_reply(Mid, 10005, 2000, [{modReply, Reply}, {modReply, Reply2}]). + + +%% -------------------------- + +msg16() -> + msg16(?MG2_MID). +msg16(Mid) -> + TimeStamp = cre_TimeNot("19990729","22020002"), + Event = cre_ObsEv("al/of",TimeStamp), + Desc = cre_ObsEvsDesc(1234,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 50005, 5000, [CmdReq]). + + +%% -------------------------- + +msg17() -> + msg17(?MGC_MID). +msg17(Mid) -> + Reply = cre_NotifyRep([#megaco_term_id{id = ?A5555}]), + msg_reply(Mid, 50005, ?megaco_null_context_id, [{notifyReply, Reply}]). + + +%% -------------------------- + +msg18() -> + msg18(?MGC_MID). +msg18(Mid) -> + On = cre_ReqedEv("al/on"), + EventsDesc = cre_EvsDesc(1235,[On]), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A5555}], + [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, []}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 50006, 5000, [CmdReq]). + + +%% -------------------------- + +msg19() -> + msg19(?MG2_MID). +msg19(Mid) -> + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4445}]), + msg_reply(Mid, 50006, 5000, [{modReply, Reply}]). + + +%% -------------------------- + +msg20() -> + msg20(?MGC_MID). +msg20(Mid) -> + LCD = cre_LocalControlDesc(sendRecv), + Parms = cre_StreamParms(LCD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + AmmReq2 = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{signalsDescriptor, []}]), + CmdReq2 = cre_CmdReq({modReq, AmmReq2}), + msg_request(Mid, 10006, 2000, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg21() -> + msg21(?MGC_MID). +msg21(Mid) -> + Tokens = [mediaToken, eventsToken, signalsToken, + digitMapToken, statsToken, packagesToken], + AuditDesc = cre_AuditDesc(Tokens), + Req = cre_AuditReq(#megaco_term_id{id = ?A5556},AuditDesc), + CmdReq = cre_CmdReq({auditValueRequest, Req}), + msg_request(Mid, 50007, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg22a() -> + msg22(1). + +msg22b() -> + msg22(10). + +msg22c() -> + msg22(25). + +msg22d() -> + msg22(50). + +msg22e() -> + msg22(75). + +msg22f() -> + msg22(100). + +msg22(N) -> + msg22(?MG2_MID, N). +msg22(Mid, N) -> + Jit = cre_PropParm("nt/jit", "40"), + LCD = cre_LocalControlDesc(sendRecv,[Jit]), + LDV = cre_PropParm("v", "0"), + LDC = cre_PropParm("c", "IN IP4 125.125.125.111"), + LDM = cre_PropParm("m", "audio 1111 RTP/AVP 4"), + LDA = cre_PropParm("a", "ptime:30"), + LD = cre_LocalRemoteDesc([[LDV, LDC, LDM, LDA]]), + RDV = cre_PropParm("v", "0"), + RDC = cre_PropParm("c", "IN IP4 124.124.124.222"), + RDM = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + RDA = cre_PropParm("a", "ptime:30"), + RD = cre_LocalRemoteDesc([[RDV, RDC, RDM, RDA]]), + StreamParms = cre_StreamParms(LCD,LD,RD), + StreamDesc = cre_StreamDesc(1,StreamParms), + Media = cre_MediaDesc(StreamDesc), + PackagesItem = cre_PkgsItem("nt",1), + PackagesItem2 = cre_PkgsItem("rtp",1), + Stat = cre_StatsParm("rtp/ps","1200"), + Stat2 = cre_StatsParm("nt/os","62300"), + Stat3 = cre_StatsParm("rtp/pr","700"), + Stat4 = cre_StatsParm("nt/or","45100"), + Stat5 = cre_StatsParm("rtp/pl","0.2"), + Stat6 = cre_StatsParm("rtp/jit","20"), + Stat7 = cre_StatsParm("rtp/delay","40"), + Statistics = [Stat, Stat2, Stat3, Stat4, Stat5, Stat6, Stat7], + Audits = [{mediaDescriptor, Media}, + {packagesDescriptor, [PackagesItem, PackagesItem2]}, + {statisticsDescriptor, Statistics}], + Reply = {auditResult, + cre_AuditRes(#megaco_term_id{id = ?A5556},Audits)}, + msg_reply(Mid, 50007, ?megaco_null_context_id, + lists:duplicate(N,{auditValueReply, Reply})). +%% msg_reply(Mid, 50007, ?megaco_null_context_id, +%% lists.duplicate([{auditValueReply, Reply}]). + + +%% -------------------------- + +msg23a() -> + msg23a(?MG2_MID). +msg23a(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 50008, 5000, [CmdReq]). + + +msg23b() -> + msg23b(?MG2_MID). +msg23b(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq1 = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_CmdReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_NotifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_CmdReq({notifyReq, NotifyReq2}), + ActionInfo = [{5000, [CmdReq1]}, {5001, [CmdReq2]}], + TransInfo = [{50008, ActionInfo}], + msg_request(Mid, TransInfo). + + +msg23c() -> + msg23c(?MG2_MID). +msg23c(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq1 = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_CmdReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_NotifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_CmdReq({notifyReq, NotifyReq2}), + ActionInfo1 = [{5000, [CmdReq1]}], + ActionInfo2 = [{5001, [CmdReq2]}], + TransInfo = [{50008, ActionInfo1}, {50009, ActionInfo2}], + msg_request(Mid, TransInfo). + + +msg23d() -> + msg23d(?MG2_MID). +msg23d(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq1 = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_CmdReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_NotifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_CmdReq({notifyReq, NotifyReq2}), + NotifyReq3 = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc), + CmdReq3 = cre_CmdReq({notifyReq, NotifyReq3}), + NotifyReq4 = cre_NotifyReq([#megaco_term_id{id = ?A4445}],Desc), + CmdReq4 = cre_CmdReq({notifyReq, NotifyReq4}), + ActionInfo1 = [{5000, [CmdReq1]}, {5001, [CmdReq2]}], + ActionInfo2 = [{5003, [CmdReq3]}, {5004, [CmdReq4]}], + TransInfo = [{50008, ActionInfo1}, {50009, ActionInfo2}], + msg_request(Mid, TransInfo). + + +%% -------------------------- + +msg24() -> + msg24(?MGC_MID). +msg24(Mid) -> + AuditDesc = cre_AuditDesc([statsToken]), + SubReq = cre_SubReq([#megaco_term_id{id = ?A5555}], AuditDesc), + SubReq2 = cre_SubReq([#megaco_term_id{id = ?A5556}], AuditDesc), + CmdReq = cre_CmdReq({subtractReq, SubReq}), + CmdReq2 = cre_CmdReq({subtractReq, SubReq2}), + msg_request(Mid, 50009, 5000, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg25() -> + msg25(?MG2_MID). +msg25(Mid) -> + Stat11 = cre_StatsParm("nt/os","45123"), + Stat12 = cre_StatsParm("nt/dur", "40"), + Stats1 = [Stat11, Stat12], + Reply1 = cre_AmmsReply([#megaco_term_id{id = ?A5555}], + [{statisticsDescriptor, Stats1}]), + Stat21 = cre_StatsParm("rtp/ps","1245"), + Stat22 = cre_StatsParm("nt/os", "62345"), + Stat23 = cre_StatsParm("rtp/pr", "780"), + Stat24 = cre_StatsParm("nt/or", "45123"), + Stat25 = cre_StatsParm("rtp/pl", "10"), + Stat26 = cre_StatsParm("rtp/jit", "27"), + Stat27 = cre_StatsParm("rtp/delay","48"), + Stats2 = [Stat21, Stat22, Stat23, Stat24, Stat25, Stat26, Stat27], + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A5556}], + [{statisticsDescriptor, Stats2}]), + msg_reply(Mid, 50009, 5000, + [{subtractReply, Reply1}, {subtractReply, Reply2}]). + + +msg30a() -> + msg_ack(?MG2_MID, [{9,9}]). + +msg30b() -> + msg_ack(?MG2_MID, [{9,13}]). + +msg30c() -> + msg_ack(?MG2_MID, + [{9,13}, {15,15}, {33,40}, {50,60}, {70,80}, {85,90}, + {101,105},{109,119},{121,130},{140,160},{170,175},{180,189}, + {201,205},{209,219},{221,230},{240,260},{270,275},{280,289}, + {301,305},{309,319},{321,330},{340,360},{370,375},{380,389}, + {401,405},{409,419},{421,430},{440,460},{470,475},{480,489}, + {501,505},{509,519},{521,530},{540,560},{570,575},{580,589} + ]). + +%% Don't think this will be used by the megaco stack, but since it +%% seem's to be a valid construction... +msg30d() -> + msg_ack(?MG2_MID, + [[{9,13}, {15,15}, {33,40}, {50,60}, {70,80}, {85,90}], + [{101,105},{109,119},{121,130},{140,160},{170,175},{180,189}], + [{201,205},{209,219},{221,230},{240,260},{270,275},{280,289}], + [{301,305},{309,319},{321,330},{340,360},{370,375},{380,389}], + [{401,405},{409,419},{421,430},{440,460},{470,475},{480,489}], + [{501,505},{509,519},{521,530},{540,560},{570,575},{580,589}] + ]). + + + +msg40() -> + msg40(?MG1_MID_NO_PORT, "901 mg col boot"). +msg40(Mid, Reason) when is_list(Reason) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChParm(restart,Address,[Reason],Profile), + Req = cre_SvcChReq([?megaco_root_termination_id],Parm), + CmdReq = cre_CmdReq({serviceChangeReq, Req}), + Auth = cre_AuthHeader(), + msg_request(Auth, Mid, 9998, ?megaco_null_context_id, [CmdReq]). + + +msg50(Mid, APT) -> + AD = cre_AuditDesc(asn1_NOVALUE, APT), + Req = cre_AuditReq(#megaco_term_id{id = ?A5556},AD), + CmdReq = cre_CmdReq({auditValueRequest, Req}), + msg_request(Mid, 50007, ?megaco_null_context_id, [CmdReq]). + +%% IndAudMediaDescriptor: +msg51(Mid, IATSDorStream) -> + IAMD = cre_IndAudMediaDesc(IATSDorStream), + IAP = cre_IndAudParam(IAMD), + APT = [IAP], + msg50(Mid, APT). + +msg51a() -> + msg51a(?MG2_MID). +msg51a(Mid) -> + PP = cre_IndAudPropertyParm("tdmc/gain"), + PPs = [PP], + IATSD = cre_IndAudTermStateDesc(PPs), + msg51(Mid, IATSD). + +msg51b() -> + msg51b(?MG2_MID). +msg51b(Mid) -> + PP = cre_IndAudPropertyParm("nt/jit"), + PPs = [PP], + IATSD = cre_IndAudTermStateDesc(PPs), + msg51(Mid, IATSD). + +msg51c() -> + msg51c(?MG2_MID). +msg51c(Mid) -> + IATSD = cre_IndAudTermStateDesc([], asn1_NOVALUE, 'NULL'), + msg51(Mid, IATSD). + +msg51d() -> + msg51d(?MG2_MID). +msg51d(Mid) -> + IATSD = cre_IndAudTermStateDesc([], 'NULL', asn1_NOVALUE), + msg51(Mid, IATSD). + +msg51e() -> + msg51e(?MG2_MID). +msg51e(Mid) -> + IALCD = cre_IndAudLocalControlDesc('NULL', asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE), + IASP = cre_IndAudStreamParms(IALCD), + msg51(Mid, IASP). + +msg51f() -> + msg51f(?MG2_MID). +msg51f(Mid) -> + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, 'NULL', + asn1_NOVALUE, asn1_NOVALUE), + IASP = cre_IndAudStreamParms(IALCD), + msg51(Mid, IASP). + +msg51g() -> + msg51g(?MG2_MID). +msg51g(Mid) -> + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, asn1_NOVALUE, + 'NULL', asn1_NOVALUE), + IASP = cre_IndAudStreamParms(IALCD), + msg51(Mid, IASP). + +msg51h() -> + msg51h(?MG2_MID). +msg51h(Mid) -> + Name = "nt/jit", + IAPP = cre_IndAudPropertyParm(Name), + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, asn1_NOVALUE, + asn1_NOVALUE, [IAPP]), + IASP = cre_IndAudStreamParms(IALCD), + SID = 123, + IASD = cre_IndAudStreamDesc(SID, IASP), + msg51(Mid, [IASD]). + + +msg51i() -> + msg51i(?MG2_MID). +msg51i(Mid) -> + Name = "nt/jit", + Name2 = "tdmc/ec", + IAPP = cre_IndAudPropertyParm(Name), + IAPP2 = cre_IndAudPropertyParm(Name2), + IALCD = cre_IndAudLocalControlDesc('NULL', 'NULL', 'NULL', + [IAPP, IAPP2]), + IASP = cre_IndAudStreamParms(IALCD), + SID = 123, + IASD = cre_IndAudStreamDesc(SID, IASP), + msg51(Mid, [IASD]). + + +%% IndAudEventsDescriptor: +msg52() -> + msg52(?MG2_MID). +msg52(Mid) -> + RequestID = 1235, + PkgdName = "tonedet/std", + IAED = cre_IndAudEvsDesc(RequestID, PkgdName), + IAP = cre_IndAudParam(IAED), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudEventBufferDescriptor: +msg53() -> + msg53(?MG2_MID). +msg53(Mid) -> + EN = "tonedet/std", + SID = 1, + IAEBD = cre_IndAudEvBufDesc(EN, SID), + IAP = cre_IndAudParam(IAEBD), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudSignalsDescriptor: +msg54(Mid, Sig) -> + IASD = cre_IndAudSigsDesc(Sig), + IAP = cre_IndAudParam(IASD), + APT = [IAP], + msg50(Mid, APT). + +msg54a() -> + msg54a(?MG2_MID). +msg54a(Mid) -> + SN = "tonegen/pt", + Sig = cre_IndAudSig(SN), + msg54(Mid, Sig). + +msg54b() -> + msg54b(?MG2_MID). +msg54b(Mid) -> + SN = "dg/d0", + Sig = cre_IndAudSig(SN), + msg54(Mid, Sig). + +msg54c() -> + msg54c(?MG2_MID). +msg54c(Mid) -> + SN = "ct/ct", + Sig = cre_IndAudSig(SN), + ID = 4321, + SSL = cre_IndAudSeqSigList(ID, Sig), + msg54(Mid, SSL). + +%% IndAudDigitMapDescriptor: +msg55() -> + msg55(?MG2_MID). +msg55(Mid) -> + DMN = "dialplan00", + IADMD = cre_IndAudDigitMapDesc(DMN), + IAP = cre_IndAudParam(IADMD), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudStatisticsDescriptor: +msg56() -> + msg56(?MG2_MID). +msg56(Mid) -> + SN = "nt/dur", + IASD = cre_IndAudStatsDesc(SN), + IAP = cre_IndAudParam(IASD), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudPackagesDescriptor: +msg57() -> + msg57(?MG2_MID). +msg57(Mid) -> + PN = "al", + PV = 1, + IAPD = cre_IndAudPkgsDesc(PN, PV), + IAP = cre_IndAudParam(IAPD), + APT = [IAP], + msg50(Mid, APT). + +%% Sum it up: +msg58_iaMediaDesc_iap(IATSD) -> + IAMD = cre_IndAudMediaDesc(IATSD), + cre_IndAudParam(IAMD). + +msg58_iaMediaDesc_iap_a() -> + PP = cre_IndAudPropertyParm("tdmc/gain"), + PPs = [PP], + IATSD = cre_IndAudTermStateDesc(PPs), + msg58_iaMediaDesc_iap(IATSD). + +msg58_iaMediaDesc_iap_b() -> + IATSD = cre_IndAudTermStateDesc([], 'NULL', asn1_NOVALUE), + msg58_iaMediaDesc_iap(IATSD). + +msg58_iaEvsDesc_iap() -> + RequestID = 1235, + PkgdName = "tonedet/std", + IAED = cre_IndAudEvsDesc(RequestID, PkgdName), + cre_IndAudParam(IAED). + +msg58_iaEvBufDesc_iap() -> + EN = "tonedet/std", + SID = 1, + IAEBD = cre_IndAudEvBufDesc(EN, SID), + cre_IndAudParam(IAEBD). + +msg58_iaSigsDesc_iap(S) -> + IASD = cre_IndAudSigsDesc(S), + cre_IndAudParam(IASD). + +msg58_iaSigsDesc_iap_a() -> + SN = "tonegen/pt", + Sig = cre_IndAudSig(SN), + msg58_iaSigsDesc_iap(Sig). + +msg58_iaSigsDesc_iap_b() -> + SN = "ct/ct", + Sig = cre_IndAudSig(SN), + ID = 4321, + SSL = cre_IndAudSeqSigList(ID, Sig), + msg58_iaSigsDesc_iap(SSL). + +msg58_iaDigMapDesc_iap() -> + DMN = "dialplan00", + IADMD = cre_IndAudDigitMapDesc(DMN), + cre_IndAudParam(IADMD). + +msg58_iaStatsDesc_iap() -> + SN = "nt/dur", + IASD = cre_IndAudStatsDesc(SN), + cre_IndAudParam(IASD). + +msg58_iaPacksDesc_iap() -> + PN = "al", + PV = 1, + IAPD = cre_IndAudPkgsDesc(PN, PV), + cre_IndAudParam(IAPD). + +msg58a() -> + msg58a(?MG2_MID). +msg58a(Mid) -> + IAMD = msg58_iaMediaDesc_iap_a(), + IAED = msg58_iaEvsDesc_iap(), + IAEBD = msg58_iaEvBufDesc_iap(), + IASiD = msg58_iaSigsDesc_iap_a(), + IADMD = msg58_iaDigMapDesc_iap(), + IAStD = msg58_iaStatsDesc_iap(), + IAPD = msg58_iaPacksDesc_iap(), + APT = [IAMD, IAED, IAEBD, IASiD, IADMD, IAStD, IAPD], + msg50(Mid, APT). + +msg58b() -> + msg58b(?MG2_MID). +msg58b(Mid) -> + IAMD = msg58_iaMediaDesc_iap_b(), + IAED = msg58_iaEvsDesc_iap(), + IAEBD = msg58_iaEvBufDesc_iap(), + IASiD = msg58_iaSigsDesc_iap_b(), + IADMD = msg58_iaDigMapDesc_iap(), + IAStD = msg58_iaStatsDesc_iap(), + IAPD = msg58_iaPacksDesc_iap(), + APT = [IAMD, IAED, IAEBD, IASiD, IADMD, IAStD, IAPD], + msg50(Mid, APT). + + +%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +%% Tests some of the changes in the v2 corr 1 (EmergencyOff and ModemDesc) + +%% Emergency On/Off (optional) tests +msg61(EM) -> + TS = cre_TimeNot("19990729", "22000000"), + Event = cre_ObsEv("al/of",TS), + Desc = cre_ObsEvsDesc(2222,[Event]), + NotReq = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc), + Cmd = ?MSG_LIB:cre_Command(notifyReq, NotReq), + CmdReq = cre_CmdReq(Cmd), + CtxReq = ?MSG_LIB:cre_ContextRequest(15, EM), + ActReq = ?MSG_LIB:cre_ActionRequest(1, CtxReq, [CmdReq]), + Acts = [ActReq], + TR = ?MSG_LIB:cre_TransactionRequest(9898, Acts), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, ?MG1_MID, [Trans]), + ?MSG_LIB:cre_MegacoMessage(Mess). + +msg61a() -> + msg61(false). + +msg61b() -> + msg61(true). + +msg61c() -> + msg61(asn1_NOVALUE). + + +msg62a() -> + MT = ?MSG_LIB:cre_ModemType(v18), + PP = cre_PropParm("c", "IN IP4 $ "), + MD = ?MSG_LIB:cre_ModemDescriptor([MT], [PP]), + AmmDesc = ?MSG_LIB:cre_AmmDescriptor(MD), + TermIDs = [#megaco_term_id{id = ?A4444}], + AmmReq = ?MSG_LIB:cre_AmmRequest(TermIDs, [AmmDesc]), + Cmd = ?MSG_LIB:cre_Command(addReq, AmmReq), + CmdReq = ?MSG_LIB:cre_CommandRequest(Cmd), + ActReq = ?MSG_LIB:cre_ActionRequest(2, [CmdReq]), + Acts = [ActReq], + TR = ?MSG_LIB:cre_TransactionRequest(9898, Acts), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, ?MG1_MID, [Trans]), + ?MSG_LIB:cre_MegacoMessage(Mess). + +msg62b() -> + MP = +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 +Transaction = 9898 { + Context = 2 { + Add = 11111111/00000000/00000000 { + Modem[V18] { + tdmc/gain=2 + } + } + } +}", +% MC = +% "!/" ?VERSION_STR " [124.124.124.222]:55555\nT=9898{C=2{A=11111111/00000000/00000000{MD[V18]{tdmc/gain=2}}}}", + list_to_binary(MP). + +%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +%% Pretty RFC 3525 messages: + +%% Added Reason +rfc3525_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + +rfc3525_msg2() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +%% Removed "," after LocalControl ending "}" +rfc3525_msg3() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 9999 { + Context = - { + Modify = A4444 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive, + tdmc/gain=2, ; in dB, + tdmc/ec=on + } + } + }, + Events = 2222 { + al/of {strict=state} + } + } + } +}". + +%% Removed the outermost "{}" pair (before the Reply token) +rfc3525_msg4() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 9999 { + Context = - { + Modify = A4444 + } +}". + +rfc3525_msg6() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Transaction = 10000 { + Context = - { + Notify = A4444 { + ObservedEvents =2222 { + 19990729T22000000:al/of{init=false} + } + } + } +}". + + +rfc3525_msg7() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 10000 { + Context = - { + Notify = A4444 + } +}". + +rfc3525_msg8() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10001 { + Context = - { + Modify = A4444 { + Events = 2223 { + al/on {strict=state}, + dd/ce {DigitMap=Dialplan0} + }, + Signals {cg/dt}, + DigitMap = Dialplan0 { + (0| 00|[1-7]xxx|8xxxxxxx|fxxxxxxx|exx|91xxxxxxxxxx|9011x.) + } + } + } +}". + +rfc3525_msg9() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10001 { + Context = - { + Modify = A4444 + } +}". + +rfc3525_msg10() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Transaction = 10002 { + Context = - { + Notify = A4444 { + ObservedEvents =2223 { + 19990729T22010001:dd/ce { + ds=\"916135551212\", + Meth=UM + } + } + } + } +}". + + +rfc3525_msg11() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 10002 { + Context = - { + Notify = A4444 + } +}". + +%% Added ? +rfc3525_msg12() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10003 { + Context = $ { + Add = A4444, + Add = $ { + Media { + Stream = 1 { + LocalControl { + Mode = ReceiveOnly, + nt/jit=40 ; in ms + }, + Local { + v=0 c=IN IP4 $ m=audio $ RTP/AVP 4 a=ptime:30 v=0 c=IN IP4 $ m=audio $ RTP/AVP 0 + } + } + } + } + } +}". + +%% Added ? +rfc3525_msg13() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a=recvonly + } ; RTP profile for G.723.1 is 4 + } + } + } + } +}". + +%% +%% Added ? +rfc3525_msg14() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50003 { + Context = $ { + Add = A5555 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive + } + } + }, + Events = 1234 { + al/of {strict=state} + }, + Signals {al/ri} + }, + Add = $ { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive, + nt/jit=40 ; in ms + }, + Local { + v=0 c=IN IP4 $ m=audio $ RTP/AVP 4 a=ptime:30 + }, + Remote { + v=0 c=IN IP4 124.124.124.222 m=audio 2222 RTP/AVP 4 a=ptime:30 + } ; RTP profile for G.723.1 is 4 + } + } + } + } +}". + +%% Added ? +rfc3525_msg15() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50003 { + Context = 5000 { + Add = A5555, + Add = A5556 { + Media { + Stream = 1 { + Local { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 + } ; RTP profile for G723.1 is 4 + } + } + } + } +}". + +%% Added ? +rfc3525_msg16a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10005 { + Context = 2000 { + Modify = A4444 { + Signals {cg/rt} + }, + Modify = A4445 { + Media { + Stream = 1 { + Remote { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 + } ; RTP profile for G723.1 is 4 + } + } + } + } +}". + +rfc3525_msg16b() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10005 { + Context = 2000 { + Modify = A4444, + Modify = A4445 + } +}". + +rfc3525_msg17a() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Transaction = 50005 { + Context = 5000 { + Notify = A5555 { + ObservedEvents = 1234 { + 19990729T22020002:al/of{init=false} + } + } + } +}". + +rfc3525_msg17b() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 50005 { + Context = - { + Notify = A5555 + } +}". + +%% Removed "{ }" after Signals +rfc3525_msg17c() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50006 { + Context = 5000 { + Modify = A5555 { + Events = 1235 { + al/on{strict=state} + }, + Signals ; to turn off ringing + } + } +}". + +rfc3525_msg17d() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50006 { + Context = 5000 { + Modify = A4445 + } +}". + +%% Removed "{ }" after Signals +rfc3525_msg18a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10006 { + Context = 2000 { + Modify = A4445 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive + } + } + } + }, + Modify = A4444 { + Signals + } + } +}". + +rfc3525_msg18b() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10006 { + Context = 2000 { + Modify = A4445, + Modify = A4444 + } +}". + +rfc3525_msg19() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50007 { + Context = - { + AuditValue = A5556 { + Audit { + Media, DigitMap, Events, Signals, Packages, Statistics + } + } + } +}". + +%% Added ? +rfc3525_msg20() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50007 { + Context = - { + AuditValue = A5556 { + Media { + TerminationState { + ServiceStates = InService, + Buffer = OFF + }, + Stream = 1 { + LocalControl { + Mode = SendReceive, + nt/jit=40 + }, + Local { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 a=ptime:30 + }, + Remote { + v=0 o=- 2890844526 2890842807 IN IP4 124.124.124.222 s=- t= 0 0 c=IN IP4 124.124.124.222 m=audio 2222 RTP/AVP 4 a=ptime:30 + } + } + }, + Events, + Signals, + DigitMap, + Packages {nt-1, rtp-1}, + Statistics { + rtp/ps=1200, ; packets sent + nt/os=62300, ; octets sent + rtp/pr=700, ; packets received + nt/or=45100, ; octets received + rtp/pl=0.2, ; % packet loss + rtp/jit=20, + rtp/delay=40 ; avg latency + } + } + } +}". + +rfc3525_msg21a() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Transaction = 50008 { + Context = 5000 { + Notify = A5555 { + ObservedEvents =1235 { + 19990729T24020002:al/on {init=false} + } + } + } +}". + +rfc3525_msg21b() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 50008 { + Context = - { + Notify = A5555 + } +}". + +rfc3525_msg22a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50009 { + Context = 5000 { + Subtract = A5555 { + Audit { + Statistics + } + }, + Subtract = A5556 { + Audit { + Statistics + } + } + } +}". + +%% Added ? +rfc3525_msg22b() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50009 { + Context = 5000 { + Subtract = A5555 { + Statistics { + nt/os=45123, ; Octets Sent + nt/dur=40 ; in seconds + } + }, + Subtract = A5556 { + Statistics { + rtp/ps=1245, ; packets sent + nt/os=62345, ; octets sent + rtp/pr=780, ; packets received + nt/or=45123, ; octets received + rtp/pl=10, ; % packets lost + rtp/jit=27, + rtp/delay=48 ; average latency + } + } + } +}". + +rfc3525_msgs() -> + [ + {msg1, rfc3525_msg1()}, + {msg2, rfc3525_msg2()}, + {msg3, rfc3525_msg3()}, + {msg4, rfc3525_msg4()}, + {msg6, rfc3525_msg6()}, + {msg7, rfc3525_msg7()}, + {msg8, rfc3525_msg8()}, + {msg9, rfc3525_msg9()}, + {msg10, rfc3525_msg10()}, + {msg11, rfc3525_msg11()}, + {msg12, rfc3525_msg12()}, + {msg13, rfc3525_msg13()}, + {msg14, rfc3525_msg14()}, + {msg15, rfc3525_msg15()}, + {msg16a, rfc3525_msg16a()}, + {msg16b, rfc3525_msg16b()}, + {msg17a, rfc3525_msg17a()}, + {msg17b, rfc3525_msg17b()}, + {msg17c, rfc3525_msg17c()}, + {msg17d, rfc3525_msg17d()}, + {msg18a, rfc3525_msg18a()}, + {msg18b, rfc3525_msg18b()}, + {msg19, rfc3525_msg19()}, + {msg20, rfc3525_msg20()}, + {msg21a, rfc3525_msg21a()}, + {msg21b, rfc3525_msg21b()}, + {msg22a, rfc3525_msg22a()}, + {msg22b, rfc3525_msg22b()} + ]. + +rfc3525_msgs_display() -> + Msgs = rfc3525_msgs(), + Fun = fun({Name, Msg}) -> + io:format("~w: ~n~s~n~n", [Name, Msg]) + end, + lists:foreach(Fun, Msgs). + +rfc3525_msgs_test() -> + put(dbg,true), + Res = rfc3525_msgs_test(megaco_pretty_text_encoder, [], 2), + erase(dbg), + io:format("~w~n", [Res]). + +rfc3525_msgs_test(Codec, Config, Ver) -> + io:format("-----------------------------------------" + "~ntesting with" + "~n Codec: ~w" + "~n Config: ~w" + "~n Version: ~w" + "~n", [Codec, Config, Ver]), + Msgs = rfc3525_msgs(), + Test = fun({N,M1}) -> + %% io:format("testing ~w: ", [N]), + io:format("~n*** testing ~w *** ~n~s~n", [N,M1]), + Bin1 = erlang:list_to_binary(M1), + case (catch Codec:decode_message(Config, Ver, Bin1)) of + {ok, M2} -> + %% io:format("d", []), + io:format("decoded:~n~p~n", [M2]), + case (catch Codec:encode_message(Config, Ver, M2)) of + {ok, Bin2} when is_binary(Bin2) -> + %% io:format("e~n", []), + io:format("encode: ~n~s~n", [erlang:binary_to_list(Bin2)]), + {N,ok}; + {ok, M3} -> + %% io:format("e~n", []), + io:format("encode: ~n~s~n", [M3]), + {N,ok}; + E -> + io:format("~n~p~n", [E]), + {N,encode_error} + end; + E -> + io:format("~n~p~n", [E]), + {N,decode_error} + end + end, + [Test(M) || M <- Msgs]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +skip(Reason) -> + megaco_codec_test_lib:skip(Reason). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +decode_message(Codec, DynamicDecode, Conf, Bin) -> + megaco_codec_test_lib:decode_message(Codec, DynamicDecode, ?VERSION, + Conf, Bin). +encode_message(Codec, Conf, Msg) -> + megaco_codec_test_lib:encode_message(Codec, ?VERSION, Conf, Msg). + +test_msgs(Codec, DynamicDecode, Conf, Msgs) -> + megaco_codec_test_lib:test_msgs(Codec, DynamicDecode, ?VERSION, Conf, + fun chk_MegacoMessage/2, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +decode_mini_message(Codec, Conf, Bin) -> + Codec:decode_mini_message(Conf, dynamic, Bin). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +chk_MegacoMessage(M1, M2) -> + ?MSG_LIB:chk_MegacoMessage(M1, M2). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +cre_MegacoMessage(Mess) -> + ?MSG_LIB:cre_MegacoMessage(Mess). + +cre_MegacoMessage(V, Mid, Body) -> + Mess = ?MSG_LIB:cre_Message(V, Mid, Body), + ?MSG_LIB:cre_MegacoMessage(Mess). + +cre_AuthHeader() -> + SecParmIdx = [239, 205, 171, 137], + SeqNum = [18, 52, 86, 120], + AD = [18, 52, 86, 120, 137, 171, 205, 239, 118, 84, 50, 16], + cre_AuthHeader(SecParmIdx, SeqNum, AD). + +cre_Msg(Mid, Body) -> + cre_Msg(?VERSION, Mid, Body). + +cre_Msg(V, Mid, Body) -> + ?MSG_LIB:cre_Message(V, Mid, Body). + +cre_AuthHeader(Idx, Num, D) -> + ?MSG_LIB:cre_AuthenticationHeader(Idx, Num, D). + +cre_TransId(TransId) -> + ?MSG_LIB:cre_TransactionId(TransId). + +cre_Trans(Trans) -> + ?MSG_LIB:cre_Transaction(Trans). + +cre_TransReq(TransId, Actions) -> + ?MSG_LIB:cre_TransactionRequest(TransId, Actions). + +cre_TransRep(TransId, Actions) -> + ?MSG_LIB:cre_TransactionReply(TransId, Actions). + +cre_TransAck(First, Last) -> + ?MSG_LIB:cre_TransactionAck(First, Last). + +cre_ActReq(CtxId, CmdReqs) -> + ?MSG_LIB:cre_ActionRequest(CtxId, CmdReqs). + +cre_ActRep(CtxId, CmdReply) -> + ?MSG_LIB:cre_ActionReply(CtxId, CmdReply). + +cre_CtxID(Id) -> + ?MSG_LIB:cre_ContextID(Id). + +%% Ind Aud related: + +cre_IndAudParam(IAP) -> + ?MSG_LIB:cre_IndAuditParameter(IAP). + +cre_IndAudMediaDesc(D) -> + ?MSG_LIB:cre_IndAudMediaDescriptor(D). + +cre_IndAudStreamDesc(SID, SP) -> + ?MSG_LIB:cre_IndAudStreamDescriptor(SID, SP). + +cre_IndAudStreamParms(LCD) -> + ?MSG_LIB:cre_IndAudStreamParms(LCD). + +cre_IndAudLocalControlDesc(SM, RV, RG, PP) -> + ?MSG_LIB:cre_IndAudLocalControlDescriptor(SM, RV, RG, PP). + +cre_IndAudPropertyParm(Name) -> + ?MSG_LIB:cre_IndAudPropertyParm(Name). + +cre_IndAudTermStateDesc(PP) -> + ?MSG_LIB:cre_IndAudTerminationStateDescriptor(PP). + +cre_IndAudTermStateDesc(PP, EBC, SS) -> + ?MSG_LIB:cre_IndAudTerminationStateDescriptor(PP, EBC, SS). + +cre_IndAudEvsDesc(RID, PN) + when is_integer(RID) -> + ?MSG_LIB:cre_IndAudEventsDescriptor(RID, PN). + +cre_IndAudEvBufDesc(EN, SID) -> + ?MSG_LIB:cre_IndAudEventBufferDescriptor(EN, SID). + +cre_IndAudSigsDesc(D) -> + ?MSG_LIB:cre_IndAudSignalsDescriptor(D). + +cre_IndAudSig(SN) -> + ?MSG_LIB:cre_IndAudSignal(SN). + +cre_IndAudSeqSigList(ID, SL) -> + ?MSG_LIB:cre_IndAudSeqSigList(ID, SL). + +cre_IndAudDigitMapDesc(DMN) -> + ?MSG_LIB:cre_IndAudDigitMapDescriptor(DMN). + +cre_IndAudStatsDesc(SN) -> + ?MSG_LIB:cre_IndAudStatisticsDescriptor(SN). + +cre_IndAudPkgsDesc(PN, PV) -> + ?MSG_LIB:cre_IndAudPackagesDescriptor(PN, PV). + +%% Parameter related +cre_PropParm(Name, Val) -> + ?MSG_LIB:cre_PropertyParm(Name, [Val]). + + +%% Statistics related +cre_StatsParm(Name, Val) -> + ?MSG_LIB:cre_StatisticsParameter(Name, [Val]). + + +% Event related +cre_EvParm(Name, Val) -> + ?MSG_LIB:cre_EventParameter(Name, Val). + +cre_ObsEv(Name, Not) -> + ?MSG_LIB:cre_ObservedEvent(Name, Not). +cre_ObsEv(Name, Not, Par) -> + ?MSG_LIB:cre_ObservedEvent(Name, Par, Not). + +cre_ReqedEv(Name) -> + ?MSG_LIB:cre_RequestedEvent(Name). +cre_ReqedEv(Name, Action) -> + ?MSG_LIB:cre_RequestedEvent(Name, Action). + + +cre_ObsEvsDesc(Id, EvList) -> + ?MSG_LIB:cre_ObservedEventsDescriptor(Id, EvList). + +cre_EvsDesc(Id, EvList) -> + ?MSG_LIB:cre_EventsDescriptor(Id, EvList). + + +%% Service change related +cre_SvcChParm(M, A, R, P) -> + ?MSG_LIB:cre_ServiceChangeParm(M, A, P, R). + +cre_SvcChResParm(A, P) -> + ?MSG_LIB:cre_ServiceChangeResParm(A, P). + +cre_SvcChReq(Tids, P) -> + ?MSG_LIB:cre_ServiceChangeRequest(Tids, P). + +cre_SvcChProf(Name, Ver) -> + ?MSG_LIB:cre_ServiceChangeProfile(Name, Ver). + +cre_SvcChRep(Tids, Res) -> + ?MSG_LIB:cre_ServiceChangeReply(Tids, Res). + + +%% Stream related +cre_StreamParms(Lcd) -> + ?MSG_LIB:cre_StreamParms(Lcd). +cre_StreamParms(Lcd, Ld) -> + ?MSG_LIB:cre_StreamParms(Lcd, Ld). +cre_StreamParms(Lcd, Ld, Rd) -> + ?MSG_LIB:cre_StreamParms(Lcd, Ld, Rd). +cre_StreamParmsL(Ld) -> + ?MSG_LIB:cre_StreamParms(asn1_NOVALUE, Ld, asn1_NOVALUE). +cre_StreamParmsR(Rd) -> + ?MSG_LIB:cre_StreamParms(asn1_NOVALUE, asn1_NOVALUE, Rd). + +cre_StreamDesc(Id, P) -> + ?MSG_LIB:cre_StreamDescriptor(Id, P). + + +%% "Local" related +cre_LocalControlDesc(Mode) -> + ?MSG_LIB:cre_LocalControlDescriptor(Mode). +cre_LocalControlDesc(Mode, Parms) -> + ?MSG_LIB:cre_LocalControlDescriptor(Mode, Parms). + +cre_LocalRemoteDesc(Grps) -> + ?MSG_LIB:cre_LocalRemoteDescriptor(Grps). + + +%% DigitMap related +cre_DigitMapDesc() -> + ?MSG_LIB:cre_DigitMapDescriptor(). +cre_DigitMapDesc(NameOrVal) -> + ?MSG_LIB:cre_DigitMapDescriptor(NameOrVal). +cre_DigitMapDesc(Name, Val) -> + ?MSG_LIB:cre_DigitMapDescriptor(Name, Val). + +cre_DigitMapValue(Body) -> + ?MSG_LIB:cre_DigitMapValue(Body). + +cre_DigitMapValue(Body, Start, Short, Long) -> + ?MSG_LIB:cre_DigitMapValue(Start, Short, Long, Body). + +%% Media related +cre_MediaDesc(SD) when is_record(SD, 'StreamDescriptor') -> + cre_MediaDesc([SD]); +cre_MediaDesc(SDs) -> + ?MSG_LIB:cre_MediaDescriptor(SDs). + + +%% Notify related +cre_NotifyReq(Tids, EvsDesc) -> + ?MSG_LIB:cre_NotifyRequest(Tids, EvsDesc). + +cre_NotifyRep(Tids) -> + ?MSG_LIB:cre_NotifyReply(Tids). + + +%% Subtract related +cre_SubReq(Tids, Desc) -> + ?MSG_LIB:cre_SubtractRequest(Tids, Desc). + + +%% Audit related +cre_AuditDesc(Tokens) -> + ?MSG_LIB:cre_AuditDescriptor(Tokens). + +cre_AuditDesc(Tokens, PropertTokens) -> + ?MSG_LIB:cre_AuditDescriptor(Tokens, PropertTokens). + +cre_AuditReq(Tid, Desc) -> + ?MSG_LIB:cre_AuditRequest(Tid, Desc). + +cre_AuditRes(Tid, Res) -> + ?MSG_LIB:cre_AuditResult(Tid, Res). + + +%% AMM/AMMS related +cre_AmmReq(Tids, Descs) -> + ?MSG_LIB:cre_AmmRequest(Tids, Descs). + +cre_AmmsReply(Tids) -> + ?MSG_LIB:cre_AmmsReply(Tids). +cre_AmmsReply(Tids, Descs) -> + ?MSG_LIB:cre_AmmsReply(Tids, Descs). + + +%% Command related +%% cre_command(Tag, Req) -> +%% ?MSG_LIB:cre_Command(Tag, Req). + +cre_CmdReq(Cmd) -> + ?MSG_LIB:cre_CommandRequest(Cmd). + + +%% Actions related +cre_ReqedActs(DmName) -> + EDM = ?MSG_LIB:cre_EventDM(DmName), + ?MSG_LIB:cre_RequestedActions(EDM). + + +%% Signal related +cre_Sig(Name) -> + ?MSG_LIB:cre_Signal(Name). + + +%% Others +cre_TimeNot(D,T) -> + ?MSG_LIB:cre_TimeNotation(D, T). + +cre_PkgsItem(Name, Ver) -> + ?MSG_LIB:cre_PackagesItem(Name, Ver). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_init(Config) -> + megaco_codec_flex_lib:init(Config). + +flex_finish(Config) -> + megaco_codec_flex_lib:finish(Config). + +flex_scanner_conf(Config) -> + megaco_codec_flex_lib:scanner_conf(Config). + +start_flex_scanner() -> + megaco_codec_flex_lib:start(). + +stop_flex_scanner(Pid) -> + megaco_codec_flex_lib:stop(Pid). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +t(F,A) -> + p(printable(get(severity),trc),trc,F,A). + +d(F,A) -> + p(printable(get(severity),dbg),dbg,F,A). + +l(F,A) -> + p(printable(get(severity),log),log,F,A). + +e(F,A) -> + p(printable(get(severity),err),err,F,A). + + +printable(trc,_) -> + true; +printable(dbg,trc) -> + false; +printable(dbg,_) -> + true; +printable(log,log) -> + true; +printable(log,err) -> + true; +printable(err,err) -> + true; +printable(_,_) -> + false. + + +p(true,L,F,A) -> + io:format("~s: " ++ F ++ "~n", [image_of(L)|A]); +p(_,_,_,_) -> + ok. + +image_of(trc) -> + "T"; +image_of(dbg) -> + "D"; +image_of(log) -> + "L"; +image_of(err) -> + "E"; +image_of(L) -> + io_lib:format("~p",[L]). + + diff --git a/lib/megaco/test/megaco_codec_v3_test.erl b/lib/megaco/test/megaco_codec_v3_test.erl new file mode 100644 index 0000000000..f49c3a677a --- /dev/null +++ b/lib/megaco/test/megaco_codec_v3_test.erl @@ -0,0 +1,8479 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test encoding/decoding (codec) module of Megaco/H.248 +%%---------------------------------------------------------------------- + +-module(megaco_codec_v3_test). + +%% ---- + +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v3.hrl"). +-include("megaco_test_lib.hrl"). + +%% ---- + +-export([msgs/0]). +-export([rfc3525_msgs_display/0, rfc3525_msgs_test/0]). + +-export([t/0, t/1]). + +-export([all/1, + + text/1, + + pretty/1, + pretty_test_msgs/1, + + compact/1, + compact_test_msgs/1, + + flex_pretty/1, + flex_pretty_init/1, + flex_pretty_finish/1, + flex_pretty_test_msgs/1, + + flex_compact/1, + flex_compact_init/1, + flex_compact_finish/1, + flex_compact_test_msgs/1, + + flex_compact_dm_timers1/1, + flex_compact_dm_timers2/1, + flex_compact_dm_timers3/1, + flex_compact_dm_timers4/1, + flex_compact_dm_timers5/1, + flex_compact_dm_timers6/1, + flex_compact_dm_timers7/1, + flex_compact_dm_timers8/1, + + binary/1, + + bin/1, + bin_test_msgs/1, + + ber/1, + ber_test_msgs/1, + + ber_bin/1, + ber_bin_test_msgs/1, + + per/1, + per_test_msgs/1, + + per_bin/1, + per_bin_test_msgs/1, + + erl_dist/1, + erl_dist_m/1, + erl_dist_m_test_msgs/1, + + tickets/0, + tickets/1, + + compact_tickets/1, + compact_otp4011_msg1/1, + compact_otp4011_msg2/1, + compact_otp4011_msg3/1, + compact_otp4013_msg1/1, + compact_otp4085_msg1/1, + compact_otp4085_msg2/1, + compact_otp4280_msg1/1, + compact_otp4299_msg1/1, + compact_otp4359_msg1/1, + compact_otp4920_msg0/1, + compact_otp4920_msg1/1, + compact_otp4920_msg2/1, + compact_otp4920_msg3/1, + compact_otp4920_msg4/1, + compact_otp4920_msg5/1, + compact_otp4920_msg6/1, + compact_otp4920_msg7/1, + compact_otp4920_msg8/1, + compact_otp4920_msg9/1, + compact_otp4920_msg10/1, + compact_otp4920_msg11/1, + compact_otp4920_msg12/1, + compact_otp4920_msg20/1, + compact_otp4920_msg21/1, + compact_otp4920_msg22/1, + compact_otp4920_msg23/1, + compact_otp4920_msg24/1, + compact_otp4920_msg25/1, + compact_otp5186_msg01/1, + compact_otp5186_msg02/1, + compact_otp5186_msg03/1, + compact_otp5186_msg04/1, + compact_otp5186_msg05/1, + compact_otp5186_msg06/1, + compact_otp5793_msg01/1, + compact_otp5836_msg01/1, + compact_otp5993_msg01/1, + compact_otp5993_msg02/1, + compact_otp5993_msg03/1, + compact_otp6017_msg01/1, + compact_otp6017_msg02/1, + compact_otp6017_msg03/1, + + flex_compact_tickets/1, + flex_compact_otp4299_msg1/1, + flex_compact_otp7431_msg01/1, + flex_compact_otp7431_msg02/1, + flex_compact_otp7431_msg03/1, + flex_compact_otp7431_msg04/1, + flex_compact_otp7431_msg05/1, + flex_compact_otp7431_msg06/1, + flex_compact_otp7431_msg07/1, + + + pretty_tickets/1, + pretty_otp4632_msg1/1, + pretty_otp4632_msg2/1, + pretty_otp4632_msg3/1, + pretty_otp4632_msg4/1, + pretty_otp4710_msg1/1, + pretty_otp4710_msg2/1, + pretty_otp4945_msg1/1, + pretty_otp4945_msg2/1, + pretty_otp4945_msg3/1, + pretty_otp4945_msg4/1, + pretty_otp4945_msg5/1, + pretty_otp4945_msg6/1, + pretty_otp4949_msg1/1, + pretty_otp4949_msg2/1, + pretty_otp4949_msg3/1, + pretty_otp5042_msg1/1, + pretty_otp5068_msg1/1, + pretty_otp5085_msg1/1, + pretty_otp5085_msg2/1, + pretty_otp5085_msg3/1, + pretty_otp5085_msg4/1, + pretty_otp5085_msg5/1, + pretty_otp5085_msg6/1, + pretty_otp5085_msg7/1, + pretty_otp5085_msg8/1, + pretty_otp5600_msg1/1, + pretty_otp5600_msg2/1, + pretty_otp5601_msg1/1, + pretty_otp5793_msg01/1, + pretty_otp5803_msg01/1, + pretty_otp5803_msg02/1, + pretty_otp5805_msg01/1, + pretty_otp5836_msg01/1, + pretty_otp5882_msg01/1, + pretty_otp6490_msg01/1, + pretty_otp6490_msg02/1, + pretty_otp6490_msg03/1, + pretty_otp6490_msg04/1, + pretty_otp6490_msg05/1, + pretty_otp6490_msg06/1, + pretty_otp7671_msg01/1, + pretty_otp7671_msg02/1, + pretty_otp7671_msg03/1, + pretty_otp7671_msg04/1, + pretty_otp7671_msg05/1, + pretty_otp8114_msg01/1, + + flex_pretty_tickets/1, + flex_pretty_otp5042_msg1/1, + flex_pretty_otp5085_msg1/1, + flex_pretty_otp5085_msg2/1, + flex_pretty_otp5085_msg3/1, + flex_pretty_otp5085_msg4/1, + flex_pretty_otp5085_msg5/1, + flex_pretty_otp5085_msg6/1, + flex_pretty_otp5085_msg7/1, + flex_pretty_otp5085_msg8/1, + flex_pretty_otp5600_msg1/1, + flex_pretty_otp5600_msg2/1, + flex_pretty_otp5601_msg1/1, + flex_pretty_otp5793_msg01/1, + flex_pretty_otp5803_msg01/1, + flex_pretty_otp5803_msg02/1, + flex_pretty_otp5805_msg01/1, + flex_pretty_otp5836_msg01/1, + flex_pretty_otp7431_msg01/1, + flex_pretty_otp7431_msg02/1, + flex_pretty_otp7431_msg03/1, + flex_pretty_otp7431_msg04/1, + flex_pretty_otp7431_msg05/1, + flex_pretty_otp7431_msg06/1, + flex_pretty_otp7431_msg07/1, + + init_per_testcase/2, fin_per_testcase/2]). + +-export([display_text_messages/0, generate_text_messages/0]). + + +%% ---- + +-define(V3, v3). +-define(EC_V3, {version3,?V3}). +-define(EC, [?EC_V3]). + +-define(VERSION, 3). +-define(VERSION_STR, "3"). +-define(MSG_LIB, megaco_test_msg_v3_lib). +-define(DEFAULT_PORT, 55555). +-define(MG1_MID_NO_PORT, {ip4Address, + #'IP4Address'{address = [124, 124, 124, 222]}}). +-define(MG1_MID, {ip4Address, #'IP4Address'{address = [124, 124, 124, 222], + portNumber = ?DEFAULT_PORT}}). +-define(MG2_MID, {ip4Address, #'IP4Address'{address = [125, 125, 125, 111], + portNumber = ?DEFAULT_PORT}}). +-define(MG3_MID, {ip4Address, #'IP4Address'{address = [125, 124, 123, 122], + portNumber = ?DEFAULT_PORT}}). +-define(MGC_MID, {ip4Address, #'IP4Address'{address = [123, 123, 123, 4], + portNumber = ?DEFAULT_PORT}}). + +-define(A4444, ["11111111", "00000000", "00000000"]). +-define(A4445, ["11111111", "00000000", "11111111"]). +-define(A5555, ["11111111", "11111111", "00000000"]). +-define(A5556, ["11111111", "11111111", "11111111"]). + + +%% ---- + +display_text_messages() -> + Msgs = + msgs7(text) ++ + msgs8(text), + megaco_codec_test_lib:display_text_messages(?VERSION, ?EC, Msgs). + + +generate_text_messages() -> + Msgs = + msgs7(text) ++ + msgs8(text), + megaco_codec_test_lib:generate_text_messages(?V3, ?VERSION, ?EC, Msgs). + + +%% ---- + + +expand(RootCase) -> + expand([RootCase], []). + +expand([], Acc) -> + lists:flatten(lists:reverse(Acc)); +expand([Case|Cases], Acc) -> + case (catch apply(?MODULE,Case,[suite])) of + [] -> + expand(Cases, [Case|Acc]); + C when is_list(C) -> + expand(Cases, [expand(C, [])|Acc]); + _ -> + expand(Cases, [Case|Acc]) + end. + + +%% ---- + +tickets() -> + Flag = process_flag(trap_exit, true), + Cases = expand(tickets), + Fun = fun(Case) -> + C = init_per_testcase(Case, [{tc_timeout, + timer:minutes(10)}]), + io:format("Eval ~w~n", [Case]), + Result = + case (catch apply(?MODULE, Case, [C])) of + {'EXIT', Reason} -> + io:format("~n~p exited:~n ~p~n", + [Case, Reason]), + {error, {Case, Reason}}; + Res -> + Res + end, + fin_per_testcase(Case, C), + Result + end, + process_flag(trap_exit, Flag), + lists:map(Fun, Cases). + + +%% ---- + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + +init_per_testcase(Case, Config) -> + %% CaseString = io_lib:format("~p", [Case]), + C = + case lists:suffix("time_test", atom_to_list(Case)) of + true -> + [{tc_timeout, timer:minutes(10)}|Config]; + false -> + put(verbosity,trc), + Config + end, + megaco_test_lib:init_per_testcase(Case, C). + +fin_per_testcase(Case, Config) -> + erase(verbosity), + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top test case + +all(suite) -> + [ + text, + binary, + erl_dist, + tickets + ]. + +text(suite) -> + [ + pretty, + flex_pretty, + compact, + flex_compact + ]. + +binary(suite) -> + [ + bin, + ber, + ber_bin, + per, + per_bin + ]. + +erl_dist(suite) -> + [ + erl_dist_m + ]. + +pretty(suite) -> + [ + pretty_test_msgs + ]. + + +compact(suite) -> + [ + compact_test_msgs + ]. + + +flex_pretty(suite) -> + {req, [], + {conf, flex_pretty_init, flex_pretty_cases(), flex_pretty_finish}}. + +flex_pretty_cases() -> + [ + flex_pretty_test_msgs + ]. + +flex_compact(suite) -> + {req, [], + {conf, flex_compact_init, flex_compact_cases(), flex_compact_finish}}. + +flex_compact_cases() -> + [ + flex_compact_test_msgs, + flex_compact_dm_timers1, + flex_compact_dm_timers2, + flex_compact_dm_timers3, + flex_compact_dm_timers4, + flex_compact_dm_timers5, + flex_compact_dm_timers6, + flex_compact_dm_timers7, + flex_compact_dm_timers8 + ]. + + +bin(suite) -> + [ + bin_test_msgs + ]. + + +ber(suite) -> + [ + ber_test_msgs + ]. + + +ber_bin(suite) -> + [ + ber_bin_test_msgs + ]. + + +per(suite) -> + [ + per_test_msgs + ]. + + +%% Support for per_bin was added to ASN.1 as of version +%% 1.3.2 (R8). And later merged into 1.3.1.3 (R7). These +%% releases are identical (as far as I know). +%% +per_bin(suite) -> + [ + per_bin_test_msgs + ]. + + +erl_dist_m(suite) -> + [ + erl_dist_m_test_msgs + ]. + +tickets(suite) -> + [ + compact_tickets, + flex_compact_tickets, + pretty_tickets, + flex_pretty_tickets + ]. + + +compact_tickets(suite) -> + [ + compact_otp4011_msg1, + compact_otp4011_msg2, + compact_otp4011_msg3, + compact_otp4013_msg1, + compact_otp4085_msg1, + compact_otp4085_msg2, + compact_otp4280_msg1, + compact_otp4299_msg1, + compact_otp4359_msg1, + compact_otp4920_msg0, + compact_otp4920_msg1, + compact_otp4920_msg2, + compact_otp4920_msg3, + compact_otp4920_msg4, + compact_otp4920_msg5, + compact_otp4920_msg6, + compact_otp4920_msg7, + compact_otp4920_msg8, + compact_otp4920_msg9, + compact_otp4920_msg10, + compact_otp4920_msg11, + compact_otp4920_msg12, + compact_otp4920_msg20, + compact_otp4920_msg21, + compact_otp4920_msg22, + compact_otp4920_msg23, + compact_otp4920_msg24, + compact_otp4920_msg25, + compact_otp5186_msg01, + compact_otp5186_msg02, + compact_otp5186_msg03, + compact_otp5186_msg04, + compact_otp5186_msg05, + compact_otp5186_msg06, + compact_otp5793_msg01, + compact_otp5836_msg01, + compact_otp5993_msg01, + compact_otp5993_msg02, + compact_otp5993_msg03, + compact_otp6017_msg01, + compact_otp6017_msg02, + compact_otp6017_msg03 + ]. + + +flex_compact_tickets(suite) -> + {req, [], + {conf, flex_compact_init, flex_compact_tickets_cases(), + flex_compact_finish}}. + +flex_compact_tickets_cases() -> + [ + flex_compact_otp4299_msg1, + flex_compact_otp7431_msg01, + flex_compact_otp7431_msg02, + flex_compact_otp7431_msg03, + flex_compact_otp7431_msg04, + flex_compact_otp7431_msg05, + flex_compact_otp7431_msg06, + flex_compact_otp7431_msg07 + ]. + + +pretty_tickets(suite) -> + [ + pretty_otp4632_msg1, + pretty_otp4632_msg2, + pretty_otp4632_msg3, + pretty_otp4632_msg4, + pretty_otp4710_msg1, + pretty_otp4710_msg2, + pretty_otp4945_msg1, + pretty_otp4945_msg2, + pretty_otp4945_msg3, + pretty_otp4945_msg4, + pretty_otp4945_msg5, + pretty_otp4945_msg6, + pretty_otp4949_msg1, + pretty_otp4949_msg2, + pretty_otp4949_msg3, + pretty_otp5042_msg1, + pretty_otp5068_msg1, + pretty_otp5085_msg1, + pretty_otp5085_msg2, + pretty_otp5085_msg3, + pretty_otp5085_msg4, + pretty_otp5085_msg5, + pretty_otp5085_msg6, + pretty_otp5085_msg7, + pretty_otp5085_msg8, + pretty_otp5600_msg1, + pretty_otp5600_msg2, + pretty_otp5601_msg1, + pretty_otp5793_msg01, + pretty_otp5803_msg01, + pretty_otp5803_msg02, + pretty_otp5805_msg01, + pretty_otp5836_msg01, + pretty_otp5882_msg01, + pretty_otp6490_msg01, + pretty_otp6490_msg02, + pretty_otp6490_msg03, + pretty_otp6490_msg04, + pretty_otp6490_msg05, + pretty_otp6490_msg06, + pretty_otp7671_msg01, + pretty_otp7671_msg02, + pretty_otp7671_msg03, + pretty_otp7671_msg04, + pretty_otp7671_msg05, + pretty_otp8114_msg01 + ]. + + +flex_pretty_tickets(suite) -> + {req, [], + {conf, flex_pretty_init, flex_pretty_tickets_cases(), + flex_pretty_finish}}. + +flex_pretty_tickets_cases() -> + [ + flex_pretty_otp5042_msg1, + flex_pretty_otp5085_msg1, + flex_pretty_otp5085_msg2, + flex_pretty_otp5085_msg3, + flex_pretty_otp5085_msg4, + flex_pretty_otp5085_msg5, + flex_pretty_otp5085_msg6, + flex_pretty_otp5085_msg7, + flex_pretty_otp5085_msg8, + flex_pretty_otp5600_msg1, + flex_pretty_otp5600_msg2, + flex_pretty_otp5601_msg1, + flex_pretty_otp5793_msg01, + flex_pretty_otp5803_msg01, + flex_pretty_otp5803_msg02, + flex_pretty_otp5805_msg01, + flex_pretty_otp5836_msg01, + flex_pretty_otp7431_msg01, + flex_pretty_otp7431_msg02, + flex_pretty_otp7431_msg03, + flex_pretty_otp7431_msg04, + flex_pretty_otp7431_msg05, + flex_pretty_otp7431_msg06, + flex_pretty_otp7431_msg07 + ]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +pretty_test_msgs(suite) -> + []; +pretty_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(text) ++ + msgs1b(text) ++ + msgs3525(text) ++ + msgs5(text) ++ + msgs6(text) ++ + msgs7(text) ++ + msgs8(text), + %% Msgs = msgs1a(text), + %% Msgs = msgs1b(text), + %% Msgs = msgs35525(text), + %% Msgs = msgs5(text), + %% Msgs = msgs6(text), + %% Msgs = msgs7(text), + DynamicDecode = false, + test_msgs(megaco_pretty_text_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_pretty_init(Config) -> + flex_init(Config). + +flex_pretty_finish(Config) -> + flex_finish(Config). + + +flex_pretty_test_msgs(suite) -> + []; +flex_pretty_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(text) ++ + msgs1b(text) ++ + msgs3525(text) ++ + msgs5(text) ++ + msgs6(text) ++ + msgs7(text) ++ + msgs8(text), + Conf = flex_scanner_conf(Config), + DynamicDecode = false, + test_msgs(megaco_pretty_text_encoder, DynamicDecode, [?EC_V3,Conf], Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +compact_test_msgs(suite) -> + []; +compact_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(text) ++ + msgs1b(text) ++ + msgs3525(text) ++ + msgs5(text) ++ + msgs6(text) ++ + msgs7(text) ++ + msgs8(text), + %% Msgs = msgs7(text), + DynamicDecode = false, + test_msgs(megaco_compact_text_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_compact_init(Config) -> + flex_init(Config). + +flex_compact_finish(Config) -> + flex_finish(Config). + + +flex_compact_test_msgs(suite) -> + []; +flex_compact_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(text) ++ + msgs1b(text) ++ + msgs3525(text) ++ + msgs5(text) ++ + msgs6(text) ++ + msgs7(text) ++ + msgs8(text), + Conf = flex_scanner_conf(Config), + DynamicDecode = true, + test_msgs(megaco_compact_text_encoder, DynamicDecode, [?EC_V3,Conf], Msgs). + + +flex_compact_dm_timers1(suite) -> + []; +flex_compact_dm_timers1(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("1", "2", "3"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers1 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({1,2,3}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers2(suite) -> + []; +flex_compact_dm_timers2(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("02", "03", "04"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers2 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({2,3,4}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers3(suite) -> + []; +flex_compact_dm_timers3(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("1", "02", "31"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers3 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({1,2,31}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers4(suite) -> + []; +flex_compact_dm_timers4(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("10", "21", "99"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers4 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({10,21,99}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers5(suite) -> + []; +flex_compact_dm_timers5(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("99", "23", "11"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers5 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({99,23,11}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers6(suite) -> + []; +flex_compact_dm_timers6(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("77", "09", "1"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers6 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({77,9,1}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers7(suite) -> + []; +flex_compact_dm_timers7(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("77", "09", "1", "99"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers7 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({77,9,1,99}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +flex_compact_dm_timers8(suite) -> + []; +flex_compact_dm_timers8(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + M = build_dm_timers_message("01", "09", "01", "02"), + B = list_to_binary(M), + Conf = flex_scanner_conf(Config), + case decode_message(megaco_compact_text_encoder, false, + [?EC_V3,Conf], B) of + {ok, M1} when is_record(M1,'MegacoMessage') -> + t("flex_compact_dm_timers8 -> " + "~n M: ~s" + "~n M1: ~p", [M, M1]), + verify_dm_timers({1,9,1,2}, M1); + Else -> + exit({decode_failed, M, Else}) + end. + + +build_dm_timers_message(T, S, L) -> + TMRs = lists:flatten(io_lib:format("T:~s,S:~s,L:~s", [T, S, L])), + build_dm_timers_message(TMRs). + +build_dm_timers_message(T, S, L, Z) -> + TMRs = lists:flatten(io_lib:format("T:~s,S:~s,L:~s,Z:~s", [T, S, L,Z])), + build_dm_timers_message(TMRs). + +build_dm_timers_message(TMRs) -> + M = io_lib:format("!/" ?VERSION_STR " [123.123.123.4]:55555\nT=10001{C=-{MF=11111111/00000000/00000000{E=2223{al/on,dd/ce{DM=dialplan00}},SG{cg/rt},DM=dialplan00{~s,(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)}}}}", [TMRs]), + lists:flatten(M). + + +verify_dm_timers(TMRs, #'MegacoMessage'{mess = Mess}) -> + #'Message'{messageBody = Body} = Mess, + case get_dm_timers(Body) of + TMRs -> + ok; + {error, Reason} -> + exit({invalid_timer, {TMRs, Reason}}); + TMRs1 -> + exit({invalid_timer_values, {TMRs, TMRs1}}) + end. + +get_dm_timers({transactions, T}) when is_list(T) -> + get_dm_timers1(T); +get_dm_timers(Other) -> + {error, {invalid_transactions, Other}}. + +get_dm_timers1([{transactionRequest,T}|Ts]) + when is_record(T,'TransactionRequest') -> + case get_dm_timers2(T) of + {ok, Timers} -> + Timers; + _ -> + get_dm_timers1(Ts) + end; +get_dm_timers1([_|Ts]) -> + get_dm_timers1(Ts); +get_dm_timers1([]) -> + {error, {no_timers, 'TransactionRequest'}}. + + +get_dm_timers2(#'TransactionRequest'{actions = Actions}) when is_list(Actions) -> + get_dm_timers3(Actions). + + +get_dm_timers3([#'ActionRequest'{commandRequests = Cmds}|Ars]) when is_list(Cmds) -> + case get_dm_timers4(Cmds) of + {ok, Timers} -> + {ok, Timers}; + _ -> + get_dm_timers3(Ars) + end; +get_dm_timers3([_|Ars]) -> + get_dm_timers3(Ars); +get_dm_timers3([]) -> + {error, {no_timers, 'ActionRequest'}}. + +get_dm_timers4([#'CommandRequest'{command = Cmd}|Cmds]) -> + case get_dm_timers5(Cmd) of + {ok, Timers} -> + {ok, Timers}; + _ -> + get_dm_timers4(Cmds) + end; +get_dm_timers4([_|Cmds]) -> + get_dm_timers4(Cmds); +get_dm_timers4([]) -> + {error, {no_timers, 'CommandRequest'}}. + + +get_dm_timers5({modReq, #'AmmRequest'{descriptors = Descriptors}}) -> + get_dm_timers6(Descriptors); +get_dm_timers5(R) -> + {error, {no_modReq, R}}. + + +get_dm_timers6([{digitMapDescriptor, #'DigitMapDescriptor'{digitMapValue = Val}}|_]) -> + case Val of + #'DigitMapValue'{startTimer = T, + shortTimer = S, + longTimer = L, + durationTimer = asn1_NOVALUE} -> + {ok, {T, S, L}}; + #'DigitMapValue'{startTimer = T, + shortTimer = S, + longTimer = L, + durationTimer = Z} -> + {ok, {T, S, L, Z}}; + _ -> + {error, no_value_in_dm} + end; +get_dm_timers6([_|Descs]) -> + get_dm_timers6(Descs); +get_dm_timers6([]) -> + {error, {no_timers, descriptors}}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bin_test_msgs(suite) -> + []; +bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(binary) ++ + msgs5(binary) ++ + msgs6(binary) ++ + msgs7(binary) ++ + msgs8(binary), + %% Msgs = msgs6(binary), + DynamicDecode = false, + test_msgs(megaco_binary_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ber_test_msgs(suite) -> + []; +ber_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(binary) ++ + msgs5(binary) ++ + msgs6(binary) ++ + msgs7(binary) ++ + msgs8(binary), + %% Msgs = msgs7(binary), + DynamicDecode = false, + test_msgs(megaco_ber_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ber_bin_test_msgs(suite) -> + []; +ber_bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(binary) ++ + msgs5(binary) ++ + msgs6(binary) ++ + msgs7(binary) ++ + msgs8(binary), + DynamicDecode = true, + test_msgs(megaco_ber_bin_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +per_test_msgs(suite) -> + []; +per_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(binary) ++ + msgs5(binary) ++ + msgs6(binary) ++ + msgs7(binary) ++ + msgs8(binary), + DynamicDecode = false, + test_msgs(megaco_per_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +per_bin_test_msgs(suite) -> + []; +per_bin_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(binary) ++ + msgs5(binary) ++ + msgs6(binary) ++ + msgs7(binary) ++ + msgs8(binary), + DynamicDecode = false, + test_msgs(megaco_per_bin_encoder, DynamicDecode, ?EC, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +erl_dist_m_test_msgs(suite) -> + []; +erl_dist_m_test_msgs(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Msgs = + msgs1a(erlang) ++ + msgs1b(erlang) ++ + msgs3525(erlang) ++ + msgs5(erlang) ++ + msgs6(erlang) ++ + msgs7(erlang) ++ + msgs8(erlang), + DynamicDecode = false, + Conf = [megaco_compressed], + test_msgs(megaco_erl_dist_encoder, DynamicDecode, Conf, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +%% Ticket test cases: + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg1(suite) -> + []; +compact_otp4011_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4011_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR " ML T=233350{C=${A=stedevice/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SR}}}}}", + ok = compact_otp4011(M), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +compact_otp4011_msg2(suite) -> + []; +compact_otp4011_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4011_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR " ML T=233350{C=${A=stedevice/01{M{O{MO=SO,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SR}}}}}", + ok = compact_otp4011(M), + %% erase(severity), + %% erase(dbg), + ok. + +%% -------------------------------------------------------------- +%% Observe that this decode SHALL fail +%% + +compact_otp4011_msg3(suite) -> + []; +compact_otp4011_msg3(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4011_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "!/" ?VERSION_STR " ML T=233350{C=${A=stedevice/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=OFF,MO=SO}}}}}", + ok = compact_otp4011(M), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4011(Msg) -> + compact_otp4011(Msg, ?EC). + +compact_otp4011(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(Reason) when is_list(Reason) -> + compact_otp4011_chk1(Reason); + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode(Msg, Decode, Check). + +compact_otp4011_chk1(R1) -> + case lists:keysearch(reason, 1, R1) of + {value, {reason, R2}} -> + compact_otp4011_chk2(R2); + false -> + {error, {unexpected_result, R1}} + end. + +compact_otp4011_chk2({0, ParserMod, {ParserFunc, [A, B]}}) + when (ParserMod =:= megaco_text_parser_v3) andalso + (ParserFunc =:= do_merge_control_streamParms) andalso + is_list(A) andalso + is_record(B, 'LocalControlDescriptor') -> + SM = B#'LocalControlDescriptor'.streamMode, + case lists:keysearch(mode, 1, A) of + {value, {mode, _Mode}} when SM /= asn1_NOVALUE -> + ok; + {value, {mode, _Mode}} -> + {error, {unexpected_streamMode_reason, {A, B}}}; + false -> + {error, {unexpected_mode_reason, {A, B}}} + end; +compact_otp4011_chk2(Bad) -> + {error, {unexpected_reason, Bad}}. + + +%% -------------------------------------------------------------- +%% Note that this decode SHALL fail, because of the misspelled +%% MEGCAO instead of the correct MEGACO. +compact_otp4013_msg1(suite) -> + []; +compact_otp4013_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4013_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = "MEGCAO/3 MG1 T=12345678{C=-{SC=root{SV{MT=RS,RE=901}}}}", + ok = compact_otp4013(M), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4013(Msg) -> + compact_otp4013(Msg, ?EC). + +compact_otp4013(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(Reason) when is_list(Reason) -> + compact_otp4013_chk1(Reason); + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode(Msg, Decode, Check). + +compact_otp4013_chk1(Reason) -> + case lists:keysearch(reason, 1, Reason) of + {value, {reason, no_version_found, _}} -> + case lists:keysearch(token, 1, Reason) of + {value, {token, [{'SafeChars',_,"megcao/3"}|_]}} -> + ok; + {value, {token, Tokens}} -> + {error, {unexpected_tokens, Tokens}}; + false -> + {error, {tokens_not_found, Reason}} + end; + {value, {reason, BadReason, _}} -> + {error, {unexpected_reason, BadReason}}; + false -> + {error, {reason_not_found, Reason}} + end. + + +%% -------------------------------------------------------------- +%% +%% +compact_otp4085_msg1(suite) -> + []; +compact_otp4085_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = compact_otp4085_erroneous_msg(), + ok = compact_otp4085_1(M), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4085_1(Msg) -> + compact_otp4085_1(Msg, ?EC). + +compact_otp4085_1(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(Reason) when is_list(Reason) -> + compact_otp4085_1_chk1(Reason); + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode(Msg, Decode, Check). + +compact_otp4085_1_chk1(Reason) -> + case lists:keysearch(reason, 1, Reason) of + {value, {reason, {Line, Module, Crap}}} when is_integer(Line) and + is_atom(Module) -> + Crap2 = + case (catch lists:flatten(Crap)) of + L when is_list(L) -> + L; + _ -> + Crap + end, + t("compact_otp4085_1_chk1 -> Expected: " + "~n Line: ~p" + "~n Module: ~p" + "~n Crap2: ~p", [Line, Module, Crap2]), + ok; + {value, BadReason} -> + e("compact_otp4085_1_chk1 -> error: " + "~n BadReason: ~p", [BadReason]), + {error, {unexpected_reason, Reason}}; + false -> + {error, {reason_not_found, Reason}} + end. + + +%% -------------------------------------------------------------- +%% This test case is just to show that the message used in +%% compact_otp4085_msg1 is actually ok when you add '}' at the end. +compact_otp4085_msg2(suite) -> + []; +compact_otp4085_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = compact_otp4085_erroneous_msg() ++ "}", + ok = compact_otp4085_2(M), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4085_2(Msg) -> + compact_otp4085_2(Msg, ?EC). + +compact_otp4085_2(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(M) when is_record(M, 'MegacoMessage') -> + ok; + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode_only(Msg, Decode, Check). + + +%% This message lack the ending parentesis (}). +compact_otp4085_erroneous_msg() -> + M = "!/" + ?VERSION_STR + " ML T=11223342{C=${A=${M{O{MO=SR,RV=OFF,RG=OFF},L{v=0," + "c=ATM NSAP $ ," + "a=eecid:$ ," + "m=audio - AAL1/ATMF -," + "}}},A=stee1181/01{M{O{MO=SR,RV=OFF,RG=OFF,tdmc/ec=off}}}}", + M. + +%% -------------------------------------------------------------- +%% +%% +compact_otp4280_msg1(suite) -> + []; +compact_otp4280_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4280_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + M = compact_otp4280_msg(), + ok = compact_otp4280(M), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4280(Msg) -> + compact_otp4280(Msg, ?EC). + +compact_otp4280(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(M) when is_record(M, 'MegacoMessage') -> + ok; + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode_only(Msg, Decode, Check). + +compact_otp4280_msg() -> + M = "!/" + ?VERSION_STR + " mgw1 P=71853646{C=-{AV=root{M{TS{root/maxnumberofcontexts=49500," + "root/maxterminationspercontext=2,root/normalmgexecutiontime=200," + "root/normalmgcexecutiontime=150," + "root/provisionalresponsetimervalue=2000,BF=OFF,SI=IV}}}}}", + M. + + +%% -------------------------------------------------------------- +%% This ticket is about comments in a message +%% +compact_otp4299_msg1(suite) -> + []; +compact_otp4299_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4299_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = compact_otp4299_msg(), + ok = compact_otp4299(Msg), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4299(Msg) -> + compact_otp4299(Msg, ?EC). + +compact_otp4299(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(M) when is_record(M, 'MegacoMessage') -> + ok; + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode_only(Msg, Decode, Check). + +compact_otp4299_msg() -> + M = ";KALLE\n" + "!/" + ?VERSION_STR + " mg58_1 P=005197711{; YET ANOTHER COMMENT\n" + "C=035146207{A=mg58_1_1_4_1_23/19; BEFORE COMMA\n" + ",; AFTER COMMA\n" + "A=eph58_1/0xA4023371{M{L{\n" + "v=0\n" + "c=ATM NSAP 39.0102.0304.0506.0708.090a.0b58.0100.0000.0000.00\n" + "m=audio - AAL1/ATMF -\n" + "a=eecid:A4023371\n" + "}}; HOBBE\n}; KALLE \"HOBBE \n}}" + ";KALLE\n\n", + M. + + +%% -------------------------------------------------------------- +%% + +compact_otp4359_msg1(suite) -> + []; +compact_otp4359_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4359_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = compact_otp4359_msg(), + ok = compact_otp4359(Msg), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4359_msg() -> + M = "!/" ?VERSION_STR " ml2 T={C=${A=${M{O {MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4359(Msg) -> + compact_otp4359(Msg, ?EC). + +compact_otp4359(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(M) when is_record(M, 'MegacoMessage') -> + compact_otp4359_chk(M); + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode_only(Msg, Decode, Check). + +compact_otp4359_chk(#'MegacoMessage'{mess = Mess}) -> + case Mess#'Message'.messageBody of + {transactions, Trans} -> + case Trans of + [{transactionRequest, TR}] -> + case TR of + #'TransactionRequest'{transactionId = asn1_NOVALUE} -> + ok; + _ -> + {error, {unexpected_trans_req, TR}} + end; + _ -> + {error, {unexpected_trans, Trans}} + end; + Body -> + {error, {unexpected_messageBody, Body}} + end. + + +%% -------------------------------------------------------------- +%% +compact_otp4920_msg0(suite) -> + []; +compact_otp4920_msg0(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg0 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg0() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg1(suite) -> + []; +compact_otp4920_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg2(suite) -> + []; +compact_otp4920_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg2() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg3(suite) -> + []; +compact_otp4920_msg3(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg3() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg4(suite) -> + []; +compact_otp4920_msg4(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg4() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg5(suite) -> + []; +compact_otp4920_msg5(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg5() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg6(suite) -> + []; +compact_otp4920_msg6(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg6() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg7(suite) -> + []; +compact_otp4920_msg7(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg7() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg8(suite) -> + []; +compact_otp4920_msg8(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg8 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg8() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg9(suite) -> + []; +compact_otp4920_msg9(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg9 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg9() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg10(suite) -> + []; +compact_otp4920_msg10(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg10 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg10() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg11(suite) -> + []; +compact_otp4920_msg11(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg11 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg11() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp4920_msg12(suite) -> + []; +compact_otp4920_msg12(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg12 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp4920_msg12() ), + %% erase(severity), + %% erase(dbg), + ok. + +%% Duplicate padding +compact_otp4920_msg20(suite) -> + []; +compact_otp4920_msg20(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg20 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp4920(compact_otp4920_msg20(), bad_mid_duplicate_padding), + %% erase(severity), + %% erase(dbg), + ok. + +%% Length +compact_otp4920_msg21(suite) -> + []; +compact_otp4920_msg21(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg21 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp4920(compact_otp4920_msg21(), bad_mid_ip6addr_length), + %% erase(severity), + %% erase(dbg), + ok. + +%% Length +compact_otp4920_msg22(suite) -> + []; +compact_otp4920_msg22(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg22 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp4920(compact_otp4920_msg22(), bad_mid_ip6addr_length), + %% erase(severity), + %% erase(dbg), + ok. + +%% Length +compact_otp4920_msg23(suite) -> + []; +compact_otp4920_msg23(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg23 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp4920(compact_otp4920_msg23(), bad_mid_ip6addr_length), + %% erase(severity), + %% erase(dbg), + ok. + +%% Length +compact_otp4920_msg24(suite) -> + []; +compact_otp4920_msg24(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg24 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp4920(compact_otp4920_msg24(), bad_mid_ip6addr_length), + %% erase(severity), + %% erase(dbg), + ok. + +%% Length +compact_otp4920_msg25(suite) -> + []; +compact_otp4920_msg25(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp4920_msg25 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp4920(compact_otp4920_msg25(), bad_mid_ip6addr_length), + %% erase(severity), + %% erase(dbg), + ok. + + +compact_otp4920(Msg, ExpectedReason) -> + compact_otp4920(Msg, ?EC, ExpectedReason). + +compact_otp4920(Msg, Conf, ExpectedReason) -> + Codec = megaco_compact_text_encoder, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(Reason) when is_list(Reason) -> + compact_otp4920_chk(Reason, ExpectedReason); + (Crap) -> + {error, {unexpected_decode_result, Crap}} + end, + megaco_codec_test_lib:expect_decode(Msg, Decode, Check). + +compact_otp4920_chk(Reason, ExpectedReason) -> + case lists:keysearch(reason, 1, Reason) of + {value, {reason, {__Line, _Mod, ActualReason}}} -> + case element(1, ActualReason) of + ExpectedReason -> + ok; + _ -> + {error, {unexpected_decode_reason, + {ActualReason, ExpectedReason}}} + end; + {value, {reason, {_Mod, ActualReason}}} -> + case element(1, ActualReason) of + ExpectedReason -> + ok; + _ -> + {error, {unexpected_decode_reason, + {ActualReason, ExpectedReason}}} + end; + {value, UnknownReason} -> + {error, {unexpected_decode_reason, UnknownReason}}; + false -> + {error, {reason_not_found, Reason}} + end. + +compact_otp4920_msg0() -> + M = "!/" ?VERSION_STR " [192.168.30.1]\nT=100{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg1() -> + M = "!/" ?VERSION_STR " [2031:0000:130F:0000:0000:09C0:876A:130B]\nT=101{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg2() -> + M = "!/" ?VERSION_STR " [2031:0:130F:0:0:9C0:876A:130B]\nT=102{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg3() -> + M = "!/" ?VERSION_STR " [2031:0:130F::9C0:876A:130B]\nT=103{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg4() -> + M = "!/" ?VERSION_STR " [::1]\nT=104{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg5() -> + M = "!/" ?VERSION_STR " [::]\nT=105{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg6() -> + M = "!/" ?VERSION_STR " [1::]\nT=106{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg7() -> + M = "!/" ?VERSION_STR " [FEDC:1::]\nT=107{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg8() -> + M = "!/" ?VERSION_STR " [2031:0:130F:0:0:9C0:135.106.19.11]\nT=108{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg9() -> + M = "!/" ?VERSION_STR " [2031:0:130F::9C0:135.106.19.11]\nT=109{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg10() -> + M = "!/" ?VERSION_STR " [::FFFF:192.168.30.1]\nT=110{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg11() -> + M = "!/" ?VERSION_STR " [::192.168.30.1]\nT=111{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +compact_otp4920_msg12() -> + M = "!/" ?VERSION_STR " [::C0A8:1E01]\nT=112{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: only one :: allowed +compact_otp4920_msg20() -> + M = "!/" ?VERSION_STR " [2031::130F::9C0]\nT=120{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg21() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:0000:0000:09C0:876A:130B]\nT=121{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg22() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0:130F:0:0:9C0:135.106.19.11]\nT=122{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg23() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:2132:4354::09C0:876A:130B]\nT=123{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg24() -> + M = "!/" ?VERSION_STR " [::2031:FFEE:0000:130F:2132:4354:09C0:876A:130B]\nT=124{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + +%% Illegal: length +compact_otp4920_msg25() -> + M = "!/" ?VERSION_STR " [2031:FFEE:0000:130F:2132:4354:09C0:876A:130B::]\nT=125{C=${A=${M{O{MO=SR,RG=OFF,RV=OFF}}}}}", + M. + + +%% -------------------------------------------------------------- +%% + +compact_otp5186_msg01(suite) -> + []; +compact_otp5186_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5186_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_error( compact_otp5186_msg01() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5186_msg02(suite) -> + []; +compact_otp5186_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5186_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_decode_encode_ok( compact_otp5186_msg02() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5186_msg03(suite) -> + []; +compact_otp5186_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5186_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% ok = compact_otp5186_msg_2(compact_otp5186_msg03(), ok, ok), + ok = ticket_compact_encode_decode_ok( compact_otp5186_msg03() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5186_msg04(suite) -> + []; +compact_otp5186_msg04(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5186_msg04 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% ok = compact_otp5186_msg_2(compact_otp5186_msg04(), ok, ok), + ok = ticket_compact_encode_decode_ok( compact_otp5186_msg04() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5186_msg05(suite) -> + []; +compact_otp5186_msg05(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5186_msg05 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% ok = compact_otp5186_msg_2(compact_otp5186_msg05(), ok, ok), + ok = ticket_compact_encode_decode_ok( compact_otp5186_msg05() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5186_msg06(suite) -> + []; +compact_otp5186_msg06(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5186_msg06 -> entry", []), + ?ACQUIRE_NODES(1, Config), + %% ok = compact_otp5186_msg_2(compact_otp5186_msg06(), ok, ok), + ok = ticket_compact_encode_decode_ok( compact_otp5186_msg06() ), + %% erase(severity), + %% erase(dbg), + ok. + +%% -- + +compact_otp5186_msg01() -> + "!/" ?VERSION_STR " <mg5>\nP=67111298{C=2699{AV=mg5_ipeph/0x0f0001{}}}". + +compact_otp5186_msg02() -> + "!/" ?VERSION_STR " <mg5>\nP=67111298{C=2699{AV=mg5_ipeph/0x0f0001}}". + +compact_otp5186_msg03() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]}, + [ + ] + } + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +compact_otp5186_msg04() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',?VERSION,{domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]}, + [ + {emptyDescriptors, + {'AuditDescriptor',asn1_NOVALUE,asn1_NOVALUE} + } + ] + } + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +compact_otp5186_msg05() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {addReply, + {'AmmsReply', + [ + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]} + ], + [ + ] + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + +compact_otp5186_msg06() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',?VERSION,{domainName,{'DomainName',"mg5",asn1_NOVALUE}}, + {transactions, + [{transactionReply, + {'TransactionReply',67111298,asn1_NOVALUE, + {actionReplies,[ + {'ActionReply',2699,asn1_NOVALUE,asn1_NOVALUE, + [ + {addReply, + {'AmmsReply', + [ + {megaco_term_id,false,["mg5_ipeph","0x0f0001"]} + ], + [ + {emptyDescriptors, + {'AuditDescriptor',asn1_NOVALUE,asn1_NOVALUE} + } + ] + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +%% -------------------------------------------------------------- + +compact_otp5793_msg01(suite) -> + []; +compact_otp5793_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_encode_decode_ok(pretty_otp5793_msg1()), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- + +compact_otp5836_msg01(suite) -> + []; +compact_otp5836_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5836_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_encode_decode_ok(compact_otp5836_msg1()), + %% erase(severity), + %% erase(dbg), + ok. + + +compact_otp5836_msg1() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"bs_sbg_4/34"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 12, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 4294967295, + asn1_NOVALUE, + asn1_NOVALUE, + [{auditValueReply, + {error, {'ErrorDescriptor', 431, asn1_NOVALUE}}} + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +%% -------------------------------------------------------------- + +compact_otp5993_msg01(suite) -> + []; +compact_otp5993_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5993_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_encode_decode_ok( compact_otp5993_msg01() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5993_msg01() -> + MT = h221, + T = #megaco_term_id{id = ?A4444}, + TL = [T], + MD = #'MuxDescriptor'{muxType = MT, + termList = TL}, + compact_otp5993_msg(MD). + + +compact_otp5993_msg02(suite) -> + []; +compact_otp5993_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5993_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_encode_decode_ok( compact_otp5993_msg02() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5993_msg02() -> + MT = h223, + T1 = #megaco_term_id{id = ?A4445}, + T2 = #megaco_term_id{id = ?A5556}, + TL = [T1, T2], + MD = #'MuxDescriptor'{muxType = MT, + termList = TL}, + compact_otp5993_msg(MD). + + +compact_otp5993_msg03(suite) -> + []; +compact_otp5993_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp5993_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_compact_encode_decode_ok( compact_otp5993_msg03() ), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp5993_msg03() -> + T1 = #megaco_term_id{id = ?A4445}, + T2 = #megaco_term_id{id = ?A5556}, + TIDs = [T1, T2], + AudRep = {contextAuditResult, TIDs}, + CmdRep = {auditValueReply, AudRep}, + ActRep = #'ActionReply'{contextId = 5993, + commandReply = [CmdRep]}, + TransRes = {actionReplies, [ActRep]}, + TransRep = #'TransactionReply'{transactionId = 3995, + transactionResult = TransRes}, + Trans = {transactionReply, TransRep}, + Body = {transactions, [Trans]}, + Msg = #'Message'{version = ?VERSION, + mId = ?MG1_MID, + messageBody = Body}, + #'MegacoMessage'{mess = Msg}. + + +compact_otp5993_msg(MD) when is_record(MD, 'MuxDescriptor') -> + AmmDesc = {muxDescriptor, MD}, + AmmReq = #'AmmRequest'{terminationID = [hd(MD#'MuxDescriptor'.termList)], + descriptors = [AmmDesc]}, + Cmd = {addReq, AmmReq}, + CmdReq = #'CommandRequest'{command = Cmd}, + ActReq = #'ActionRequest'{contextId = 5993, + commandRequests = [CmdReq]}, + TransReq = #'TransactionRequest'{transactionId = 3995, + actions = [ActReq]}, + Trans = {transactionRequest, TransReq}, + Body = {transactions, [Trans]}, + Msg = #'Message'{version = ?VERSION, + mId = ?MG1_MID, + messageBody = Body}, + #'MegacoMessage'{mess = Msg}. + + +%% -------------------------------------------------------------- + +compact_otp6017_msg01(suite) -> + []; +compact_otp6017_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp6017_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(0), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp6017_msg02(suite) -> + []; +compact_otp6017_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp6017_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(16#FFFFFFFE), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp6017_msg03(suite) -> + []; +compact_otp6017_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("compact_otp6017_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = compact_otp6017(16#FFFFFFFF), + %% erase(severity), + %% erase(dbg), + ok. + +compact_otp6017(BadCID) -> + d("compact_otp6017 -> entry with" + "~n BadCID: ~p", [BadCID]), + Conf = ?EC, + M = compact_otp6017_msg(BadCID), + Bin = list_to_binary(M), + case decode_message(megaco_compact_text_encoder, false, Conf, Bin) of + {ok, Msg} -> + d("compact_otp6017 -> Msg: ~n~p", [Msg]), + exit({unexpected_decode_success, {Msg, M}}); + {error, Reason} when is_list(Reason) -> % Expected result + case lists:keysearch(reason, 1, Reason) of + {value, {reason, {_Line, _Mod, {bad_ContextID, BadCID}}}} -> + io:format(" ~w", [BadCID]), + ok; + {value, {reason, ActualReason}} -> + d("compact_otp6017 -> wrong reason: ~n~p", [ActualReason]), + exit({unexpected_reason, ActualReason}); + false -> + d("compact_otp6017 -> no reason: ~n~p", [Reason]), + exit({reason_not_found, Reason}) + end; + Crap -> + d("compact_otp6017 -> unexpected decode result: ~n~p", [Crap]), + exit({unexpected_decode_result, Crap}) + end. + +compact_otp6017_msg(CID) when is_integer(CID) -> + "!/" ?VERSION_STR " MG1 T=12345678{C=" ++ + integer_to_list(CID) ++ + "{SC=root{SV{MT=RS,RE=901}}}}". + + +%% ============================================================== +%% +%% F l e x C o m p a c t T e s t c a s e s +%% + +flex_compact_otp4299_msg1(suite) -> + []; +flex_compact_otp4299_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp4299_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Msg = compact_otp4299_msg(), + Conf = flex_scanner_conf(Config), + ok = compact_otp4299(Msg, [?EC_V3,Conf]), + %% erase(severity), + %% erase(dbg), + ok. + + +flex_compact_otp7431_msg01(suite) -> + []; +flex_compact_otp7431_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg01 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(ok, flex_compact_otp7431_msg1(), [Conf]). + +flex_compact_otp7431_msg02(suite) -> + []; +flex_compact_otp7431_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg02 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg2(), [Conf]). + +flex_compact_otp7431_msg03(suite) -> + []; +flex_compact_otp7431_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg03 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg3(), [Conf]). + +flex_compact_otp7431_msg04(suite) -> + []; +flex_compact_otp7431_msg04(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg04 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg4(), [Conf]). + +flex_compact_otp7431_msg05(suite) -> + []; +flex_compact_otp7431_msg05(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg05 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg5(), [Conf]). + +flex_compact_otp7431_msg06(suite) -> + []; +flex_compact_otp7431_msg06(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg06 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg6(), [Conf]). + +flex_compact_otp7431_msg07(suite) -> + []; +flex_compact_otp7431_msg07(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_comppact_otp7431_msg07 -> entry", []), + Conf = flex_scanner_conf(Config), + flex_compact_otp7431(error, flex_compact_otp7431_msg7(), [Conf]). + + +flex_compact_otp7431(Expected, Msg, Conf) -> + otp7431(Expected, megaco_compact_text_encoder, Msg, Conf). + +flex_compact_otp7431_msg1() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a=recvonly +}}}}}}". + +flex_compact_otp7431_msg2() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a= } +}}}}}". + + +flex_compact_otp7431_msg3() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a } +}}}}}". + + +flex_compact_otp7431_msg4() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a} +}}}}}". + + +flex_compact_otp7431_msg5() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v= } +}}}}}". + + +flex_compact_otp7431_msg6() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v } +}}}}}". + +flex_compact_otp7431_msg7() -> + "!/1 [124.124.124.222]:55555 +P=10003{C=2000{A=a4444,A=a4445{M{ST=1{L{ +v} +}}}}}". + + +%% ============================================================== +%% +%% P r e t t y T e s t c a s e s +%% + +pretty_otp4632_msg1(suite) -> + []; +pretty_otp4632_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4632_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp4632_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4632_msg1() -> + msg4(?MG1_MID_NO_PORT, "901 mg col boot"). + +pretty_otp4632_msg2(suite) -> + []; +pretty_otp4632_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4632_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp4632_msg2() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4632_msg2() -> + msg4(?MG1_MID_NO_PORT, "901"). + + +pretty_otp4632_msg3(suite) -> + []; +pretty_otp4632_msg3(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4632_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_encode_ok( pretty_otp4632_msg3() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4632_msg3() -> + M = "MEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = \"901\"\n\t\t\t}\n\t\t}\n\t}\n}", + M. + + +pretty_otp4632_msg4(suite) -> + []; +pretty_otp4632_msg4(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4632_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(B2, B1) -> pretty_otp4632_msg4_chk(B1, B2) end, + ok = ticket_pretty_decode_encode_only(pretty_otp4632_msg4(), Check), + %% erase(severity), + %% erase(dbg), + ok. + + +pretty_otp4632_msg4() -> + M = "MEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = 901\n\t\t\t}\n\t\t}\n\t}\n}", + M. + +pretty_otp4632_msg4_chk(B1, B2) when is_binary(B1) and is_binary(B2) -> + S1 = binary_to_list(B1), + S2 = binary_to_list(B2), + %% io:format("~n" + %% "S1: ~s~n" + %% "S2: ~s~n", [S1, S2]), + pretty_otp4632_msg4_chk(S1, S2); + +pretty_otp4632_msg4_chk([], []) -> + messages_not_eq; +pretty_otp4632_msg4_chk([], Rest2) -> + {messages_not_eq2, Rest2}; +pretty_otp4632_msg4_chk(Rest1, []) -> + {messages_not_eq1, Rest1}; +pretty_otp4632_msg4_chk([$R,$e,$a,$s,$o,$n,$ ,$=,$ ,$",$9,$0,$1,$"|_Rest1], + [$R,$e,$a,$s,$o,$n,$ ,$=,$ ,$9,$0,$1|_Rest2]) -> + ok; +pretty_otp4632_msg4_chk([_H1|Rest1], [_H2|Rest2]) -> + pretty_otp4632_msg4_chk(Rest1, Rest2). + + +%% -------------------------------------------------------------- +%% +pretty_otp4710_msg1(suite) -> + []; +pretty_otp4710_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4710_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp4710_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4710_msg1() -> + msg40(). + + +pretty_otp4710_msg2(suite) -> + []; +pretty_otp4710_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4710_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(B1, B2) -> pretty_otp4710_msg2_chk(B1, B2) end, + ok = ticket_pretty_decode_encode_only(pretty_otp4710_msg2(), Check), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4710_msg2() -> + "Authentication = 0xEFCDAB89:0x12345678:0x1234567889ABCDEF76543210\nMEGACO/" ?VERSION_STR " [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = \"901 mg col boot\"\n\t\t\t}\n\t\t}\n\t}\n}". + +pretty_otp4710_msg2_chk(B1, B2) when is_binary(B1) and is_binary(B2) -> + S1 = binary_to_list(B1), + S2 = binary_to_list(B2), + pretty_otp4710_msg2_chk(S1, S2); + +pretty_otp4710_msg2_chk(Msg, Msg) -> + ok; + +pretty_otp4710_msg2_chk( + [$A,$u,$t,$h,$e,$n,$t,$i,$c,$a,$t,$i,$o,$n,$=,$ |Msg0], + [$A,$u,$t,$h,$e,$n,$t,$i,$c,$a,$t,$i,$o,$n,$=,$ |Msg1]) -> + {AH0, Rest0} = pretty_otp4710_msg2_chk_ah(Msg0, []), + {AH1, Rest1} = pretty_otp4710_msg2_chk_ah(Msg1, []), + case AH0 == AH1 of + true -> + exit({message_not_equal, Rest0, Rest1}); + false -> + exit({auth_header_not_equal, AH0, AH1}) + end. + +pretty_otp4710_msg2_chk_ah([], _Acc) -> + exit(no_auth_header_found); +pretty_otp4710_msg2_chk_ah([$M,$E,$G,$A,$C,$O,$/,_|Rest], Acc) -> + {lists:reverse(Acc), Rest}; +pretty_otp4710_msg2_chk_ah([C|R], Acc) -> + pretty_otp4710_msg2_chk_ah(R, [C|Acc]). + + +%% -------------------------------------------------------------- +%% +pretty_otp4945_msg1(suite) -> + []; +pretty_otp4945_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4945_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp4945_msg1_chk(R) end, + ok = ticket_pretty_decode_error(pretty_otp4945_msg1(), Check), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4945_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + +pretty_otp4945_msg1_chk(R) when is_list(R) -> + ExpMissing = [serviceChangeReason], + Check = fun(Reason) -> + pretty_otp4945_chk(Reason, ExpMissing) + end, + ticket_check_decode_only_error_reason(R, Check). + + +pretty_otp4945_msg2(suite) -> + []; +pretty_otp4945_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4945_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp4945_msg2_chk(R) end, + ok = ticket_pretty_decode_error(pretty_otp4945_msg2(), Check), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4945_msg2() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + +pretty_otp4945_msg2_chk(R) when is_list(R) -> + ExpMissing = [serviceChangeMethod], + Check = fun(Reason) -> + pretty_otp4945_chk(Reason, ExpMissing) + end, + ticket_check_decode_only_error_reason(R, Check). + + +pretty_otp4945_msg3(suite) -> + []; +pretty_otp4945_msg3(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4945_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp4945_msg3_chk(R) end, + ok = ticket_pretty_decode_error(pretty_otp4945_msg3(), Check), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4945_msg3() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + +pretty_otp4945_msg3_chk(R) when is_list(R) -> + ExpMissing = [serviceChangeReason, serviceChangeMethod], + Check = fun(Reason) -> + pretty_otp4945_chk(Reason, ExpMissing) + end, + ticket_check_decode_only_error_reason(R, Check). + + +pretty_otp4945_msg4(suite) -> + []; +pretty_otp4945_msg4(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4945_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_only( pretty_otp4945_msg4() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4945_msg4() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4945_msg5(suite) -> + []; +pretty_otp4945_msg5(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4945_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp4945_msg5_chk(R) end, + ok = ticket_pretty_decode_error(pretty_otp4945_msg5(), Check), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4945_msg5() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + Profile = ResGW/1, + ServiceChangeAddress = 55555, + Profile = ResGW/2 + } + } + } +}". + +pretty_otp4945_msg5_chk(R) when is_list(R) -> + Check = fun({at_most_once_serviceChangeParm, {profile, _, _}}) -> + ok; + (Reason) -> + {error, {unexpected_reason, Reason}} + end, + ticket_check_decode_only_error_reason(R, Check). + + +pretty_otp4945_msg6(suite) -> + []; +pretty_otp4945_msg6(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4945_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp4945_msg6_chk(R) end, + ok = ticket_pretty_decode_error(pretty_otp4945_msg6(), Check), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4945_msg6() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + MgcIdToTry = kalle, + Profile = ResGW/1 + } + } + } +}". + +pretty_otp4945_msg6_chk(R) when is_list(R) -> + Check = fun({not_both_address_mgcid_serviceChangeParm, _, _}) -> + ok; + (Reason) -> + {error, {unexpected_reason, Reason}} + end, + ticket_check_decode_only_error_reason(R, Check). + + +pretty_otp4945_chk({missing_required_serviceChangeParm, Missing}, + ExpMissing) when is_list(Missing) -> + case ExpMissing -- Missing of + [] -> + ok; + Diff -> + {error, {unexpected_missing_serviceChangeParm, Diff}} + end; +pretty_otp4945_chk(Reason, _ExpMissing) -> + {error, {unexpected_reason, Reason}}. + + +%% -------------------------------------------------------------- +%% +pretty_otp4949_msg1(suite) -> + []; +pretty_otp4949_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4949_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_only( pretty_otp4949_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4949_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +pretty_otp4949_msg2(suite) -> + []; +pretty_otp4949_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4949_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp4949_msg2_chk(R) end, + ok = ticket_pretty_decode_error( pretty_otp4949_msg2(), Check), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4949_msg2() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Profile = ResGW/1, + ServiceChangeAddress = 55555, + Profile = ResGW/2 + } + } + } +}". + +pretty_otp4949_msg2_chk(R) when is_list(R) -> + Check = fun({at_most_once_servChgReplyParm, {profile, _, _}}) -> + ok; + (Reason) -> + {error, {unexpected_reason, Reason}} + end, + ticket_check_decode_only_error_reason(R, Check). + + +pretty_otp4949_msg3(suite) -> + []; +pretty_otp4949_msg3(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp4949_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp4949_msg3_chk(R) end, + ok = ticket_pretty_decode_error( pretty_otp4949_msg3(), Check ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp4949_msg3() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + MgcIdToTry = kalle, + Profile = ResGW/1 + } + } + } +}". + +pretty_otp4949_msg3_chk(R) when is_list(R) -> + Check = fun({not_both_address_mgcid_servChgReplyParm, _, _}) -> + ok; + (Reason) -> + {error, {unexpected_reason, Reason}} + end, + ticket_check_decode_only_error_reason(R, Check). + + +%% -------------------------------------------------------------- +%% +pretty_otp5042_msg1(suite) -> + []; +pretty_otp5042_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5042_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_only( pretty_otp5042_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5042_msg1() -> +"MEGACO/" ?VERSION_STR " <CATAPULT>:2944 +Transaction = 102 { +Context = 5 { Notify = MUX/1 { ObservedEvents = 1 { +h245bh/h245msgin { Stream = 1 +, h245enc = +0270020600088175000653401004100403E802E00180018001780680000034301160000700088175010101007A0100020001800001320000C0000219D005027F0070500100040100021080000319D005027F00504001008000041C001250000700088175010000400280010003000880000518AA027F400006850130008011020100000001030002000300040005000006 + } } + } } }". + + +%% -------------------------------------------------------------- +%% +pretty_otp5068_msg1(suite) -> + []; +pretty_otp5068_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5068_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_only( pretty_otp5068_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5068_msg1() -> +{'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,[109,103,51,51]}, + {transactions, + [{transactionReply, + {'TransactionReply', + 190, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', %% Comments: Detta upprepas m�nga g�nger + 0, + asn1_NOVALUE, + asn1_NOVALUE, + [{auditValueReply, + {auditResult, + {'AuditResult', + {megaco_term_id,false, + [[99,101,100,101,118,49,47,52,47,49,47,49],[51,49]]}, + [{mediaDescriptor, + {'MediaDescriptor', + {'TerminationStateDescriptor', + [], + asn1_NOVALUE, + inSvc}, + asn1_NOVALUE} + } + ] + } + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } +}. + + + +%% -------------------------------------------------------------- +%% +pretty_otp5085_msg1(suite) -> + []; +pretty_otp5085_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg1() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + asn1_NOVALUE, + [] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg2(suite) -> + []; +pretty_otp5085_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg2() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg2() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + asn1_NOVALUE, + [] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg3(suite) -> + []; +pretty_otp5085_msg3(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg3() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg3() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + #'ContextRequest'{priority = 3}, + [] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg4(suite) -> + []; +pretty_otp5085_msg4(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg4() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg4() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + asn1_NOVALUE, + [{addReply, cre_AmmsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg5(suite) -> + []; +pretty_otp5085_msg5(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg5() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg5() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"mg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + asn1_NOVALUE, + #'ContextRequest'{priority = 5}, + [{addReply, cre_AmmsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg6(suite) -> + []; +pretty_otp5085_msg6(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg6() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg6() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 6}, + [{addReply, cre_AmmsReply([#megaco_term_id{id = ?A4444}])}, + {notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg7(suite) -> + []; +pretty_otp5085_msg7(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg7() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg7() -> + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 7}, + [{notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +pretty_otp5085_msg8(suite) -> + []; +pretty_otp5085_msg8(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5085_msg8 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg8() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5085_msg8() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + {'MegacoMessage', + asn1_NOVALUE, + {'Message', + ?VERSION, + {deviceName,"msg36"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 230, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 400, + {'ErrorDescriptor',504,asn1_NOVALUE}, + #'ContextRequest'{priority = 8, + emergency = true, + topologyReq = + [#'TopologyRequest'{terminationFrom = From1, + terminationTo = To1, + topologyDirection = bothway}, + #'TopologyRequest'{terminationFrom = From2, + terminationTo = To2, + topologyDirection = oneway} + ], + iepscallind = true, + contextProp = [cre_PropParm("tdmc/gain", "2")]}, + [{notifyReply, cre_NotifyRep([#megaco_term_id{id = ?A5555}])}] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + +%% -------------------------------------------------------------- +%% +pretty_otp5600_msg1(suite) -> + []; +pretty_otp5600_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5600_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5600_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5600_msg1() -> + SRE = #'SecondRequestedEvent'{ pkgdName = "al/on", + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE ] }, + + SIG = { signal, #'Signal'{ signalName = "cg/dt", + sigParList = [] } }, + + RA = #'RequestedActions'{ secondEvent = SED, + signalsDescriptor = [ SIG ] }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + + +pretty_otp5600_msg2(suite) -> + []; +pretty_otp5600_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5600_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5600_msg2() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5600_msg2() -> + SIG = { signal, #'Signal'{ signalName = "cg/dt", + sigParList = [] } }, + + SRA = #'SecondRequestedActions'{ signalsDescriptor = [ SIG ] }, + + SRE = #'SecondRequestedEvent'{ pkgdName = "al/on", + eventAction = SRA, + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE ] }, + + RA = #'RequestedActions'{ secondEvent = SED }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + + +%% -------------------------------------------------------------- +%% +pretty_otp5601_msg1(suite) -> + []; +pretty_otp5601_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5601_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5601_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5601_msg1() -> + SRE1 = #'SecondRequestedEvent'{ pkgdName = "al/on", + evParList = [] }, + + SRA = #'SecondRequestedActions'{ eventDM = { digitMapName, "dialllan0" }}, + + SRE2 = #'SecondRequestedEvent'{ pkgdName = "dd/ce", + eventAction = SRA, + evParList = [] }, + + SED = #'SecondEventsDescriptor'{ requestID = 2, + eventList = [ SRE1, SRE2 ] }, + + RA = #'RequestedActions'{ secondEvent = SED }, + + RE = #'RequestedEvent'{ pkgdName = "al/of", + eventAction = RA, + evParList = [] }, + + EV = #'EventsDescriptor'{ requestID = 1, eventList = [ RE ] }, + + TermID = {megaco_term_id, true, [[$*]] }, + + AMMR = #'AmmRequest'{ terminationID = [ TermID ], + descriptors = [ { eventsDescriptor, EV } ] }, + + CR = #'CommandRequest'{command = {modReq, AMMR}}, + + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + ARs = [AR], + TR = #'TransactionRequest'{transactionId = 5600, actions = ARs}, + TRs = [{transactionRequest, TR}], + Mess = #'Message'{version = ?VERSION, + mId = ?MGC_MID, + messageBody = {transactions, TRs}}, + #'MegacoMessage'{mess = Mess}. + + +%% -------------------------------------------------------------- +%% +pretty_otp5793_msg01(suite) -> + []; +pretty_otp5793_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5793_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5793_msg1() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',3, + {deviceName,"bs_sbg_4/99"}, + {transactions, + [{transactionReply, + {'TransactionReply', + 370, + asn1_NOVALUE, + {actionReplies, + [{'ActionReply', + 3, + asn1_NOVALUE, + asn1_NOVALUE, + [{auditValueReply, + {contextAuditResult, + [{megaco_term_id, + false, + ["ip", + "104", + "1", + "18"]}]}}, + {auditValueReply, + {contextAuditResult, + [{megaco_term_id, + false, + ["ip", + "104", + "2", + "19"] + } + ] + } + } + ] + } + ] + },asn1_NOVALUE,asn1_NOVALUE + } + } + ] + } + } + }. + + + +%% -------------------------------------------------------------- +%% +pretty_otp5803_msg01(suite) -> + []; +pretty_otp5803_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5803_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_encode_ok( pretty_otp5803_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5803_msg1() -> +"MEGACO/" ?VERSION_STR " [134.138.234.29]Transaction=384{ + Context=27{ + Modify=ip/104/1/76{ + Media{ + Stream=1{ + Local{}, + Remote{} + }, + Stream=2{ + Local{}, + Remote{} + } + }, + Audit{ + Media{ + Stream=1{ + Statistics{*/*} + }, + Stream=2{ + Statistics{*/*} + } + } + } + }, + Modify=ip/104/2/77{ + Media{ + Stream=1{ + Local{}, + Remote{} + }, + Stream=2{ + Local{}, + Remote{} + } + } + } + } +}". + + +pretty_otp5803_msg02(suite) -> + []; +pretty_otp5803_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5803_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_encode_ok( pretty_otp5803_msg2() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5803_msg2() -> +"MEGACO/" ?VERSION_STR " [134.138.234.29]Transaction=384{ + Context=27{ + Modify=ip/104/1/76{ + Media{ + Stream=1{ + Local{}, + Remote{} + }, + Stream=2{ + Local{}, + Remote{} + } + }, + Audit{ + Media{ + Stream=1{ + Statistics{*/*} + } + } + } + }, + Modify=ip/104/2/77{ + Media{ + Stream=1{ + Local{}, + Remote{} + }, + Stream=2{ + Local{}, + Remote{} + } + } + } + } +}". + + +%% -------------------------------------------------------------- +%% +pretty_otp5805_msg01(suite) -> + []; +pretty_otp5805_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5805_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_error( pretty_otp5805_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5805_msg1() -> +"MEGACO/4 [134.138.234.29] +Transaction=1{ + Context=*{ + AuditValue=ip/0/*{ + Audit{} + } + } +}". + + +%% -------------------------------------------------------------- +%% +pretty_otp5836_msg01(suite) -> + []; +pretty_otp5836_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5836_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( compact_otp5836_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +pretty_otp5882_msg01(suite) -> + []; +pretty_otp5882_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("pretty_otp5882_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Check = fun(R) -> pretty_otp5882_msg01_chk(R) end, + ok = ticket_pretty_encode_error( pretty_otp5882_msg01(), Check ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp5882_msg01_chk({message_encode_failed, {error, {Reason, _}}, _}) -> + case Reason of + {invalid_LocalControlDescriptor, empty} -> + ok; + _ -> + {error, {unexpected_error_actual_reason, Reason}} + end; +pretty_otp5882_msg01_chk(Reason) -> + {error, {unexpected_reason, Reason}}. + + +pretty_otp5882_msg01() -> + LCD = #'LocalControlDescriptor'{}, % Create illegal LCD + Parms = cre_StreamParms(LCD), + StreamDesc = cre_StreamDesc(1, Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + CID = cre_CtxID(7301), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(7302), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + + + +%% -------------------------------------------------------------- +%% +pretty_otp6490_msg01(suite) -> + []; +pretty_otp6490_msg01(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg01 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp6490_msg01(), [] ), + %% erase(dbg), + erase(severity), + ok. + +pretty_otp6490_msg02(suite) -> + []; +pretty_otp6490_msg02(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg02 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp6490_msg02(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg03(suite) -> + []; +pretty_otp6490_msg03(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg03 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp6490_msg03(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg04(suite) -> + []; +pretty_otp6490_msg04(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg04 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp6490_msg04(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg05(suite) -> + []; +pretty_otp6490_msg05(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg05 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp6490_msg05(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg06(suite) -> + []; +pretty_otp6490_msg06(Config) when is_list(Config) -> + %% put(severity, trc), + %% put(dbg, true), + d("pretty_otp6490_msg06 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp6490_msg06(), [] ), + %% erase(severity), + %% erase(dbg), + ok. + +pretty_otp6490_msg(EBD) -> + AmmDesc = ?MSG_LIB:cre_AmmDescriptor(EBD), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4445}], [AmmDesc]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + CID = cre_CtxID(64901), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(64902), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +pretty_otp6490_msg01() -> + EvSpecs = [], % This will result in an error + EBD = EvSpecs, % This is because the lib checks that the size is valid + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg02() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg03() -> + EvPar1 = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + EvPar2 = ?MSG_LIB:cre_EventParameter("kalle", ["anka"]), + EvPar3 = ?MSG_LIB:cre_EventParameter("flippa", ["ur"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar1,EvPar2,EvPar3]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg04() -> + EvPar1 = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + EvPar2 = ?MSG_LIB:cre_EventParameter("kalle", ["anka"]), + EvPar3 = ?MSG_LIB:cre_EventParameter("flippa", ["ur"]), + PkgdName1 = ?MSG_LIB:cre_PkgdName("foo", "a"), + EvName1 = ?MSG_LIB:cre_EventName(PkgdName1), + EvSpec1 = ?MSG_LIB:cre_EventSpec(EvName1, [EvPar1,EvPar2,EvPar3]), + EvPar4 = ?MSG_LIB:cre_EventParameter("hej", ["hopp"]), + PkgdName2 = ?MSG_LIB:cre_PkgdName("bar", "b"), + EvName2 = ?MSG_LIB:cre_EventName(PkgdName2), + EvSpec2 = ?MSG_LIB:cre_EventSpec(EvName2, [EvPar4]), + EvSpecs = [EvSpec1,EvSpec2], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg05() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName("foo", root), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + +pretty_otp6490_msg06() -> + EvPar = ?MSG_LIB:cre_EventParameter("sune", ["mangs"]), + PkgdName = ?MSG_LIB:cre_PkgdName(root, root), + EvName = ?MSG_LIB:cre_EventName(PkgdName), + EvSpec = ?MSG_LIB:cre_EventSpec(EvName, [EvPar]), + EvSpecs = [EvSpec], + EBD = ?MSG_LIB:cre_EventBufferDescriptor(EvSpecs), + pretty_otp6490_msg(EBD). + + +%% -------------------------------------------------------------- +%% + +pretty_otp7671_msg01(suite) -> + []; +pretty_otp7671_msg01(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg01 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg01(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg02(suite) -> + []; +pretty_otp7671_msg02(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg02 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg02(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg03(suite) -> + []; +pretty_otp7671_msg03(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg03 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg03(), [] ), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg04(suite) -> + []; +pretty_otp7671_msg04(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg04 -> entry", []), + %% ?ACQUIRE_NODES(1, Config), + ok = pretty_otp7671( pretty_otp7671_msg04(), [] , error, ignore), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671_msg05(suite) -> + []; +pretty_otp7671_msg05(Config) when is_list(Config) -> +%% put(severity, trc), +%% put(dbg, true), + d("pretty_otp7671_msg05 -> entry", []), + Check = fun(M1, M2) -> cmp_otp7671_msg05(M1, M2) end, + ok = pretty_otp7671( pretty_otp7671_msg05(), [] , ok, ok, Check), +%% erase(dbg), +%% erase(severity), + ok. + +pretty_otp7671(Msg, Conf) -> + pretty_otp7671(Msg, Conf, ok). + +pretty_otp7671(Msg, Conf, ExpectedEncode) -> + pretty_otp7671(Msg, Conf, ExpectedEncode, ok). + +pretty_otp7671(Msg, Conf, ExpectedEncode, ExpectedDecode) -> + otp7671(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode). + +pretty_otp7671(Msg, Conf, ExpectedEncode, ExpectedDecode, Check) -> + otp7671(Msg, megaco_pretty_text_encoder, Conf, + ExpectedEncode, ExpectedDecode, Check). + +otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode) -> + Check = fun(M1, M2) -> + exit({unexpected_decode_result, M1, M2}) + end, + otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode, Check). + +otp7671(Msg, Codec, Conf, ExpectedEncode, ExpectedDecode, Check) -> + case (catch encode_message(Codec, Conf, Msg)) of + {error, _Reason} when ExpectedEncode =:= error -> + ok; + {error, Reason} when ExpectedEncode =:= ok -> + exit({unexpected_encode_failure, Reason}); + {ok, Bin} when ExpectedEncode =:= error -> + exit({unexpected_encode_success, Msg, binary_to_list(Bin)}); + {ok, Bin} when ExpectedEncode =:= ok -> + case decode_message(Codec, false, Conf, Bin) of + {ok, Msg} when ExpectedDecode =:= ok -> + ok; + {ok, Msg2} when ExpectedDecode =:= ok -> + Check(Msg, Msg2); + {ok, Msg} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg}); + {ok, Msg2} when ExpectedDecode =:= error -> + exit({unexpected_decode_success, Msg, Msg2}); + {error, _Reason} when ExpectedDecode =:= error -> + ok; + {error, Reason} when ExpectedDecode == ok -> + exit({unexpected_decode_failure, Msg, Reason}) + end + end. + + +pretty_otp7671_msg(DigitMapDesc) -> + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{digitMapDescriptor, DigitMapDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(?MGC_MID, 10001, ?megaco_null_context_id, [CmdReq]). + +pretty_otp7671_msg01() -> + Name = "dialplan01", + DigitMapDesc = cre_DigitMapDesc(Name), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg02() -> + Name = "dialplan02", + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body), + DigitMapDesc = cre_DigitMapDesc(Name, Value), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg03() -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body), + DigitMapDesc = cre_DigitMapDesc(Value), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg04() -> + DigitMapDesc = cre_DigitMapDesc(), + pretty_otp7671_msg(DigitMapDesc). + +pretty_otp7671_msg05() -> + {'MegacoMessage',asn1_NOVALUE, + {'Message',?VERSION, + {domainName,{'DomainName',"tgc",asn1_NOVALUE}}, + {transactions, + [{transactionRequest, + {'TransactionRequest',12582952, + [{'ActionRequest',0,asn1_NOVALUE,asn1_NOVALUE, + [{'CommandRequest', + {modReq, + {'AmmRequest', + [{megaco_term_id,false,["root"]}], + [{digitMapDescriptor, + {'DigitMapDescriptor',"dialplan1", + {'DigitMapValue',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,[], + asn1_NOVALUE}}}]}}, + asn1_NOVALUE,asn1_NOVALUE}]}]}}]}}}. + +cmp_otp7671_msg05(#'MegacoMessage'{authHeader = asn1_NOVALUE, + mess = M1}, + #'MegacoMessage'{authHeader = asn1_NOVALUE, + mess = M2}) -> + #'Message'{messageBody = Body1} = M1, + #'Message'{messageBody = Body2} = M2, + {transactions, Trans1} = Body1, + {transactions, Trans2} = Body2, + [{transactionRequest, TR1}] = Trans1, + [{transactionRequest, TR2}] = Trans2, + #'TransactionRequest'{actions = Acts1} = TR1, + #'TransactionRequest'{actions = Acts2} = TR2, + [#'ActionRequest'{commandRequests = CR1}] = Acts1, + [#'ActionRequest'{commandRequests = CR2}] = Acts2, + [#'CommandRequest'{command = Cmd1}] = CR1, + [#'CommandRequest'{command = Cmd2}] = CR2, + {modReq, #'AmmRequest'{descriptors = Descs1}} = Cmd1, + {modReq, #'AmmRequest'{descriptors = Descs2}} = Cmd2, + [{digitMapDescriptor, + #'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value1}}] = Descs1, + [{digitMapDescriptor, + #'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Value2}}] = Descs2, + #'DigitMapValue'{startTimer = asn1_NOVALUE, + shortTimer = asn1_NOVALUE, + longTimer = asn1_NOVALUE, + digitMapBody = [], + durationTimer = asn1_NOVALUE} = Value1, + asn1_NOVALUE = Value2, + ok. + + +%% -------------------------------------------------------------- +%% + + +pretty_otp8114_msg01(suite) -> + []; +pretty_otp8114_msg01(Config) when is_list(Config) -> + put(severity, trc), + put(dbg, true), + d("pretty_otp8114_msg01 -> entry", []), + ok = otp8114( pretty_otp8114_msg01(), megaco_pretty_text_encoder, ?EC), + erase(dbg), + erase(severity), + ok. + +pretty_otp8114_msg01() -> + "MEGACO/" ?VERSION_STR " [10.10.10.10]:1234\nTransaction = 1 {\n\tContext =\n1 {\n\t\tModify = ip/1/1/1 {\n\t\t\tMedia {\n\t\t\t\tStream = 1\n{\n\t\t\t\t\t\tLocalControl {\n\t\t\t\t\t\tMode =\nSendReceive\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tEvents = 1\n{\n\t\t\t\tadid/ipstop\n{\n\t\t\t\t\tdt=30,\n\t\t\t\t\tdir=\"BOTH\"\n\t\t\t\t},\n\t\t\t\tg/cause\n\n\t\t\t}\n\t\t}\n\t}\n}". + + +otp8114(InitialMessage, Codec, Conf) -> + Decode = fun(M) -> Codec:decode_message(Conf, M) end, + Encode = fun(B) -> Codec:encode_message(Conf, B) end, + InitialData = InitialMessage, + Instructions = + [ + %% List to binary + megaco_codec_test_lib:expect_instruction( + "Convert (initial) message to a binary", + fun(Msg) when is_list(Msg) -> + %% io:format("~s~n", [Msg]), + {ok, list_to_binary(Msg)}; + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Bin}, _Msg) when is_binary(Bin) -> + {ok, Bin}; + (Bad, _Msg) -> + {error, {failed_to_binary, Bad}} + end), + + %% Initial decode + megaco_codec_test_lib:expect_instruction( + "Decode (initial) message", + fun(Bin) when is_binary(Bin) -> + (catch Decode(Bin)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Msg}, _Bin) when is_record(Msg, 'MegacoMessage') -> + %% io:format("~p~n", [Msg]), + {ok, Msg}; + (Bad, _) -> + {error, {initial_decode_failed, Bad}} + end), + + %% Encode + megaco_codec_test_lib:expect_instruction( + "Encode message", + fun(Msg) when is_record(Msg, 'MegacoMessage') -> + (catch Encode(Msg)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Bin}, _Msg) when is_binary(Bin) -> + %% io:format("~s~n", [binary_to_list(Bin)]), + {ok, Bin}; + (Bad, _) -> + {error, {encode_failed, Bad}} + end), + + %% Decode + megaco_codec_test_lib:expect_instruction( + "(final) Decode message", + fun(Bin) when is_binary(Bin) -> + (catch Decode(Bin)); + (Bad) -> + {error, {invalid_data, Bad}} + end, + fun({ok, Msg}, _Bin) when is_record(Msg, 'MegacoMessage') -> + %% io:format("~p~n", [Msg]), + {ok, Msg}; + (Bad, _) -> + {error, {decode_failed, Bad}} + end) + ], + megaco_codec_test_lib:expect_exec(Instructions, InitialData). + + +%% ============================================================== +%% +%% F l e x P r e t t y T e s t c a s e s +%% + +flex_pretty_otp5042_msg1(suite) -> + []; +flex_pretty_otp5042_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5042_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + ok = ticket_pretty_decode_only( pretty_otp5042_msg1() ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +flex_pretty_otp5085_msg1(suite) -> + []; +flex_pretty_otp5085_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5085_msg2(suite) -> + []; +flex_pretty_otp5085_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5085_msg3(suite) -> + []; +flex_pretty_otp5085_msg3(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg3 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5085_msg4(suite) -> + []; +flex_pretty_otp5085_msg4(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg4 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5085_msg5(suite) -> + []; +flex_pretty_otp5085_msg5(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg5 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5085_msg6(suite) -> + []; +flex_pretty_otp5085_msg6(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg6 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5085_msg7(suite) -> + []; +flex_pretty_otp5085_msg7(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg7 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5085_msg8(suite) -> + []; +flex_pretty_otp5085_msg8(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5085_msg8 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5085_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +flex_pretty_otp5600_msg1(suite) -> + []; +flex_pretty_otp5600_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5600_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5600_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5600_msg2(suite) -> + []; +flex_pretty_otp5600_msg2(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5600_msg2 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5600_msg2(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +flex_pretty_otp5601_msg1(suite) -> + []; +flex_pretty_otp5601_msg1(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5601_msg1 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5601_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +flex_pretty_otp5793_msg01(suite) -> + []; +flex_pretty_otp5793_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5793_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( pretty_otp5793_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +flex_pretty_otp5803_msg01(suite) -> + []; +flex_pretty_otp5803_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5803_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_decode_encode_ok( pretty_otp5803_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + +flex_pretty_otp5803_msg02(suite) -> + []; +flex_pretty_otp5803_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5803_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_decode_encode_ok( pretty_otp5803_msg2(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +flex_pretty_otp5805_msg01(suite) -> + []; +flex_pretty_otp5805_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5805_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_decode_error( pretty_otp5805_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + + +%% -------------------------------------------------------------- +%% +flex_pretty_otp5836_msg01(suite) -> + []; +flex_pretty_otp5836_msg01(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp5836_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + ok = ticket_pretty_encode_decode_ok( compact_otp5836_msg1(), [Conf] ), + %% erase(severity), + %% erase(dbg), + ok. + + +flex_pretty_otp7431_msg01(suite) -> + []; +flex_pretty_otp7431_msg01(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg01 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(ok, flex_pretty_otp7431_msg1(), [Conf]). + +flex_pretty_otp7431_msg02(suite) -> + []; +flex_pretty_otp7431_msg02(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp7431_msg02 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg2(), [Conf]). + +flex_pretty_otp7431_msg03(suite) -> + []; +flex_pretty_otp7431_msg03(Config) when is_list(Config) -> + %% put(severity,trc), + %% put(dbg,true), + d("flex_pretty_otp7431_msg03 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg3(), [Conf]). + +flex_pretty_otp7431_msg04(suite) -> + []; +flex_pretty_otp7431_msg04(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg04 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg4(), [Conf]). + +flex_pretty_otp7431_msg05(suite) -> + []; +flex_pretty_otp7431_msg05(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg05 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg5(), [Conf]). + +flex_pretty_otp7431_msg06(suite) -> + []; +flex_pretty_otp7431_msg06(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg06 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg6(), [Conf]). + +flex_pretty_otp7431_msg07(suite) -> + []; +flex_pretty_otp7431_msg07(Config) when is_list(Config) -> + d("flex_pretty_otp7431_msg07 -> entry", []), + ?ACQUIRE_NODES(1, Config), + Conf = flex_scanner_conf(Config), + flex_pretty_otp7431(error, flex_pretty_otp7431_msg7(), [Conf]). + +flex_pretty_otp7431(Expected, Msg, Conf) -> + otp7431(Expected, megaco_pretty_text_encoder, Msg, Conf). + +otp7431(Expected, Codec, Msg0, Conf0) -> + Bin0 = list_to_binary(Msg0), + Conf = [?EC_V3|Conf0], + case decode_message(Codec, false, Conf, Bin0) of + {ok, _Msg1} when Expected =:= ok -> + io:format(" decoded", []); + {error, {bad_property_parm, Reason}} when (Expected =:= error) andalso + is_list(Reason) -> + io:format("expected result: ~s", [Reason]), + ok; + Else -> + io:format("unexpected result", []), + exit({unexpected_decode_result, Else}) + end. + + +flex_pretty_otp7431_msg1() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a=recvonly + } ; RTP profile for G.723.1 is 4 + } + } + } + } + }". + +flex_pretty_otp7431_msg2() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a= } + } + } + } + } + }". + +flex_pretty_otp7431_msg3() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a } + } + } + } + } + }". + +flex_pretty_otp7431_msg4() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v=0 + o=- 2890844526 2890842807 IN IP4 124.124.124.222 + s=- + t= 0 0 + c=IN IP4 124.124.124.222 + m=audio 2222 RTP/AVP 4 + a=ptime:30 + a} + } + } + } + } + }". + +flex_pretty_otp7431_msg5() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v= } + } + } + } + } + }". + +flex_pretty_otp7431_msg6() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v } + } + } + } + } + }". + +flex_pretty_otp7431_msg7() -> + "MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { + v} + } + } + } + } + }". + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +msgs() -> + [M || {_, M, _, _} <- msgs(text)]. + +msgs(Encoding) -> + msgs1a(Encoding) ++ + msgs1b(Encoding) ++ + msgs3525(Encoding) ++ + msgs5(Encoding) ++ + msgs6(Encoding) ++ + msgs7(Encoding) ++ + msgs8(Encoding). + +msgs1a(_) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [ + {msg01a, msg1a(), Plain, [{dbg,false}]}, + {msg01b, msg1b(), Plain, [{dbg,false}]}, + {msg02, msg2(), Plain, [{dbg,false}]}, + {msg03, msg3(), Plain, [{dbg,false}]}, + {msg04, msg4(), Plain, [{dbg,false}]}, + {msg05, msg5(), Plain, [{dbg,false}]}, + {msg06a, msg6a(), Plain, [{dbg,false}]}, + {msg06b, msg6b(), Plain, [{dbg,false}]}, + {msg07, msg7(), Plain, [{dbg,false}]}, + {msg08a, msg8a(), Plain, [{dbg,false}]}, + {msg08b, msg8b(), Plain, [{dbg,false}]}, + {msg09, msg9(), Plain, [{dbg,false}]}, + {msg10, msg10(), Plain, [{dbg,false}]}, + {msg11, msg11(), Plain, [{dbg,false}]}, + {msg12, msg12(), Plain, [{dbg,false}]}, + {msg13, msg13(), Plain, [{dbg,false}]}, + {msg14, msg14(), Plain, [{dbg,false}]}, + {msg15, msg15(), Plain, [{dbg,false}]}, + {msg16, msg16(), Plain, [{dbg,false}]}, + {msg17, msg17(), Plain, [{dbg,false}]}, + {msg18, msg18(), Plain, [{dbg,false}]}, + {msg19, msg19(), Plain, [{dbg,false}]}, + {msg20, msg20(), Plain, [{dbg,false}]}, + {msg21, msg21(), Plain, [{dbg,false}]}, + {msg22a, msg22a(), Plain, [{dbg,false}]}, + {msg22b, msg22b(), Plain, [{dbg,false}]}, + {msg22c, msg22c(), Plain, [{dbg,false}]}, + {msg22d, msg22d(), Plain, [{dbg,false}]}, + {msg22e, msg22e(), Plain, [{dbg,false}]}, + {msg22f, msg22f(), Plain, [{dbg,false}]}, + {msg23a, msg23a(), Plain, [{dbg,false}]}, + {msg23b, msg23b(), Plain, [{dbg,false}]}, + {msg23c, msg23c(), Plain, [{dbg,false}]}, + {msg23d, msg23d(), Plain, [{dbg,false}]}, + {msg24, msg24(), Plain, [{dbg,false}]}, + {msg25, msg25(), Plain, [{dbg,false}]}, + {msg30a, msg30a(), Plain, [{dbg,false}]}, + {msg30b, msg30b(), Plain, [{dbg,false}]}, + {msg30c, msg30c(), Plain, [{dbg,false}]}, + {msg30d, msg30d(), Plain, [{dbg,false}]} + ]. + + +msgs1b(_) -> + TransFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:trans_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + ActionsFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:actions_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + ActionFirst = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:action_first_encode_decode(Codec, DD, + Ver, EC, M) + end, + [ + {msg01a_tf, msg1a(), TransFirst, [{dbg,false}]}, + {msg02_tf, msg2(), TransFirst, [{dbg,false}]}, + {msg10_tf, msg10(), TransFirst, [{dbg,false}]}, + {msg11_tf, msg11(), TransFirst, [{dbg,false}]}, + {msg23d_tf, msg23d(), TransFirst, [{dbg,false}]}, + {msg30b_tf, msg30b(), TransFirst, [{dbg,false}]}, + {msg30c_tf, msg30c(), TransFirst, [{dbg,false}]}, + {msg01a_asf, msg1a(), ActionsFirst, [{dbg,false}]}, + {msg02_asf, msg2(), ActionsFirst, [{dbg,false}]}, + {msg10_asf, msg10(), ActionsFirst, [{dbg,false}]}, + {msg23d_asf, msg23d(), ActionsFirst, [{dbg,false}]}, + {msg01a_af, msg1a(), ActionFirst, [{dbg,false}]}, + {msg02_af, msg2(), ActionFirst, [{dbg,false}]}, + {msg10_af, msg10(), ActionFirst, [{dbg,false}]}, + {msg23d_af, msg23d(), ActionFirst, [{dbg,false}]} + ]. + + +msgs3525(_) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [{msgs3_name(Name), rfc3525_decode(M), Plain, [{dbg, false}]} || + {Name, M} <- rfc3525_msgs()]. + +msgs3_name(N) -> + list_to_atom("rfc3525_" ++ atom_to_list(N)). + +rfc3525_decode(M) when is_list(M) -> + rfc3525_decode(list_to_binary(M)); +rfc3525_decode(M) when is_binary(M) -> + case (catch decode_message(megaco_pretty_text_encoder, false, ?EC, M)) of + {ok, Msg} -> + Msg; + Error -> + {error, {rfc3525_decode_error, Error}} + end. + + +msgs5(_) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + [ + {msg51a, msg51a(), Plain, [{dbg, false}]}, + {msg51b, msg51b(), Plain, [{dbg, false}]}, + {msg51c, msg51c(), Plain, [{dbg, false}]}, + {msg51d, msg51d(), Plain, [{dbg, false}]}, + {msg51e, msg51e(), Plain, [{dbg, false}]}, + {msg51f, msg51f(), Plain, [{dbg, false}]}, + {msg51g, msg51g(), Plain, [{dbg, false}]}, + {msg51h, msg51h(), Plain, [{dbg, false}]}, + {msg51i, msg51i(), Plain, [{dbg, false}]}, + {msg52, msg52(), Plain, [{dbg, false}]}, + {msg53, msg53(), Plain, [{dbg, false}]}, + {msg54a, msg54a(), Plain, [{dbg, false}]}, + {msg54b, msg54b(), Plain, [{dbg, false}]}, + {msg54c, msg54c(), Plain, [{dbg, false}]}, + {msg55, msg55(), Plain, [{dbg, false}]}, + {msg56, msg56(), Plain, [{dbg, false}]}, + {msg57, msg57(), Plain, [{dbg, false}]}, + {msg58a, msg58a(), Plain, [{dbg, false}]}, + {msg58b, msg58b(), Plain, [{dbg, false}]} + ]. + + +msgs6(Encoding) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + + PlainEDFail = + fun(Codec, DD, Ver, EC, M) -> + Res = + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M), + case Res of + {error, {message_encode_failed, Reason, _M}} -> + case Reason of + {error, {{deprecated, _}, _}} -> + ok; + _ -> + Res + end; + _ -> + Res + end + end, + + PlainDE = + fun(Codec, _DD, Ver, EC, B) -> + Res = + megaco_codec_test_lib:decode_message(Codec, false, Ver, + EC, B), + case Res of + {ok, M} -> + #'MegacoMessage'{mess = Mess} = M, + #'Message'{messageBody = {transactions, TRs}} = Mess, + [{transactionRequest, TR}] = TRs, + #'TransactionRequest'{actions = Actions} = TR, + [Action] = Actions, + #'ActionRequest'{commandRequests = CmdReqs} = Action, + [CmdReq] = CmdReqs, + #'CommandRequest'{command = Cmd} = CmdReq, + {addReq,AmmReq} = Cmd, + #'AmmRequest'{descriptors = []} = AmmReq, + ok; + _ -> + Res + end + end, + + Msgs = + [ + {msg61a, msg61a(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg61b, msg61b(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg61c, msg61c(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg62a, msg62a(), PlainEDFail, [{dbg,false}],[text,binary,erlang]}, + {msg62b, msg62b(), PlainDE, [{dbg,false}],[text]} + ], + [{N,M,F,C}||{N,M,F,C,E} <- Msgs,lists:member(Encoding,E)]. + + +msgs7(Encoding) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + + Msgs = + [ + {msg71a, msg71a(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b01, msg71b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b02, msg71b02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b03, msg71b03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b04, msg71b04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b05, msg71b05(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b06, msg71b06(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b07, msg71b07(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b08, msg71b08(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b09, msg71b09(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b10, msg71b10(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b11, msg71b11(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b12, msg71b12(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b13, msg71b13(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b14, msg71b14(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b15, msg71b15(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b16, msg71b16(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b17, msg71b17(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b18, msg71b18(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b19, msg71b19(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b20, msg71b20(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b21, msg71b21(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71b22, msg71b22(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c01, msg71c01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c02, msg71c02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c03, msg71c03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c04, msg71c04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c05, msg71c05(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c06, msg71c06(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c07, msg71c07(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c08, msg71c08(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c09, msg71c09(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c10, msg71c10(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c11, msg71c11(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c12, msg71c12(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c13, msg71c13(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c14, msg71c14(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71c15, msg71c15(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71d01, msg71d01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71d02, msg71d02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71d03, msg71d03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg71d04, msg71d04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72a01, msg72a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72a02, msg72a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72a03, msg72a03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72b01, msg72b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72b02, msg72b02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72b03, msg72b03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72b04, msg72b04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72c01, msg72c01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72c02, msg72c02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72c03, msg72c03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg72c04, msg72c04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73a, msg73a(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73b01, msg73b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73b02, msg73b02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73c01, msg73c01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg73c02, msg73c02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a01, msg74a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a02, msg74a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a03, msg74a03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a04, msg74a04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a05, msg74a05(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg74a06, msg74a06(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg75a01, msg75a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg75a02, msg75a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg76a01, msg76a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg76a02, msg76a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg76b01, msg76b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + %% {msg76b02, msg76b02(), Plain, [{dbg,true}],[text,binary,erlang]}, + {msg77a01, msg77a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a01, msg78a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a02, msg78a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a03, msg78a03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a04, msg78a04(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a05, msg78a05(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a06, msg78a06(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a07, msg78a07(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a08, msg78a08(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg78a09, msg78a09(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg79a01, msg79a01(), Plain, [{dbg,false}],[text,binary,erlang]} + ], + [{N,M,F,C}||{N,M,F,C,E} <- Msgs,lists:member(Encoding,E)]. + + +msgs8(Encoding) -> + Plain = + fun(Codec, DD, Ver, EC, M) -> + megaco_codec_test_lib:plain_encode_decode(Codec, DD, Ver, + EC, M) + end, + + Msgs = + [ + {msg80a01, msg80a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg80a02, msg80a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg80a03, msg80a03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg80b01, msg80b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg80b02, msg80b02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg80b03, msg80b03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg81a01, msg81a01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg81a02, msg81a02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg81a03, msg81a03(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg81b01, msg81b01(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg81b02, msg81b02(), Plain, [{dbg,false}],[text,binary,erlang]}, + {msg81b03, msg81b03(), Plain, [{dbg,false}],[text,binary,erlang]} + ], + [{N,M,F,C}||{N,M,F,C,E} <- Msgs,lists:member(Encoding,E)]. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +msg_actions([], Actions) -> + lists:reverse(Actions); +msg_actions([{CtxId, CmdReqs}|ActionInfo], Actions) -> + Action = ?MSG_LIB:cre_ActionRequest(CtxId,CmdReqs), + msg_actions(ActionInfo, [Action|Actions]). + +megaco_trans_req([], Transactions) -> + {transactions, lists:reverse(Transactions)}; +megaco_trans_req([{TransId, ActionInfo}|TransInfo], Transactions) -> + Actions = msg_actions(ActionInfo, []), + TR = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + megaco_trans_req(TransInfo, [Trans|Transactions]). + +megaco_message(Version, Mid, Body) -> + Mess = ?MSG_LIB:cre_Message(Version, Mid, Body), + cre_MegacoMessage(Mess). + +msg_request(Mid, TransInfo) -> + TransReq = megaco_trans_req(TransInfo, []), + megaco_message(?VERSION, Mid, TransReq). + +msg_request(Mid, TransId, ContextId, CmdReq) -> + Action = ?MSG_LIB:cre_ActionRequest(ContextId, CmdReq), + Actions = [Action], + TR = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg_request(Auth, Mid, TransId, ContextId, CmdReq) -> + Action = ?MSG_LIB:cre_ActionRequest(ContextId, CmdReq), + Actions = [Action], + TR = ?MSG_LIB:cre_TransactionRequest(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + cre_MegacoMessage(Auth, Mess). + +msg_reply(Mid, TransId, Actions) -> + TR = cre_TransRep(TransId, Actions), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg_reply(Mid, TransId, ContextId, CmdReply) -> + Action = cre_ActRep(ContextId, CmdReply), + Actions = [Action], + msg_reply(Mid, TransId, Actions). + +msg_ack(Mid, [Range|_] = Ranges) when is_tuple(Range) -> + msg_ack(Mid, [Ranges]); + +msg_ack(Mid, Ranges) -> + %% TRAs = make_tras(Ranges, []), + TRAs = make_tras(Ranges), + Req = {transactions, TRAs}, + cre_MegacoMessage(?VERSION, Mid, Req). + +make_tras(TRARanges) -> + F = fun(R) -> {transactionResponseAck, make_tra(R)} end, + lists:map(F, TRARanges). + +make_tra(Ranges) -> + F = fun({F,L}) -> cre_TransAck(F,L) end, + lists:map(F, Ranges). + + +%% ------------------------------------------------------------------------- + + +msg1(Mid, Tid) -> + Gain = cre_PropParm("tdmc/gain", "2"), + Ec = cre_PropParm("tdmc/ec", "g165"), + LCD = cre_LocalControlDesc(sendRecv,[Gain, Ec]), + V = cre_PropParm("v", "0"), + %% C = cre_PropParm("c", "IN IP4 $ "), + C = cre_PropParm("c", [$I,$N,$ ,$I,$P,$4,$ ,$$,$ ]), + M = cre_PropParm("m", "audio $ RTP/AVP 0"), + A = cre_PropParm("a", "fmtp:PCMU VAD=X-NNVAD"), + LD = cre_LocalRemoteDesc([[V, C, M, A]]), + Parms = cre_StreamParms(LCD,LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + ReqEvent = cre_ReqEv("al/of"), + EventsDesc = cre_EvsDesc(2222,[ReqEvent]), + AmmReq = cre_AmmReq([#megaco_term_id{id = Tid}], + [{mediaDescriptor, MediaDesc}, + {eventsDescriptor, EventsDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + Msg = msg_request(Mid, 9999, ?megaco_null_context_id, [CmdReq]), + Msg. + +msg1a() -> + msg1a(?MGC_MID). +msg1a(Mid) -> + msg1(Mid, ?A4444). + +msg1b() -> + msg1b(?MGC_MID). +msg1b(Mid) -> + msg1(Mid, ?A4445). + + +%% -------------------------- + + +msg2() -> + msg2(?MGC_MID). +msg2(Mid) -> + msg2(Mid, ?A4444). +msg2(Mid, Tid) -> + Gain = cre_PropParm("tdmc/gain", "2"), + Ec = cre_PropParm("tdmc/ec", "g165"), + LCD = cre_LocalControlDesc(sendRecv,[Gain, Ec]), + V = cre_PropParm("v", "0"), + %% C = cre_PropParm("c", "IN IP4 $ "), + C = cre_PropParm("c", [$I,$N,$ ,$I,$P,$4,$ ,$$,$ ]), + M = cre_PropParm("m", "audio $ RTP/AVP 0"), + A = cre_PropParm("a", "fmtp:PCMU VAD=X-NNVAD"), + LD = cre_LocalRemoteDesc([[V, C, M, A]]), + Parms = cre_StreamParms(LCD,LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + EventParm = cre_EvParm("strict",["exact"]), + ReqEvent = cre_ReqEv("al/of", [EventParm]), + EventsDesc = cre_EvsDesc(2222,[ReqEvent]), + AmmReq = cre_AmmReq([#megaco_term_id{id = Tid}], + [{mediaDescriptor, MediaDesc}, + {eventsDescriptor, EventsDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 9999, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg3() -> + msg3(?MG1_MID). +msg3(Mid) -> + TimeStamp = cre_TimeNot("19990729", "22000000"), + Event = cre_ObsEv("al/of",TimeStamp), + Desc = cre_ObsEvsDesc(2222,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 10000, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg4() -> + msg4(?MG1_MID_NO_PORT, "901 mg col boot"). +msg4(Mid, Reason) when is_list(Reason) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChParm(restart,Address,[Reason],Profile), + Req = cre_SvcChReq([?megaco_root_termination_id],Parm), + CmdReq = cre_CmdReq({serviceChangeReq, Req}), + msg_request(Mid, 9998, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg5() -> + msg5(?MGC_MID). +msg5(Mid) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChResParm(Address,Profile), + Reply = cre_SvcChRep([?megaco_root_termination_id], + {serviceChangeResParms,Parm}), + msg_reply(Mid, 9998, ?megaco_null_context_id, + [{serviceChangeReply, Reply}]). + + +%% -------------------------- + +msg6(Mid, Tid) -> + Reply = cre_AmmsReply([#megaco_term_id{id = Tid}]), + msg_reply(Mid, 9999, ?megaco_null_context_id, [{modReply, Reply}]). + +msg6a() -> + msg6a(?MG1_MID). +msg6a(Mid) -> + msg6(Mid, ?A4444). + +msg6b() -> + msg6b(?MG2_MID). +msg6b(Mid) -> + msg6(Mid, ?A5555). + + +%% -------------------------- + +msg7() -> + msg7(?MGC_MID). +msg7(Mid) -> + Reply = cre_NotifyRep([#megaco_term_id{id = ?A4444}]), + msg_reply(Mid, 10000, ?megaco_null_context_id, [{notifyReply, Reply}]). + + +%% -------------------------- + +msg8(Mid, DigitMapValue) -> + Strict = cre_EvParm("strict",["state"]), + On = cre_ReqEv("al/on", [Strict]), + Name = "dialplan00", + EDM = cre_EvDM(Name), + Action = cre_ReqActs(EDM), + Ce = cre_ReqEv("dd/ce", Action), + EventsDesc = cre_EvsDesc(2223, [On, Ce]), + Signal = cre_Sig("cg/rt"), + DigMapDesc = cre_DigitMapDesc(Name, DigitMapValue), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, [{signal, Signal}]}, + {digitMapDescriptor, DigMapDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 10001, ?megaco_null_context_id, [CmdReq]). + +msg8a() -> + msg8a(?MGC_MID). +msg8a(Mid) -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body), + msg8(Mid, Value). + +msg8b() -> + msg8b(?MGC_MID). +msg8b(Mid) -> + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + Value = cre_DigitMapValue(Body, 1, 23, 99), + msg8(Mid, Value). + + +%% -------------------------- + +msg9() -> + msg9(?MG1_MID). +msg9(Mid) -> + TimeStamp = cre_TimeNot("19990729","22010001"), + Parm = cre_EvParm("ds",["916135551212"]), + Event = cre_ObsEv("dd/ce",TimeStamp,[Parm]), + Desc = cre_ObsEvsDesc(2223,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A4444}], Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 10002, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg10() -> + msg10(?MGC_MID). +msg10(Mid) -> + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}],[]), + CmdReq = cre_CmdReq({addReq, AmmReq}), + Jit = cre_PropParm("nt/jit", "40"), + LCD = cre_LocalControlDesc(recvOnly,[Jit]), + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 $ "), + M = cre_PropParm("m", "audio $ RTP/AVP 4"), + A = cre_PropParm("a", "ptime:30"), + V2 = cre_PropParm("v", "0"), + C2 = cre_PropParm("c", "IN IP4 $ "), + M2 = cre_PropParm("m", "audio $ RTP/AVP 0"), + LD = cre_LocalRemoteDesc([[V, C, M, A], [V2, C2, M2]]), + Parms = cre_StreamParms(LCD, LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + ChooseTid = #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}, + AmmReq2 = cre_AmmReq([ChooseTid],[{mediaDescriptor, MediaDesc}]), + CmdReq2 = cre_CmdReq({addReq, AmmReq2}), + msg_request(Mid, 10003, ?megaco_choose_context_id, [CmdReq, CmdReq2]). + + +msg11() -> + msg11(?MG1_MID). +msg11(Mid) -> + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 124.124.124.222"), + M = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + A = cre_PropParm("a", "ptime:30"), + A2 = cre_PropParm("a", "recvonly"), + LD = cre_LocalRemoteDesc([[V, C, M, A, A2]]), + Parms = cre_StreamParmsL(LD), + StreamDesc = cre_StreamDesc(1, Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + msg_reply(Mid, 10003, 2000, [{addReply, Reply}, {addReply, Reply2}]). + + +%% -------------------------- + +msg12() -> + msg12(?MGC_MID). +msg12(Mid) -> + LCD = cre_LocalControlDesc(sendRecv), + Parms = cre_StreamParms(LCD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Signal = cre_Sig("al/ri"), + Descs = [{mediaDescriptor, MediaDesc}, + {signalsDescriptor, [{signal, Signal}]}], + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A5555}], Descs), + CmdReq = cre_CmdReq({addReq, AmmReq}), + Jit = cre_PropParm("nt/jit", "40"), + LCD2 = cre_LocalControlDesc(sendRecv, [Jit]), + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 $ "), + M = cre_PropParm("m", "audio $ RTP/AVP 4"), + A = cre_PropParm("a", "ptime:30"), + LD2 = cre_LocalRemoteDesc([[V, C, M, A]]), + V2 = cre_PropParm("v", "0"), + C2 = cre_PropParm("c", "IN IP4 124.124.124.222"), + M2 = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + RD2 = cre_LocalRemoteDesc([[V2, C2, M2]]), + Parms2 = cre_StreamParms(LCD2,LD2,RD2), + StreamDesc2 = cre_StreamDesc(1,Parms2), + MediaDesc2 = cre_MediaDesc(StreamDesc2), + ChooseTid = #megaco_term_id{contains_wildcards = true, + id = [[?megaco_choose]]}, + AmmReq2 = cre_AmmReq([ChooseTid],[{mediaDescriptor, MediaDesc2}]), + CmdReq2 = cre_CmdReq({addReq, AmmReq2}), + msg_request(Mid, 50003, ?megaco_choose_context_id, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg13() -> + msg13(?MG2_MID). +msg13(Mid) -> + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 125.125.125.111"), + M = cre_PropParm("m", "audio 1111 RTP/AVP 4"), + LD = cre_LocalRemoteDesc([[V, C, M]]), + Parms = cre_StreamParmsL(LD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Reply = cre_AmmsReply([#megaco_term_id{id = ?A5556}], + [{mediaDescriptor, MediaDesc}]), + msg_reply(Mid, 50003, 5000, [{addReply, Reply}]). + + +%% -------------------------- + +msg14() -> + msg14(?MGC_MID). +msg14(Mid) -> + Signal = cre_Sig("cg/rt"), + AmmReq1 = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{signalsDescriptor, [{signal, Signal}]}]), + CmdReq1 = cre_CmdReq({modReq, AmmReq1}), + + Gain = cre_PropParm("tdmc/gain", "2"), + Ec = cre_PropParm("tdmc/ec", "g165"), + LCD = cre_LocalControlDesc(sendRecv, [Gain, Ec]), + Parms2 = cre_StreamParms(LCD), + StreamDesc2 = cre_StreamDesc(1,Parms2), + MediaDesc2 = cre_MediaDesc(StreamDesc2), + AmmReq2 = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc2}]), + CmdReq2 = cre_CmdReq({modReq, AmmReq2}), + + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 125.125.125.111"), + M = cre_PropParm("m", "audio 1111 RTP/AVP 4"), + RD = cre_LocalRemoteDesc([[V, C, M]]), + Parms3 = cre_StreamParmsR(RD), + StreamDesc3 = cre_StreamDesc(2,Parms3), + MediaDesc3 = cre_MediaDesc(StreamDesc3), + AmmReq3 = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc3}]), + CmdReq3 = cre_CmdReq({modReq, AmmReq3}), + msg_request(Mid, 10005, 2000, [CmdReq1, CmdReq2, CmdReq3]). + + +%% -------------------------- + +msg15() -> + msg15(?MG1_MID). +msg15(Mid) -> + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A4445}]), + msg_reply(Mid, 10005, 2000, [{modReply, Reply}, {modReply, Reply2}]). + + +%% -------------------------- + +msg16() -> + msg16(?MG2_MID). +msg16(Mid) -> + TimeStamp = cre_TimeNot("19990729","22020002"), + Event = cre_ObsEv("al/of",TimeStamp), + Desc = cre_ObsEvsDesc(1234,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 50005, 5000, [CmdReq]). + + +%% -------------------------- + +msg17() -> + msg17(?MGC_MID). +msg17(Mid) -> + Reply = cre_NotifyRep([#megaco_term_id{id = ?A5555}]), + msg_reply(Mid, 50005, ?megaco_null_context_id, [{notifyReply, Reply}]). + + +%% -------------------------- + +msg18() -> + msg18(?MGC_MID). +msg18(Mid) -> + On = cre_ReqEv("al/on"), + EventsDesc = cre_EvsDesc(1235,[On]), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A5555}], + [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, []}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(Mid, 50006, 5000, [CmdReq]). + + +%% -------------------------- + +msg19() -> + msg19(?MG2_MID). +msg19(Mid) -> + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4445}]), + msg_reply(Mid, 50006, 5000, [{modReply, Reply}]). + + +%% -------------------------- + +msg20() -> + msg20(?MGC_MID). +msg20(Mid) -> + LCD = cre_LocalControlDesc(sendRecv), + Parms = cre_StreamParms(LCD), + StreamDesc = cre_StreamDesc(1,Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + AmmReq2 = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{signalsDescriptor, []}]), + CmdReq2 = cre_CmdReq({modReq, AmmReq2}), + msg_request(Mid, 10006, 2000, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg21() -> + msg21(?MGC_MID). +msg21(Mid) -> + Tokens = [mediaToken, eventsToken, signalsToken, + digitMapToken, statsToken, packagesToken], + AuditDesc = cre_AuditDesc(Tokens), + Req = cre_AuditReq(#megaco_term_id{id = ?A5556},AuditDesc), + CmdReq = cre_CmdReq({auditValueRequest, Req}), + msg_request(Mid, 50007, ?megaco_null_context_id, [CmdReq]). + + +%% -------------------------- + +msg22a() -> + msg22(1). + +msg22b() -> + msg22(10). + +msg22c() -> + msg22(25). + +msg22d() -> + msg22(50). + +msg22e() -> + msg22(75). + +msg22f() -> + msg22(100). + +msg22(N) -> + msg22(?MG2_MID, N). +msg22(Mid, N) -> + Jit = cre_PropParm("nt/jit", "40"), + LCD = cre_LocalControlDesc(sendRecv,[Jit]), + LDV = cre_PropParm("v", "0"), + LDC = cre_PropParm("c", "IN IP4 125.125.125.111"), + LDM = cre_PropParm("m", "audio 1111 RTP/AVP 4"), + LDA = cre_PropParm("a", "ptime:30"), + LD = cre_LocalRemoteDesc([[LDV, LDC, LDM, LDA]]), + RDV = cre_PropParm("v", "0"), + RDC = cre_PropParm("c", "IN IP4 124.124.124.222"), + RDM = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + RDA = cre_PropParm("a", "ptime:30"), + RD = cre_LocalRemoteDesc([[RDV, RDC, RDM, RDA]]), + StreamParms = cre_StreamParms(LCD,LD,RD), + StreamDesc = cre_StreamDesc(1,StreamParms), + Media = cre_MediaDesc(StreamDesc), + PackagesItem = cre_PkgsItem("nt",1), + PackagesItem2 = cre_PkgsItem("rtp",1), + Stat = cre_StatsParm("rtp/ps","1200"), + Stat2 = cre_StatsParm("nt/os","62300"), + Stat3 = cre_StatsParm("rtp/pr","700"), + Stat4 = cre_StatsParm("nt/or","45100"), + Stat5 = cre_StatsParm("rtp/pl","0.2"), + Stat6 = cre_StatsParm("rtp/jit","20"), + Stat7 = cre_StatsParm("rtp/delay","40"), + Statistics = [Stat, Stat2, Stat3, Stat4, Stat5, Stat6, Stat7], + Audits = [{mediaDescriptor, Media}, + {packagesDescriptor, [PackagesItem, PackagesItem2]}, + {statisticsDescriptor, Statistics}], + Reply = {auditResult, + cre_AuditRes(#megaco_term_id{id = ?A5556},Audits)}, + msg_reply(Mid, 50007, ?megaco_null_context_id, + lists:duplicate(N,{auditValueReply, Reply})). +%% msg_reply(Mid, 50007, ?megaco_null_context_id, +%% lists.duplicate([{auditValueReply, Reply}]). + + +%% -------------------------- + +msg23a() -> + msg23a(?MG2_MID). +msg23a(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq = cre_CmdReq({notifyReq, NotifyReq}), + msg_request(Mid, 50008, 5000, [CmdReq]). + + +msg23b() -> + msg23b(?MG2_MID). +msg23b(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq1 = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_CmdReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_NotifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_CmdReq({notifyReq, NotifyReq2}), + ActionInfo = [{5000, [CmdReq1]}, {5001, [CmdReq2]}], + TransInfo = [{50008, ActionInfo}], + msg_request(Mid, TransInfo). + + +msg23c() -> + msg23c(?MG2_MID). +msg23c(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq1 = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_CmdReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_NotifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_CmdReq({notifyReq, NotifyReq2}), + ActionInfo1 = [{5000, [CmdReq1]}], + ActionInfo2 = [{5001, [CmdReq2]}], + TransInfo = [{50008, ActionInfo1}, {50009, ActionInfo2}], + msg_request(Mid, TransInfo). + + +msg23d() -> + msg23d(?MG2_MID). +msg23d(Mid) -> + TimeStamp = cre_TimeNot("19990729","24020002"), + Event = cre_ObsEv("al/on",TimeStamp), + Desc = cre_ObsEvsDesc(1235,[Event]), + NotifyReq1 = cre_NotifyReq([#megaco_term_id{id = ?A5555}],Desc), + CmdReq1 = cre_CmdReq({notifyReq, NotifyReq1}), + NotifyReq2 = cre_NotifyReq([#megaco_term_id{id = ?A5556}],Desc), + CmdReq2 = cre_CmdReq({notifyReq, NotifyReq2}), + NotifyReq3 = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc), + CmdReq3 = cre_CmdReq({notifyReq, NotifyReq3}), + NotifyReq4 = cre_NotifyReq([#megaco_term_id{id = ?A4445}],Desc), + CmdReq4 = cre_CmdReq({notifyReq, NotifyReq4}), + ActionInfo1 = [{5000, [CmdReq1]}, {5001, [CmdReq2]}], + ActionInfo2 = [{5003, [CmdReq3]}, {5004, [CmdReq4]}], + TransInfo = [{50008, ActionInfo1}, {50009, ActionInfo2}], + msg_request(Mid, TransInfo). + + +%% -------------------------- + +msg24() -> + msg24(?MGC_MID). +msg24(Mid) -> + AuditDesc = cre_AuditDesc([statsToken]), + SubReq = cre_SubReq([#megaco_term_id{id = ?A5555}], AuditDesc), + SubReq2 = cre_SubReq([#megaco_term_id{id = ?A5556}], AuditDesc), + CmdReq = cre_CmdReq({subtractReq, SubReq}), + CmdReq2 = cre_CmdReq({subtractReq, SubReq2}), + msg_request(Mid, 50009, 5000, [CmdReq, CmdReq2]). + + +%% -------------------------- + +msg25() -> + msg25(?MG2_MID). +msg25(Mid) -> + Stat11 = cre_StatsParm("nt/os","45123"), + Stat12 = cre_StatsParm("nt/dur", "40"), + Stats1 = [Stat11, Stat12], + Reply1 = cre_AmmsReply([#megaco_term_id{id = ?A5555}], + [{statisticsDescriptor, Stats1}]), + Stat21 = cre_StatsParm("rtp/ps","1245"), + Stat22 = cre_StatsParm("nt/os", "62345"), + Stat23 = cre_StatsParm("rtp/pr", "780"), + Stat24 = cre_StatsParm("nt/or", "45123"), + Stat25 = cre_StatsParm("rtp/pl", "10"), + Stat26 = cre_StatsParm("rtp/jit", "27"), + Stat27 = cre_StatsParm("rtp/delay","48"), + Stats2 = [Stat21, Stat22, Stat23, Stat24, Stat25, Stat26, Stat27], + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A5556}], + [{statisticsDescriptor, Stats2}]), + msg_reply(Mid, 50009, 5000, + [{subtractReply, Reply1}, {subtractReply, Reply2}]). + + +msg30a() -> + msg_ack(?MG2_MID, [{9,9}]). + +msg30b() -> + msg_ack(?MG2_MID, [{9,13}]). + +msg30c() -> + msg_ack(?MG2_MID, + [{9,13}, {15,15}, {33,40}, {50,60}, {70,80}, {85,90}, + {101,105},{109,119},{121,130},{140,160},{170,175},{180,189}, + {201,205},{209,219},{221,230},{240,260},{270,275},{280,289}, + {301,305},{309,319},{321,330},{340,360},{370,375},{380,389}, + {401,405},{409,419},{421,430},{440,460},{470,475},{480,489}, + {501,505},{509,519},{521,530},{540,560},{570,575},{580,589} + ]). + +%% Don't think this will be used by the megaco stack, but since it +%% seem's to be a valid construction... +msg30d() -> + msg_ack(?MG2_MID, + [[{9,13}, {15,15}, {33,40}, {50,60}, {70,80}, {85,90}], + [{101,105},{109,119},{121,130},{140,160},{170,175},{180,189}], + [{201,205},{209,219},{221,230},{240,260},{270,275},{280,289}], + [{301,305},{309,319},{321,330},{340,360},{370,375},{380,389}], + [{401,405},{409,419},{421,430},{440,460},{470,475},{480,489}], + [{501,505},{509,519},{521,530},{540,560},{570,575},{580,589}] + ]). + + + +msg40() -> + msg40(?MG1_MID_NO_PORT, "901 mg col boot"). +msg40(Mid, Reason) when is_list(Reason) -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChParm(restart,Address,[Reason],Profile), + Req = cre_SvcChReq([?megaco_root_termination_id],Parm), + CmdReq = cre_CmdReq({serviceChangeReq, Req}), + Auth = cre_AuthHeader(), + msg_request(Auth, Mid, 9998, ?megaco_null_context_id, [CmdReq]). + + +msg50(Mid, APT) -> + AD = cre_AuditDesc(asn1_NOVALUE, APT), + Req = cre_AuditReq(#megaco_term_id{id = ?A5556},AD), + CmdReq = cre_CmdReq({auditValueRequest, Req}), + msg_request(Mid, 50007, ?megaco_null_context_id, [CmdReq]). + +%% IndAudMediaDescriptor: +msg51(Mid, IATSDorStream) -> + IAMD = cre_IndAudMediaDesc(IATSDorStream), + IAP = cre_IndAudParam(IAMD), + APT = [IAP], + msg50(Mid, APT). + +msg51a() -> + msg51a(?MG2_MID). +msg51a(Mid) -> + PP = cre_IndAudPropertyParm("tdmc/gain"), + PPs = [PP], + IATSD = cre_IndAudTermStateDesc(PPs), + msg51(Mid, IATSD). + +msg51b() -> + msg51b(?MG2_MID). +msg51b(Mid) -> + PP = cre_IndAudPropertyParm("nt/jit"), + PPs = [PP], + IATSD = cre_IndAudTermStateDesc(PPs), + msg51(Mid, IATSD). + +msg51c() -> + msg51c(?MG2_MID). +msg51c(Mid) -> + IATSD = cre_IndAudTermStateDesc([], asn1_NOVALUE, 'NULL'), + msg51(Mid, IATSD). + +msg51d() -> + msg51d(?MG2_MID). +msg51d(Mid) -> + IATSD = cre_IndAudTermStateDesc([], 'NULL', asn1_NOVALUE), + msg51(Mid, IATSD). + +msg51e() -> + msg51e(?MG2_MID). +msg51e(Mid) -> + IALCD = cre_IndAudLocalControlDesc('NULL', asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE), + IASP = cre_IndAudStreamParms(IALCD), + msg51(Mid, IASP). + +msg51f() -> + msg51f(?MG2_MID). +msg51f(Mid) -> + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, 'NULL', + asn1_NOVALUE, asn1_NOVALUE), + IASP = cre_IndAudStreamParms(IALCD), + msg51(Mid, IASP). + +msg51g() -> + msg51g(?MG2_MID). +msg51g(Mid) -> + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, asn1_NOVALUE, + 'NULL', asn1_NOVALUE), + IASP = cre_IndAudStreamParms(IALCD), + msg51(Mid, IASP). + +msg51h() -> + msg51h(?MG2_MID). +msg51h(Mid) -> + Name = "nt/jit", + IAPP = cre_IndAudPropertyParm(Name), + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, asn1_NOVALUE, + asn1_NOVALUE, [IAPP]), + IASP = cre_IndAudStreamParms(IALCD), + SID = 123, + IASD = cre_IndAudStreamDesc(SID, IASP), + msg51(Mid, [IASD]). + + +msg51i() -> + msg51i(?MG2_MID). +msg51i(Mid) -> + Name = "nt/jit", + Name2 = "tdmc/ec", + IAPP = cre_IndAudPropertyParm(Name), + IAPP2 = cre_IndAudPropertyParm(Name2), + IALCD = cre_IndAudLocalControlDesc('NULL', 'NULL', 'NULL', + [IAPP, IAPP2]), + IASP = cre_IndAudStreamParms(IALCD), + SID = 123, + IASD = cre_IndAudStreamDesc(SID, IASP), + msg51(Mid, [IASD]). + + +%% IndAudEventsDescriptor: +msg52() -> + msg52(?MG2_MID). +msg52(Mid) -> + RequestID = 1235, + PkgdName = "tonedet/std", + IAED = cre_IndAudEvsDesc(RequestID, PkgdName), + IAP = cre_IndAudParam(IAED), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudEventBufferDescriptor: +msg53() -> + msg53(?MG2_MID). +msg53(Mid) -> + EN = "tonedet/std", + SID = 1, + IAEBD = cre_IndAudEvBufDesc(EN, SID), + IAP = cre_IndAudParam(IAEBD), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudSignalsDescriptor: +msg54(Mid, Sig) -> + IASD = cre_IndAudSigsDesc(Sig), + IAP = cre_IndAudParam(IASD), + APT = [IAP], + msg50(Mid, APT). + +msg54a() -> + msg54a(?MG2_MID). +msg54a(Mid) -> + SN = "tonegen/pt", + Sig = cre_IndAudSig(SN), + msg54(Mid, Sig). + +msg54b() -> + msg54b(?MG2_MID). +msg54b(Mid) -> + SN = "dg/d0", + Sig = cre_IndAudSig(SN), + msg54(Mid, Sig). + +msg54c() -> + msg54c(?MG2_MID). +msg54c(Mid) -> + SN = "ct/ct", + Sig = cre_IndAudSig(SN), + ID = 4321, + SSL = cre_IndAudSeqSigList(ID, Sig), + msg54(Mid, SSL). + +%% IndAudDigitMapDescriptor: +msg55() -> + msg55(?MG2_MID). +msg55(Mid) -> + DMN = "dialplan00", + IADMD = cre_IndAudDigitMapDesc(DMN), + IAP = cre_IndAudParam(IADMD), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudStatisticsDescriptor: +msg56() -> + msg56(?MG2_MID). +msg56(Mid) -> + SN = "nt/dur", + IASD = cre_IndAudStatsDesc(SN), + IAP = cre_IndAudParam(IASD), + APT = [IAP], + msg50(Mid, APT). + +%% IndAudPackagesDescriptor: +msg57() -> + msg57(?MG2_MID). +msg57(Mid) -> + PN = "al", + PV = 1, + IAPD = cre_IndAudPkgsDesc(PN, PV), + IAP = cre_IndAudParam(IAPD), + APT = [IAP], + msg50(Mid, APT). + +%% Sum it up: +msg58_iaMediaDesc_iap(IATSD) -> + IAMD = cre_IndAudMediaDesc(IATSD), + cre_IndAudParam(IAMD). + +msg58_iaMediaDesc_iap_a() -> + PP = cre_IndAudPropertyParm("tdmc/gain"), + PPs = [PP], + IATSD = cre_IndAudTermStateDesc(PPs), + msg58_iaMediaDesc_iap(IATSD). + +msg58_iaMediaDesc_iap_b() -> + IATSD = cre_IndAudTermStateDesc([], 'NULL', asn1_NOVALUE), + msg58_iaMediaDesc_iap(IATSD). + +msg58_iaEvsDesc_iap() -> + RequestID = 1235, + PkgdName = "tonedet/std", + IAED = cre_IndAudEvsDesc(RequestID, PkgdName), + cre_IndAudParam(IAED). + +msg58_iaEvBufDesc_iap() -> + EN = "tonedet/std", + SID = 1, + IAEBD = cre_IndAudEvBufDesc(EN, SID), + cre_IndAudParam(IAEBD). + +msg58_iaSigsDesc_iap(S) -> + IASD = cre_IndAudSigsDesc(S), + cre_IndAudParam(IASD). + +msg58_iaSigsDesc_iap_a() -> + SN = "tonegen/pt", + Sig = cre_IndAudSig(SN), + msg58_iaSigsDesc_iap(Sig). + +msg58_iaSigsDesc_iap_b() -> + SN = "ct/ct", + Sig = cre_IndAudSig(SN), + ID = 4321, + SSL = cre_IndAudSeqSigList(ID, Sig), + msg58_iaSigsDesc_iap(SSL). + +msg58_iaDigMapDesc_iap() -> + DMN = "dialplan00", + IADMD = cre_IndAudDigitMapDesc(DMN), + cre_IndAudParam(IADMD). + +msg58_iaStatsDesc_iap() -> + SN = "nt/dur", + IASD = cre_IndAudStatsDesc(SN), + cre_IndAudParam(IASD). + +msg58_iaPacksDesc_iap() -> + PN = "al", + PV = 1, + IAPD = cre_IndAudPkgsDesc(PN, PV), + cre_IndAudParam(IAPD). + +msg58a() -> + msg58a(?MG2_MID). +msg58a(Mid) -> + IAMD = msg58_iaMediaDesc_iap_a(), + IAED = msg58_iaEvsDesc_iap(), + IAEBD = msg58_iaEvBufDesc_iap(), + IASiD = msg58_iaSigsDesc_iap_a(), + IADMD = msg58_iaDigMapDesc_iap(), + IAStD = msg58_iaStatsDesc_iap(), + IAPD = msg58_iaPacksDesc_iap(), + APT = [IAMD, IAED, IAEBD, IASiD, IADMD, IAStD, IAPD], + msg50(Mid, APT). + +msg58b() -> + msg58b(?MG2_MID). +msg58b(Mid) -> + IAMD = msg58_iaMediaDesc_iap_b(), + IAED = msg58_iaEvsDesc_iap(), + IAEBD = msg58_iaEvBufDesc_iap(), + IASiD = msg58_iaSigsDesc_iap_b(), + IADMD = msg58_iaDigMapDesc_iap(), + IAStD = msg58_iaStatsDesc_iap(), + IAPD = msg58_iaPacksDesc_iap(), + APT = [IAMD, IAED, IAEBD, IASiD, IADMD, IAStD, IAPD], + msg50(Mid, APT). + + +%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +%% Tests some of the changes in the v2 corr 1 (EmergencyOff and ModemDesc) + +%% Emergency On/Off (optional) tests +msg61(EM) -> + TS = cre_TimeNot("19990729", "22000000"), + Event = cre_ObsEv("al/of",TS), + Desc = cre_ObsEvsDesc(2222,[Event]), + NotReq = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc), + Cmd = ?MSG_LIB:cre_Command(notifyReq, NotReq), + CmdReq = cre_CmdReq(Cmd), + CtxReq = cre_CtxReq(15, EM), + ActReq = ?MSG_LIB:cre_ActionRequest(1, CtxReq, [CmdReq]), + Acts = [ActReq], + TR = ?MSG_LIB:cre_TransactionRequest(9898, Acts), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, ?MG1_MID, [Trans]), + cre_MegacoMessage(Mess). + +msg61a() -> + msg61(false). + +msg61b() -> + msg61(true). + +msg61c() -> + msg61(asn1_NOVALUE). + + +msg62a() -> + MT = ?MSG_LIB:cre_ModemType(v18), + PP = cre_PropParm("c", "IN IP4 $ "), + MD = ?MSG_LIB:cre_ModemDescriptor([MT], [PP]), + AmmDesc = ?MSG_LIB:cre_AmmDescriptor(MD), + TermIDs = [#megaco_term_id{id = ?A4444}], + AmmReq = ?MSG_LIB:cre_AmmRequest(TermIDs, [AmmDesc]), + Cmd = ?MSG_LIB:cre_Command(addReq, AmmReq), + CmdReq = ?MSG_LIB:cre_CommandRequest(Cmd), + ActReq = ?MSG_LIB:cre_ActionRequest(2, [CmdReq]), + Acts = [ActReq], + TR = ?MSG_LIB:cre_TransactionRequest(9898, Acts), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, ?MG1_MID, [Trans]), + cre_MegacoMessage(Mess). + +msg62b() -> + MP = +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 +Transaction = 9898 { + Context = 2 { + Add = 11111111/00000000/00000000 { + Modem[V18] { + tdmc/gain=2 + } + } + } +}", +% MC = +% "!/" ?VERSION_STR " [124.124.124.222]:55555\nT=9898{C=2{A=11111111/00000000/00000000{MD[V18]{tdmc/gain=2}}}}", + list_to_binary(MP). + +%% ActionRequest with various combinations of ContextRequest and +%% ContextAttrAuditRequest +msg71(CR, CAAR) -> + TS1 = cre_TimeNot("19990729", "22000000"), + TS2 = cre_TimeNot("19990729", "22000111"), + Event1 = cre_ObsEv("al/of",TS1), + Event2 = cre_ObsEv("al/on",TS2), + Desc1 = cre_ObsEvsDesc(2222,[Event1]), + Desc2 = cre_ObsEvsDesc(2222,[Event2]), + NR1 = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc1), + NR2 = cre_NotifyReq([#megaco_term_id{id = ?A4444}],Desc2), + Cmd1 = ?MSG_LIB:cre_Command(notifyReq, NR1), + Cmd2 = ?MSG_LIB:cre_Command(notifyReq, NR2), + CR1 = cre_CmdReq(Cmd1), + CR2 = cre_CmdReq(Cmd2), + ActReq = ?MSG_LIB:cre_ActionRequest(1, CR, CAAR, [CR1, CR2]), + Acts = [ActReq], + TR = ?MSG_LIB:cre_TransactionRequest(9898, Acts), + Trans = ?MSG_LIB:cre_Transaction(TR), + Mess = ?MSG_LIB:cre_Message(?VERSION, ?MG1_MID, [Trans]), + cre_MegacoMessage(Mess). + +msg71a() -> + CR = cre_CtxReq(), + CAAR = cre_CtxAttrAuditReq(), + msg71(CR, CAAR). + +msg71b(CR) -> + CAAR = asn1_NOVALUE, + msg71(CR, CAAR). + +msg71b01() -> + CR = cre_CtxReq(15), + msg71b(CR). + +msg71b02() -> + CR = cre_CtxReq(true), + msg71b(CR). + +msg71b03() -> + CR = cre_CtxReq(false), + msg71b(CR). + +msg71b04() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(Top), + msg71b(CR). + +msg71b05() -> + CR = cre_CtxReq(15, true), + msg71b(CR). + +msg71b06() -> + CR = cre_CtxReq(15, false), + msg71b(CR). + +msg71b07() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, Top), + msg71b(CR). + +msg71b08() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, true, Top), + msg71b(CR). + +msg71b09() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, false, Top), + msg71b(CR). + +msg71b10() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = onewayboth, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, false, Top), + msg71b(CR). + +msg71b11() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = onewayexternal, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, false, Top), + msg71b(CR). + +msg71b12() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, true, Top, true), + msg71b(CR). + +msg71b13() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, true, Top, false), + msg71b(CR). + +msg71b14() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", "2"), + Props = [PP], + CR = cre_CtxReq(15, true, Top, Props), + msg71b(CR). + +msg71b15() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2"], relation, greaterThan), + Props = [PP], + CR = cre_CtxReq(15, true, Top, Props), + msg71b(CR). + +msg71b16() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","10"], range, true), + Props = [PP], + CR = cre_CtxReq(15, true, Top, Props), + msg71b(CR). + +msg71b17() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("nt/jit", ["40","50","50"], sublist, true), + Props = [PP], + CR = cre_CtxReq(15, true, Top, Props), + msg71b(CR). + +msg71b18() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CR = cre_CtxReq(15, true, Top, true, Props), + msg71b(CR). + +msg71b19() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, true, Top, false), + msg71b(CR). + +msg71b20() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CR = cre_CtxReq(15, true, Top, false, Props), + msg71b(CR). + +msg71b21() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CID1 = cre_CtxID(10191), + CID2 = cre_CtxID(10192), + CIDs = [CID1, CID2], + CR = cre_CtxReq(15, true, Top, false, CIDs), + msg71b(CR). + +msg71b22() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CID1 = cre_CtxID(10191), + CID2 = cre_CtxID(10192), + CIDs = [CID1, CID2], + CR = cre_CtxReq(15, true, Top, false, Props, CIDs), + msg71b(CR). + +msg71c(CAAR) -> + CR = asn1_NOVALUE, + msg71(CR, CAAR). + +msg71c01() -> + CAAR = cre_CtxAttrAuditReq('NULL', 'NULL', 'NULL'), + msg71c(CAAR). + +msg71c02() -> + CAAR = cre_CtxAttrAuditReq('NULL', 'NULL', asn1_NOVALUE), + msg71c(CAAR). + +msg71c03() -> + CAAR = cre_CtxAttrAuditReq('NULL', asn1_NOVALUE, 'NULL'), + msg71c(CAAR). + +msg71c04() -> + CAAR = cre_CtxAttrAuditReq(asn1_NOVALUE, 'NULL', 'NULL'), + msg71c(CAAR). + +msg71c05() -> + CAAR = cre_CtxAttrAuditReq(asn1_NOVALUE, asn1_NOVALUE, 'NULL'), + msg71c(CAAR). + +msg71c06() -> + CAAR = cre_CtxAttrAuditReq(asn1_NOVALUE, 'NULL', asn1_NOVALUE), + msg71c(CAAR). + +msg71c07() -> + CAAR = cre_CtxAttrAuditReq('NULL', asn1_NOVALUE, asn1_NOVALUE), + msg71c(CAAR). + +msg71c08() -> + CAAR = cre_CtxAttrAuditReq('NULL', asn1_NOVALUE, 'NULL', 'NULL'), + msg71c(CAAR). + +msg71c09() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + CAAR = cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, CPA), + msg71c(CAAR). + +msg71c10() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + SPrio = 10, + CAAR = cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, CPA, SPrio), + msg71c(CAAR). + +msg71c11() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + SPrio = 10, + SEm = true, + CAAR = cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, CPA, + SPrio, SEm, asn1_NOVALUE, asn1_NOVALUE), + msg71c(CAAR). + +msg71c12() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + SPrio = 10, + SEm = true, + SIeps = false, + CAAR = cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, CPA, + SPrio, SEm, SIeps), + msg71c(CAAR). + +msg71c13() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + SPrio = 10, + SEm = false, + SIeps = true, + SLog = cre_SelectLogic(andAUDITSelect), + CAAR = cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, CPA, + SPrio, SEm, SIeps, SLog), + msg71c(CAAR). + +msg71c14() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + SPrio = 10, + SEm = true, + SIeps = true, + SLog = cre_SelectLogic(orAUDITSelect), + CAAR = cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, CPA, + SPrio, SEm, SIeps, SLog), + msg71c(CAAR). + +msg71c15() -> + Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + SPrio = 10, + SLog = cre_SelectLogic(orAUDITSelect), + CAAR = cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, CPA, + SPrio, SLog), + msg71c(CAAR). + +msg71d01() -> + CR = cre_CtxReq(15, true), + CAAR = cre_CtxAttrAuditReq('NULL', 'NULL', 'NULL'), + msg71(CR, CAAR). + +msg71d02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2"], relation, unequalTo), + Props = [PP], + CR = cre_CtxReq(15, true, Top, true, Props), + + CAAR_Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + CAAR = cre_CtxAttrAuditReq(CAAR_Top, Em, Prio, Ieps, CPA), + + msg71(CR, CAAR). + +msg71d03() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2"], relation, unequalTo), + Props = [PP], + CR = cre_CtxReq(15, true, Top, false, Props), + + CAAR_Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + CAAR = cre_CtxAttrAuditReq(CAAR_Top, Em, Prio, Ieps, CPA), + + msg71(CR, CAAR). + +msg71d04() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2"], relation, unequalTo), + Props = [PP], + CID1 = cre_CtxID(10191), + CID2 = cre_CtxID(10192), + CIDs = [CID1, CID2], + CR = cre_CtxReq(15, true, Top, false, Props, CIDs), + + CAAR_Top = 'NULL', + Em = 'NULL', + Prio = 'NULL', + Ieps = 'NULL', + IAPP1 = cre_IndAudPropertyParm("tdmc/gain"), + IAPP2 = cre_IndAudPropertyParm("nt/jit"), + CPA = [IAPP1, IAPP2], + SPrio = 10, + SEm = true, + SIeps = true, + SLog = cre_SelectLogic(orAUDITSelect), + CAAR = cre_CtxAttrAuditReq(CAAR_Top, Em, Prio, Ieps, CPA, + SPrio, SEm, SIeps, SLog), + msg71(CR, CAAR). + +msg72(ED, CR) -> + V = cre_PropParm("v", "0"), + C = cre_PropParm("c", "IN IP4 124.124.124.222"), + M = cre_PropParm("m", "audio 2222 RTP/AVP 4"), + A = cre_PropParm("a", "a=ptime:30"), + A2 = cre_PropParm("a", "recvonly"), + LD = cre_LocalRemoteDesc([[V, C, M, A, A2]]), + Parms = cre_StreamParmsL(LD), + StreamDesc = cre_StreamDesc(1, Parms), + MediaDesc = cre_MediaDesc(StreamDesc), + Reply = cre_AmmsReply([#megaco_term_id{id = ?A4444}]), + Reply2 = cre_AmmsReply([#megaco_term_id{id = ?A4445}], + [{mediaDescriptor, MediaDesc}]), + CmdRep = [{addReply, Reply}, {addReply, Reply2}], + Action = cre_ActRep(2000, ED, CR, CmdRep), + msg_reply(?MGC_MID, 10003, [Action]). + +msg72a(CR) -> + ED = asn1_NOVALUE, + msg72(ED, CR). + +msg72a01() -> + CR = cre_CtxReq(false), + msg72a(CR). + +msg72a02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(Top), + msg72a(CR). + +msg72a03() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = bothway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, Top), + msg72a(CR). + +msg72b(CR) -> + EC = ?MSG_LIB:cre_ErrorCode(?megaco_not_ready), + ED = ?MSG_LIB:cre_ErrorDescriptor(EC), + msg72(ED, CR). + +msg72b01() -> + CR = cre_CtxReq(15, false), + msg72b(CR). + +msg72b02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = isolate, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, false, Top), + msg72b(CR). + +msg72b03() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, true, Top, true), + msg72b(CR). + +msg72b04() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = bothway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + CR = cre_CtxReq(15, true, Top, false), + msg72b(CR). + +msg72c(CR) -> + EC = ?MSG_LIB:cre_ErrorCode(?megaco_not_ready), + ET = ?MSG_LIB:cre_ErrorText("Just another error string"), + ED = ?MSG_LIB:cre_ErrorDescriptor(EC, ET), + msg72(ED, CR). + +msg72c01() -> + CR = cre_CtxReq(15), + msg72c(CR). + +msg72c02() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = oneway, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", "2"), + Props = [PP], + CR = cre_CtxReq(15, true, Top, Props), + msg72c(CR). + +msg72c03() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CR = cre_CtxReq(15, true, Top, true, Props), + msg72c(CR). + +msg72c04() -> + From1 = #megaco_term_id{id = ["11111111", "00000000", "00000000"]}, + To1 = #megaco_term_id{id = ["11111111", "00000000", "00001111"]}, + Dir1 = oneway, + Top1 = cre_TopologyRequest(From1, To1, Dir1), + From2 = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + To2 = #megaco_term_id{id = ["11111111", "00001111", "00001111"]}, + Dir2 = isolate, + Top2 = cre_TopologyRequest(From2, To2, Dir2), + Top = [Top1, Top2], + PP = cre_PropParm("tdmc/gain", ["2","4","8"], sublist, false), + Props = [PP], + CR = cre_CtxReq(15, true, Top, false, Props), + msg72c(CR). + + +msg73() -> + Stat1 = cre_StatsParm("rtp/ps"), + Stat2 = cre_StatsParm("nt/os","62300"), + Stat3 = cre_StatsParm("rtp/pr","700"), + Stat4 = cre_StatsParm("nt/or","45100"), + Stat5 = cre_StatsParm("rtp/pl","0.2"), + Stat6 = cre_StatsParm("rtp/jit","20"), + Stat7 = cre_StatsParm("rtp/delay","40"), + Stats = [Stat1, Stat2, Stat3, Stat4, Stat5, Stat6, Stat7], + cre_StatsDesc(Stats). + +%% StatisticsDescriptor in AmmDescriptor +msg73a() -> + StatDesc = msg73(), + AmmDesc = cre_AmmDesc(StatDesc), + TermIDs = [#megaco_term_id{id = ["11111111", "00001111", "00000000"]}], + AmmReq = cre_AmmReq(TermIDs, [AmmDesc]), + Cmd = cre_Cmd(addReq, AmmReq), + CmdReq = cre_CmdReq(Cmd), + CID = cre_CtxID(7301), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(7302), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + + +%% StatisticsDescriptor in IndAudStreamParms +msg73b1() -> + IASD = cre_IndAudStatsDesc("nt/dur"), + cre_IndAudStreamParms(IASD). + +msg73b2(IAMD) -> + IAP = cre_IndAudParam(IAMD), + AD = cre_AuditDesc([IAP]), + TermID = #megaco_term_id{id = ["11111111", "00001111", "00000000"]}, + AudReq = cre_AuditReq(TermID, AD), + Cmd = cre_Cmd(auditValueRequest, AudReq), + CmdReq = cre_CmdReq(Cmd), + CID = cre_CtxID(7311), + ActReq = cre_ActReq(CID, [CmdReq]), + Actions = [ActReq], + TransId = cre_TransId(7312), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg73b01() -> + IASP = msg73b1(), + IAMD = cre_IndAudMediaDesc(IASP), + msg73b2(IAMD). + +msg73b02() -> + IASP = msg73b1(), + SID = cre_StreamID(303), + IASD = cre_IndAudStreamDesc(SID, IASP), + IAMD = cre_IndAudMediaDesc([IASD]), + msg73b2(IAMD). + +%% StatisticsDescriptor in StreamParms +msg73c1() -> + StatDesc = msg73(), + SP = cre_StreamParms(StatDesc), + SID = cre_StreamID(505), + cre_StreamDesc(SID, SP). + +msg73c2(MD) -> + ARP = cre_AuditRetParam(MD), + TA = cre_TermAudit([ARP]), + TermIDs = [#megaco_term_id{id = ["11111111", "00001111", "00000000"]}], + AmmsRep = cre_AmmsReply(TermIDs, TA), + CmdRep = cre_CmdRep(moveReply, AmmsRep), + CID = cre_CtxID(606), + ActRep = cre_ActRep(CID, [CmdRep]), + TransId = cre_TransId(8899), + TransRep = cre_TransRep(TransId, [ActRep]), + Trans = cre_Trans(TransRep), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg73c01() -> + SD = msg73c1(), + MD = cre_MediaDesc(SD), + msg73c2(MD). + +msg73c02() -> + SD = msg73c1(), + MD = cre_MediaDesc([SD]), + msg73c2(MD). + + +%% New Signal (direction and requestID); msg74 +msg74a1(D) -> + Dir = cre_SigDir(D), + cre_Sig("cg/rt", Dir, asn1_NOVALUE). + +msg74a2(D, RID) -> + Dir = cre_SigDir(D), + cre_Sig("cg/rt", Dir, RID). + +msg74a3(D, RID) -> + Name = "al/ri", + SID = cre_StreamID(7401), + ST = cre_SigType(brief), + Dur = 7499, + NC = cre_NotifCompl([onTimeOut,otherReason]), + KA = cre_BOOLEAN(true), + SPL = [], + Dir = cre_SigDir(D), + cre_Sig(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID). + +msg74a4(Sig) -> + SR = cre_SigReq(Sig), + SD = cre_SigsDesc([SR]), + AD = cre_AmmDesc(SD), + TermIDs = [#megaco_term_id{id = ?A4444}], + AR = cre_AmmReq(TermIDs, [AD]), + Cmd = cre_Cmd(modReq, AR), + cre_CmdReq(Cmd). + +msg74a01() -> + Sig = msg74a1(internal), + CR = msg74a4(Sig), + CID = cre_CtxID(7411), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7421), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a02() -> + Sig = msg74a1(both), + CR = msg74a4(Sig), + CID = cre_CtxID(7412), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7422), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a03() -> + RID = cre_ReqID(7433), + Sig = msg74a2(external, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7413), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7423), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a04() -> + RID = cre_ReqID(7434), + Sig = msg74a2(both, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7414), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7424), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a05() -> + RID = cre_ReqID(7435), + Sig = msg74a3(both, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7415), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7425), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg74a06() -> + RID = cre_ReqID(7436), + Sig = msg74a3(internal, RID), + CR = msg74a4(Sig), + CID = cre_CtxID(7416), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7426), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + + + +%% New ServiceChangeParm (serviceChangeIncompleteFlag); msg75 +msg75a(IncFlag) -> + Method = cre_SvcChMethod(restart), + Address = cre_SvcChAddr(portNumber, ?DEFAULT_PORT), + Reason = "901 mg col boot", + Profile = cre_SvcChProf("resgw",1), + Parm = cre_SvcChParm(Method, Address, [Reason], Profile, IncFlag), + TermIDs = [?megaco_root_termination_id], + Req = cre_SvcChReq(TermIDs, Parm), + Cmd = cre_Cmd(serviceChangeReq, Req), + CR = cre_CmdReq(Cmd), + CID = cre_CtxID(7501), + ActReq = cre_ActReq(CID, [CR]), + Actions = [ActReq], + TransId = cre_TransId(7502), + TransReq = cre_TransReq(TransId, Actions), + Trans = cre_Trans(TransReq), + Mid = ?MG1_MID, + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg75a01() -> + msg75a(asn1_NOVALUE). + +msg75a02() -> + msg75a('NULL'). + + +msg76(IAMD) -> + IAP = cre_IndAudParam(IAMD), + AD = cre_AuditDesc(asn1_NOVALUE, [IAP]), + AR = cre_AuditReq(#megaco_term_id{id = ?A5556}, AD), + CR = cre_CmdReq({auditValueRequest, AR}), + msg_request(?MG2_MID, 50076, ?megaco_null_context_id, [CR]). + +%% IndAudLocalControlDescriptor and IndAudPropertyParm +msg76a(IALCD) when is_record(IALCD, 'IndAudLocalControlDescriptor') -> + IASP = cre_IndAudStreamParms(IALCD), + SID = 123, + IASD = cre_IndAudStreamDesc(SID, IASP), + IAMD = cre_IndAudMediaDesc([IASD]), + msg76(IAMD). + +msg76a01() -> + Name1 = "nt/jit", + IAPP1 = cre_IndAudPropertyParm(Name1), + Name2 = "tdmc/ec", + IAPP2 = cre_IndAudPropertyParm(Name2), + SMS = cre_StreamMode(recvOnly), + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, 'NULL', 'NULL', + [IAPP1, IAPP2], SMS), + msg76a(IALCD). + +msg76a02() -> + Name1 = "tdmc/gain", + PP1 = cre_PropParm("tdmc/gain", "2"), + IAPP1 = cre_IndAudPropertyParm(Name1, PP1), + Name2 = "tdmc/gain", + PP2 = cre_PropParm("tdmc/gain", "3"), + IAPP2 = cre_IndAudPropertyParm(Name2, PP2), + SMS = cre_StreamMode(recvOnly), + IALCD = cre_IndAudLocalControlDesc(asn1_NOVALUE, 'NULL', 'NULL', + [IAPP1, IAPP2], SMS), + msg76a(IALCD). + +%% IndAudTerminationStateDescription + ServiceState +msg76b(IATSD) -> + IAMD = cre_IndAudMediaDesc(IATSD), + msg76(IAMD). + +msg76b01() -> + SSS = cre_ServiceState(outOfSvc), + IATSD = cre_IndAudTermStateDesc([], asn1_NOVALUE, asn1_NOVALUE, SSS), + msg76b(IATSD). + +%% msg76b02() -> +%% PP = cre_PropParm("tdmc/gain", "2"), +%% IAPP = cre_IndAudPropertyParm("nt/jit", PP), +%% IAPPs = [IAPP], +%% SSS = cre_ServiceState(outOfSvc), +%% IATSD = cre_IndAudTermStateDesc(IAPPs, 'NULL', asn1_NOVALUE, SSS), +%% msg76b(IATSD). + +msg77a01() -> + SN = "tonegen/pt", + Sig = cre_IndAudSig(SN, 7701), + msg54(?MG2_MID, Sig). + + +msg78a(Events) -> + EventsDesc = cre_EvsDesc(2223, Events), + Signal = cre_Sig("cg/rt"), + Name = "dialplan00", + Body = "(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)", + DigitMapValue = cre_DigitMapValue(Body), + DigMapDesc = cre_DigitMapDesc(Name, DigitMapValue), + AmmReq = cre_AmmReq([#megaco_term_id{id = ?A4444}], + [{eventsDescriptor, EventsDesc}, + {signalsDescriptor, [{signal, Signal}]}, + {digitMapDescriptor, DigMapDesc}]), + CmdReq = cre_CmdReq({modReq, AmmReq}), + msg_request(?MG2_MID, 10001, ?megaco_null_context_id, [CmdReq]). + +msg78a01() -> + Name1 = "al/on", + Strict = cre_EvParm("strict", ["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + Name2 = "al/on", + SID2 = 7801, + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + NB2 = cre_NotifBehav(notifyImmediate, 'NULL'), + RED2 = asn1_NOVALUE, + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB2, RED2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, SID2, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a02() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + Name2 = "al/on", + SID2 = 7802, + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + NB2 = cre_NotifBehav(neverNotify, 'NULL'), + RED2 = asn1_NOVALUE, + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB2, RED2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, SID2, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a03() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + Name2 = "al/on", + SID2 = 7803, + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + RED2 = cre_RegEmbedDesc(), + NB2 = cre_NotifBehav(notifyRegulated, RED2), + REvD2 = asn1_NOVALUE, + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB2, REvD2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, SID2, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a04() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + Name2 = "al/on", + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + SRE2 = cre_SecReqEv("al/on"), + SED2 = cre_SecEvsDesc(7814, [SRE2]), + RED2 = cre_RegEmbedDesc(SED2), + NB2 = cre_NotifBehav(notifyRegulated, RED2), + REvD2 = asn1_NOVALUE, + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB2, REvD2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, 7824, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a05() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + Name2 = "al/on", + SID2 = 7805, + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + SD2 = cre_SigsDesc(), + RED2 = cre_RegEmbedDesc(SD2), + NB2 = cre_NotifBehav(notifyRegulated, RED2), + REvD2 = asn1_NOVALUE, + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB2, REvD2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, SID2, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a06() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + Name2 = "al/on", + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + SRE2 = cre_SecReqEv("al/on"), + SED2 = cre_SecEvsDesc(7816, [SRE2]), + Sig2 = cre_Sig("cg/rt", external, asn1_NOVALUE), + SR2 = cre_SigReq(Sig2), + SRs2 = [SR2], + SD2 = cre_SigsDesc(SRs2), + RED2 = cre_RegEmbedDesc(SED2, SD2), + NB2 = cre_NotifBehav(notifyRegulated, RED2), + REvD2 = asn1_NOVALUE, + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB2, REvD2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, 7826, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a07() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + Name2 = "al/on", + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + SRE2 = cre_SecReqEv("al/on"), + SED2 = cre_SecEvsDesc(7817, [SRE2]), + Sig2 = cre_Sig("cg/rt", external, asn1_NOVALUE), + SR2 = cre_SigReq(Sig2), + SRs2 = [SR2], + SD2 = cre_SigsDesc(SRs2), + RED2 = cre_RegEmbedDesc(SED2, SD2), + NB2 = cre_NotifBehav(notifyRegulated, RED2), + REvD2 = 'NULL', + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB2, REvD2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, 7827, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a08() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + + Name2 = "al/on", + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + + Sig21 = cre_Sig("al/ri", both, asn1_NOVALUE), + SR21 = cre_SigReq(Sig21), + SRs21 = [SR21], + SD21 = cre_SigsDesc(SRs21), + RED21 = cre_RegEmbedDesc(SD21), + NB21 = cre_NotifBehav(notifyRegulated, RED21), + SRA2 = cre_SecReqActs(KA2, EDM2, asn1_NOVALUE, NB21, 'NULL'), + SRE2 = cre_SecReqEv("al/of", 7816, SRA2), + SED2 = cre_SecEvsDesc(7826, [SRE2]), + + Sig22 = cre_Sig("cg/rt", external, asn1_NOVALUE), + SR22 = cre_SigReq(Sig22), + SRs22 = [SR22], + SD22 = cre_SigsDesc(SRs22), + RED22 = cre_RegEmbedDesc(SED2, SD22), + NB22 = cre_NotifBehav(notifyRegulated, RED22), + REvD2 = 'NULL', + + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB22, REvD2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, 7836, RA2, EPL2), + msg78a([RE1, RE2]). + +msg78a09() -> + Name1 = "al/on", + Strict = cre_EvParm("strict",["state"]), + EPL1 = [Strict], + RE1 = cre_ReqEv(Name1, EPL1), + + Name2 = "al/on", + KA2 = true, + EDM2 = cre_EvDM("dialplan00"), + + SID21 = cre_StreamID(7819), + ST21 = cre_SigType(timeOut), + Dur21 = 7898, + NC21 = cre_NotifCompl([onTimeOut, onInterruptByEvent, otherReason]), + KA21 = cre_BOOLEAN(false), + SPL21 = [], + Dir21 = cre_SigDir(both), + RID21 = cre_ReqID(7829), + + Sig21 = cre_Sig("cg/rt", SID21, ST21, Dur21, NC21, KA21, SPL21, Dir21, + RID21, 7839), + SR21 = cre_SigReq(Sig21), + SRs21 = [SR21], + SD21 = cre_SigsDesc(SRs21), + RED21 = cre_RegEmbedDesc(SD21), + NB21 = cre_NotifBehav(notifyRegulated, RED21), + + SRA2 = cre_SecReqActs(KA2, EDM2, asn1_NOVALUE, NB21, 'NULL'), + SRE2 = cre_SecReqEv("al/of", 7849, SRA2), + SED2 = cre_SecEvsDesc(7859, [SRE2]), + + SID22 = cre_StreamID(7869), + ST22 = cre_SigType(brief), + Dur22 = 17809, + NC22 = cre_NotifCompl([onTimeOut, otherReason]), + KA22 = cre_BOOLEAN(true), + SPL22 = [], + Dir22 = cre_SigDir(external), + RID22 = cre_ReqID(7879), + + Sig22 = cre_Sig("cg/rt", SID22, ST22, Dur22, NC22, KA22, SPL22, Dir22, + RID22, 7889), + SR22 = cre_SigReq(Sig22), + SRs22 = [SR22], + SD22 = cre_SigsDesc(SRs22), + RED22 = cre_RegEmbedDesc(SED2, SD22), + + NB22 = cre_NotifBehav(notifyRegulated, RED22), + REvD2 = 'NULL', + + RA2 = cre_ReqActs(KA2, EDM2, asn1_NOVALUE, asn1_NOVALUE, NB22, REvD2), + EPL2 = EPL1, + RE2 = cre_ReqEv(Name2, 7899, RA2, EPL2), + msg78a([RE1, RE2]). + + +msg79a01() -> + TID1 = #megaco_term_id{id = ?A4444}, + TID2 = #megaco_term_id{id = ?A4445}, + TID3 = #megaco_term_id{id = ?A5555}, + TIDs = cre_TermIDList([TID1, TID2, TID3]), + ErC = cre_ErrCode(?megaco_not_ready), + ErD = cre_ErrDesc(ErC), + ARP1 = cre_AuditRetParam(ErD), + RE = cre_ReqEv("al/of"), + EvD = cre_EvsDesc(7911,[RE]), + ARP2 = cre_AuditRetParam(EvD), + Tks = [mediaToken, digitMapToken, statsToken, packagesToken], + AD = cre_AuditDesc(Tks), + ARP3 = cre_AuditRetParam(AD), + TAR = cre_TermAudit([ARP1, ARP2, ARP3]), + TLAR = cre_TermListAuditRes(TIDs, TAR), + AudR = cre_AuditRep(TLAR), + CR = cre_CmdRep(auditValueReply, AudR), + ActR = cre_ActRep(7921, [CR]), + Acts = [ActR], + msg_reply(?MG2_MID, 7931, Acts). + + +%% -- + +msg80() -> + Address = {portNumber, ?DEFAULT_PORT}, + Profile = cre_SvcChProf("resgw", 1), + Parm = cre_SvcChResParm(Address, Profile), + Reply = cre_SvcChRep([?megaco_root_termination_id], + {serviceChangeResParms, Parm}), + CmdRep = cre_CmdRep(serviceChangeReply, Reply), + cre_ActRep(80, [CmdRep]). + +msg80a(Mid, SN) -> + TransId = 8000, + ActRep = msg80(), + TransRep = cre_TransRep(TransId, [ActRep], SN), + Trans = cre_Trans(TransRep), + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg80a01() -> + msg80a(?MG1_MID, 1). + +msg80a02() -> + msg80a(?MG2_MID, 1000). + +msg80a03() -> + msg80a(?MG3_MID, 65535). + +msg80b(Mid, SN) -> + TransId = 8989, + ActRep = msg80(), + TransRep = cre_TransRep(TransId, [ActRep], SN, 'NULL'), + Trans = cre_Trans(TransRep), + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg80b01() -> + msg80b(?MG1_MID, 1). + +msg80b02() -> + msg80b(?MG2_MID, 1000). + +msg80b03() -> + msg80b(?MG3_MID, 65535). + +msg81a(Mid, SN) -> + TransId = 8101, + SegReply = cre_SegRep(TransId, SN), + Trans = cre_Trans(SegReply), + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg81a01() -> + msg81a(?MG1_MID, 1). + +msg81a02() -> + msg81a(?MG2_MID, 1000). + +msg81a03() -> + msg81a(?MG3_MID, 65535). + +msg81b(Mid, SN) -> + TransId = 8102, + SegReply = cre_SegRep(TransId, SN, 'NULL'), + Trans = cre_Trans(SegReply), + Mess = cre_Msg(Mid, [Trans]), + cre_MegacoMessage(Mess). + +msg81b01() -> + msg81b(?MG1_MID, 1). + +msg81b02() -> + msg81b(?MG2_MID, 1000). + +msg81b03() -> + msg81b(?MG3_MID, 65535). + + +%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +%% Pretty RFC 3525 messages: + +%% Added Reason +rfc3525_msg1() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222] Transaction = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + Method = Restart, + Reason = 901, + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + +rfc3525_msg2() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 9998 { + Context = - { + ServiceChange = ROOT { + Services { + ServiceChangeAddress = 55555, + Profile = ResGW/1 + } + } + } +}". + + +%% Removed "," after LocalControl ending "}" +rfc3525_msg3() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 9999 { + Context = - { + Modify = A4444 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive, + tdmc/gain=2, ; in dB, + tdmc/ec=on + } + } + }, + Events = 2222 { + al/of {strict=state} + } + } + } +}". + +%% Removed the outermost "{}" pair (before the Reply token) +rfc3525_msg4() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 9999 { + Context = - { + Modify = A4444 + } +}". + +rfc3525_msg6() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Transaction = 10000 { + Context = - { + Notify = A4444 { + ObservedEvents =2222 { + 19990729T22000000:al/of{init=false} + } + } + } +}". + + +rfc3525_msg7() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 10000 { + Context = - { + Notify = A4444 + } +}". + +rfc3525_msg8() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10001 { + Context = - { + Modify = A4444 { + Events = 2223 { + al/on {strict=state}, + dd/ce {DigitMap=Dialplan0} + }, + Signals {cg/dt}, + DigitMap = Dialplan0 { + (0| 00|[1-7]xxx|8xxxxxxx|fxxxxxxx|exx|91xxxxxxxxxx|9011x.) + } + } + } +}". + +rfc3525_msg9() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10001 { + Context = - { + Modify = A4444 + } +}". + +rfc3525_msg10() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Transaction = 10002 { + Context = - { + Notify = A4444 { + ObservedEvents =2223 { + 19990729T22010001:dd/ce { + ds=\"916135551212\", + Meth=UM + } + } + } + } +}". + + +rfc3525_msg11() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 10002 { + Context = - { + Notify = A4444 + } +}". + +%% Added ? +rfc3525_msg12() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10003 { + Context = $ { + Add = A4444, + Add = $ { + Media { + Stream = 1 { + LocalControl { + Mode = ReceiveOnly, + nt/jit=40 ; in ms + }, + Local { + v=0 c=IN IP4 $ m=audio $ RTP/AVP 4 a=ptime:30 v=0 c=IN IP4 $ m=audio $ RTP/AVP 0 + } + } + } + } + } +}". + +%% Added ? +rfc3525_msg13() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10003 { + Context = 2000 { + Add = A4444, + Add = A4445 { + Media { + Stream = 1 { + Local { +v=0 +o=- 2890844526 2890842807 IN IP4 124.124.124.222 +s=- +t= 0 0 +c=IN IP4 124.124.124.222 +m=audio 2222 RTP/AVP 4 +a=ptime:30 +a=recvonly + } ; RTP profile for G.723.1 is 4 + } + } + } + } +}". + +%% +%% Added ? +rfc3525_msg14() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50003 { + Context = $ { + Add = A5555 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive + } + } + }, + Events = 1234 { + al/of {strict=state} + }, + Signals {al/ri} + }, + Add = $ { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive, + nt/jit=40 ; in ms + }, + Local { + v=0 c=IN IP4 $ m=audio $ RTP/AVP 4 a=ptime:30 + }, + Remote { + v=0 c=IN IP4 124.124.124.222 m=audio 2222 RTP/AVP 4 a=ptime:30 + } ; RTP profile for G.723.1 is 4 + } + } + } + } +}". + +%% Added ? +rfc3525_msg15() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50003 { + Context = 5000 { + Add = A5555, + Add = A5556 { + Media { + Stream = 1 { + Local { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 + } ; RTP profile for G723.1 is 4 + } + } + } + } +}". + +%% Added ? +rfc3525_msg16a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10005 { + Context = 2000 { + Modify = A4444 { + Signals {cg/rt} + }, + Modify = A4445 { + Media { + Stream = 1 { + Remote { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 + } ; RTP profile for G723.1 is 4 + } + } + } + } +}". + +rfc3525_msg16b() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10005 { + Context = 2000 { + Modify = A4444, + Modify = A4445 + } +}". + +rfc3525_msg17a() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Transaction = 50005 { + Context = 5000 { + Notify = A5555 { + ObservedEvents = 1234 { + 19990729T22020002:al/of{init=false} + } + } + } +}". + +rfc3525_msg17b() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 50005 { + Context = - { + Notify = A5555 + } +}". + +%% Removed "{ }" after Signals +rfc3525_msg17c() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50006 { + Context = 5000 { + Modify = A5555 { + Events = 1235 { + al/on{strict=state} + }, + Signals ; to turn off ringing + } + } +}". + +rfc3525_msg17d() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50006 { + Context = 5000 { + Modify = A4445 + } +}". + +%% Removed "{ }" after Signals +rfc3525_msg18a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 10006 { + Context = 2000 { + Modify = A4445 { + Media { + Stream = 1 { + LocalControl { + Mode = SendReceive + } + } + } + }, + Modify = A4444 { + Signals + } + } +}". + +rfc3525_msg18b() -> +"MEGACO/" ?VERSION_STR " [124.124.124.222]:55555 Reply = 10006 { + Context = 2000 { + Modify = A4445, + Modify = A4444 + } +}". + +rfc3525_msg19() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50007 { + Context = - { + AuditValue = A5556 { + Audit { + Media, DigitMap, Events, Signals, Packages, Statistics + } + } + } +}". + +%% Added ? +rfc3525_msg20() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50007 { + Context = - { + AuditValue = A5556 { + Media { + TerminationState { + ServiceStates = InService, + Buffer = OFF + }, + Stream = 1 { + LocalControl { + Mode = SendReceive, + nt/jit=40 + }, + Local { + v=0 o=- 7736844526 7736842807 IN IP4 125.125.125.111 s=- t= 0 0 c=IN IP4 125.125.125.111 m=audio 1111 RTP/AVP 4 a=ptime:30 + }, + Remote { + v=0 o=- 2890844526 2890842807 IN IP4 124.124.124.222 s=- t= 0 0 c=IN IP4 124.124.124.222 m=audio 2222 RTP/AVP 4 a=ptime:30 + } + } + }, + Events, + Signals, + DigitMap, + Packages {nt-1, rtp-1}, + Statistics { + rtp/ps=1200, ; packets sent + nt/os=62300, ; octets sent + rtp/pr=700, ; packets received + nt/or=45100, ; octets received + rtp/pl=0.2, ; % packet loss + rtp/jit=20, + rtp/delay=40 ; avg latency + } + } + } +}". + +rfc3525_msg21a() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Transaction = 50008 { + Context = 5000 { + Notify = A5555 { + ObservedEvents =1235 { + 19990729T24020002:al/on {init=false} + } + } + } +}". + +rfc3525_msg21b() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Reply = 50008 { + Context = - { + Notify = A5555 + } +}". + +rfc3525_msg22a() -> +"MEGACO/" ?VERSION_STR " [123.123.123.4]:55555 Transaction = 50009 { + Context = 5000 { + Subtract = A5555 { + Audit { + Statistics + } + }, + Subtract = A5556 { + Audit { + Statistics + } + } + } +}". + +%% Added ? +rfc3525_msg22b() -> +"MEGACO/" ?VERSION_STR " [125.125.125.111]:55555 Reply = 50009 { + Context = 5000 { + Subtract = A5555 { + Statistics { + nt/os=45123, ; Octets Sent + nt/dur=40 ; in seconds + } + }, + Subtract = A5556 { + Statistics { + rtp/ps=1245, ; packets sent + nt/os=62345, ; octets sent + rtp/pr=780, ; packets received + nt/or=45123, ; octets received + rtp/pl=10, ; % packets lost + rtp/jit=27, + rtp/delay=48 ; average latency + } + } + } +}". + +rfc3525_msgs() -> + [ + {msg1, rfc3525_msg1()}, + {msg2, rfc3525_msg2()}, + {msg3, rfc3525_msg3()}, + {msg4, rfc3525_msg4()}, + {msg6, rfc3525_msg6()}, + {msg7, rfc3525_msg7()}, + {msg8, rfc3525_msg8()}, + {msg9, rfc3525_msg9()}, + {msg10, rfc3525_msg10()}, + {msg11, rfc3525_msg11()}, + {msg12, rfc3525_msg12()}, + {msg13, rfc3525_msg13()}, + {msg14, rfc3525_msg14()}, + {msg15, rfc3525_msg15()}, + {msg16a, rfc3525_msg16a()}, + {msg16b, rfc3525_msg16b()}, + {msg17a, rfc3525_msg17a()}, + {msg17b, rfc3525_msg17b()}, + {msg17c, rfc3525_msg17c()}, + {msg17d, rfc3525_msg17d()}, + {msg18a, rfc3525_msg18a()}, + {msg18b, rfc3525_msg18b()}, + {msg19, rfc3525_msg19()}, + {msg20, rfc3525_msg20()}, + {msg21a, rfc3525_msg21a()}, + {msg21b, rfc3525_msg21b()}, + {msg22a, rfc3525_msg22a()}, + {msg22b, rfc3525_msg22b()} + ]. + +rfc3525_msgs_display() -> + Msgs = rfc3525_msgs(), + Fun = fun({Name, Msg}) -> + io:format("~w: ~n~s~n~n", [Name, Msg]) + end, + lists:foreach(Fun, Msgs). + +rfc3525_msgs_test() -> + put(dbg,true), + Res = rfc3525_msgs_test(megaco_pretty_text_encoder, [], 2), + erase(dbg), + io:format("~w~n", [Res]). + +rfc3525_msgs_test(Codec, Config, Ver) -> + io:format("-----------------------------------------" + "~ntesting with" + "~n Codec: ~w" + "~n Config: ~w" + "~n Version: ~w" + "~n", [Codec, Config, Ver]), + Msgs = rfc3525_msgs(), + Test = fun({N,M1}) -> + %% io:format("testing ~w: ", [N]), + io:format("~n*** testing ~w *** ~n~s~n", [N,M1]), + Bin1 = erlang:list_to_binary(M1), + case (catch Codec:decode_message(Config, Ver, Bin1)) of + {ok, M2} -> + %% io:format("d", []), + io:format("decoded:~n~p~n", [M2]), + case (catch Codec:encode_message(Config, Ver, M2)) of + {ok, Bin2} when is_binary(Bin2) -> + %% io:format("e~n", []), + io:format("encode: ~n~s~n", [erlang:binary_to_list(Bin2)]), + {N,ok}; + {ok, M3} -> + %% io:format("e~n", []), + io:format("encode: ~n~s~n", [M3]), + {N,ok}; + E -> + io:format("~n~p~n", [E]), + {N,encode_error} + end; + E -> + io:format("~n~p~n", [E]), + {N,decode_error} + end + end, + [Test(M) || M <- Msgs]. + +%% -------------------------- + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% skip(Reason) -> +%% megaco_codec_test_lib:skip(Reason). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ticket_compact_encode_decode_ok(Msg) -> + ticket_compact_encode_decode_ok(Msg, []). + +ticket_compact_encode_decode_ok(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + ticket_encode_decode_ok(Msg, Codec, Conf). + +ticket_pretty_encode_decode_ok(Msg) -> + ticket_pretty_encode_decode_ok(Msg, []). + +ticket_pretty_encode_decode_ok(Msg, Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_encode_decode_ok(Msg, Codec, Conf). + +ticket_encode_decode_ok(Msg, Codec, Conf0) -> + Conf = [?EC_V3|Conf0], + Encode = fun(M) -> encode_message(Codec, Conf, M) end, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Check = fun(M1, M2) -> chk_MegacoMessage(M1, M2) end, + megaco_codec_test_lib:expect_encode_decode(Msg, Encode, Decode, Check). + +%% -- + +%% ticket_compact_encode_error(Msg) -> +%% ticket_compact_encode_error(Msg, []). + +%% ticket_compact_encode_error(Msg, Conf) -> +%% Codec = megaco_compact_text_encoder, +%% ticket_encode_error(Msg, Codec, Conf). + +%% ticket_pretty_encode_error(Msg) -> +%% ticket_pretty_encode_error(Msg, []). + +ticket_pretty_encode_error(Msg, Conf) when is_list(Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_encode_error(Msg, Codec, Conf); +ticket_pretty_encode_error(Msg, Check) when is_function(Check) -> + ticket_pretty_encode_error(Msg, [], Check). + +ticket_pretty_encode_error(Msg, Conf, Check) when is_function(Check) -> + Codec = megaco_pretty_text_encoder, + ticket_encode_error(Msg, Codec, Conf, Check). + +ticket_encode_error(Msg, Codec, Conf) when is_list(Conf) -> + Check = fun(_) -> ok end, % Only called when encode failes + ticket_encode_error(Msg, Codec, Conf, Check). + +ticket_encode_error(Msg, Codec, Conf0, Check) -> + Conf = [?EC_V3|Conf0], + Encode = fun(M) -> encode_message(Codec, Conf, M) end, + megaco_codec_test_lib:expect_encode(Msg, Encode, Check). + +%% -- + +ticket_compact_decode_encode_ok(Msg) -> + ticket_compact_decode_encode_ok(Msg, []). + +ticket_compact_decode_encode_ok(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + ticket_decode_encode_ok(Msg, Codec, Conf). + +ticket_pretty_decode_encode_ok(Msg) -> + ticket_pretty_decode_encode_ok(Msg, []). + +ticket_pretty_decode_encode_ok(Msg, Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_decode_encode_ok(Msg, Codec, Conf). + +ticket_decode_encode_ok(Msg, Codec, Conf0) -> + Conf = [?EC_V3|Conf0], + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Encode = fun(M) -> encode_message(Codec, Conf, M) end, + Check = fun(M1, M2) -> chk_MegacoMessage(M1, M2) end, + megaco_codec_test_lib:expect_decode_encode(Msg, Decode, Encode, Check). + +%% -- + +ticket_pretty_decode_encode_only(Msg, Check) -> + ticket_pretty_decode_encode_only(Msg, Check, []). + +ticket_pretty_decode_encode_only(Msg, Check, Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_decode_encode_only(Msg, Codec, Check, Conf). + +ticket_decode_encode_only(Msg, Codec, Check, Conf0) -> + Conf = [?EC_V3|Conf0], + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + Encode = fun(M) -> encode_message(Codec, Conf, M) end, + megaco_codec_test_lib:expect_decode_encode_only(Msg, Decode, Encode, + Check). + +%% -- + +ticket_pretty_encode_decode_only(Msg) -> + ticket_pretty_encode_decode_only(Msg, []). + +ticket_pretty_encode_decode_only(Msg, Conf) when is_list(Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_encode_decode_only(Msg, Codec, Conf); +ticket_pretty_encode_decode_only(Msg, Check) when is_function(Check) -> + ticket_pretty_encode_decode_only(Msg, Check, []). + +ticket_pretty_encode_decode_only(Msg, Check, Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_encode_decode_only(Msg, Codec, Check, Conf). + +ticket_encode_decode_only(Msg, Codec, Conf) -> + Check = fun(_) -> ok end, + ticket_encode_decode_only(Msg, Codec, Check, Conf). + +ticket_encode_decode_only(Msg, Codec, Check, Conf0) -> + Conf = [?EC_V3|Conf0], + Encode = fun(M) -> encode_message(Codec, Conf, M) end, + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + megaco_codec_test_lib:expect_encode_decode_only(Msg, Encode, Decode, + Check). + +%% -- + +ticket_pretty_decode_only(Msg) -> + ticket_pretty_decode_only(Msg, []). + +ticket_pretty_decode_only(Msg, Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_decode_only(Msg, Codec, Conf). + +ticket_decode_only(Msg, Codec, Conf) -> + Check = fun(_) -> ok end, + ticket_decode_only(Msg, Codec, Check, Conf). + +ticket_decode_only(Msg, Codec, Check, Conf0) -> + Conf = [?EC_V3|Conf0], + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + megaco_codec_test_lib:expect_decode_only(Msg, Decode, Check). + +ticket_check_decode_only_error_reason(R, Check) + when is_list(R) and is_function(Check) -> + case lists:keysearch(reason, 1, R) of + {value, {reason, Reason}} -> + Check(Reason); + false -> + {error, {reason_not_found, R}} + end. + + +%% -- + +ticket_compact_decode_error(Msg) -> + ticket_compact_decode_error(Msg, []). + +ticket_compact_decode_error(Msg, Conf) -> + Codec = megaco_compact_text_encoder, + ticket_decode_error(Msg, Codec, Conf). + +ticket_pretty_decode_error(Msg) -> + ticket_pretty_decode_error(Msg, []). + +ticket_pretty_decode_error(Msg, Conf) when is_list(Conf) -> + Codec = megaco_pretty_text_encoder, + ticket_decode_error(Msg, Codec, Conf); +ticket_pretty_decode_error(Msg, Check) when is_function(Check) -> + ticket_pretty_decode_error(Msg, [], Check). + +ticket_pretty_decode_error(Msg, Conf, Check) -> + Codec = megaco_pretty_text_encoder, + ticket_decode_error(Msg, Codec, Conf, Check). + +ticket_decode_error(Msg, Codec, Conf) -> + Check = fun(X) -> + d("decode error reason: ~n~p~n", [X]), + ok + end, % Only called when decode failes + ticket_decode_error(Msg, Codec, Conf, Check). + +ticket_decode_error(Msg, Codec, Conf0, Check) -> + Conf = [?EC_V3|Conf0], + Decode = fun(B) -> decode_message(Codec, false, Conf, B) end, + megaco_codec_test_lib:expect_decode(Msg, Decode, Check). + +%% -- + +%% ticket_expect_exec(Instructions, Msg) -> +%% megaco_codec_test_lib:expect_exec(Instructions, Msg). + +%% ticket_expect_instruction(Desc, Cmd, Verify) -> +%% megaco_codec_test_lib:expect_instruction(Desc, Cmd, Verify). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% pretty_decode_message(DynamicDecode, Conf, Bin) -> +%% decode_message(megaco_pretty_text_encoder, DynamicDecode, Conf, Bin). + +%% compact_decode_message(DynamicDecode, Conf, Bin) -> +%% decode_message(megaco_compact_text_encoder, DynamicDecode, Conf, Bin). + +decode_message(Codec, DynamicDecode, Conf, Bin) -> + megaco_codec_test_lib:decode_message(Codec, DynamicDecode, ?VERSION, + Conf, Bin). + +%% pretty_encode_message(Conf, Msg) -> +%% encode_message(megaco_pretty_text_encoder, Conf, Msg). + +%% compact_encode_message(Conf, Msg) -> +%% encode_message(megaco_compact_text_encoder, Conf, Msg). + +encode_message(Codec, Conf, Msg) -> + megaco_codec_test_lib:encode_message(Codec, ?VERSION, Conf, Msg). + +test_msgs(Codec, DynamicDecode, Conf, Msgs) -> + megaco_codec_test_lib:test_msgs(Codec, DynamicDecode, ?VERSION, Conf, + fun chk_MegacoMessage/2, Msgs). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +chk_MegacoMessage(M1, M2) -> + ?MSG_LIB:chk_MegacoMessage(M1, M2). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +cre_MegacoMessage(Mess) -> + ?MSG_LIB:cre_MegacoMessage(Mess). + +cre_MegacoMessage(Auth, Mess) -> + ?MSG_LIB:cre_MegacoMessage(Auth, Mess). + +cre_MegacoMessage(V, Mid, Body) -> + Mess = ?MSG_LIB:cre_Message(V, Mid, Body), + cre_MegacoMessage(Mess). + +cre_AuthHeader() -> + SecParmIdx = [239, 205, 171, 137], + SeqNum = [18, 52, 86, 120], + AD = [18, 52, 86, 120, 137, 171, 205, 239, 118, 84, 50, 16], + cre_AuthHeader(SecParmIdx, SeqNum, AD). + +cre_AuthHeader(Idx, Num, D) -> + ?MSG_LIB:cre_AuthenticationHeader(Idx, Num, D). + +cre_Msg(Mid, Body) -> + cre_Msg(?VERSION, Mid, Body). + +cre_Msg(V, Mid, Body) -> + ?MSG_LIB:cre_Message(V, Mid, Body). + +cre_TransId(TransId) -> + ?MSG_LIB:cre_TransactionId(TransId). + +cre_Trans(Trans) -> + ?MSG_LIB:cre_Transaction(Trans). + +cre_TransReq(TransId, Actions) -> + ?MSG_LIB:cre_TransactionRequest(TransId, Actions). + +cre_TransRep(TransId, Actions) -> + ?MSG_LIB:cre_TransactionReply(TransId, Actions). + +cre_TransRep(TransId, Actions, SN) -> + ?MSG_LIB:cre_TransactionReply(TransId, Actions, SN). + +cre_TransRep(TransId, Actions, SN, SC) -> + ?MSG_LIB:cre_TransactionReply(TransId, Actions, SN, SC). + +cre_SegRep(TransId, SN) -> + ?MSG_LIB:cre_SegmentReply(TransId, SN). + +cre_SegRep(TransId, SN, SC) -> + ?MSG_LIB:cre_SegmentReply(TransId, SN, SC). + +cre_TransAck(First, Last) -> + ?MSG_LIB:cre_TransactionAck(First, Last). + +cre_ActReq(CtxId, CmdReqs) -> + ?MSG_LIB:cre_ActionRequest(CtxId, CmdReqs). + +cre_ActRep(CtxId, CmdReps) -> + ?MSG_LIB:cre_ActionReply(CtxId, CmdReps). + +cre_ActRep(CtxId, ED, CR, CmdReps) -> + ?MSG_LIB:cre_ActionReply(CtxId, ED, CR, CmdReps). + +cre_CtxReq() -> + ?MSG_LIB:cre_ContextRequest(). + +cre_CtxReq(A) -> + ?MSG_LIB:cre_ContextRequest(A). + +cre_CtxReq(A, B) -> + ?MSG_LIB:cre_ContextRequest(A, B). + +cre_CtxReq(A, B, C) -> + ?MSG_LIB:cre_ContextRequest(A, B, C). + +cre_CtxReq(A, B, C, D) -> + ?MSG_LIB:cre_ContextRequest(A, B, C, D). + +cre_CtxReq(A, B, C, D, E) -> + ?MSG_LIB:cre_ContextRequest(A, B, C, D, E). + +cre_CtxReq(Prio, Em, Top, Ieps, CtxProp, CtxList) -> + ?MSG_LIB:cre_ContextRequest(Prio, Em, Top, Ieps, CtxProp, CtxList). + +cre_CtxAttrAuditReq() -> + ?MSG_LIB:cre_ContextAttrAuditRequest(). + +% cre_CtxAttrAuditReq(A) -> +% ?MSG_LIB:cre_ContextAttrAuditRequest(A). + +% cre_CtxAttrAuditReq(A, B) -> +% ?MSG_LIB:cre_ContextAttrAuditRequest(A, B). + +cre_CtxAttrAuditReq(A, B, C) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(A, B, C). + +cre_CtxAttrAuditReq(A, B, C, D) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(A, B, C, D). + +cre_CtxAttrAuditReq(A, B, C, D, E) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(A, B, C, D, E). + +cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, Ctx, SPrio) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx, SPrio). + +cre_CtxAttrAuditReq(A, B, C, D, E, F, G) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(A, B, C, D, E, F, G). + +cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, Ctx, SPrio, SEm, SIeps) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx, + SPrio, SEm, SIeps). + +cre_CtxAttrAuditReq(Top, Em, Prio, Ieps, Ctx, SPrio, SEm, SIeps, SLog) -> + ?MSG_LIB:cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx, + SPrio, SEm, SIeps, SLog). + +cre_TopologyRequest(From, To, Dir) -> + ?MSG_LIB:cre_TopologyRequest(From, To, Dir). + +%% Ind Aud related: + +cre_IndAudParam(IAP) -> + ?MSG_LIB:cre_IndAuditParameter(IAP). + +cre_IndAudMediaDesc(D) -> + ?MSG_LIB:cre_IndAudMediaDescriptor(D). + +cre_IndAudStreamDesc(SID, SP) -> + ?MSG_LIB:cre_IndAudStreamDescriptor(SID, SP). + +cre_IndAudStreamParms(LCD) -> + ?MSG_LIB:cre_IndAudStreamParms(LCD). + +cre_IndAudLocalControlDesc(A, B, C, D) -> + ?MSG_LIB:cre_IndAudLocalControlDescriptor(A, B, C, D). + +cre_IndAudLocalControlDesc(SM, RV, RG, PP, SMS) -> + ?MSG_LIB:cre_IndAudLocalControlDescriptor(SM, RV, RG, PP, SMS). + +cre_IndAudPropertyParm(Name) -> + ?MSG_LIB:cre_IndAudPropertyParm(Name). + +cre_IndAudPropertyParm(Name, PP) -> + ?MSG_LIB:cre_IndAudPropertyParm(Name, PP). + +cre_IndAudTermStateDesc(PP) -> + ?MSG_LIB:cre_IndAudTerminationStateDescriptor(PP). + +cre_IndAudTermStateDesc(PP, EBC, SS) -> + ?MSG_LIB:cre_IndAudTerminationStateDescriptor(PP, EBC, SS). + +cre_IndAudTermStateDesc(PP, EBC, SS, SSS) -> + ?MSG_LIB:cre_IndAudTerminationStateDescriptor(PP, EBC, SS, SSS). + +cre_IndAudEvsDesc(RID, PN) + when is_integer(RID) -> + ?MSG_LIB:cre_IndAudEventsDescriptor(RID, PN). + +cre_IndAudEvBufDesc(EN, SID) -> + ?MSG_LIB:cre_IndAudEventBufferDescriptor(EN, SID). + +cre_IndAudSigsDesc(D) -> + ?MSG_LIB:cre_IndAudSignalsDescriptor(D). + +cre_IndAudSig(SN) -> + ?MSG_LIB:cre_IndAudSignal(SN). + +cre_IndAudSig(SN, SigRID) -> + ?MSG_LIB:cre_IndAudSignal(SN, SigRID). + +cre_IndAudSeqSigList(ID, SL) -> + ?MSG_LIB:cre_IndAudSeqSigList(ID, SL). + +cre_IndAudDigitMapDesc(DMN) -> + ?MSG_LIB:cre_IndAudDigitMapDescriptor(DMN). + +cre_IndAudStatsDesc(SN) -> + ?MSG_LIB:cre_IndAudStatisticsDescriptor(SN). + +cre_IndAudPkgsDesc(PN, PV) -> + ?MSG_LIB:cre_IndAudPackagesDescriptor(PN, PV). + +%% Parameter related +cre_PropParm(Name, Val) -> + ?MSG_LIB:cre_PropertyParm(Name, [Val]). + +cre_PropParm(Name, Vals, Tag, EI) -> + ?MSG_LIB:cre_PropertyParm(Name, Vals, Tag, EI). + + +%% Statistics related +cre_StatsDesc(SPs) -> + ?MSG_LIB:cre_StatisticsDescriptor(SPs). + +cre_StatsParm(Name) -> + ?MSG_LIB:cre_StatisticsParameter(Name). + +cre_StatsParm(Name, Val) -> + ?MSG_LIB:cre_StatisticsParameter(Name, [Val]). + + +% Event related +cre_EvParm(Name, Val) -> + ?MSG_LIB:cre_EventParameter(Name, Val). + +cre_ObsEv(Name, Not) -> + ?MSG_LIB:cre_ObservedEvent(Name, Not). +cre_ObsEv(Name, Not, Par) -> + ?MSG_LIB:cre_ObservedEvent(Name, Par, Not). + +cre_ReqEv(Name) -> + ?MSG_LIB:cre_RequestedEvent(Name). +cre_ReqEv(Name, EPL) -> + ?MSG_LIB:cre_RequestedEvent(Name, EPL). +cre_ReqEv(Name, SID, RA, EPL) -> + ?MSG_LIB:cre_RequestedEvent(Name, SID, RA, EPL). + + +cre_ObsEvsDesc(Id, EvList) -> + ?MSG_LIB:cre_ObservedEventsDescriptor(Id, EvList). + +cre_EvsDesc(Id, EvList) -> + ?MSG_LIB:cre_EventsDescriptor(Id, EvList). + + +%% Service change related +cre_SvcChParm(M, A, R, P) -> + ?MSG_LIB:cre_ServiceChangeParm(M, A, P, R). + +cre_SvcChParm(M, A, R, P, IF) -> + ?MSG_LIB:cre_ServiceChangeParm(M, A, asn1_NOVALUE, P, R, asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE, IF). + +cre_SvcChResParm(A, P) -> + ?MSG_LIB:cre_ServiceChangeResParm(A, P). + +cre_SvcChReq(Tids, P) -> + ?MSG_LIB:cre_ServiceChangeRequest(Tids, P). + +cre_SvcChProf(Name, Ver) -> + ?MSG_LIB:cre_ServiceChangeProfile(Name, Ver). + +cre_SvcChAddr(Tag, Val) -> + ?MSG_LIB:cre_ServiceChangeAddress(Tag, Val). + +cre_SvcChMethod(M) -> + ?MSG_LIB:cre_ServiceChangeMethod(M). + +cre_SvcChRep(Tids, Res) -> + ?MSG_LIB:cre_ServiceChangeReply(Tids, Res). + + +%% Stream related +cre_StreamID(Id) -> + ?MSG_LIB:cre_StreamID(Id). + +cre_StreamParms(Lcd) -> + ?MSG_LIB:cre_StreamParms(Lcd). +cre_StreamParms(Lcd, Ld) -> + ?MSG_LIB:cre_StreamParms(Lcd, Ld). +cre_StreamParms(Lcd, Ld, Rd) -> + ?MSG_LIB:cre_StreamParms(Lcd, Ld, Rd). +cre_StreamParmsL(Ld) -> + ?MSG_LIB:cre_StreamParms(asn1_NOVALUE, Ld, asn1_NOVALUE). +cre_StreamParmsR(Rd) -> + ?MSG_LIB:cre_StreamParms(asn1_NOVALUE, asn1_NOVALUE, Rd). + +cre_StreamDesc(Id, P) -> + ?MSG_LIB:cre_StreamDescriptor(Id, P). + + +%% "Local" related +cre_LocalControlDesc(Mode) -> + ?MSG_LIB:cre_LocalControlDescriptor(Mode). +cre_LocalControlDesc(Mode, Parms) -> + ?MSG_LIB:cre_LocalControlDescriptor(Mode, Parms). + +cre_LocalRemoteDesc(Grps) -> + ?MSG_LIB:cre_LocalRemoteDescriptor(Grps). + + +%% DigitMap related +cre_DigitMapDesc() -> + ?MSG_LIB:cre_DigitMapDescriptor(). +cre_DigitMapDesc(NameOrVal) -> + ?MSG_LIB:cre_DigitMapDescriptor(NameOrVal). +cre_DigitMapDesc(Name, Val) -> + ?MSG_LIB:cre_DigitMapDescriptor(Name, Val). + +cre_DigitMapValue(Body) -> + ?MSG_LIB:cre_DigitMapValue(Body). + +cre_DigitMapValue(Body, Start, Short, Long) -> + ?MSG_LIB:cre_DigitMapValue(Start, Short, Long, Body). + +%% Media related +cre_MediaDesc(SD) when is_record(SD, 'StreamDescriptor') -> + cre_MediaDesc([SD]); +cre_MediaDesc(SDs) -> + ?MSG_LIB:cre_MediaDescriptor(SDs). + + +%% Notify related +cre_NotifyReq(Tids, EvsDesc) -> + ?MSG_LIB:cre_NotifyRequest(Tids, EvsDesc). + +cre_NotifyRep(Tids) -> + ?MSG_LIB:cre_NotifyReply(Tids). + + +%% Subtract related +cre_SubReq(Tids, Desc) -> + ?MSG_LIB:cre_SubtractRequest(Tids, Desc). + + +%% Audit related +cre_AuditDesc(Tokens) -> + ?MSG_LIB:cre_AuditDescriptor(Tokens). + +cre_AuditDesc(Tokens, PropertTokens) -> + ?MSG_LIB:cre_AuditDescriptor(Tokens, PropertTokens). + +cre_AuditReq(Tid, Desc) -> + ?MSG_LIB:cre_AuditRequest(Tid, Desc). + +cre_AuditRep(AR) -> + ?MSG_LIB:cre_AuditReply(AR). + +cre_AuditRes(Tid, Res) -> + ?MSG_LIB:cre_AuditResult(Tid, Res). + +cre_TermAudit(ARP) -> + ?MSG_LIB:cre_TerminationAudit(ARP). + +cre_AuditRetParam(D) -> + ?MSG_LIB:cre_AuditReturnParameter(D). + +cre_TermListAuditRes(TIDs, TA) -> + ?MSG_LIB:cre_TermListAuditResult(TIDs, TA). + +%% AMM/AMMS related +cre_AmmDesc(D) -> + ?MSG_LIB:cre_AmmDescriptor(D). + +cre_AmmReq(Tids, Descs) -> + ?MSG_LIB:cre_AmmRequest(Tids, Descs). + +cre_AmmsReply(Tids) -> + ?MSG_LIB:cre_AmmsReply(Tids). +cre_AmmsReply(Tids, Descs) -> + ?MSG_LIB:cre_AmmsReply(Tids, Descs). + + +%% Command related +cre_Cmd(Tag, Req) -> + ?MSG_LIB:cre_Command(Tag, Req). + +cre_CmdReq(Cmd) -> + ?MSG_LIB:cre_CommandRequest(Cmd). + +cre_CmdRep(Tag, Rep) -> + ?MSG_LIB:cre_CommandReply(Tag, Rep). + + +%% Actions related +cre_ReqActs(A) -> + ?MSG_LIB:cre_RequestedActions(A). + +cre_ReqActs(KA, EDM, SE, SD, NB, RED) -> + ?MSG_LIB:cre_RequestedActions(KA, EDM, SE, SD, NB, RED). + +%% cre_SecReqActs() -> +%% ?MSG_LIB:cre_SecondRequestedActions(). + +%% cre_SecReqActs(A) -> +%% ?MSG_LIB:cre_SecondRequestedActions(A). + +cre_SecReqActs(KA, EDM, SD, NB, RED) -> + ?MSG_LIB:cre_SecondRequestedActions(KA, EDM, SD, NB, RED). + +cre_EvDM(Name) when is_list(Name) -> + ?MSG_LIB:cre_EventDM(Name). + +cre_RegEmbedDesc() -> + ?MSG_LIB:cre_RegulatedEmbeddedDescriptor(). + +cre_RegEmbedDesc(D) -> + ?MSG_LIB:cre_RegulatedEmbeddedDescriptor(D). + +cre_RegEmbedDesc(SED, SD) -> + ?MSG_LIB:cre_RegulatedEmbeddedDescriptor(SED, SD). + +%% cre_SecEvsDesc(REDs) -> +%% ?MSG_LIB:cre_SecondEventsDescriptor(REDs). + +cre_SecEvsDesc(RID, REDs) -> + ?MSG_LIB:cre_SecondEventsDescriptor(RID, REDs). + +cre_SecReqEv(N) -> + cre_SecReqEv(N, []). + +cre_SecReqEv(N, EPL) -> + ?MSG_LIB:cre_SecondRequestedEvent(N, EPL). + +cre_SecReqEv(N, SID, EA) when is_list(N) and + is_integer(SID) and + is_record(EA, 'SecondRequestedActions') -> + cre_SecReqEv(N, SID, EA, []); +cre_SecReqEv(A, B, C) -> + ?MSG_LIB:cre_SecondRequestedEvent(A, B, C). + +cre_SecReqEv(N, SID, EA, EPL) -> + ?MSG_LIB:cre_SecondRequestedEvent(N, SID, EA, EPL). + +%% Signal related +cre_SigsDesc() -> + cre_SigsDesc([]). + +cre_SigsDesc(SRs) -> + ?MSG_LIB:cre_SignalsDescriptor(SRs). + +cre_SigDir(D) -> + ?MSG_LIB:cre_SignalDirection(D). + +cre_Sig(Name) -> + cre_Sig(Name, []). + +cre_Sig(Name, SPL) -> + ?MSG_LIB:cre_Signal(Name, SPL). + +cre_Sig(Name, Dir, RID) -> + cre_Sig(Name, [], Dir, RID). + +cre_Sig(Name, SPL, Dir, RID) -> + cre_Sig(Name, asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE, + asn1_NOVALUE, SPL, Dir, RID). + +cre_Sig(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID) -> + ?MSG_LIB:cre_Signal(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID). + +cre_Sig(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID, ISD) -> + ?MSG_LIB:cre_Signal(Name, SID, ST, Dur, NC, KA, SPL, Dir, RID, ISD). + +cre_SigReq(S) -> + ?MSG_LIB:cre_SignalRequest(S). + +cre_NotifBehav(Tag, Val) -> + ?MSG_LIB:cre_NotifyBehaviour(Tag, Val). + +cre_NotifCompl(NC) -> + ?MSG_LIB:cre_NotifyCompletion(NC). + +cre_SigType(ST) -> + ?MSG_LIB:cre_SignalType(ST). + + +%% Others +cre_ErrCode(EC) -> + ?MSG_LIB:cre_ErrorCode(EC). + +cre_ErrDesc(EC) -> + ?MSG_LIB:cre_ErrorDescriptor(EC). + +cre_TermIDList(TIDs) -> + ?MSG_LIB:cre_TerminationIDList(TIDs). + +cre_ServiceState(SS) -> + ?MSG_LIB:cre_ServiceState(SS). + +cre_StreamMode(SS) -> + ?MSG_LIB:cre_StreamMode(SS). + +cre_SelectLogic(Tag) -> + ?MSG_LIB:cre_SelectLogic(Tag). + +cre_CtxID(CID) -> + ?MSG_LIB:cre_ContextID(CID). + +cre_ReqID(RID) -> + ?MSG_LIB:cre_RequestID(RID). + +cre_TimeNot(D,T) -> + ?MSG_LIB:cre_TimeNotation(D, T). + +cre_PkgsItem(Name, Ver) -> + ?MSG_LIB:cre_PackagesItem(Name, Ver). + +cre_BOOLEAN(B) -> + ?MSG_LIB:cre_BOOLEAN(B). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +flex_init(Config) -> + megaco_codec_flex_lib:init(Config). + +flex_finish(Config) -> + megaco_codec_flex_lib:finish(Config). + +flex_scanner_conf(Config) -> + megaco_codec_flex_lib:scanner_conf(Config). + +%% start_flex_scanner() -> +%% megaco_codec_flex_lib:start(). + +%% stop_flex_scanner(Pid) -> +%% megaco_codec_flex_lib:stop(Pid). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +t(F,A) -> + p(printable(get(severity),trc),trc,F,A). + +d(F,A) -> + p(printable(get(severity),dbg),dbg,F,A). + +%% l(F,A) -> +%% p(printable(get(severity),log),log,F,A). + +e(F,A) -> + p(printable(get(severity),err),err,F,A). + + +printable(trc,_) -> + true; +printable(dbg,trc) -> + false; +printable(dbg,_) -> + true; +printable(log,log) -> + true; +printable(log,err) -> + true; +printable(err,err) -> + true; +printable(_,_) -> + false. + + +p(true,L,F,A) -> + io:format("~s:" ++ F ++ "~n", [image_of(L)|A]); +p(_,_,_,_) -> + ok. + +image_of(trc) -> + "TRC"; +image_of(dbg) -> + "DBG"; +image_of(log) -> + "LOG"; +image_of(err) -> + "ERR"; +image_of(L) -> + io_lib:format("~p",[L]). + diff --git a/lib/megaco/test/megaco_config_test.erl b/lib/megaco/test/megaco_config_test.erl new file mode 100644 index 0000000000..453c1b8964 --- /dev/null +++ b/lib/megaco/test/megaco_config_test.erl @@ -0,0 +1,1110 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test application config +%%---------------------------------------------------------------------- + +-module(megaco_config_test). + +-compile(export_all). + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/src/app/megaco_internal.hrl"). + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + +min(M) -> timer:minutes(M). + +%% Test server callbacks +init_per_testcase(Case, Config) -> + C = lists:keydelete(tc_timeout, 1, Config), + do_init_per_testcase(Case, [{tc_timeout, min(3)}|C]). + +do_init_per_testcase(Case, Config) -> + process_flag(trap_exit, true), + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + process_flag(trap_exit, false), + megaco_test_lib:fin_per_testcase(Case, Config). + + +-record(command, {id, desc, cmd, verify}). + +-define(TEST_VERBOSITY, debug). +-define(NUM_CNT_PROCS, 100). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top test case + +all(suite) -> + [ + config, + transaction_id_counter, + tickets + ]. + +transaction_id_counter(suite) -> + [ + transaction_id_counter_mg, + transaction_id_counter_mgc + ]. + +tickets(suite) -> + [ + otp_7216, + otp_8167, + otp_8183 + ]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Config test case + +config(suite) -> + []; +config(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Mid = fake_mid, + + %% Nice values + Int = 3, + IT = #megaco_incr_timer{max_retries = Int}, + + %% Evil values + NonInt = non_int, + IT2 = #megaco_incr_timer{wait_for = NonInt}, + IT3 = #megaco_incr_timer{factor = NonInt}, + IT4 = #megaco_incr_timer{max_retries = NonInt}, + IT5 = #megaco_incr_timer{max_retries = non_infinity}, + + %% Command range values + Initial = 100, + Verify = 200, + Nice = 300, + Evil = 400, + End = 500, + + Commands = + [ + %% Initial commands + initial_command( Initial + 0, + "enable trace", + fun() -> megaco:enable_trace(100, io) end, ok), + initial_command( Initial + 1, + "start", + fun() -> megaco:start() end, ok), + initial_command( Initial + 2, + "Verify no active requests", + fun() -> megaco:system_info(n_active_requests) end, + 0), + initial_command( Initial + 3, + "Verify no active replies", + fun() -> megaco:system_info(n_active_replies) end, + 0), + initial_command( Initial + 4, + "Verify no active connections", + fun() -> + megaco:system_info(n_active_connections) + end, + 0), + initial_command( Initial + 5, + "Verify no connections", + fun() -> megaco:system_info(connections) end, []), + initial_command( Initial + 6, + "Verify no users", + fun() -> megaco:system_info(users) end, []), + initial_command( Initial + 7, + "Start user", + fun() -> megaco:start_user(Mid, []) end, ok), + + + %% Verify user defaults + verify_user_default_command(Mid, Verify + 1, connections, []), + verify_user_default_command(Mid, Verify + 2, min_trans_id, 1), + verify_user_default_command(Mid, Verify + 3, max_trans_id, infinity), + verify_user_default_command(Mid, Verify + 4, request_timer, + #megaco_incr_timer{}), + verify_user_default_command(Mid, Verify + 5, long_request_timer, timer:seconds(60)), + verify_user_default_command(Mid, Verify + 6, auto_ack, false), + verify_user_default_command(Mid, Verify + 7, pending_timer, 30000), + verify_user_default_command(Mid, Verify + 8, reply_timer, 30000), + verify_user_default_command(Mid, Verify + 9, send_mod, megaco_tcp), + verify_user_default_command(Mid, Verify + 10, encoding_mod, + megaco_pretty_text_encoder), + verify_user_default_command(Mid, Verify + 11, encoding_config, []), + verify_user_default_command(Mid, Verify + 12, protocol_version, 1), + verify_user_default_command(Mid, Verify + 13, reply_data, undefined), + verify_user_default_command(Mid, Verify + 14, receive_handle, + fun(H) when is_record(H, megaco_receive_handle) -> {ok, H}; + (R) -> {error, R} + end), + + + %% Nice update + nice_user_update_command(Mid, Nice + 1, min_trans_id, Int), + nice_user_update_command(Mid, Nice + 2, max_trans_id, Int), + nice_user_update_command(Mid, Nice + 3, max_trans_id, infinity), + nice_user_update_command(Mid, Nice + 4, request_timer, Int), + nice_user_update_command(Mid, Nice + 5, request_timer, infinity), + nice_user_update_command(Mid, Nice + 6, request_timer, IT), + nice_user_update_command(Mid, Nice + 7, long_request_timer, Int), + nice_user_update_command(Mid, Nice + 8, long_request_timer, infinity), + nice_user_update_command(Mid, Nice + 9, long_request_timer, IT), + nice_user_update_command(Mid, Nice + 10, auto_ack, true), + nice_user_update_command(Mid, Nice + 11, auto_ack, false), + nice_user_update_command(Mid, Nice + 12, pending_timer, Int), + nice_user_update_command(Mid, Nice + 13, pending_timer, infinity), + nice_user_update_command(Mid, Nice + 14, pending_timer, IT), + nice_user_update_command(Mid, Nice + 15, reply_timer, Int), + nice_user_update_command(Mid, Nice + 16, reply_timer, infinity), + nice_user_update_command(Mid, Nice + 17, reply_timer, IT), + nice_user_update_command(Mid, Nice + 18, send_mod, an_atom), + nice_user_update_command(Mid, Nice + 19, encoding_mod, an_atom), + nice_user_update_command(Mid, Nice + 20, encoding_config, []), + nice_user_update_command(Mid, Nice + 21, protocol_version, Int), + nice_user_update_command(Mid, Nice + 23, reply_data, IT), + nice_user_update_command(Mid, Nice + 23, resend_indication, true), + nice_user_update_command(Mid, Nice + 24, resend_indication, false), + nice_user_update_command(Mid, Nice + 25, resend_indication, flag), + + + %% Evil update + evil_user_update_command(Mid, Evil + 1, min_trans_id, NonInt), + evil_user_update_command(Mid, Evil + 2, max_trans_id, NonInt), + evil_user_update_command(Mid, Evil + 3, max_trans_id, non_infinity), + evil_user_update_command(Mid, Evil + 4, request_timer, NonInt), + evil_user_update_command(Mid, Evil + 5, request_timer, non_infinity), + evil_user_update_command(Mid, Evil + 6, request_timer, IT2), + evil_user_update_command(Mid, Evil + 7, request_timer, IT3), + evil_user_update_command(Mid, Evil + 8, request_timer, IT4), + evil_user_update_command(Mid, Evil + 9, request_timer, IT5), + evil_user_update_command(Mid, Evil + 10, long_request_timer, NonInt), + evil_user_update_command(Mid, Evil + 11, long_request_timer, non_infinity), + evil_user_update_command(Mid, Evil + 12, long_request_timer, IT2), + evil_user_update_command(Mid, Evil + 13, long_request_timer, IT3), + evil_user_update_command(Mid, Evil + 14, long_request_timer, IT4), + evil_user_update_command(Mid, Evil + 15, long_request_timer, IT5), + evil_user_update_command(Mid, Evil + 16, auto_ack, non_bool), + evil_user_update_command(Mid, Evil + 17, pending_timer, NonInt), + evil_user_update_command(Mid, Evil + 18, pending_timer, non_infinity), + evil_user_update_command(Mid, Evil + 19, pending_timer, IT2), + evil_user_update_command(Mid, Evil + 20, pending_timer, IT3), + evil_user_update_command(Mid, Evil + 21, pending_timer, IT4), + evil_user_update_command(Mid, Evil + 22, pending_timer, IT5), + evil_user_update_command(Mid, Evil + 23, reply_timer, NonInt), + evil_user_update_command(Mid, Evil + 24, reply_timer, non_infinity), + evil_user_update_command(Mid, Evil + 25, reply_timer, IT2), + evil_user_update_command(Mid, Evil + 26, reply_timer, IT3), + evil_user_update_command(Mid, Evil + 27, reply_timer, IT4), + evil_user_update_command(Mid, Evil + 28, reply_timer, IT5), + evil_user_update_command(Mid, Evil + 29, send_mod, {non_atom}), + evil_user_update_command(Mid, Evil + 30, encoding_mod, {non_atom}), + evil_user_update_command(Mid, Evil + 31, encoding_config, non_list), + evil_user_update_command(Mid, Evil + 32, protocol_version, NonInt), + evil_user_update_command(Mid, Evil + 33, resend_indication, flagg), + + + exit_command(End + 1, + "Verify non-existing system info", + fun() -> megaco:system_info(non_exist) end), + exit_command(End + 2, + "Verify non-existing user user info", + fun() -> megaco:user_info(non_exist, trans_id) end), + exit_command(End + 3, "Verify non-existing user info", + fun() -> megaco:user_info(Mid, non_exist) end), + + error_command(End + 4, + "Try updating user info for non-existing user", + fun() -> + megaco:update_user_info(non_exist, trans_id, 1) + end, + no_such_user, 2), + error_command(End + 11, + "Try updating non-existing user info", + fun() -> + megaco:update_user_info(Mid, trans_id, 4711) + end, + bad_user_val, 4), + error_command(End + 12, + "Try start already started user", + fun() -> + megaco:start_user(Mid, []) + end, + user_already_exists, 2), + + command(End + 13, "Verify started users", + fun() -> megaco:system_info(users) end, [Mid]), + command(End + 14, "Stop user", fun() -> megaco:stop_user(Mid) end, ok), + command(End + 15, "Verify started users", + fun() -> megaco:system_info(users) end, []), + error_command(End + 16, "Try stop not started user", + fun() -> megaco:stop_user(Mid) end, no_such_user, 2), + error_command(End + 17, "Try start megaco (it's already started)", + fun() -> megaco:start() end, already_started, 2), + command(End + 18, "Stop megaco", fun() -> megaco:stop() end, ok), + error_command(End + 19, "Try stop megaco (it's not running)", + fun() -> megaco:stop() end, not_started, 2) + ], + + + exec(Commands). + + + +exec([]) -> + ok; +exec([#command{id = No, + desc = Desc, + cmd = Cmd, + verify = Verify}|Commands]) -> + io:format("Executing command ~2w: ~s: ", [No, Desc]), + case (catch Verify((catch Cmd()))) of + {ok, OK} -> + io:format("ok => ~p~n", [OK]), + exec(Commands); + {error, Reason} -> + io:format("error => ~p~n", [Reason]), + {error, {bad_result, No, Reason}}; + Error -> + io:format("exit => ~p~n", [Error]), + {error, {unexpected_result, No, Error}} + end. + +initial_command(No, Desc0, Cmd, VerifyVal) when is_function(Cmd) -> + Desc = lists:flatten(io_lib:format("Initial - ~s", [Desc0])), + command(No, Desc, Cmd, VerifyVal). + +verify_user_default_command(Mid, No, Key, Verify) -> + Desc = lists:flatten(io_lib:format("Defaults - Verify ~w", [Key])), + Cmd = fun() -> megaco:user_info(Mid, Key) end, + command(No, Desc, Cmd, Verify). + +nice_user_update_command(Mid, No, Key, Val) -> + Desc = lists:flatten(io_lib:format("Nice - Update ~w", [Key])), + Cmd = fun() -> megaco:update_user_info(Mid, Key, Val) end, + Verify = fun(ok) -> + case (catch megaco:user_info(Mid, Key)) of + {'EXIT', R} -> + {error, {value_retreival_failed, R}}; + Val -> + {ok, Val}; + Invalid -> + {error, {value_update_failed, Val, Invalid}} + end; + (R) -> + {error, R} + end, + command(No, Desc, Cmd, Verify). + + +evil_user_update_command(Mid, No, Key, Val) -> + Desc = lists:flatten(io_lib:format("Evil: Update ~w", [Key])), + Cmd = fun() -> + case (catch megaco:user_info(Mid, Key)) of + {'EXIT', R} -> + {{error, {old_value_retreival_failed, R}}, + ignore}; + OldVal -> + {OldVal, + (catch megaco:update_user_info(Mid, Key, Val))} + end + end, + Verify = fun({{error, _} = Error, ignore}) -> + Error; + ({OldVal, {error, {bad_user_val, _, _, _}}}) -> + case (catch megaco:user_info(Mid, Key)) of + {'EXIT', R} -> + {error, {value_retreival_failed, R}}; + OldVal -> + {ok, OldVal}; + Invalid -> + {error, {value_update_failed, OldVal, Invalid}} + end; + (R) -> + {error, R} + end, + command(No, Desc, Cmd, Verify). + +exit_command(No, Desc, Cmd) when is_function(Cmd) -> + Verify = fun({'EXIT', _} = E) -> + {ok, E}; + (R) -> + {error, R} + end, + command(No, Desc, Cmd, Verify). + +error_command(No, Desc, Cmd, MainReason, TS) when is_function(Cmd) -> + Verify = fun({error, Reason}) -> + io:format("verify -> Reason: ~n~p~n", [Reason]), + case Reason of + {MainReason, _} when TS == 2 -> + {ok, MainReason}; + {MainReason, _, _, _} when TS == 4 -> + {ok, MainReason}; + _ -> + {error, Reason} + end; + (R) -> + {error, R} + end, + command(No, Desc, Cmd, Verify). + +command(No, Desc, Cmd, Verify) when is_integer(No) and is_list(Desc) and + is_function(Cmd) and is_function(Verify) -> + #command{id = No, + desc = Desc, + cmd = Cmd, + verify = Verify}; +command(No, Desc, Cmd, VerifyVal) when is_integer(No) and is_list(Desc) and + is_function(Cmd) -> + Verify = fun(Val) -> + case Val of + VerifyVal -> + {ok, Val}; + _ -> + {error, Val} + end + end, + #command{id = No, + desc = Desc, + cmd = Cmd, + verify = Verify}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +transaction_id_counter_mg(suite) -> + []; +transaction_id_counter_mg(doc) -> + ["This test case is intended to test and verify the " + "transaction counter handling of the application " + "in with one connection (MG). "]; +transaction_id_counter_mg(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, transaction_id_counter_mg), + + process_flag(trap_exit, true), + + i("starting"), + + {ok, _ConfigPid} = megaco_config:start_link(), + + %% Basic user data + UserMid = {deviceName, "mg"}, + UserConfig = [ + {min_trans_id, 1} + ], + + %% Basic connection data + RemoteMid = {deviceName, "mgc"}, + RecvHandle = #megaco_receive_handle{local_mid = UserMid, + encoding_mod = ?MODULE, + encoding_config = [], + send_mod = ?MODULE}, + SendHandle = dummy_send_handle, + ControlPid = self(), + + %% Start user + i("start user"), + ok = megaco_config:start_user(UserMid, UserConfig), + + %% Create connection + i("create connection"), + {ok, CD} = + megaco_config:connect(RecvHandle, RemoteMid, SendHandle, ControlPid), + + %% Set counter limits + i("set counter max limit"), + CH = CD#conn_data.conn_handle, + megaco_config:update_conn_info(CH, max_trans_id, 1000), + + %% Create the counter worker procs + i("create counter working procs"), + Pids = create_counter_working_procs(CH, ?NUM_CNT_PROCS, []), + + %% Start the counter worker procs + i("release the counter working procs"), + start_counter_working_procs(Pids), + + %% Await the counter worker procs termination + i("await the counter working procs completion"), + await_completion_counter_working_procs(Pids), + + %% Verify result + i("verify counter result"), + TransId = megaco_config:conn_info(CH, trans_id), + 1 = TransId, + + %% Stop test + i("disconnect"), + {ok, _, _} = megaco_config:disconnect(CH), + i("stop user"), + ok = megaco_config:stop_user(UserMid), + i("stop megaco_config"), + ok = megaco_config:stop(), + + i("done"), + ok. + + + +create_counter_working_procs(_CH, 0, Pids) -> + Pids; +create_counter_working_procs(CH, N, Pids) -> + TC = get(tc), + Pid = erlang:spawn_link(fun() -> counter_init(CH, TC) end), + create_counter_working_procs(CH, N-1, [Pid | Pids]). + +counter_init(CH, TC) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, lists:flatten(io_lib:format("CNT-~p", [self()]))), + put(tc, TC), + UserMid = CH#megaco_conn_handle.local_mid, + Min = megaco_config:user_info(UserMid, min_trans_id), + Max = megaco_config:conn_info(CH, max_trans_id), + Num = Max - Min + 1, + receive + start -> + %% i("received start command (~p)", [Num]), + ok + end, + counter_loop(CH, Num). + +counter_loop(_CH, 0) -> + %% i("done"), + exit(normal); +counter_loop(CH, Num) when (Num > 0) -> + megaco_config:incr_trans_id_counter(CH, 1), + counter_loop(CH, Num-1). + +start_counter_working_procs([]) -> + %% i("released"), + ok; +start_counter_working_procs([Pid | Pids]) -> + Pid ! start, + start_counter_working_procs(Pids). + +await_completion_counter_working_procs([]) -> + ok; +await_completion_counter_working_procs(Pids) -> + receive + {'EXIT', Pid, normal} -> + Pids2 = lists:delete(Pid, Pids), + await_completion_counter_working_procs(Pids2); + _Any -> + await_completion_counter_working_procs(Pids) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +transaction_id_counter_mgc(suite) -> + []; +transaction_id_counter_mgc(doc) -> + ["This test case is intended to test and verify the " + "transaction counter handling of the application " + "in with several connections (MGC). "]; +transaction_id_counter_mgc(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, transaction_id_counter_mgc), + process_flag(trap_exit, true), + + i("starting"), + + {ok, _ConfigPid} = megaco_config:start_link(), + + %% Basic user data + UserMid = {deviceName, "mgc"}, + UserConfig = [ + {min_trans_id, 1} + ], + + %% Basic connection data + RemoteMids = + [ + {deviceName, "mg01"}, + {deviceName, "mg02"}, + {deviceName, "mg03"}, + {deviceName, "mg04"}, + {deviceName, "mg05"}, + {deviceName, "mg06"}, + {deviceName, "mg07"}, + {deviceName, "mg08"}, + {deviceName, "mg09"}, + {deviceName, "mg10"} + ], + RecvHandles = + [ + #megaco_receive_handle{local_mid = UserMid, + encoding_mod = ?MODULE, + encoding_config = [], + send_mod = ?MODULE}, + #megaco_receive_handle{local_mid = UserMid, + encoding_mod = ?MODULE, + encoding_config = [], + send_mod = ?MODULE}, + #megaco_receive_handle{local_mid = UserMid, + encoding_mod = ?MODULE, + encoding_config = [], + send_mod = ?MODULE}, + #megaco_receive_handle{local_mid = UserMid, + encoding_mod = ?MODULE, + encoding_config = [], + send_mod = ?MODULE}, + #megaco_receive_handle{local_mid = UserMid, + encoding_mod = ?MODULE, + encoding_config = [], + send_mod = ?MODULE}, + #megaco_receive_handle{local_mid = UserMid, + encoding_mod = ?MODULE, + encoding_config = [], + send_mod = ?MODULE}, + #megaco_receive_handle{local_mid = UserMid, + encoding_mod = ?MODULE, + encoding_config = [], + send_mod = ?MODULE}, + #megaco_receive_handle{local_mid = UserMid, + encoding_mod = ?MODULE, + encoding_config = [], + send_mod = ?MODULE}, + #megaco_receive_handle{local_mid = UserMid, + encoding_mod = ?MODULE, + encoding_config = [], + send_mod = ?MODULE}, + #megaco_receive_handle{local_mid = UserMid, + encoding_mod = ?MODULE, + encoding_config = [], + send_mod = ?MODULE} + ], + SendHandle = dummy_send_handle, + ControlPid = self(), + + %% Start user + i("start user"), + ok = megaco_config:start_user(UserMid, UserConfig), + + %% Create connection + i("create connection(s)"), + CDs = create_connections(RecvHandles, RemoteMids, SendHandle, ControlPid), + + %% Set counter limits + i("set counter max limit(s)"), + set_counter_max_limits(CDs, 1000), + + %% Create the counter worker procs + i("create counter working procs"), + Pids = create_counter_working_procs(CDs, ?NUM_CNT_PROCS), + + %% Start the counter worker procs + i("release the counter working procs"), + start_counter_working_procs(Pids), + + %% Await the counter worker procs termination + i("await the counter working procs completion"), + await_completion_counter_working_procs(Pids), + + %% Verify result + i("verify counter result"), + verify_counter_results(CDs), + + %% Stop test + i("disconnect"), + delete_connections(CDs), + i("stop user"), + ok = megaco_config:stop_user(UserMid), + i("stop megaco_config"), + ok = megaco_config:stop(), + + i("done"), + ok. + +create_connections(RecvHandles, RemoteMids, SendHandle, ControlPid) -> + create_connections(RecvHandles, RemoteMids, SendHandle, ControlPid, []). + +create_connections([], [], _SendHandle, _ControlPid, Acc) -> + lists:reverse(Acc); +create_connections([RecvHandle | RecvHandles], + [RemoteMid | RemoteMids], + SendHandle, ControlPid, Acc) -> + {ok, CD} = + megaco_config:connect(RecvHandle, RemoteMid, SendHandle, ControlPid), + create_connections(RecvHandles, RemoteMids, + SendHandle, ControlPid, [CD | Acc]). + + +set_counter_max_limits([], _MaxTransId) -> + ok; +set_counter_max_limits([#conn_data{conn_handle = CH} | CDs], MaxTransId) -> + megaco_config:update_conn_info(CH, max_trans_id, MaxTransId), + set_counter_max_limits(CDs, MaxTransId). + + +create_counter_working_procs(CDs, NumCntProcs) -> + lists:flatten(create_counter_working_procs2(CDs, NumCntProcs)). + +create_counter_working_procs2([], _NumCntProcs) -> + []; +create_counter_working_procs2([#conn_data{conn_handle = CH} | CDs], + NumCntProcs) -> + [create_counter_working_procs(CH, NumCntProcs, []) | + create_counter_working_procs2(CDs, NumCntProcs)]. + + +verify_counter_results([]) -> + ok; +verify_counter_results([#conn_data{conn_handle = CH} | CDs]) -> + TransId = megaco_config:conn_info(CH, trans_id), + if + (TransId =:= 1) -> + ok; + true -> + ?ERROR({trans_id_verification_failed, CH, TransId}) + end, + verify_counter_results(CDs). + + +delete_connections([]) -> + ok; +delete_connections([#conn_data{conn_handle = CH} | CDs]) -> + {ok, _, _} = megaco_config:disconnect(CH), + delete_connections(CDs). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_7216(suite) -> + []; +otp_7216(Config) when is_list(Config) -> + put(tc, otp_7216), + p("start"), + + p("start the megaco config process"), + megaco_config:start_link(), + + LocalMid1 = {deviceName, "local-mid-1"}, + %% LocalMid2 = {deviceName, "local-mid-2"}, + RemoteMid1 = {deviceName, "remote-mid-1"}, + %% RemoteMid2 = {deviceName, "remote-mid-2"}, + RH = #megaco_receive_handle{local_mid = LocalMid1, + encoding_mod = dummy_codec_module, + encoding_config = [], + send_mod = dummy_transport_module}, + MinTransId = 7216, + MaxTransId = MinTransId + 10, + User1Config = [{min_trans_id, MinTransId}, + {max_trans_id, MaxTransId}], + + VerifySerial = + fun(Actual, Expected) -> + if + Actual == Expected -> + ok; + true -> + throw({error, {invalid_counter_value, Actual}}) + end + end, + + p("start local user: ~p", [LocalMid1]), + ok = megaco_config:start_user(LocalMid1, User1Config), + + p("connect"), + {ok, CD} = megaco_config:connect(RH, RemoteMid1, + dummy_send_handle, self()), + p("connect ok: CD = ~n~p", [CD]), + CH = CD#conn_data.conn_handle, + + + p("*** make the first counter increment ***"), + {ok, CD01} = megaco_config:incr_trans_id_counter(CH, 1), + Serial01 = CD01#conn_data.serial, + p("serial: ~p", [Serial01]), + VerifySerial(Serial01, MinTransId), + p("counter increment 1 ok"), + + + p("*** make two more counter increments ***"), + {ok, _} = megaco_config:incr_trans_id_counter(CH, 1), + {ok, CD02} = megaco_config:incr_trans_id_counter(CH, 1), + Serial02 = CD02#conn_data.serial, + p("serial: ~p", [Serial02]), + VerifySerial(Serial02, MinTransId+2), + p("counter increment 2 ok"), + + + p("*** make a big counter increment ***"), + {ok, CD03} = megaco_config:incr_trans_id_counter(CH, 8), + Serial03 = CD03#conn_data.serial, + p("serial: ~p", [Serial03]), + VerifySerial(Serial03, MinTransId+2+8), + p("counter increment 3 ok"), + + + p("*** make a wrap-around counter increment ***"), + {ok, CD04} = megaco_config:incr_trans_id_counter(CH, 1), + Serial04 = CD04#conn_data.serial, + p("serial: ~p", [Serial04]), + VerifySerial(Serial04, MinTransId), + p("counter increment 4 ok"), + + + p("*** make a big counter increment ***"), + {ok, CD05} = megaco_config:incr_trans_id_counter(CH, 10), + Serial05 = CD05#conn_data.serial, + p("serial: ~p", [Serial05]), + VerifySerial(Serial05, MinTransId+10), + p("counter increment 5 ok"), + + + p("*** make a big wrap-around counter increment ***"), + {ok, CD06} = megaco_config:incr_trans_id_counter(CH, 3), + Serial06 = CD06#conn_data.serial, + p("serial: ~p", [Serial06]), + VerifySerial(Serial06, MinTransId+(3-1)), + p("counter increment 6 ok"), + + + p("*** make a big counter increment ***"), + {ok, CD07} = megaco_config:incr_trans_id_counter(CH, 7), + Serial07 = CD07#conn_data.serial, + p("serial: ~p", [Serial07]), + VerifySerial(Serial07, MinTransId+(3-1)+7), + p("counter increment 7 ok"), + + + p("*** make a big wrap-around counter increment ***"), + {ok, CD08} = megaco_config:incr_trans_id_counter(CH, 5), + Serial08 = CD08#conn_data.serial, + p("serial: ~p", [Serial08]), + VerifySerial(Serial08, MinTransId+(5-1-1)), + p("counter increment 8 ok"), + + + p("disconnect"), + {ok, CD, RCD} = megaco_config:disconnect(CH), + p("disconnect ok: RCD = ~n~p", [RCD]), + + p("stop user"), + ok = megaco_config:stop_user(LocalMid1), + + p("stop megaco config process"), + megaco_config:stop(), + + p("done"), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_8167(suite) -> + []; +otp_8167(Config) when is_list(Config) -> + put(tc, otp8167), + p("start"), + + p("start the megaco config process"), + megaco_config:start_link(), + + LocalMid1 = {deviceName, "local-mid-1"}, + LocalMid2 = {deviceName, "local-mid-2"}, + RemoteMid1 = {deviceName, "remote-mid-1"}, + %% RemoteMid2 = {deviceName, "remote-mid-2"}, + RH1 = #megaco_receive_handle{local_mid = LocalMid1, + encoding_mod = dummy_codec_module, + encoding_config = [], + send_mod = dummy_transport_module}, +%% RH2 = #megaco_receive_handle{local_mid = LocalMid2, +%% encoding_mod = dummy_codec_module, +%% encoding_config = [], +%% send_mod = dummy_transport_module}, + + User1ConfigA = [{call_proxy_gc_timeout, 1}], + User1ConfigB = [{call_proxy_gc_timeout, 0}], + User2ConfigA = [{call_proxy_gc_timeout, -1}], + User2ConfigB = [{call_proxy_gc_timeout, infinity}], + User2ConfigC = [{call_proxy_gc_timeout, "1"}], + User2ConfigD = [{call_proxy_gc_timeout, 1.0}], + + p("start local user (1A): ~p", [LocalMid1]), + ok = megaco_config:start_user(LocalMid1, User1ConfigA), + p("stop local user (1A): ~p", [LocalMid1]), + ok = megaco_config:stop_user(LocalMid1), + + p("start local user (1B): ~p", [LocalMid1]), + ok = megaco_config:start_user(LocalMid1, User1ConfigB), + p("try (and fail) change value for item call_proxy_gc_timeout for local user: ~p -> ~p", + [LocalMid1, -1]), + {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, -1}} = + megaco_config:update_user_info(LocalMid1, call_proxy_gc_timeout, -1), + p("try (and fail) change value for item call_proxy_gc_timeout for local user: ~p -> ~p", + [LocalMid1, infinity]), + {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, infinity}} = + megaco_config:update_user_info(LocalMid1, call_proxy_gc_timeout, infinity), + p("try (and fail) change value for item call_proxy_gc_timeout for local user: ~p -> ~p", + [LocalMid1, "1"]), + {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, "1"}} = + megaco_config:update_user_info(LocalMid1, call_proxy_gc_timeout, "1"), + p("try (and fail) change value for item call_proxy_gc_timeout for local user: ~p -> ~p", + [LocalMid1, 1.0]), + {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, 1.0}} = + megaco_config:update_user_info(LocalMid1, call_proxy_gc_timeout, 1.0), + p("change value for item call_proxy_gc_timeout for local user: ~p", [LocalMid1]), + ok = megaco_config:update_user_info(LocalMid1, call_proxy_gc_timeout, 10101), + + p("connect"), + {ok, CD} = megaco_config:connect(RH1, RemoteMid1, + dummy_send_handle, self()), + p("connect ok: CD = ~n~p", [CD]), + CH = CD#conn_data.conn_handle, + + p("get value for item call_proxy_gc_timeout for connection: ~p", [CH]), + 10101 = megaco_config:conn_info(CH, call_proxy_gc_timeout), + + p("change value for item call_proxy_gc_timeout for connection: ~p -> ~p", + [CH, 20202]), + ok = megaco_config:update_conn_info(CH, call_proxy_gc_timeout, 20202), + + p("try (and fail) change value for item call_proxy_gc_timeout for connection: ~p -> ~p", + [CH, -1]), + {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, -1}} = + megaco_config:update_conn_info(CH, call_proxy_gc_timeout, -1), + + p("try (and fail) change value for item call_proxy_gc_timeout for connection: ~p -> ~p", + [CH, infinity]), + {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, infinity}} = + megaco_config:update_conn_info(CH, call_proxy_gc_timeout, infinity), + + p("try (and fail) change value for item call_proxy_gc_timeout for connection: ~p -> ~p", + [CH, "1"]), + {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, "1"}} = + megaco_config:update_conn_info(CH, call_proxy_gc_timeout, "1"), + + p("try (and fail) change value for item call_proxy_gc_timeout for connection: ~p -> ~p", + [CH, 1.0]), + {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, 1.0}} = + megaco_config:update_conn_info(CH, call_proxy_gc_timeout, 1.0), + + p("disconnect: ~p", [CH]), + {ok, _, _} = megaco_config:disconnect(CH), + + p("stop local user (1B): ~p", [LocalMid1]), + ok = megaco_config:stop_user(LocalMid1), + + p("try (and fail) start local user (2A): ~p", [LocalMid2]), + {error, {bad_user_val, LocalMid2, call_proxy_gc_timeout, -1}} = + megaco_config:start_user(LocalMid2, User2ConfigA), + + p("try (and fail) start local user (2B): ~p", [LocalMid2]), + {error, {bad_user_val, LocalMid2, call_proxy_gc_timeout, infinity}} = + megaco_config:start_user(LocalMid2, User2ConfigB), + + p("try (and fail) start local user (2C): ~p", [LocalMid2]), + {error, {bad_user_val, LocalMid2, call_proxy_gc_timeout, "1"}} = + megaco_config:start_user(LocalMid2, User2ConfigC), + + p("try (and fail) start local user (2D): ~p", [LocalMid2]), + {error, {bad_user_val, LocalMid2, call_proxy_gc_timeout, 1.0}} = + megaco_config:start_user(LocalMid2, User2ConfigD), + + p("done"), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_8183(suite) -> + []; +otp_8183(Config) when is_list(Config) -> + put(tc, otp8183), + p("start"), + + p("start the megaco config process"), + megaco_config:start_link(), + + LocalMid1 = {deviceName, "local-mid-1"}, + LocalMid2 = {deviceName, "local-mid-2"}, + RemoteMid1 = {deviceName, "remote-mid-1"}, +%% RemoteMid2 = {deviceName, "remote-mid-2"}, + RH1 = #megaco_receive_handle{local_mid = LocalMid1, + encoding_mod = dummy_codec_module, + encoding_config = [], + send_mod = dummy_transport_module}, +%% RH2 = #megaco_receive_handle{local_mid = LocalMid2, +%% encoding_mod = dummy_codec_module, +%% encoding_config = [], +%% send_mod = dummy_transport_module}, + + OkValA = 100, + OkValB = 0, + OkValC = plain, + OkValD = 10101, + OkValE = 20202, + BadValA = -1, + BadValB = pain, + BadValC = "1", + BadValD = 1.0, + User1ConfigA = [{request_keep_alive_timeout, OkValA}], + User1ConfigB = [{request_keep_alive_timeout, OkValB}], + User1ConfigC = [{request_keep_alive_timeout, OkValC}], + User2ConfigA = [{request_keep_alive_timeout, BadValA}], + User2ConfigB = [{request_keep_alive_timeout, BadValB}], + User2ConfigC = [{request_keep_alive_timeout, BadValC}], + User2ConfigD = [{request_keep_alive_timeout, BadValD}], + + p("start local user (1A): ~p", [LocalMid1]), + ok = megaco_config:start_user(LocalMid1, User1ConfigA), + p("stop local user (1A): ~p", [LocalMid1]), + ok = megaco_config:stop_user(LocalMid1), + + p("start local user (1B): ~p", [LocalMid1]), + ok = megaco_config:start_user(LocalMid1, User1ConfigB), + p("stop local user (1B): ~p", [LocalMid1]), + ok = megaco_config:stop_user(LocalMid1), + + p("start local user (1C): ~p", [LocalMid1]), + ok = megaco_config:start_user(LocalMid1, User1ConfigC), + + p("try (and fail) change value for item call_proxy_gc_timeout for local user: ~p -> ~p", + [LocalMid1, BadValA]), + {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValA}} = + megaco_config:update_user_info(LocalMid1, request_keep_alive_timeout, BadValA), + + p("try (and fail) change value for item request_keep_alive_timeout for local user: ~p -> ~p", + [LocalMid1, BadValB]), + {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValB}} = + megaco_config:update_user_info(LocalMid1, request_keep_alive_timeout, BadValB), + + p("try (and fail) change value for item request_keep_alive_timeout for local user: ~p -> ~p", + [LocalMid1, BadValC]), + {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValC}} = + megaco_config:update_user_info(LocalMid1, request_keep_alive_timeout, BadValC), + + p("try (and fail) change value for item request_keep_alive_timeout for local user: ~p -> ~p", + [LocalMid1, BadValD]), + {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValD}} = + megaco_config:update_user_info(LocalMid1, request_keep_alive_timeout, BadValD), + + p("change value for item request_keep_alive_timeout for local user: ~p", [LocalMid1]), + ok = megaco_config:update_user_info(LocalMid1, request_keep_alive_timeout, OkValD), + + p("connect"), + {ok, CD} = megaco_config:connect(RH1, RemoteMid1, + dummy_send_handle, self()), + p("connect ok: CD = ~n~p", [CD]), + CH = CD#conn_data.conn_handle, + + p("get value for item request_keep_alive_timeout for connection: ~p", [CH]), + OkValD = megaco_config:conn_info(CH, request_keep_alive_timeout), + + p("change value for item request_keep_alive_timeout for connection: ~p -> ~p", + [CH, OkValE]), + ok = megaco_config:update_conn_info(CH, request_keep_alive_timeout, OkValE), + + p("try (and fail) change value for item request_keep_alive_timeout for connection: ~p -> ~p", + [CH, BadValA]), + {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValA}} = + megaco_config:update_conn_info(CH, request_keep_alive_timeout, BadValA), + + p("try (and fail) change value for item request_keep_alive_timeout for connection: ~p -> ~p", + [CH, BadValB]), + {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValB}} = + megaco_config:update_conn_info(CH, request_keep_alive_timeout, BadValB), + + p("try (and fail) change value for item request_keep_alive_timeout for connection: ~p -> ~p", + [CH, BadValC]), + {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValC}} = + megaco_config:update_conn_info(CH, request_keep_alive_timeout, BadValC), + + p("try (and fail) change value for item request_keep_alive_timeout for connection: ~p -> ~p", + [CH, BadValD]), + {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValD}} = + megaco_config:update_conn_info(CH, request_keep_alive_timeout, BadValD), + + p("disconnect: ~p", [CH]), + {ok, _, _} = megaco_config:disconnect(CH), + + p("stop local user (1B): ~p", [LocalMid1]), + ok = megaco_config:stop_user(LocalMid1), + + p("try (and fail) start local user (2A): ~p", [LocalMid2]), + {error, {bad_user_val, LocalMid2, request_keep_alive_timeout, BadValA}} = + megaco_config:start_user(LocalMid2, User2ConfigA), + + p("try (and fail) start local user (2B): ~p", [LocalMid2]), + {error, {bad_user_val, LocalMid2, request_keep_alive_timeout, BadValB}} = + megaco_config:start_user(LocalMid2, User2ConfigB), + + p("try (and fail) start local user (2C): ~p", [LocalMid2]), + {error, {bad_user_val, LocalMid2, request_keep_alive_timeout, BadValC}} = + megaco_config:start_user(LocalMid2, User2ConfigC), + + p("try (and fail) start local user (2D): ~p", [LocalMid2]), + {error, {bad_user_val, LocalMid2, request_keep_alive_timeout, BadValD}} = + megaco_config:start_user(LocalMid2, User2ConfigD), + + p("done"), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +p(F) -> + p(F, []). + +p(F, A) -> + io:format("[~w] " ++ F ++ "~n", [get(tc)|A]). + + +i(F) -> + i(F, []). + +i(F, A) -> + print(info, get(verbosity), now(), get(tc), "INF", F, A). + +printable(_, debug) -> true; +printable(info, info) -> true; +printable(_,_) -> false. + +print(Severity, Verbosity, Ts, Tc, P, F, A) -> + print(printable(Severity,Verbosity), Ts, Tc, P, F, A). + +print(true, Ts, Tc, P, F, A) -> + io:format("*** [~s] ~s ~p ~s:~w ***" + "~n " ++ F ++ "~n", + [format_timestamp(Ts), P, self(), get(sname), Tc | A]); +print(_, _, _, _, _, _) -> + ok. + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). + diff --git a/lib/megaco/test/megaco_digit_map_test.erl b/lib/megaco/test/megaco_digit_map_test.erl new file mode 100644 index 0000000000..22e115278f --- /dev/null +++ b/lib/megaco/test/megaco_digit_map_test.erl @@ -0,0 +1,637 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Verify the application specifics of the Megaco application +%%---------------------------------------------------------------------- +-module(megaco_digit_map_test). + +-compile(export_all). + +-include("megaco_test_lib.hrl"). + + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + + +%% Test server callbacks +init_per_testcase(Case, Config) -> + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all(suite) -> + Cases = + [ + tickets + ], + Cases. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +tickets(suite) -> + [ + otp_5750, + otp_5799, + otp_5826, + otp_7449 + ]. + + +otp_5750(suite) -> + [ + otp_5750_01, + otp_5750_02 + ]. + +otp_5799(suite) -> + [ + otp_5799_01 + ]. + +otp_5826(suite) -> + [ + otp_5826_01, + otp_5826_02, + otp_5826_03 + ]. + +otp_7449(suite) -> + [ + otp_7449_1, + otp_7449_2 + ]. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_5750_01(suite) -> + []; +otp_5750_01(doc) -> + []; +otp_5750_01(Config) when is_list(Config) -> + DM = "1 | 123", + + %% First case + Tests = + [ + {1, + fun() -> + (catch tde(DM, "1")) + end, + fun({ok, {full, "1"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + + {2, + fun() -> + (catch tde(DM, "123")) + end, + fun({ok, {unambiguous, "123"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + + {3, + fun() -> + (catch tde(DM, "124")) + end, + fun({error, _}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end} + ], + + dm_tests(Tests), + + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_5750_02(suite) -> + []; +otp_5750_02(doc) -> + []; +otp_5750_02(Config) when is_list(Config) -> + DM = "xxx | xxL3 | xxS4", + + %% First case + Tests = + [ + {1, + fun() -> + (catch otp_5750_02_exec(500, DM, "113")) + end, + fun({ok, {unambiguous, "113"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + + {2, + fun() -> + (catch otp_5750_02_exec(500, DM, "114")) + end, + fun({ok, {unambiguous, "114"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + + {3, + fun() -> + (catch otp_5750_02_exec(5000, DM, "11ssss3")) + end, + fun({ok, {unambiguous, "113"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + + {4, + fun() -> + (catch otp_5750_02_exec(5000, DM, "11ssss4")) + end, + fun({ok, {unambiguous, "114"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end} + + ], + + dm_tests(Tests), + + ok. + +otp_5750_02_exec(To, DM, Evs) -> + Pid = self(), + Tester = + spawn(fun() -> + Res = tde(DM, Evs), + Pid ! {result, self(), Res} + end), + receive + {result, Tester, Res} -> + Res + after To -> + {error, timeout} + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_5799_01(suite) -> + []; +otp_5799_01(doc) -> + []; +otp_5799_01(Config) when is_list(Config) -> + DM = "234 | 23456", + + %% First case + Tests = + [ + {1, + fun() -> + (catch tde(DM, "2349")) + end, + fun({ok, {full, "234", $9}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end} + ], + + dm_tests(Tests), + + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_5826_01(suite) -> + []; +otp_5826_01(doc) -> + []; +otp_5826_01(Config) when is_list(Config) -> + DM = "123Z56", + + %% First case + Tests = + [ + {1, + fun() -> + (catch tde(DM, [$1,$2,$3,{long, $5},$6])) + end, + fun({ok, {unambiguous, "123Z56"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {2, + fun() -> + (catch tde(DM, [$1,$2,{long, $3},{long,$5},$6])) + end, + fun({ok, {unambiguous, "123Z56"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {3, + fun() -> + (catch tde(DM, [$1,$2,$3,{long,$5},{long,$6}])) + end, + fun({ok, {unambiguous, "123Z56"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {4, + fun() -> + (catch tde(DM, [$1,$2,{long, $3},{long,$5},{long,$6}])) + end, + fun({ok, {unambiguous, "123Z56"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end} + ], + + dm_tests(Tests), + + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_5826_02(suite) -> + []; +otp_5826_02(doc) -> + []; +otp_5826_02(Config) when is_list(Config) -> + DM = "12356", + + %% First case + Tests = + [ + {1, + fun() -> + (catch tde(DM, [$1,$2,$3,{long, $5},$6])) + end, + fun({ok, {unambiguous, "12356"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end} + ], + + dm_tests(Tests), + + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_5826_03(suite) -> + []; +otp_5826_03(doc) -> + []; +otp_5826_03(Config) when is_list(Config) -> + DM = "12346 | 12Z346 | 12Z34Z7 | 1234Z8", + + %% First case + Tests = + [ + {1, + fun() -> + (catch tde(DM, [$1,$2,{long, $3},$4,$6])) + end, + fun({ok, {unambiguous, "12Z346"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {2, + fun() -> + (catch tde(DM, [$1, {long, $2}, {long, $3},$4, $6])) + end, + fun({ok, {unambiguous, "12Z346"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {3, + fun() -> + (catch tde(DM, [$1,$2,{long, $3},{long, $4},$6])) + end, + fun({ok, {unambiguous, "12Z346"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {4, + fun() -> + (catch tde(DM, [$1,$2,{long, $3},$4,{long, $7}])) + end, + fun({ok, {unambiguous, "12Z34Z7"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {5, + fun() -> + (catch tde(DM, [$1,$2,{long, $3},$4,{long, $8}])) + end, + fun({error, + {unexpected_event, {long, $8}, _Collected, _Expected}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {6, + fun() -> + (catch tde(DM, [$1,$2,$3,$4,{long, $8}])) + end, + fun({ok, {unambiguous, "1234Z8"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end} + ], + + dm_tests(Tests), + + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_7449_1(suite) -> + []; +otp_7449_1(doc) -> + []; +otp_7449_1(Config) when is_list(Config) -> + DM = "([0-9ef])", + + %% First case + Tests = + [ + {1, + fun() -> + (catch tde(DM, [$0])) + end, + fun({ok, {unambiguous, "0"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {2, + fun() -> + (catch tde(DM, [$1])) + end, + fun({ok, {unambiguous, "1"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {3, + fun() -> + (catch tde(DM, [$2])) + end, + fun({ok, {unambiguous, "2"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {4, + fun() -> + (catch tde(DM, [$3])) + end, + fun({ok, {unambiguous, "3"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {5, + fun() -> + (catch tde(DM, [$4])) + end, + fun({ok, {unambiguous, "4"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {6, + fun() -> + (catch tde(DM, [$5])) + end, + fun({ok, {unambiguous, "5"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {7, + fun() -> + (catch tde(DM, [$6])) + end, + fun({ok, {unambiguous, "6"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {8, + fun() -> + (catch tde(DM, [$7])) + end, + fun({ok, {unambiguous, "7"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {9, + fun() -> + (catch tde(DM, [$8])) + end, + fun({ok, {unambiguous, "8"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {10, + fun() -> + (catch tde(DM, [$9])) + end, + fun({ok, {unambiguous, "9"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {11, + fun() -> + (catch tde(DM, [$a])) + end, + fun({error, {unexpected_event, $a, _Collected, _Expected}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {12, + fun() -> + (catch tde(DM, [$e])) + end, + fun({ok, {unambiguous, "e"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {13, + fun() -> + (catch tde(DM, [$f])) + end, + fun({ok, {unambiguous, "f"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {14, + fun() -> + (catch tde(DM, [$a])) + end, + fun({error, {unexpected_event, $a, + [] = _Collected, + [{letter, [{range, $0, $9}, + {single, $e}, + {single, $f}]}] = _Expected}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end} + ], + + dm_tests(Tests), + + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_7449_2(suite) -> + []; +otp_7449_2(doc) -> + []; +otp_7449_2(Config) when is_list(Config) -> + DM = "([0-9]ef)", + + %% First case + Tests = + [ + {1, + fun() -> + (catch tde(DM, [$0,$e,$f])) + end, + fun({ok, {unambiguous, "0ef"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {2, + fun() -> + (catch tde(DM, [$1,$e,$f])) + end, + fun({ok, {unambiguous, "1ef"}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {3, + fun() -> + (catch tde(DM, [$2])) + end, + fun({error, {unexpected_event, + inter_event_timeout, [$2] = _Collected, + [{single, $e}] = _Expecting}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {4, + fun() -> + (catch tde(DM, [$3,$f,$f])) + end, + fun({error, {unexpected_event, $f, [$3] = _Collected, + [{single, $e}] = _Expected}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end}, + {5, + fun() -> + (catch tde(DM, [$a,$e,$f])) + end, + fun({error, {unexpected_event, $a, + [] = _Collected, + [{letter, [{range, $0, $9}]}] = _Expected}}) -> + ok; + (Else) -> + {error, {unexpected_digit_map_result, Else}} + end} + ], + + dm_tests(Tests), + + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +dm_tests([]) -> + ok; +dm_tests([{No, Exec, Ver}|Tests]) + when is_integer(No) andalso is_function(Exec) andalso is_function(Ver) -> + case dm_test(Exec, Ver) of + ok -> + dm_tests(Tests); + {error, Reason} -> + ?ERROR({No, Reason}); + Error -> + ?ERROR({No, Error}) + end. + +dm_test(Exec, Verify) -> + (catch Verify(Exec())). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +tde(DM, Evs) -> megaco:test_digit_event(DM, Evs). + diff --git a/lib/megaco/test/megaco_examples_test.erl b/lib/megaco/test/megaco_examples_test.erl new file mode 100644 index 0000000000..ef15cb1bde --- /dev/null +++ b/lib/megaco/test/megaco_examples_test.erl @@ -0,0 +1,174 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test application config +%%---------------------------------------------------------------------- + +-module(megaco_examples_test). + +-compile(export_all). + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + +%% Test server callbacks +init_per_testcase(Case, Config) -> + put(dbg,true), + purge_examples(), + load_examples(), + megaco:enable_trace(max, io), + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + purge_examples(), + erase(dbg), + megaco:disable_trace(), + megaco_test_lib:fin_per_testcase(Case, Config). + +example_modules() -> + [megaco_simple_mg, megaco_simple_mgc]. + +load_examples() -> + case code:lib_dir(megaco) of + {error, Reason} -> + {error, Reason}; + Dir -> + [code:load_abs(filename:join([Dir, examples, simple, M])) || M <- example_modules()] + end. + +purge_examples() -> + case code:lib_dir(megaco) of + {error, Reason} -> + {error, Reason}; + _Dir -> + [code:purge(M) || M <- example_modules()] + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top test case + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +all(doc) -> + ["Run all examples mentioned in the documentation", + "Are really all examples covered?"]; +all(suite) -> + [ + simple + ]. + +simple(suite) -> + []; +simple(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + d("simple -> proxy start",[]), + ProxyPid = megaco_test_lib:proxy_start({?MODULE, ?LINE}), + + d("simple -> start megaco",[]), + ?VERIFY(ok, megaco:start()), + + d("simple -> start mgc",[]), + ?APPLY(ProxyPid, fun() -> megaco_simple_mgc:start() end), + receive + {res, _, {ok, MgcAll}} when is_list(MgcAll) -> + MgcBad = [MgcRes || MgcRes <- MgcAll, element(1, MgcRes) /= ok], + ?VERIFY([], MgcBad), + %% MgcGood = MgcAll -- MgcBad, + %% MgcRecHandles = [MgcRH || {ok, _MgcPort, MgcRH} <- MgcGood], + + d("simple -> start mg",[]), + ?APPLY(ProxyPid, fun() -> megaco_simple_mg:start() end), + receive + {res, _, MgList} when is_list(MgList) andalso (length(MgList) =:= 4) -> + d("simple -> received res: ~p",[MgList]), + Verify = + fun({_MgMid, {TransId, Res}}) when TransId =:= 1 -> + case Res of + {ok, [AR]} when is_record(AR, 'ActionReply') -> + case AR#'ActionReply'.commandReply of + [{serviceChangeReply, SCR}] -> + case SCR#'ServiceChangeReply'.serviceChangeResult of + {serviceChangeResParms, MgcMid} when MgcMid /= asn1_NOVALUE -> + ok; + Error -> + ?ERROR(Error) + end; + Error -> + ?ERROR(Error) + end; + Error -> + ?ERROR(Error) + end; + (Error) -> + ?ERROR(Error) + end, + lists:map(Verify, MgList); + Error -> + ?ERROR(Error) + end; + Error -> + ?ERROR(Error) + end, + d("simple -> verify info()",[]), + info(), + d("simple -> verify system_info(users)",[]), + users(), + d("simple -> stop mgc",[]), + ?VERIFY(5, length(megaco_simple_mgc:stop())), + d("simple -> verify system_info(users)",[]), + users(), + d("simple -> stop megaco",[]), + ?VERIFY(ok, megaco:stop()), + d("simple -> kill (exit) ProxyPid: ~p",[ProxyPid]), + exit(ProxyPid, shutdown), % Controlled kill of transport supervisors + + ok. + + +info() -> + case (catch megaco:info()) of + {'EXIT', _} = Error -> + ?ERROR(Error); + Info -> + ?LOG("Ok, ~p~n", [Info]) + end. + +users() -> + case (catch megaco:system_info(users)) of + {'EXIT', _} = Error -> + ?ERROR(Error); + Users -> + ?LOG("Ok, ~p~n", [Users]) + end. + + + + +d(F,A) -> + d(get(dbg),F,A). + +d(true,F,A) -> + io:format("DBG: " ++ F ++ "~n",A); +d(_, _F, _A) -> + ok. diff --git a/lib/megaco/test/megaco_flex_test.erl b/lib/megaco/test/megaco_flex_test.erl new file mode 100644 index 0000000000..3dbcf53e7a --- /dev/null +++ b/lib/megaco/test/megaco_flex_test.erl @@ -0,0 +1,230 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test various aspects of the flex scanner handling +%% +%% Test: ts:run(megaco, megaco_flex_test, [batch]). +%% +%%---------------------------------------------------------------------- + +-module(megaco_flex_test). + +-include("megaco_test_lib.hrl"). + +-export([ + t/0, t/1, + + init_per_testcase/2, fin_per_testcase/2, + + all/1, + flex_init/1, flex_fin/1, + + plain/1, + port_exit/1, + garbage_in/1 + + ]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +init_per_testcase(Case, Config) -> + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all(suite) -> + Cases = + [ + plain, + port_exit, + garbage_in + ], + {req, [], {conf, flex_init, Cases, flex_fin}}. + +flex_init(suite) -> + []; +flex_init(doc) -> + []; +flex_init(Config) when is_list(Config) -> + case megaco_flex_scanner:is_enabled() of + true -> + Config; + false -> + ?SKIP(flex_scanner_not_enabled) + end. + +flex_fin(suite) -> []; +flex_fin(doc) -> []; +flex_fin(Config) when is_list(Config) -> + Config. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +plain(suite) -> + []; +plain(doc) -> + ["This is to simply test that it is possible to start and stop the " + "flex handler."]; +plain(Config) when is_list(Config) -> + put(tc, plain), + p("begin"), + process_flag(trap_exit, true), + p("start the flex handler"), + {ok, Pid, _PortInfo} = flex_scanner_handler_start(), + p("stop handler"), + flex_scanner_handler_stop(Pid), + p("end"), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +port_exit(suite) -> + []; +port_exit(doc) -> + ["Test that the handler detects and handles an exiting port."]; +port_exit(Config) when is_list(Config) -> + put(tc, port_exit), + p("begin"), + process_flag(trap_exit, true), + + p("start the flex handler"), + {ok, Pid, {flex, PortOrPorts}} = flex_scanner_handler_start(), + Port = case PortOrPorts of + P when is_port(P) -> + P; + Ports when is_tuple(Ports) -> + %% It does not matter which of the ports we choose + element(1, PortOrPorts); + Ports when is_list(Ports) -> + %% It does not matter which of the ports we choose + hd(Ports) + end, + + p("simulate crash"), + exit(Port, simulated_crash), + + p("await handler exit"), + receive + {'EXIT', Pid, _} -> + p("end"), + ok + after 5000 -> + p("timeout - stop handler"), + flex_scanner_handler_stop(Pid), + p("end after timeout"), + {error, timeout} + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +garbage_in(suite) -> + []; +garbage_in(doc) -> + ["Send in various unexpected messages and requeststo the handler " + "to see that it does die on us. "]; +garbage_in(Config) when is_list(Config) -> + put(tc, garbage_in), + p("begin"), + process_flag(trap_exit, true), + + p("start the flex handler"), + {ok, Pid, _PortInfo} = flex_scanner_handler_start(), + + p("make an invalid call"), + {error, _} = gen_server:call(Pid, garbage_request), + p("make an invalid cast"), + gen_server:cast(Pid, garbage_msg), + p("send an unknown message"), + Pid ! garbage_info, + + p("wait for any garbage response"), + receive + Any -> + p("end with unexpected message: ~p", [Any]), + {error, {unexpected_msg, Any}} + after 1000 -> + p("end with nothing received - stop handler"), + flex_scanner_handler_stop(Pid), + ok + end. + + + +%% ------- Misc functions -------- + +flex_scanner_handler_start() -> + case megaco_flex_scanner_handler:start_link() of + {error, {failed_starting_scanner, {error, {load_driver, _}}}} -> + p("failed loading driver"), + ?SKIP(could_not_load_driver); + {error, {failed_starting_scanner, {load_driver, _}}} -> + p("failed loading driver"), + ?SKIP(could_not_load_driver); + {error, {failed_starting_scanner, {load_driver, _}, _}} -> + p("failed loading driver"), + ?SKIP(could_not_load_driver); + Else -> + p("driver load result: ~p", [Else]), + Else + end. + +flex_scanner_handler_stop(Pid) -> + megaco_flex_scanner_handler:stop(Pid). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +p(F) -> + p(F, []). + +p(F, A) -> + TC = get(tc), + io:format("*** [~s] ~p ~w ***" + "~n " ++ F ++ "~n", + [formated_timestamp(), self(), TC | A]). + +formated_timestamp() -> + format_timestamp(erlang:now()). + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY, MM, DD} = Date, + {Hour, Min, Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). + + diff --git a/lib/megaco/test/megaco_load_test.erl b/lib/megaco/test/megaco_load_test.erl new file mode 100644 index 0000000000..5a22b7b4ee --- /dev/null +++ b/lib/megaco/test/megaco_load_test.erl @@ -0,0 +1,692 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Verify the application specifics of the Megaco application +%%---------------------------------------------------------------------- +-module(megaco_load_test). + +-compile(export_all). + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). + +-define(TEST_VERBOSITY, debug). +-define(MGC_VERBOSITY, silence). +-define(MG_VERBOSITY, silence). + +-define(SINGLE_USER_LOAD_NUM_REQUESTS, 1000). +-define(MULTI_USER_LOAD_NUM_REQUESTS, 1000). + +-define(MGC_START(Pid, Mid, ET, Conf, Verb), + megaco_test_mgc:start(Pid, Mid, ET, + [{megaco_trace, false}] ++ Conf, Verb)). +-define(MGC_STOP(Pid), megaco_test_mgc:stop(Pid)). +-define(MGC_USER_INFO(Pid,Tag), megaco_test_mgc:user_info(Pid,Tag)). +-define(MGC_CONN_INFO(Pid,Tag), megaco_test_mgc:conn_info(Pid,Tag)). +-define(MGC_SET_VERBOSITY(Pid, V), megaco_test_mgc:verbosity(Pid, V)). + +-define(MG_START(Pid, Mid, Enc, Transp, Conf, Verb), + megaco_test_mg:start(Pid, Mid, Enc, Transp, + [{megaco_trace, false}, + {transport_opts, [{serialize, true}]}] ++ Conf, + Verb)). +-define(MG_STOP(Pid), megaco_test_mg:stop(Pid)). +-define(MG_USER_INFO(Pid,Tag), megaco_test_mg:user_info(Pid,Tag)). +-define(MG_CONN_INFO(Pid,Tag), megaco_test_mg:conn_info(Pid,Tag)). +-define(MG_SERV_CHANGE(Pid), megaco_test_mg:service_change(Pid)). +-define(MG_MLOAD(Pid, NL, NR), + timer:tc(megaco_test_mg, apply_multi_load, [Pid, NL, NR])). +-define(MG_LOAD(Pid, NL, NR), megaco_test_mg:apply_multi_load(Pid, NL, NR)). +-define(MG_SET_VERBOSITY(Pid, V), megaco_test_mg:verbosity(Pid, V)). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + +min(M) -> timer:minutes(M). + +%% Test server callbacks +init_per_testcase(single_user_light_load = Case, Config) -> + C = lists:keydelete(tc_timeout, 1, Config), + do_init_per_testcase(Case, [{tc_timeout, min(2)}|C]); +init_per_testcase(single_user_medium_load = Case, Config) -> + C = lists:keydelete(tc_timeout, 1, Config), + do_init_per_testcase(Case, [{tc_timeout, min(5)}|C]); +init_per_testcase(single_user_heavy_load = Case, Config) -> + C = lists:keydelete(tc_timeout, 1, Config), + do_init_per_testcase(Case, [{tc_timeout, min(10)}|C]); +init_per_testcase(single_user_extreme_load = Case, Config) -> + C = lists:keydelete(tc_timeout, 1, Config), + do_init_per_testcase(Case, [{tc_timeout, min(20)}|C]); +init_per_testcase(multi_user_light_load = Case, Config) -> + C = lists:keydelete(tc_timeout, 1, Config), + do_init_per_testcase(Case, [{tc_timeout, min(2)}|C]); +init_per_testcase(multi_user_medium_load = Case, Config) -> + C = lists:keydelete(tc_timeout, 1, Config), + do_init_per_testcase(Case, [{tc_timeout, min(5)}|C]); +init_per_testcase(multi_user_heavy_load = Case, Config) -> + C = lists:keydelete(tc_timeout, 1, Config), + do_init_per_testcase(Case, [{tc_timeout, min(10)}|C]); +init_per_testcase(multi_user_extreme_load = Case, Config) -> + C = lists:keydelete(tc_timeout, 1, Config), + do_init_per_testcase(Case, [{tc_timeout, min(20)}|C]); +init_per_testcase(Case, Config) -> + do_init_per_testcase(Case, Config). + +do_init_per_testcase(Case, Config) -> + process_flag(trap_exit, true), + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + process_flag(trap_exit, false), + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all(suite) -> + Cases = + [ + single_user_light_load, + single_user_medium_load, + single_user_heavy_load, + single_user_extreme_load, + multi_user_light_load, + multi_user_medium_load, + multi_user_heavy_load, + multi_user_extreme_load + ], + Cases. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +single_user_light_load(suite) -> + []; +single_user_light_load(doc) -> + []; +single_user_light_load(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(tc, single_user_light_load), + put(sname, "TEST"), + i("starting"), + + load_controller(Config, + fun(Env) -> + populate(Env), + exit( single_user_load(5) ) + end), + + i("done", []), + ok. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +single_user_medium_load(suite) -> + []; +single_user_medium_load(doc) -> + []; +single_user_medium_load(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(tc, single_user_medium_load), + put(sname, "TEST"), + i("starting"), + + load_controller(Config, + fun(Env) -> + populate(Env), + exit( single_user_load(15) ) + end), + + i("done", []), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +single_user_heavy_load(suite) -> + []; +single_user_heavy_load(doc) -> + []; +single_user_heavy_load(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(tc, single_user_heavy_load), + put(sname, "TEST"), + i("starting"), + + load_controller(Config, + fun(Env) -> + populate(Env), + exit( single_user_load(25) ) + end), + + i("done", []), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +single_user_extreme_load(suite) -> + []; +single_user_extreme_load(doc) -> + []; +single_user_extreme_load(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(tc, single_user_extreme_load), + put(sname, "TEST"), + i("starting"), + + load_controller(Config, + fun(Env) -> + populate(Env), + exit( single_user_load(100) ) + end), + + i("done", []), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_user_light_load(suite) -> + []; +multi_user_light_load(doc) -> + []; +multi_user_light_load(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(tc, multi_user_light_load), + put(sname, "TEST"), + i("starting"), + + load_controller(Config, + fun(Env) -> + populate(Env), + exit( multi_user_load(3,1) ) + end), + + i("done", []), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_user_medium_load(suite) -> + []; +multi_user_medium_load(doc) -> + []; +multi_user_medium_load(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(tc, multi_user_medium_load), + put(sname, "TEST"), + i("starting"), + + load_controller(Config, + fun(Env) -> + populate(Env), + exit( multi_user_load(3,5) ) + end), + + i("done", []), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_user_heavy_load(suite) -> + []; +multi_user_heavy_load(doc) -> + []; +multi_user_heavy_load(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(tc, multi_user_heavy_load), + put(sname, "TEST"), + i("starting"), + + load_controller(Config, + fun(Env) -> + populate(Env), + exit( multi_user_load(3,10) ) + end), + + i("done", []), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_user_extreme_load(suite) -> + []; +multi_user_extreme_load(doc) -> + []; +multi_user_extreme_load(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(tc, multi_user_extreme_load), + put(sname, "TEST"), + i("starting"), + + load_controller(Config, + fun(Env) -> + populate(Env), + exit( multi_user_load(3,15) ) + end), + + i("done", []), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +populate([]) -> + ok; +populate([{Key,Val}|Env]) -> + put(Key, Val), + populate(Env). + +load_controller(Config, Fun) when is_list(Config) and is_function(Fun) -> + process_flag(trap_exit, true), + {value, {tc_timeout, TcTimeout}} = + lists:keysearch(tc_timeout, 1, Config), + SkipTimeout = trunc(95*TcTimeout/100), % 95% of TcTimeout + Env = get(), + Loader = erlang:spawn_link(fun() -> Fun(Env) end), + receive + {'EXIT', Loader, normal} -> + d("load_controller -> " + "loader [~p] terminated with normal", [Loader]), + ok; + {'EXIT', Loader, ok} -> + d("load_controller -> " + "loader [~p] terminated with ok~n", [Loader]), + ok; + {'EXIT', Loader, Reason} -> + i("load_controller -> " + "loader [~p] terminated with" + "~n ~p", [Loader, Reason]), + erlang:error({unexpected_loader_result, Reason}) + after SkipTimeout -> + i("load_controller -> " + "loader [~p] timeout", [Loader]), + exit(Loader, kill), + ?SKIP({timeout, SkipTimeout, TcTimeout}) + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +single_user_load(NumLoaders) -> + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("Nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + %% Start the MGC and MGs + i("[MGC] start"), + MgcMid = {deviceName, "ctrl"}, + ET = [{text, tcp, [{serialize, true}]}], + DSI = maybe_display_system_info(NumLoaders), + {ok, Mgc} = ?MGC_START(MgcNode, MgcMid, ET, DSI, ?MGC_VERBOSITY), + + i("[MG] start"), + MgMid = {deviceName, "mg"}, + {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, DSI, ?MG_VERBOSITY), + + d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]), + + i("[MG] connect to the MGC (service change)"), + ServChRes = ?MG_SERV_CHANGE(Mg), + d("service change result: ~p", [ServChRes]), + + megaco_test_mg:update_conn_info(Mg,reply_timer,1000), + megaco_test_mgc:update_conn_info(Mgc,reply_timer,1000), + + d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]), + + d("apply the load"), + Res = ?MG_MLOAD(Mg, NumLoaders, ?SINGLE_USER_LOAD_NUM_REQUESTS), + case Res of + {Time, {ok, Ok, Err}} -> + Sec = Time / 1000000, + io:format("~nmultiple loaders result: ~n" + " Number of successfull: ~w~n" + " Number of failure: ~w~n" + " Time: ~w seconds~n" + " Calls / seconds ~w~n~n", + [Ok, Err, Sec, (NumLoaders * ?SINGLE_USER_LOAD_NUM_REQUESTS)/Sec]); + {Time, Error} -> + io:format("SUL: multiple loaders failed: ~p after ~w~n", + [Error, Time]) + end, + + i("flush the message queue: ~p", [megaco_test_lib:flush()]), + + i("verbosity to trace"), + ?MGC_SET_VERBOSITY(Mgc, debug), + ?MG_SET_VERBOSITY(Mg, debug), + + %% Tell MG to stop + i("[MG] stop"), + ?MG_STOP(Mg), + + i("flush the message queue: ~p", [megaco_test_lib:flush()]), + + %% Tell Mgc to stop + i("[MGC] stop"), + ?MGC_STOP(Mgc), + + i("flush the message queue: ~p", [megaco_test_lib:flush()]), + + ok. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_user_load(NumUsers, NumLoaders) + when (is_integer(NumUsers) andalso (NumUsers > 1) andalso + is_integer(NumLoaders) andalso (NumLoaders >= 1)) -> + MgcNode = make_node_name(mgc), + MgNodes = make_node_names(mg, NumUsers), + d("Nodes: " + "~n MgcNode: ~p" + "~n MgNodes: ~p", [MgcNode, MgNodes]), + ok = megaco_test_lib:start_nodes([MgcNode| MgNodes], ?FILE, ?LINE), + + %% Start the MGC and MGs + i("[MGC] start"), + MgcMid = {deviceName, "ctrl"}, + ET = [{text, tcp, [{serialize, false}]}], + DSI = maybe_display_system_info(2 * NumUsers * NumLoaders), + {ok, Mgc} = ?MGC_START(MgcNode, MgcMid, ET, DSI, ?MGC_VERBOSITY), + + megaco_test_mgc:update_user_info(Mgc,reply_timer,1000), + d("MGC user info: ~p", [?MGC_USER_INFO(Mgc, all)]), + + MgUsers = make_mids(MgNodes), + + d("start MGs, apply the load and stop MGs"), + ok = multi_load(MgUsers, DSI, NumLoaders, ?MULTI_USER_LOAD_NUM_REQUESTS), + + i("flush the message queue: ~p", [megaco_test_lib:flush()]), + + ?MGC_SET_VERBOSITY(Mgc, debug), + + %% Tell Mgc to stop + i("[MGC] stop"), + ?MGC_STOP(Mgc), + + i("flush the message queue: ~p", [megaco_test_lib:flush()]), + + ok. + + +multi_load(MGs, DSI, NumLoaders, NumReqs) -> + d("multi_load -> entry with" + "~n MGs: ~p" + "~n DSI: ~p" + "~n NumLoaders: ~p" + "~n NumReqs: ~p", [MGs, DSI, NumLoaders, NumReqs]), + + Pids = multi_load_collector_start(MGs, DSI, NumLoaders, NumReqs, []), + case timer:tc(?MODULE, do_multi_load, [Pids, NumLoaders, NumReqs]) of + {Time, {ok, OKs, []}} -> + Sec = Time / 1000000, + multi_load_collector_calc(Sec, OKs); + {Time, Error} -> + Sec = Time/1000000, + io:format("~nmulti load failed after ~.1f:~n~p~n~n", [Sec,Error]), + {error, Error} + end. + +do_multi_load(Pids, _NumLoaders, _NumReqs) -> + Fun = + fun({P,_}) -> + d("apply multi load for ~p", [P]), + P ! {apply_multi_load, self()} + end, + lists:foreach(Fun, Pids), + await_multi_load_collectors(Pids, [], []). + +multi_load_collector_start([], _DSI, _NumLoaders, _NumReqs, Pids) -> + Pids; +multi_load_collector_start([{Mid, Node}|MGs], DSI, NumLoaders, NumReqs, Pids) -> + Env = get(), + Pid = spawn_link(?MODULE, multi_load_collector, + [self(), Node, Mid, DSI, NumLoaders, NumReqs, Env]), + multi_load_collector_start(MGs, DSI, NumLoaders, NumReqs, [{Pid,Mid}|Pids]). + +get_env(Key, Env) -> + case lists:keysearch(Key, 1, Env) of + {value, {Key, Val}} -> + Val; + _ -> + undefined + end. + +multi_load_collector(Parent, Node, Mid, DSI, NumLoaders, NumReqs, Env) -> + put(verbosity, get_env(verbosity, Env)), + put(tc, get_env(tc, Env)), + put(sname, get_env(sname, Env) ++ "-loader"), + case ?MG_START(Node, Mid, text, tcp, DSI, ?MG_VERBOSITY) of + {ok, Pid} -> + d("MG ~p user info: ~n~p", [Mid, ?MG_USER_INFO(Pid,all)]), + ServChRes = ?MG_SERV_CHANGE(Pid), + d("service change result: ~p", [ServChRes]), + megaco_test_mg:update_conn_info(Pid,reply_timer,1000), + d("MG ~p conn info: ~p", [Mid, ?MG_CONN_INFO(Pid,all)]), + multi_load_collector_loop(Parent, Pid, Mid, NumLoaders, NumReqs); + Else -> + Parent ! {load_start_failed, self(), Mid, Else} + end. + +multi_load_collector_loop(Parent, Pid, Mid, NumLoaders, NumReqs) -> + d("multi_load_collector_loop -> entry with" + "~n Parent: ~p" + "~n Pid: ~p" + "~n Mid: ~p" + "~n NumLoaders: ~p" + "~n NumReqs: ~p" + "~nwhen" + "~n self(): ~p" + "~n node(): ~p", + [Parent, Pid, Mid, NumLoaders, NumReqs, self(), node()]), + receive + {apply_multi_load, Parent} -> + Res = ?MG_LOAD(Pid, NumLoaders, NumReqs), + Parent ! {load_complete, self(), Mid, Res}, + ?MG_SET_VERBOSITY(Pid, debug), + ?MG_STOP(Pid), + exit(normal) + end. + + +await_multi_load_collectors([], Oks, Errs) -> + i("await_multi_load_collectors -> done"), + {ok, Oks, Errs}; +await_multi_load_collectors(Pids, Oks, Errs) -> + receive + {load_complete, Pid, Mg, {ok, Ok, Err}} -> + i("await_multi_load_collectors -> " + "received ok complete from " + "~n ~p [~p]", [Pid, Mg]), + Pids2 = lists:keydelete(Pid, 1, Pids), + Oks2 = [{Mg, Ok, Err}|Oks], + await_multi_load_collectors(Pids2, Oks2, Errs); + {load_complete, Pid, Mg, Error} -> + i("await_multi_load_collectors -> " + "received error complete from " + "~n ~p [~p]: " + "~n ~p", [Pid, Mg, Error]), + Pids2 = lists:keydelete(Pid, 1, Pids), + Errs2 = [{Mg, Error}|Errs], + await_multi_load_collectors(Pids2, Oks, Errs2); + + {'EXIT', Pid, normal} -> + %% This is assumed to be one of the collectors + i("await_multi_load_collectors -> " + "received (normal) exit signal from ~p", [Pid]), + await_multi_load_collectors(Pids, Oks, Errs); + + {'EXIT', Pid, Reason} -> + i("await_multi_load_collectors -> " + "received unexpected exit from ~p:" + "~n ~p", [Pid, Reason]), + case lists:keydelete(Pid, 1, Pids) of + Pids -> + %% Not one of my procs, or a proc I have already + %% received a complete from. + await_multi_load_collectors(Pids, Oks, Errs); + Pids2 -> + [{Pid,Mg}] = Pids -- Pids2, + Errs2 = [{Mg, {unexpected_exit, Reason}}|Errs], + await_multi_load_collectors(Pids, Oks, Errs2) + end; + + Else -> + i("await_multi_load_collectors -> received unexpected message:" + "~n~p", [Else]), + await_multi_load_collectors(Pids, Oks, Errs) + after + 5000 -> + i("await_multi_load_collectors -> still awaiting reply from:" + "~n~p", [Pids]), + await_multi_load_collectors(Pids, Oks, Errs) + end. + + +%% Note that this is an approximation...we run all the +%% MGs in parrallel, so it should be "accurate"... +multi_load_collector_calc(Sec, Oks) -> + Succs = lists:sum([Ok || {_, Ok, _} <- Oks]), + Fails = lists:sum([Err || {_, _, Err} <- Oks]), + io:format("~ntotal multiple loaders result: ~n" + " Number of successfull: ~w~n" + " Number of failure: ~w~n" + " Total Calls / seconds: ~.2f~n~n", + [Succs, Fails, Sec]), + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +make_node_names(Name, Num) -> + make_node_names(Name, Num, []). + +make_node_names(_, 0, Names) -> + Names; +make_node_names(BaseName, N, Names) -> + Name = lists:flatten(io_lib:format("~p~w", [BaseName,N])), + make_node_names(BaseName, N-1, [make_node_name(Name)|Names]). + +make_node_name(Name) when is_atom(Name) -> + make_node_name(atom_to_list(Name)); +make_node_name(Name) when is_list(Name) -> + case string:tokens(atom_to_list(node()), [$@]) of + [_,Host] -> + list_to_atom(lists:concat([Name ++ "@" ++ Host])); + _ -> + exit("Test node must be started with '-sname'") + end. + +make_mids(MgNodes) when is_list(MgNodes) andalso (length(MgNodes) > 0) -> + make_mids(MgNodes, []). + +make_mids([], Mids) -> + lists:reverse(Mids); +make_mids([MgNode|MgNodes], Mids) -> + case string:tokens(atom_to_list(MgNode), [$@]) of + [Name, _] -> + Mid = {deviceName, Name}, + make_mids(MgNodes, [{Mid, MgNode}|Mids]); + _Else -> + exit("Test node must be started with '-sname'") + end. + +tim() -> + {A,B,C} = erlang:now(), + A*1000000000+B*1000+(C div 1000). + +sleep(X) -> receive after X -> ok end. + +error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A). + +maybe_display_system_info(NumLoaders) when NumLoaders > 50 -> + [{display_system_info, timer:seconds(2)}]; +maybe_display_system_info(NumLoaders) when NumLoaders > 10 -> + [{display_system_info, timer:seconds(1)}]; +maybe_display_system_info(_) -> + []. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +i(F) -> + i(F, []). + +i(F, A) -> + print(info, get(verbosity), now(), get(tc), "INF", F, A). + +d(F) -> + d(F, []). + +d(F, A) -> + print(debug, get(verbosity), now(), get(tc), "DBG", F, A). + +printable(_, debug) -> true; +printable(info, info) -> true; +printable(_,_) -> false. + +print(Severity, Verbosity, Ts, Tc, P, F, A) -> + print(printable(Severity,Verbosity), Ts, Tc, P, F, A). + +print(true, Ts, Tc, P, F, A) -> + io:format("*** [~s] ~s ~p ~s:~w ***" + "~n " ++ F ++ "~n", + [format_timestamp(Ts), P, self(), get(sname), Tc | A]); +print(_, _, _, _, _, _) -> + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +random_init() -> + {A,B,C} = now(), + random:seed(A,B,C). + +random() -> + 10 * random:uniform(50). + +apply_load_timer() -> + erlang:send_after(random(), self(), apply_load_timeout). + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). diff --git a/lib/megaco/test/megaco_mess_otp8212_test.erl b/lib/megaco/test/megaco_mess_otp8212_test.erl new file mode 100644 index 0000000000..109886ebc4 --- /dev/null +++ b/lib/megaco/test/megaco_mess_otp8212_test.erl @@ -0,0 +1,181 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: A fun implementation of user callbacks +%%---------------------------------------------------------------------- + +-module(megaco_mess_otp8212_test). + +-behaviour(megaco_user). + +%% Megaco user callback exports +-export([ + handle_connect/2, handle_connect/3, + handle_disconnect/3, + %% handle_syntax_error/3, handle_syntax_error/4, + %% handle_message_error/3, handle_message_error/4, + handle_trans_request/3, %% handle_trans_request/4, + %% handle_trans_long_request/3, handle_trans_long_request/4, + %% handle_trans_reply/4, handle_trans_reply/5, + %% handle_trans_ack/4, handle_trans_ack/5, + handle_unexpected_trans/3, handle_unexpected_trans/4 %% , + %% handle_trans_request_abort/4, handle_trans_request_abort/5, + %% handle_segment_reply/5, handle_segment_reply/6 + ]). + +%% Megaco encoder callback exports +-export([ + encode_message/3, + decode_message/3 + ]). + +%% Megaco transport callback exports +-export([ + send_message/2 + ]). + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). + + +%%---------------------------------------------------------------------- +%% Megaco user callback +%%---------------------------------------------------------------------- + +%% -- handle_connect/2 -- + +handle_connect(_, _) -> + %% i("handle_connect -> entry"), + ok. + +handle_connect(_, _, otp8212_extra) -> + %% i("handle_connect -> entry"), + ok; +handle_connect(_, _, {otp8212_extra, _}) -> + %% i("handle_connect -> entry"), + ok. + +handle_disconnect(Conn, _, {user_disconnect, {otp8212_done, Pid}}) -> + %% i("handle_disconnect -> entry"), + Pid ! {disconnected, Conn}, + ok. + +handle_trans_request(_, _, _) -> %% incoming SC + %% i("handle_trans_request -> entry"), + {discard_ack, ["sc reply"]}. + +handle_unexpected_trans(_ConnHandle, _ProtocolVersion, _Trans) -> +%% i("handle_unexpected_trans -> entry with" +%% "~n ConnHandle: ~p" +%% "~n ProtocolVersion: ~p" +%% "~n Trans: ~p", [ConnHandle, ProtocolVersion, Trans]), + ok. +handle_unexpected_trans(_ConnHandle, _ProtocolVersion, _Trans, {otp8212_extra, Pid}) -> +%% i("handle_unexpected_trans -> entry with" +%% "~n ConnHandle: ~p" +%% "~n ProtocolVersion: ~p" +%% "~n Trans: ~p", [ConnHandle, ProtocolVersion, Trans]), + Pid ! {handle_unexpected_trans, otp8212_extra}, + ok. + + +%%---------------------------------------------------------------------- +%% Megaco encoder callback +%%---------------------------------------------------------------------- + + +%% Should only be encoding MGC's outgoing request, which we expect +%% has transaction id = 1. + +-define(REQUEST(Id, A), + #'MegacoMessage' + {mess + = #'Message' + {version = 1, + mId = {deviceName,"MGC"}, + messageBody + = {transactions, [{transactionRequest, + #'TransactionRequest'{transactionId = Id, + actions = A}}]}}}). + +-define(REPLY(A), + #'MegacoMessage' + {mess + = #'Message' + {version = 1, + mId = {deviceName,"MGC"}, + messageBody + = {transactions, + [{transactionReply, + #'TransactionReply'{transactionResult + = {actionReplies, [A]}}}]}}}). + +request() -> + list_to_binary("!/1 MGC T=1{C=-{SC=ROOT{SV{MT=RS,RE=\"901\"}}}}"). + +sc_reply() -> + list_to_binary("!/1 MGC P=19731{C=-{SC=root}}"). + +encode_message(_, _, ?REQUEST(1, "action request")) -> + %% i("encode_message -> entry with request"), + {ok, request()}; + +encode_message(_, _, ?REPLY("sc reply")) -> + %% i("encode_message -> entry with reply"), + {ok, sc_reply()}. + +decode_message(_, V248, Bin) -> + %% i("decode_message -> entry"), + megaco_compact_text_encoder:decode_message([], V248, Bin). + + +%%---------------------------------------------------------------------- +%% Megaco transport callback +%%---------------------------------------------------------------------- + +%% Outgoing SC reply. +%% send_message(otp8212_scr, _) -> +%% i("send_message(scr) -> entry"), +%% ok; + +%% Outgoing request: fake reception of the the reply. +send_message({RH, ControlPid, _, WrongMidStr}, _) -> + %% i("send_message -> entry"), + spawn(fun() -> receive_reply(200, RH, ControlPid, WrongMidStr) end), + ok. + +receive_reply(After, RH, ControlPid, WrongMidStr) -> + timer:sleep(After), + %% i("receive_reply -> issue reply"), + megaco:process_received_message(RH, ControlPid, + otp8212_sendhandle, + reply(WrongMidStr), + {otp8212_extra, ControlPid}). + +reply(WrongMidStr) -> %% note "wrong" mid. + list_to_binary("!/1 " ++ WrongMidStr ++ " P=1{C=-{SC=root}}"). + +%% i(F) -> +%% i(F, []). + +%% i(F, A) -> +%% io:format(F ++ "~n", A). diff --git a/lib/megaco/test/megaco_mess_test.erl b/lib/megaco/test/megaco_mess_test.erl new file mode 100644 index 0000000000..368800fa54 --- /dev/null +++ b/lib/megaco/test/megaco_mess_test.erl @@ -0,0 +1,13733 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Verify the implementation of the ITU-T protocol H.248 +%%---------------------------------------------------------------------- +%% Run the entire test suite with: +%% +%% megaco_test_lib:t(megaco_test). +%% megaco_test_lib:t({megaco_test, all}). +%% +%% Or parts of it: +%% +%% megaco_test_lib:t({megaco_test, accept}). +%%---------------------------------------------------------------------- +-module(megaco_mess_test). + +%% -compile(export_all). +-export([ + all/1, + init_per_testcase/2, + fin_per_testcase/2, + + connect/1, + + request_and_reply/1, + request_and_reply_plain/1, + request_and_no_reply/1, + request_and_reply_pending_ack_no_pending/1, + request_and_reply_pending_ack_one_pending/1, + single_trans_req_and_reply/1, + single_trans_req_and_reply_sendopts/1, + request_and_reply_and_ack/1, + request_and_reply_and_no_ack/1, + request_and_reply_and_late_ack/1, + trans_req_and_reply_and_req/1, + + pending_ack/1, + pending_ack_plain/1, + request_and_pending_and_late_reply/1, + + dist/1, + + tickets/1, + otp_4359/1, + otp_4836/1, + otp_5805/1, + otp_5881/1, + otp_5887/1, + otp_6253/1, + otp_6275/1, + otp_6276/1, + otp_6442/1, + otp_6442_resend_request1/1, + otp_6442_resend_request2/1, + otp_6442_resend_reply1/1, + otp_6442_resend_reply2/1, + otp_6865/1, + otp_6865_request_and_reply_plain_extra1/1, + otp_6865_request_and_reply_plain_extra2/1, + otp_7189/1, + otp_7259/1, + otp_7713/1, + otp_8183/1, + otp_8183_request1/1, + otp_8212/1 + ]). + +%% -behaviour(megaco_user). +-export([ + handle_connect/3, + handle_disconnect/4, + handle_syntax_error/4, + handle_message_error/4, + handle_trans_request/4, + handle_trans_long_request/4, + handle_trans_reply/5, + handle_trans_ack/5, + handle_unexpected_trans/4, + handle_trans_request_abort/5 + ]). + +%% -behaviour(megaco_transport). +-export([ + send_message/2, + unblock/1 + ]). + +-ifdef(megaco_hipe_special). +-export([ + %% Case: request_and_reply_pending_ack_no_pending + rarpanp_mgc_verify_handle_connect/1, + rarpanp_mgc_verify_service_change_req/2, + rarpanp_mgc_verify_notify_request/1, + rarpanp_mgc_verify_handle_disconnect/1, + rarpanp_mg_verify_service_change_rep_msg/1, + rarpanp_mg_verify_notify_rep_msg/3, + + %% Case: request_and_reply_pending_ack_one_pending + rarpaop_mgc_verify_handle_connect/1, + rarpaop_mgc_verify_service_change_req/2, + rarpaop_mgc_verify_notify_request/1, + rarpaop_mgc_verify_reply_ack/1, + rarpaop_mgc_verify_handle_disconnect/1, + rarpaop_mg_verify_service_change_rep_msg/1, + rarpaop_mg_verify_pending_msg/2, + rarpaop_mg_verify_notify_rep_msg/3, + + %% Case: single_trans_req_and_reply + strar_mgc_verify_handle_connect/1, + strar_mgc_verify_service_change_req/2, + strar_mgc_verify_notify_request/1, + strar_mgc_verify_handle_disconnect/1, + strar_mg_verify_handle_connect/1, + strar_mg_verify_service_change_reply/1, + strar_mg_verify_notify_reply/1, + + %% Case: single_trans_req_and_reply_sendopts + straro_mgc_verify_handle_connect/1, + straro_mgc_verify_service_change_req/2, + straro_mgc_verify_notify_request/1, + straro_mgc_verify_handle_trans_ack/1, + straro_mg_verify_handle_connect/1, + straro_mg_verify_service_change_reply/1, + straro_mg_verify_handle_disconnect/1, + + %% Case: request_and_reply_and_ack + raraa_mgc_verify_handle_connect/1, + raraa_mgc_verify_service_change_req/2, + raraa_mgc_verify_notify_req/1, + raraa_mgc_verify_handle_trans_ack/1, + raraa_mgc_verify_handle_disconnect/1, + raraa_mg_verify_service_change_rep_msg/1, + raraa_mg_verify_notify_rep_msg/5, + + %% Case: request_and_reply_and_no_ack + rarana_mgc_verify_handle_connect/1, + rarana_mgc_verify_service_change_req/2, + rarana_mgc_verify_notify_req/1, + rarana_mgc_verify_handle_trans_ack/1, + rarana_mgc_verify_handle_disconnect/1, + rarana_mg_verify_service_change_rep_msg/1, + rarana_mg_verify_notify_rep_msg/5, + + %% Case: request_and_reply_and_late_ack + rarala_mgc_verify_handle_connect/1, + rarala_mgc_verify_service_change_req/2, + rarala_mgc_verify_notify_req/1, + rarala_mgc_verify_handle_trans_ack/1, + rarala_mgc_verify_handle_disconnect/1, + rarala_mg_verify_service_change_rep_msg/1, + rarala_mg_verify_notify_rep_msg/5, + + %% Case: trans_req_and_reply_and_req + trarar_mgc_verify_handle_connect/1, + trarar_mgc_verify_service_change_req/2, + trarar_mgc_verify_notify_req/2, + trarar_mgc_verify_handle_disconnect/1, + trarar_mg_verify_service_change_rep_msg/1, + trarar_mg_verify_notify_rep_msg/5, + + %% Case: pending_ack_plain + pap_mgc_verify_handle_connect/1, + pap_mgc_verify_service_change_req/2, + pap_mgc_verify_notify_req/1, + pap_mgc_verify_notify_req_long/1, + pap_mgc_verify_handle_trans_ack/1, + pap_mgc_verify_handle_disconnect/1, + pap_mg_verify_service_change_rep_msg/1, + pap_mg_verify_pending_msg/2, + pap_mg_verify_notify_rep_msg/5, + + %% Case: request_and_pending_and_late_reply + rapalr_mgc_verify_service_change_req_msg/1, + rapalr_mgc_verify_notify_req_msg/5, + rapalr_mgc_verify_trans_ack_msg/2, + rapalr_mg_verify_handle_connect/1, + rapalr_mg_verify_service_change_rep/1, + rapalr_mg_verify_notify_rep/1, + + %% Case: otp_4836 + otp_4836_mgc_verify_service_change_req_msg/1, + otp_4836_mgc_verify_notify_req_msg/1, + + %% Case: otp_5805 + otp_5805_mgc_verify_handle_connect/1, + otp_5805_mgc_verify_service_change_req/2, + otp_5805_mgc_verify_handle_syntax_error/1, + otp_5805_mgc_verify_handle_disconnect/1, + otp_5805_mg_verify_service_change_rep_msg/1, + otp_5805_mg_verify_error_descriptor_msg/1, + + %% Case: otp_5881 + otp_5881_mgc_verify_service_change_req_msg/1, + otp_5881_mgc_verify_notify_req_msg/1, + + %% Case: otp_5887 + otp_5887_mgc_verify_service_change_req_msg/1, + otp_5887_mgc_verify_notify_req_msg/1, + + %% Case: otp_6275 + otp_6275_mgc_verify_service_change_req_msg/1, + otp_6275_mgc_verify_notify_rep_msg/1, + otp_6275_mg_verify_handle_connect/1, + otp_6275_mg_verify_notify_req/1, + otp_6275_mg_verify_handle_trans_rep/1, + + %% Case: otp_6442_resend_request1 + otp_6442_resend_request1_mg_verify_handle_connect/1, + otp_6442_resend_request1_mg_verify_service_change_rep/1, + otp_6442_resend_request1_mg_verify_notify_rep/1, + + %% Case: otp_6442_resend_request2 + otp_6442_resend_request2_mg_verify_handle_connect/1, + otp_6442_resend_request2_mg_verify_service_change_rep/1, + otp_6442_resend_request2_mg_verify_notify_rep/1, + + %% Case: otp_6442_resend_reply1 + otp_6442_resend_reply1_mg_verify_handle_connect/1, + otp_6442_resend_reply1_mg_verify_service_change_rep/1, + otp_6442_resend_reply1_mg_verify_notify_req/2, + otp_6442_resend_reply1_mg_verify_ack/1, + + %% Case: otp_6442_resend_reply2 + otp_6442_resend_reply2_mg_verify_handle_connect/1, + otp_6442_resend_reply2_mg_verify_service_change_rep/1, + otp_6442_resend_reply2_mg_verify_notify_req/2, + otp_6442_resend_reply2_mg_verify_ack/1, + + %% Case: otp_6865_request_and_reply_plain_extra2 + otp6865e2_mgc_verify_handle_connect/1, + otp6865e2_mgc_verify_service_change_req/3, + otp6865e2_mgc_verify_notify_req/4, + otp6865e2_mgc_verify_reply_ack/2, + otp6865e2_mgc_verify_notify_reply/2, + otp6865e2_mgc_verify_handle_disconnect/1, + otp6865e2_mg_verify_service_change_rep_msg/1, + otp6865e2_mg_verify_notify_rep_msg/6, + otp6865e2_mg_verify_notify_req_msg/1, + + %% Case: otp_7189 + otp_7189_mgc_verify_handle_connect/1, + otp_7189_mgc_verify_service_change_req/2, + otp_7189_mgc_verify_handle_trans_reply_req/1, + otp_7189_mgc_verify_handle_disconnect/1, + otp_7189_mg_verify_service_change_rep_msg/1, + otp_7189_mg_verify_notify_req_msg/1, + + %% Case: otp_6442_resend_request1 + otp_8183_request1_mg_verify_handle_connect/1, + otp_8183_request1_mg_verify_service_change_rep/1, + otp_8183_request1_mg_verify_notify_rep/1, + + %% Utility + encode_msg/3, + decode_msg/3 + ]). +-endif. + +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). +-include("megaco_test_lib.hrl"). + +-define(VERSION, 1). + +-define(TEST_VERBOSITY, debug). +-define(MGC_VERBOSITY, debug). +-define(MG_VERBOSITY, debug). + +-define(MGC_START(Pid, Mid, ET, Conf, Verb), + megaco_test_mgc:start(Pid, Mid, ET, Conf, Verb)). +-define(MGC_STOP(Pid), megaco_test_mgc:stop(Pid)). +-define(MGC_REQ_PEND(Pid,To), megaco_test_mgc:request_pending(Pid,To)). +-define(MGC_REQ_HP(Pid,To), megaco_test_mgc:request_handle_pending(Pid,To)). +-define(MGC_ACK_INFO(Pid), megaco_test_mgc:ack_info(Pid,self())). + +-define(MG_START(Pid, Mid, Enc, Transp, Conf, Verb), + megaco_test_mg:start(Pid, Mid, Enc, Transp, Conf, Verb)). +-define(MG_STOP(Pid), megaco_test_mg:stop(Pid)). +-define(MG_SERV_CHANGE(Pid), megaco_test_mg:service_change(Pid)). +-define(MG_NOTIF_REQ(Pid), megaco_test_mg:notify_request(Pid)). +-define(MG_AWAIT_NOTIF_REP(Pid), megaco_test_mg:await_notify_reply(Pid)). +-define(MG_CONN_INFO(Pid,Tag), megaco_test_mg:conn_info(Pid,Tag)). +-define(MG_USER_INFO(Pid,Tag), megaco_test_mg:user_info(Pid,Tag)). +-define(MG_NOTIF_RAR(Pid), megaco_test_mg:notify_request_and_reply(Pid)). + +-define(SEND(Expr), + ?VERIFY(ok, megaco_mess_user_test:apply_proxy(fun() -> Expr end))). + +-define(USER(Expected, Reply), + megaco_mess_user_test:reply(?MODULE, + ?LINE, + fun(Actual) -> + case ?VERIFY(Expected, Actual) of + Expected -> {ok, Reply}; + UnExpected -> {error, {reply_verify, + ?MODULE, + ?LINE, + UnExpected}} + end + end)). + +%% t() -> megaco_test_lib:t(?MODULE). +%% t(Case) -> megaco_test_lib:t({?MODULE, Case}). + + +min(M) -> timer:minutes(M). + +%% Test server callbacks +% init_per_testcase(pending_ack = Case, Config) -> +% put(dbg,true), +% megaco_test_lib:init_per_testcase(Case, Config); +init_per_testcase(otp_7189 = Case, Config) -> + C = lists:keydelete(tc_timeout, 1, Config), + megaco_test_lib:init_per_testcase(Case, [{tc_timeout, min(2)} |C]); +init_per_testcase(request_and_no_reply = Case, Config) -> + C = lists:keydelete(tc_timeout, 1, Config), + megaco_test_lib:init_per_testcase(Case, [{tc_timeout, min(2)} |C]); +init_per_testcase(Case, Config) -> + C = lists:keydelete(tc_timeout, 1, Config), + megaco_test_lib:init_per_testcase(Case, [{tc_timeout, min(1)} |C]). + +% fin_per_testcase(pending_ack = Case, Config) -> +% erase(dbg), +% megaco_test_lib:fin_per_testcase(Case, Config); +fin_per_testcase(Case, Config) -> + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all(suite) -> + [ + connect, + request_and_reply, + pending_ack, + dist, + + %% Tickets last + tickets + ]. + +request_and_reply(suite) -> + [ + request_and_reply_plain, + request_and_no_reply, + request_and_reply_pending_ack_no_pending, + request_and_reply_pending_ack_one_pending, + single_trans_req_and_reply, + single_trans_req_and_reply_sendopts, + request_and_reply_and_ack, + request_and_reply_and_no_ack, + request_and_reply_and_late_ack, + trans_req_and_reply_and_req + ]. + +pending_ack(suite) -> + [ + pending_ack_plain, + request_and_pending_and_late_reply + ]. + +tickets(suite) -> + [ + otp_4359, + otp_4836, + otp_5805, + otp_5881, + otp_5887, + otp_6253, + otp_6275, + otp_6276, + otp_6442, + otp_6865, + otp_7189, + otp_7259, + otp_7713, + otp_8183, + otp_8212 + ]. + +otp_6442(suite) -> + [ + otp_6442_resend_request1, + otp_6442_resend_request2, + otp_6442_resend_reply1, + otp_6442_resend_reply2 + ]. + +otp_6865(suite) -> + [ + otp_6865_request_and_reply_plain_extra1, + otp_6865_request_and_reply_plain_extra2 + ]. + +otp_8183(suite) -> + [ + otp_8183_request1 + ]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +connect(suite) -> + []; +connect(doc) -> + []; +connect(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + PrelMid = preliminary_mid, + MgMid = ipv4_mid(4711), + + ?VERIFY(ok, application:start(megaco)), + ?VERIFY(ok, megaco:start_user(MgMid, [{send_mod, bad_send_mod}, + {request_timer, infinity}, + {reply_timer, infinity}])), + + MgRH = user_info(MgMid, receive_handle), + {ok, PrelCH} = ?VERIFY({ok, _}, megaco:connect(MgRH, PrelMid, sh, self())), + + connections([PrelCH]), + ?VERIFY([PrelCH], megaco:user_info(MgMid, connections)), + + ?VERIFY(bad_send_mod, megaco:user_info(MgMid, send_mod)), + ?VERIFY(bad_send_mod, megaco:conn_info(PrelCH, send_mod)), + SC = service_change_request(), + ?VERIFY({1, {error, {send_message_failed, {'EXIT', + {undef, [{bad_send_mod, send_message, [sh, _]} | _]}}}}}, + megaco:call(PrelCH, [SC], [])), + + ?VERIFY(ok, megaco:disconnect(PrelCH, shutdown)), + + ?VERIFY(ok, megaco:stop_user(MgMid)), + ?VERIFY(ok, application:stop(megaco)), + ?RECEIVE([]), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +request_and_reply_plain(suite) -> + []; +request_and_reply_plain(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + d("request_and_reply_plain -> start proxy",[]), + megaco_mess_user_test:start_proxy(), + + PrelMid = preliminary_mid, + MgMid = ipv4_mid(4711), + MgcMid = ipv4_mid(), + UserMod = megaco_mess_user_test, + d("request_and_reply_plain -> start megaco app",[]), + ?VERIFY(ok, application:start(megaco)), + UserConfig = [{user_mod, UserMod}, {send_mod, UserMod}, + {request_timer, infinity}, {reply_timer, infinity}], + d("request_and_reply_plain -> start (MG) user ~p",[MgMid]), + ?VERIFY(ok, megaco:start_user(MgMid, UserConfig)), + + d("request_and_reply_plain -> start (MGC) user ~p",[MgcMid]), + ?VERIFY(ok, megaco:start_user(MgcMid, UserConfig)), + + d("request_and_reply_plain -> get receive info for ~p",[MgMid]), + MgRH = user_info(MgMid, receive_handle), + d("request_and_reply_plain -> get receive info for ~p",[MgcMid]), + MgcRH = user_info(MgcMid, receive_handle), + d("request_and_reply_plain -> start transport",[]), + {ok, MgPid, MgSH} = + ?VERIFY({ok, _, _}, UserMod:start_transport(MgRH, MgcRH)), + PrelMgCH = #megaco_conn_handle{local_mid = MgMid, + remote_mid = preliminary_mid}, + MgCH = #megaco_conn_handle{local_mid = MgMid, + remote_mid = MgcMid}, + MgcCH = #megaco_conn_handle{local_mid = MgcMid, + remote_mid = MgMid}, + d("request_and_reply_plain -> (MG) try connect to MGC",[]), + ?SEND(megaco:connect(MgRH, PrelMid, MgSH, MgPid)), % Mg prel + d("request_and_reply_plain -> (MGC) await connect from MG",[]), + ?USER({connect, PrelMgCH, _V, []}, ok), + ?RECEIVE([{res, _, {ok, PrelMgCH}}]), + + d("request_and_reply_plain -> (MG) send service change request",[]), + Req = service_change_request(), + ?SEND(megaco:call(PrelMgCH, [Req], [])), + + d("request_and_reply_plain -> (MGC) send service change reply",[]), + ?USER({connect, MgcCH, _V, []}, ok), % Mgc auto + Rep = service_change_reply(MgcMid), + ?USER({request, MgcCH, _V, [[Req]]}, {discard_ack, [Rep]}), + ?USER({connect, MgCH, _V, []}, ok), % Mg confirm + ?RECEIVE([{res, _, {1, {ok, [Rep]}}}]), + + d("request_and_reply_plain -> get (system info) connections",[]), + connections([MgCH, MgcCH]), + d("request_and_reply_plain -> get (~p) connections",[MgMid]), + ?VERIFY([MgCH], megaco:user_info(MgMid, connections)), + d("request_and_reply_plain -> get (~p) connections",[MgcMid]), + ?VERIFY([MgcCH], megaco:user_info(MgcMid, connections)), + + Reason = shutdown, + d("request_and_reply_plain -> (MG) disconnect",[]), + ?SEND(megaco:disconnect(MgCH, Reason)), + ?USER({disconnect, MgCH, _V, [{user_disconnect, Reason}]}, ok), + ?RECEIVE([{res, _, ok}]), + ?VERIFY(ok, megaco:stop_user(MgMid)), + + d("request_and_reply_plain -> (MGC) disconnect",[]), + ?SEND(megaco:disconnect(MgcCH, Reason)), + ?USER({disconnect, MgcCH, _V, [{user_disconnect, Reason}]}, ok), + ?RECEIVE([{res, _, ok}]), + ?VERIFY(ok, megaco:stop_user(MgcMid)), + + d("request_and_reply_plain -> stop megaco app",[]), + ?VERIFY(ok, application:stop(megaco)), + ?RECEIVE([]), + d("request_and_reply_plain -> done",[]), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% OTP-4760 +request_and_no_reply(suite) -> + []; +request_and_no_reply(doc) -> + []; +request_and_no_reply(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, request_and_no_reply), + i("starting"), + + MgcNode = make_node_name(mgc), + Mg1Node = make_node_name(mg1), + Mg2Node = make_node_name(mg2), + Mg3Node = make_node_name(mg3), + Mg4Node = make_node_name(mg4), + d("start nodes: " + "~n MgcNode: ~p" + "~n Mg1Node: ~p" + "~n Mg2Node: ~p" + "~n Mg3Node: ~p" + "~n Mg4Node: ~p", + [MgcNode, Mg1Node, Mg2Node, Mg3Node, Mg4Node]), + Nodes = [MgcNode, Mg1Node, Mg2Node, Mg3Node, Mg4Node], + ok = megaco_test_lib:start_nodes(Nodes, ?FILE, ?LINE), + + %% Start the MGC + i("[MGC] start"), + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + {ok, Mgc} = + ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY), + + i("[MG] start"), + Mg1Mid = {deviceName, "mg1"}, + Mg2Mid = {deviceName, "mg2"}, + Mg3Mid = {deviceName, "mg3"}, + Mg4Mid = {deviceName, "mg4"}, + ReqTmr = #megaco_incr_timer{wait_for = 3000, + factor = 1, + incr = 0, + max_retries = 2 + }, + LongReqTmr = #megaco_incr_timer{wait_for = 10000, + factor = 1, + incr = 0, + max_retries = 3 + }, + %% Start the MGs + PendingTmr = 10000, + ReplyTmr = 16000, + MgConfig = [{request_timer, ReqTmr}, + {long_request_timer, LongReqTmr}, + {pending_timer, PendingTmr}, + {reply_timer, ReplyTmr}], + {ok, Mg1} = ?MG_START(Mg1Node, Mg1Mid, text, tcp, MgConfig, ?MG_VERBOSITY), + {ok, Mg2} = ?MG_START(Mg2Node, Mg2Mid, text, udp, MgConfig, ?MG_VERBOSITY), + {ok, Mg3} = ?MG_START(Mg3Node, Mg3Mid, binary, tcp, MgConfig, ?MG_VERBOSITY), + {ok, Mg4} = ?MG_START(Mg4Node, Mg4Mid, binary, udp, MgConfig, ?MG_VERBOSITY), + + d("MG1 user info: ~p", [?MG_USER_INFO(Mg1, all)]), + d("MG1 conn info: ~p", [?MG_CONN_INFO(Mg1, all)]), + d("MG2 user info: ~p", [?MG_USER_INFO(Mg2, all)]), + d("MG2 conn info: ~p", [?MG_CONN_INFO(Mg2, all)]), + d("MG3 user info: ~p", [?MG_USER_INFO(Mg3, all)]), + d("MG3 conn info: ~p", [?MG_CONN_INFO(Mg3, all)]), + d("MG4 user info: ~p", [?MG_USER_INFO(Mg4, all)]), + d("MG4 conn info: ~p", [?MG_CONN_INFO(Mg4, all)]), + + i("[MG1] connect to the MGC (service change)"), + ServChRes1 = ?MG_SERV_CHANGE(Mg1), + d("service change result: ~p", [ServChRes1]), + d("MG1 user info: ~p", [?MG_USER_INFO(Mg1, all)]), + d("MG1 conn info: ~p", [?MG_CONN_INFO(Mg1, all)]), + + i("[MG2] connect to the MGC (service change)"), + ServChRes2 = ?MG_SERV_CHANGE(Mg2), + d("service change result: ~p", [ServChRes2]), + d("MG2 user info: ~p", [?MG_USER_INFO(Mg2, all)]), + d("MG2 conn info: ~p", [?MG_CONN_INFO(Mg2, all)]), + + i("[MG3] connect to the MGC (service change)"), + ServChRes3 = ?MG_SERV_CHANGE(Mg3), + d("service change result: ~p", [ServChRes3]), + d("MG3 user info: ~p", [?MG_USER_INFO(Mg3, all)]), + d("MG3 conn info: ~p", [?MG_CONN_INFO(Mg3, all)]), + + i("[MG4] connect to the MGC (service change)"), + ServChRes4 = ?MG_SERV_CHANGE(Mg4), + d("service change result: ~p", [ServChRes4]), + d("MG4 user info: ~p", [?MG_USER_INFO(Mg4, all)]), + d("MG4 conn info: ~p", [?MG_CONN_INFO(Mg4, all)]), + + d("tell the MGC to ignore requests"), + ?MGC_REQ_PEND(Mgc, infinity), + + d("[MG1] send the notify"), + ?MG_NOTIF_REQ(Mg1), + + d("[MG2] send the notify"), + ?MG_NOTIF_REQ(Mg2), + + d("[MG3] send the notify"), + ?MG_NOTIF_REQ(Mg3), + + d("[MG4] send the notify"), + ?MG_NOTIF_REQ(Mg4), + + d("[MG1] await notify reply"), + {ok, {_Vsn1, {error, timeout}}} = ?MG_AWAIT_NOTIF_REP(Mg1), + d("[MG1] received expected reply"), + + d("[MG2] await notify reply"), + {ok, {_Vsn2, {error, timeout}}} = ?MG_AWAIT_NOTIF_REP(Mg2), + d("[MG2] received expected reply"), + + d("[MG3] await notify reply"), + {ok, {_Vsn3, {error, timeout}}} = ?MG_AWAIT_NOTIF_REP(Mg3), + d("[MG3] received expected reply"), + + d("[MG4] await notify reply"), + {ok, {_Vsn4, {error, timeout}}} = ?MG_AWAIT_NOTIF_REP(Mg4), + d("[MG4] received expected reply"), + + d("MG1 user info: ~p", [?MG_USER_INFO(Mg1, all)]), + d("MG1 conn info: ~p", [?MG_CONN_INFO(Mg1, all)]), + d("MG2 user info: ~p", [?MG_USER_INFO(Mg2, all)]), + d("MG2 conn info: ~p", [?MG_CONN_INFO(Mg2, all)]), + d("MG3 user info: ~p", [?MG_USER_INFO(Mg3, all)]), + d("MG3 conn info: ~p", [?MG_CONN_INFO(Mg3, all)]), + d("MG4 user info: ~p", [?MG_USER_INFO(Mg4, all)]), + d("MG4 conn info: ~p", [?MG_CONN_INFO(Mg4, all)]), + + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +request_and_reply_pending_ack_no_pending(suite) -> + []; +request_and_reply_pending_ack_no_pending(doc) -> + ["This test case tests that megaco correctly handles the return " + "value handle_pending_ack from handle_trans_request when NO " + "pending message has been sent"]; +request_and_reply_pending_ack_no_pending(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, rar_panp), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + Nodes = [MgcNode, MgNode], + ok = megaco_test_lib:start_nodes(Nodes, ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = rarpanp_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_tcp_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = rarpanp_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_tcp_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(rarpanp_mgc_verify_handle_connect_fun(), + {?MODULE, rarpanp_mgc_verify_handle_connect, []}). +-define(rarpanp_mgc_verify_service_change_req_fun(Mid), + {?MODULE, rarpanp_mgc_verify_service_change_req, [Mid]}). +-define(rarpanp_mgc_verify_notify_req_fun(), + {?MODULE, rarpanp_mgc_verify_notify_request, []}). +-define(rarpanp_mgc_verify_handle_disconnect_fun(), + {?MODULE, rarpanp_mgc_verify_handle_disconnect, []}). +-else. +-define(rarpanp_mgc_verify_handle_connect_fun(), + fun rarpanp_mgc_verify_handle_connect/1). +-define(rarpanp_mgc_verify_service_change_req_fun(Mid), + rarpanp_mgc_verify_service_change_req_fun(Mid)). +-define(rarpanp_mgc_verify_notify_req_fun(), + rarpanp_mgc_verify_notify_request_fun()). +-define(rarpanp_mgc_verify_handle_disconnect_fun(), + fun rarpanp_mgc_verify_handle_disconnect/1). +-endif. + +rarpanp_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?rarpanp_mgc_verify_handle_connect_fun(), + ScrVerify = ?rarpanp_mgc_verify_service_change_req_fun(Mid), + NrVerify = ?rarpanp_mgc_verify_notify_req_fun(), + DiscoVerify = ?rarpanp_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun rarpanp_mgc_verify_handle_connect/1, +%% ScrVerify = rarpanp_mgc_verify_service_change_req_fun(Mid), +%% NrVerify = rarpanp_mgc_verify_notify_request_fun(), +%% DiscoVerify = fun rarpanp_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, sent_pending_limit, 100}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_conn_info, all}, + {megaco_callback, handle_trans_request, ScrVerify}, + {megaco_callback, handle_trans_request, NrVerify}, + {megaco_callback, nocall, 10000}, + {megaco_callback, handle_disconnect, DiscoVerify}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + +%% Connect verification +rarpanp_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + {ok, CH, ok}; +rarpanp_mgc_verify_handle_connect(Else) -> + {error, Else, ok}. + +%% Service Change verification +-ifndef(megaco_hipe_special). +rarpanp_mgc_verify_service_change_req_fun(Mid) -> + fun(Req) -> + rarpanp_mgc_verify_service_change_req(Req, Mid) + end. +-endif. + +rarpanp_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("rarpanp_mgc_verify_service_change_req -> entry with" + "~n AR: ~p" + "~n Mid: ~p" + "~n", [AR, Mid]), + (catch rarpanp_mgc_do_verify_service_change_req(AR, Mid)); +rarpanp_mgc_verify_service_change_req(Crap, _Mid) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +rarpanp_mgc_do_verify_service_change_req(AR, Mid) -> + io:format("rarpanp_mgc_do_verify_service_change_req -> entry with" + "~n AR: ~p" + "~n Mid: ~p" + "~n", [AR, Mid]), + CR = + case AR of + #'ActionRequest'{commandRequests = [CmdReq]} -> + CmdReq; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Err4 = {invalid_termination_id, Tid}, + ED4 = cre_ErrDesc(Tid), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + case Parms of + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + AckData = [rarpanp_mgc_service_change_reply_ar(Mid, 1)], + Reply = {discard_ack, AckData}, + {ok, AR, Reply}; + _ -> + Err5 = {invalid_SCP, Parms}, + ED5 = cre_ErrDesc(Parms), + ErrReply5 = {discard_ack, ED5}, + {error, Err5, ErrReply5} + end. + + +%% Notify Request verification +-ifndef(megaco_hipe_special). +rarpanp_mgc_verify_notify_request_fun() -> + fun(Req) -> + rarpanp_mgc_verify_notify_request(Req) + end. +-endif. + +rarpanp_mgc_verify_notify_request( + {handle_trans_request, _, ?VERSION, [AR]}) -> + (catch rarpanp_mgc_do_verify_notify_request(AR)); +rarpanp_mgc_verify_notify_request(Crap) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +rarpanp_mgc_do_verify_notify_request(AR) -> + io:format("rarpanp_mgc_do_verify_notify_request -> entry with" + "~n AR: ~p" + "~n", [AR]), + {Cid, CR} = + case AR of + #'ActionRequest'{contextId = CtxID, + commandRequests = [CmdReq]} -> + {CtxID, CmdReq}; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + {Tid, OED} = + case NR of + #'NotifyRequest'{terminationID = [TermID], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + {TermID, ObsEvsDesc}; + _ -> + Err4 = {invalid_NR, NR}, + ED4 = cre_ErrDesc(NR), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + Err5 = {invalid_OED, OED}, + ED5 = cre_ErrDesc(NR), + ErrReply5 = {discard_ack, ED5}, + throw({error, Err5, ErrReply5}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + AckData = notify_request_verified, + Replies = [rarpanp_mgc_notify_reply_ar(Cid, Tid)], + Reply = {{handle_pending_ack, AckData}, Replies}, + {ok, AR, Reply}; + _ -> + Err6 = {invalid_OE, OE}, + ED6 = cre_ErrDesc(OE), + ErrReply6 = {discard_ack, ED6}, + throw({error, Err6, ErrReply6}) + end. + + +%% Disconnect verification +rarpanp_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, _R}) -> + {ok, CH, ok}; +rarpanp_mgc_verify_handle_disconnect(Else) -> + {error, Else, ok}. + +rarpanp_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + AR. + +rarpanp_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(rarpanp_mg_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(rarpanp_mg_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(rarpanp_mg_verify_service_change_rep_msg_fun(), + {?MODULE, rarpanp_mg_verify_service_change_rep_msg, []}). +-define(rarpanp_mg_verify_notify_rep_msg_fun(TransId, TermId), + {?MODULE, rarpanp_mg_verify_notify_rep_msg, [TransId, TermId]}). +-else. +-define(rarpanp_mg_decode_msg_fun(Mod, Conf), + rarpanp_mg_decode_msg_fun(Mod, Conf)). +-define(rarpanp_mg_encode_msg_fun(Mod, Conf), + rarpanp_mg_encode_msg_fun(Mod, Conf)). +-define(rarpanp_mg_verify_service_change_rep_msg_fun(), + rarpanp_mg_verify_service_change_rep_msg_fun()). +-define(rarpanp_mg_verify_notify_rep_msg_fun(TransId, TermId), + rarpanp_mg_verify_notify_rep_msg_fun(TransId, TermId)). +-endif. + +rarpanp_mg_event_sequence(text, tcp) -> + DecodeFun = ?rarpanp_mg_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ?rarpanp_mg_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mg"}, + ServiceChangeReq = rarpanp_mg_service_change_request_msg(Mid, 1, 0), + ScrVerifyFun = ?rarpanp_mg_verify_service_change_rep_msg_fun(), + TransId = 2, + TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq = rarpanp_mg_notify_request_msg(Mid, TransId, 1, TermId, 1), + NrVerifyFun = ?rarpanp_mg_verify_notify_rep_msg_fun(TransId, TermId), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {connect, 2944}, + {send, "service-change-request", ServiceChangeReq}, + {expect_receive, "service-change-reply", {ScrVerifyFun, 10000}}, + {send, "notify request", NotifyReq}, + {expect_receive, "notify-reply", {NrVerifyFun, 10000}}, + {expect_nothing, 11000}, + disconnect + ], + EvSeq. + + +-ifndef(megaco_hipe_special). +rarpanp_mg_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +rarpanp_mg_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +rarpanp_mg_verify_service_change_rep_msg_fun() -> + fun(Msg) -> + (catch rarpanp_mg_verify_service_change_rep_msg(Msg)) + end. +-endif. + +rarpanp_mg_verify_service_change_rep_msg(#'MegacoMessage'{mess = Mess} = M) -> + io:format("rarpanp_mg_verify_service_change_rep_msg -> entry with" + "~n Mess: ~p" + "~n", [Mess]), + Body = + case Mess of + #'Message'{version = _V, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = _Tid, + immAckRequired = asn1_NOVALUE, + transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = _Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + SCRes = + case SCR of + #'ServiceChangeReply'{terminationID = _TermID, + serviceChangeResult = ServChRes} -> + ServChRes; + _ -> + throw({error, {invalid_serviceChangeReply, SCR}}) + end, + SCRP = + case SCRes of + {serviceChangeResParms, Parms} -> + Parms; + _ -> + throw({error, {invalid_serviceChangeResult, SCRes}}) + end, + case SCRP of + #'ServiceChangeResParm'{serviceChangeMgcId = _MgcMid} -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeResParms, SCRP}} + end; +rarpanp_mg_verify_service_change_rep_msg(Crap) -> + {error, {invalid_message, Crap}}. + +-ifndef(megaco_hipe_special). +rarpanp_mg_verify_notify_rep_msg_fun(TransId, TermId) -> + fun(Msg) -> + (catch rarpanp_mg_verify_notify_rep_msg(Msg, TransId, TermId)) + end. +-endif. + +rarpanp_mg_verify_notify_rep_msg(#'MegacoMessage'{mess = Mess} = M, + TransId, TermId) -> + io:format("rarpanp_mg_verify_notify_rep_msg -> entry with" + "~n TransId: ~p" + "~n TermId: ~p" + "~n Mess: ~p" + "~n", [TransId, TermId, Mess]), + Body = + case Mess of + #'Message'{version = _V, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = TransId, + immAckRequired = asn1_NOVALUE, % No ack + transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = _Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + NR = + case CR of + {notifyReply, NotifyRep} -> + NotifyRep; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + + case NR of + #'NotifyReply'{terminationID = [TermId], + errorDescriptor = asn1_NOVALUE} -> + io:format("rarpanp_mg_verify_notify_rep_msg -> done when verifyed" + "~n", []), + {ok, M}; + #'NotifyReply'{terminationID = A, + errorDescriptor = B} -> + throw({error, {invalid_notifyReply, + {A, TermId}, + {B, asn1_NOVALUE}}}); + _ -> + throw({error, {invalid_notifyReply, NR}}) + end; +rarpanp_mg_verify_notify_rep_msg(_TransId, _TermId, Crap) -> + {error, {invalid_message, Crap}}. + +rarpanp_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +rarpanp_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = rarpanp_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +rarpanp_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +rarpanp_mg_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = rarpanp_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +request_and_reply_pending_ack_one_pending(suite) -> + []; +request_and_reply_pending_ack_one_pending(doc) -> + ["This test case tests that megaco correctly handles the return " + "value handle_pending_ack from handle_trans_request when ONE " + "pending message has been sent"]; +request_and_reply_pending_ack_one_pending(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, rar_paop), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator"), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + %% MgcEvSeq = rarpaop_mgc_event_sequence(text, tcp), + MgcEvSeq = rarpaop_mgc_event_sequence(binary, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_tcp_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + %% MgEvSeq = rarpaop_mg_event_sequence(text, tcp), + MgEvSeq = rarpaop_mg_event_sequence(binary, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_tcp_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(rarpaop_mgc_verify_handle_connect_fun(), + {?MODULE, rarpaop_mgc_verify_handle_connect, []}). +-define(rarpaop_mgc_verify_service_change_req_fun(Mid), + {?MODULE, rarpaop_mgc_verify_service_change_req, [Mid]}). +-define(rarpaop_mgc_verify_notify_req_fun(), + {?MODULE, rarpaop_mgc_verify_notify_request, []}). +-define(rarpaop_mgc_verify_reply_ack_fun(), + {?MODULE, rarpaop_mgc_verify_reply_ack, []}). +-define(rarpaop_mgc_verify_handle_disconnect_fun(), + {?MODULE, rarpaop_mgc_verify_handle_disconnect, []}). +-else. +-define(rarpaop_mgc_verify_handle_connect_fun(), + fun rarpaop_mgc_verify_handle_connect/1). +-define(rarpaop_mgc_verify_service_change_req_fun(Mid), + rarpaop_mgc_verify_service_change_req_fun(Mid)). +-define(rarpaop_mgc_verify_notify_req_fun(), + rarpaop_mgc_verify_notify_request_fun()). +-define(rarpaop_mgc_verify_reply_ack_fun(), + rarpaop_mgc_verify_reply_ack_fun()). +-define(rarpaop_mgc_verify_handle_disconnect_fun(), + fun rarpaop_mgc_verify_handle_disconnect/1). +-endif. + +rarpaop_mgc_event_sequence(text, tcp) -> + Port = 2944, + TranspMod = megaco_tcp, + EncMod = megaco_pretty_text_encoder, + EncConf = [], + rarpaop_mgc_event_sequence(Port, TranspMod, EncMod, EncConf); +rarpaop_mgc_event_sequence(binary, tcp) -> + Port = 2945, + TranspMod = megaco_tcp, + EncMod = megaco_ber_bin_encoder, + EncConf = [], + rarpaop_mgc_event_sequence(Port, TranspMod, EncMod, EncConf). + +rarpaop_mgc_event_sequence(Port, TranspMod, EncMod, EncConf) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, Port}, + {transport_module, TranspMod}, + {encoding_module, EncMod}, + {encoding_config, EncConf} + ], + ConnectVerify = ?rarpaop_mgc_verify_handle_connect_fun(), + ScrVerify = ?rarpaop_mgc_verify_service_change_req_fun(Mid), + NrVerify = ?rarpaop_mgc_verify_notify_req_fun(), + AckVerify = ?rarpaop_mgc_verify_reply_ack_fun(), + DiscoVerify = ?rarpaop_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun rarpaop_mgc_verify_handle_connect/1, +%% ScrVerify = rarpaop_mgc_verify_service_change_req_fun(Mid), +%% NrVerify = rarpaop_mgc_verify_notify_request_fun(), +%% AckVerify = rarpaop_mgc_verify_reply_ack_fun(), +%% DiscoVerify = fun rarpaop_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, sent_pending_limit, 100}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_conn_info, all}, + {megaco_callback, handle_trans_request, ScrVerify}, + {megaco_callback, handle_trans_request, NrVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, nocall, 10000}, + {megaco_callback, handle_disconnect, DiscoVerify}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + +%% Connect verification +rarpaop_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + {ok, CH, ok}; +rarpaop_mgc_verify_handle_connect(Else) -> + {error, Else, ok}. + +%% Service Change verification +-ifndef(megaco_hipe_special). +rarpaop_mgc_verify_service_change_req_fun(Mid) -> + fun(Req) -> + rarpaop_mgc_verify_service_change_req(Req, Mid) + end. +-endif. + +rarpaop_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + (catch rarpaop_do_verify_service_change_req(AR, Mid)); +rarpaop_mgc_verify_service_change_req(Crap, _Mid) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +rarpaop_do_verify_service_change_req(AR, Mid) -> + CR = + case AR of + #'ActionRequest'{commandRequests = [CmdReq]} -> + CmdReq; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Err4 = {invalid_termination_id, Tid}, + ED4 = cre_ErrDesc(Tid), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + case Parms of + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + AckData = [rarpaop_mgc_service_change_reply_ar(Mid, 1)], + Reply = {discard_ack, AckData}, + {ok, AR, Reply}; + _ -> + Err5 = {invalid_SCP, Parms}, + ED5 = cre_ErrDesc(Parms), + ErrReply5 = {discard_ack, ED5}, + {error, Err5, ErrReply5} + end. + + +%% Notify Request verification +-ifndef(megaco_hipe_special). +rarpaop_mgc_verify_notify_request_fun() -> + fun(Req) -> + rarpaop_mgc_verify_notify_request(Req) + end. +-endif. + +rarpaop_mgc_verify_notify_request({handle_trans_request, _, ?VERSION, [AR]}) -> + (catch rarpaop_mgc_do_verify_notify_request(AR)); +rarpaop_mgc_verify_notify_request(Crap) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +rarpaop_mgc_do_verify_notify_request(AR) -> + {Cid, CR} = + case AR of + #'ActionRequest'{contextId = CtxID, + commandRequests = [CmdReq]} -> + {CtxID, CmdReq}; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + {Tid, OED} = + case NR of + #'NotifyRequest'{terminationID = [TermID], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + {TermID, ObsEvsDesc}; + _ -> + Err4 = {invalid_NR, NR}, + ED4 = cre_ErrDesc(NR), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + Err5 = {invalid_OED, OED}, + ED5 = cre_ErrDesc(NR), + ErrReply5 = {discard_ack, ED5}, + throw({error, Err5, ErrReply5}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + AckData = notify_request_verified, + Replies = [rarpaop_mgc_notify_reply_ar(Cid, Tid)], + Reply = {{handle_pending_ack, AckData}, Replies}, + {ok, 5000, AR, Reply}; + _ -> + Err6 = {invalid_OE, OE}, + ED6 = cre_ErrDesc(OE), + ErrReply6 = {discard_ack, ED6}, + throw({error, Err6, ErrReply6}) + end. + + +%% Ack verification +-ifndef(megaco_hipe_special). +rarpaop_mgc_verify_reply_ack_fun() -> + fun(M) -> + rarpaop_mgc_verify_reply_ack(M) + end. +-endif. + +rarpaop_mgc_verify_reply_ack({handle_trans_ack, _, ?VERSION, ok, _}) -> + io:format("rarpaop_mgc_verify_reply_ack -> ok~n", []), + {ok, ok, ok}; +rarpaop_mgc_verify_reply_ack({handle_trans_ack, _, ?VERSION, AS, AD} = Crap) -> + io:format("rarpaop_mgc_verify_reply_ack -> incorrect ack-status:" + "~n AS: ~p" + "~n AD: ~p" + "~n", [AS, AD]), + ED = cre_ErrDesc({invalid_ack_status, {AS, AD}}), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}; +rarpaop_mgc_verify_reply_ack(Crap) -> + io:format("rarpaop_mgc_verify_reply_ack -> invalid ack:" + "~n Crap: ~p" + "~n", [Crap]), + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + + +%% Disconnect verification +rarpaop_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, _R}) -> + {ok, CH, ok}; +rarpaop_mgc_verify_handle_disconnect(Else) -> + {error, Else, ok}. + +rarpaop_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + AR. + +rarpaop_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(rarpaop_mg_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(rarpaop_mg_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(rarpaop_mg_verify_service_change_rep_msg_fun(), + {?MODULE, rarpaop_mg_verify_service_change_rep_msg, []}). +-define(rarpaop_mg_verify_pending_msg_fun(TransId), + {?MODULE, rarpaop_mg_verify_pending_msg, [TransId]}). +-define(rarpaop_mg_verify_notify_rep_msg_fun(TransId, TermId), + {?MODULE, rarpaop_mg_verify_notify_rep_msg, [TransId, TermId]}). +-else. +-define(rarpaop_mg_decode_msg_fun(Mod, Conf), + rarpaop_mg_decode_msg_fun(Mod, Conf)). +-define(rarpaop_mg_encode_msg_fun(Mod, Conf), + rarpaop_mg_encode_msg_fun(Mod, Conf)). +-define(rarpaop_mg_verify_service_change_rep_msg_fun(), + rarpaop_mg_verify_service_change_rep_msg_fun()). +-define(rarpaop_mg_verify_pending_msg_fun(TransId), + rarpaop_mg_verify_pending_msg_fun(TransId)). +-define(rarpaop_mg_verify_notify_rep_msg_fun(TransId, TermId), + rarpaop_mg_verify_notify_rep_msg_fun(TransId, TermId)). +-endif. + +rarpaop_mg_event_sequence(text, tcp) -> + Port = 2944, + EncMod = megaco_pretty_text_encoder, + EncConf = [], + rarpaop_mg_event_sequence(Port, EncMod, EncConf); +rarpaop_mg_event_sequence(binary, tcp) -> + Port = 2945, + EncMod = megaco_ber_bin_encoder, + EncConf = [], + rarpaop_mg_event_sequence(Port, EncMod, EncConf). + +rarpaop_mg_event_sequence(Port, EncMod, EncConf) -> + DecodeFun = ?rarpaop_mg_decode_msg_fun(EncMod, EncConf), + EncodeFun = ?rarpaop_mg_encode_msg_fun(EncMod, EncConf), + Mid = {deviceName, "mg"}, + TransId = 2, + TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + ServiceChangeReq = rarpaop_mg_service_change_request_msg(Mid, 1, 0), + NotifyReq = rarpaop_mg_notify_request_msg(Mid, TransId, 1, TermId, 1), + Ack = rarpaop_mg_ack_msg(Mid, TransId), + ScrVerifyFun = ?rarpaop_mg_verify_service_change_rep_msg_fun(), + PendVerifyFun = ?rarpaop_mg_verify_pending_msg_fun(TransId), + NrVerifyFun = ?rarpaop_mg_verify_notify_rep_msg_fun(TransId, TermId), +%% ScrVerifyFun = rarpaop_mg_verify_service_change_rep_msg_fun(), +%% PendVerifyFun = rarpaop_mg_verify_pending_msg_fun(TransId), +%% NrVerifyFun = rarpaop_mg_verify_notify_rep_msg_fun(TransId, TermId), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {connect, Port}, + {send, "service-change-request", ServiceChangeReq}, + {expect_receive, "service-change-reply", {ScrVerifyFun, 10000}}, + {send, "notify request", NotifyReq}, + {sleep, 2000}, + {send, "notify request", NotifyReq}, + {expect_receive, "pending", {PendVerifyFun, 5000}}, + {expect_receive, "notify-reply", {NrVerifyFun, 5000}}, + {send, "reply ack", Ack}, + {expect_nothing, 11000}, + disconnect + ], + EvSeq. + +-ifndef(megaco_hipe_special). +rarpaop_mg_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +rarpaop_mg_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +rarpaop_mg_verify_service_change_rep_msg_fun() -> + fun(Msg) -> + (catch rarpaop_mg_verify_service_change_rep_msg(Msg)) + end. +-endif. + +rarpaop_mg_verify_service_change_rep_msg(#'MegacoMessage'{mess = Mess} = M) -> + Body = + case Mess of + #'Message'{version = _V, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = _Tid, + immAckRequired = asn1_NOVALUE, + transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = _Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + SCRes = + case SCR of + #'ServiceChangeReply'{terminationID = _TermID, + serviceChangeResult = ServChRes} -> + ServChRes; + _ -> + throw({error, {invalid_serviceChangeReply, SCR}}) + end, + SCRP = + case SCRes of + {serviceChangeResParms, Parms} -> + Parms; + _ -> + throw({error, {invalid_serviceChangeResult, SCRes}}) + end, + case SCRP of + #'ServiceChangeResParm'{serviceChangeMgcId = _MgcMid} -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeResParms, SCRP}} + end; +rarpaop_mg_verify_service_change_rep_msg(Crap) -> + {error, {invalid_message, Crap}}. + +-ifndef(megaco_hipe_special). +rarpaop_mg_verify_pending_msg_fun(TransId) -> + fun(Msg) -> + (catch rarpaop_mg_verify_pending_msg(Msg, TransId)) + end. +-endif. + +rarpaop_mg_verify_pending_msg(#'MegacoMessage'{mess = Mess} = M, TransId) -> + Body = + case Mess of + #'Message'{version = _V, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TP = + case Trans of + {transactionPending, TransPending} -> + TransPending; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + case TP of + #'TransactionPending'{transactionId = TransId} -> + {ok, M}; + _ -> + throw({error, {invalid_transactionPending, TP}}) + end; +rarpaop_mg_verify_pending_msg(Crap, _TransId) -> + {error, {invalid_message, Crap}}. + +-ifndef(megaco_hipe_special). +rarpaop_mg_verify_notify_rep_msg_fun(TransId, TermId) -> + fun(Msg) -> + (catch rarpaop_mg_verify_notify_rep_msg(Msg, TransId, TermId)) + end. +-endif. + +rarpaop_mg_verify_notify_rep_msg(#'MegacoMessage'{mess = Mess} = M, + TransId, TermId) -> + Body = + case Mess of + #'Message'{version = _V, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = TransId, + immAckRequired = 'NULL', % Ack + transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = _Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + NR = + case CR of + {notifyReply, NotifyRep} -> + NotifyRep; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + + case NR of + #'NotifyReply'{terminationID = [TermId], + errorDescriptor = asn1_NOVALUE} -> + {ok, M}; + #'NotifyReply'{terminationID = A, + errorDescriptor = B} -> + throw({error, {invalid_notifyReply, + {A, TermId}, + {B, asn1_NOVALUE}}}); + _ -> + throw({error, {invalid_notifyReply, NR}}) + end; +rarpaop_mg_verify_notify_rep_msg(Crap, _TransId, _TermId) -> + {error, {invalid_message, Crap}}. + +rarpaop_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +rarpaop_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = rarpaop_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +rarpaop_mg_ack_msg(Mid, TransId) -> + TR = cre_transRespAck(cre_transAck(TransId)), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +rarpaop_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +rarpaop_mg_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = rarpaop_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +single_trans_req_and_reply(suite) -> + []; +single_trans_req_and_reply(doc) -> + ["Receive a (single) transaction request and then send a " + "reply (discard ack). " + "The MGC is a megaco instance (megaco event sequence) and the " + "MG is emulated (tcp event sequence)"]; +single_trans_req_and_reply(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, strar), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = strar_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = strar_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId], 30000), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(strar_mgc_verify_handle_connect_fun(), + {?MODULE, strar_mgc_verify_handle_connect, []}). +-define(strar_mgc_verify_service_change_req_fun(Mid), + {?MODULE, strar_mgc_verify_service_change_req, [Mid]}). +-define(strar_mgc_verify_notify_req_fun(), + {?MODULE, strar_mgc_verify_notify_request, []}). +-define(strar_mgc_verify_handle_disconnect_fun(), + {?MODULE, strar_mgc_verify_handle_disconnect, []}). +-else. +-define(strar_mgc_verify_handle_connect_fun(), + fun strar_mgc_verify_handle_connect/1). +-define(strar_mgc_verify_service_change_req_fun(Mid), + strar_mgc_verify_service_change_req_fun(Mid)). +-define(strar_mgc_verify_notify_req_fun(), + strar_mgc_verify_notify_request_fun()). +-define(strar_mgc_verify_handle_disconnect_fun(), + fun strar_mgc_verify_handle_disconnect/1). +-endif. + +strar_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + %% Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, +%% ReqTmr = #megaco_incr_timer{wait_for = 500, +%% factor = 1, +%% max_retries = 1}, + ConnectVerify = ?strar_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?strar_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?strar_mgc_verify_notify_req_fun(), + DiscoVerify = ?strar_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun strar_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = strar_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = strar_mgc_verify_notify_request_fun(), +%% DiscoVerify = fun strar_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +strar_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("strar_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +strar_mgc_verify_handle_connect(Else) -> + io:format("strar_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +-ifndef(megaco_hipe_special). +strar_mgc_verify_service_change_req_fun(Mid) -> + fun(Req) -> + strar_mgc_verify_service_change_req(Req, Mid) + end. +-endif. + +strar_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + (catch strar_mgc_do_verify_service_change_req(AR, Mid)); +strar_mgc_verify_service_change_req(Crap, _Mid) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +strar_mgc_do_verify_service_change_req(AR, Mid) -> + io:format("strar_mgc_verify_service_change_req -> entry with" + "~n AR: ~p" + "~n Mid: ~p" + "~n", [AR, Mid]), + CR = + case AR of + #'ActionRequest'{commandRequests = [CmdReq]} -> + CmdReq; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Err4 = {invalid_termination_id, Tid}, + ED4 = cre_ErrDesc(Tid), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + case Parms of + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + AckData = [strar_mgc_service_change_reply_ar(Mid, 1)], + Reply = {discard_ack, AckData}, + {ok, AR, Reply}; + _ -> + Err5 = {invalid_SCP, Parms}, + ED5 = cre_ErrDesc(Parms), + ErrReply5 = {discard_ack, ED5}, + {error, Err5, ErrReply5} + end. + +-ifndef(megaco_hipe_special). +strar_mgc_verify_notify_request_fun() -> + fun(Req) -> + strar_mgc_verify_notify_request(Req) + end. +-endif. + +strar_mgc_verify_notify_request({handle_trans_request, _, ?VERSION, [AR]}) -> + (catch strar_mgc_do_verify_notify_request(AR)); +strar_mgc_verify_notify_request(Crap) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +strar_mgc_do_verify_notify_request(AR) -> + io:format("strar_mgc_do_verify_notify_request -> ok" + "~n AR: ~p~n", [AR]), + {Cid, CR} = + case AR of + #'ActionRequest'{contextId = CtxID, + commandRequests = [CmdReq]} when (CtxID == 1) or + (CtxID == 2) -> + {CtxID, CmdReq}; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + {Tid, OED} = + case NR of + #'NotifyRequest'{terminationID = [TermID], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + {TermID, ObsEvsDesc}; + _ -> + Err4 = {invalid_NR, NR}, + ED4 = cre_ErrDesc(NR), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + Err5 = {invalid_OED, OED}, + ED5 = cre_ErrDesc(NR), + ErrReply5 = {discard_ack, ED5}, + throw({error, Err5, ErrReply5}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + Replies = [strar_mgc_notify_reply_ar(Cid, Tid)], + Reply = {discard_ack, Replies}, + {ok, AR, Reply}; + _ -> + Err6 = {invalid_OE, OE}, + ED6 = cre_ErrDesc(OE), + ErrReply6 = {discard_ack, ED6}, + {error, Err6, ErrReply6} + end. + +strar_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("strar_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +strar_mgc_verify_handle_disconnect(Else) -> + io:format("strar_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +strar_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +strar_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +%% strar_mgc_notify_reply(Mid, TransId, Cid, TermId) -> +%% AR = strar_mgc_notify_reply_ar(Cid, TermId), +%% TRes = cre_transResult([AR]), +%% TR = cre_transReply(TransId, TRes), +%% Trans = cre_transaction(TR), +%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), +%% cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(strar_mg_verify_handle_connect_fun(), + {?MODULE, strar_mg_verify_handle_connect, []}). +-define(strar_mg_verify_service_change_reply_fun(), + {?MODULE, strar_mg_verify_service_change_reply, []}). +-define(strar_mg_verify_notify_reply_fun(), + {?MODULE, strar_mg_verify_notify_reply, []}). +-else. +-define(strar_mg_verify_handle_connect_fun(), + strar_mg_verify_handle_connect_fun()). +-define(strar_mg_verify_service_change_reply_fun(), + strar_mg_verify_service_change_reply_fun()). +-define(strar_mg_verify_notify_reply_fun(), + strar_mg_verify_notify_reply_fun()). +-endif. + +strar_mg_event_sequence(text, tcp) -> + Mid = {deviceName, "mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [strar_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [strar_mg_notify_request_ar(Rid, Tid, Cid)] + end, + ConnectVerify = ?strar_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?strar_mg_verify_service_change_reply_fun(), + NotifyReplyVerify = ?strar_mg_verify_notify_reply_fun(), +%% ConnectVerify = strar_mg_verify_handle_connect_fun(), +%% ServiceChangeReplyVerify = strar_mg_verify_service_change_reply_fun(), +%% NotifyReplyVerify = fun strar_mg_verify_notify_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_conn_info, all}, + {megaco_cast, NR(1,1), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 3000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +-ifndef(megaco_hipe_special). +strar_mg_verify_handle_connect_fun() -> + fun(Ev) -> + strar_mg_verify_handle_connect(Ev) + end. +-endif. + +strar_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("strar_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +strar_mg_verify_handle_connect(Else) -> + io:format("strar_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +-ifndef(megaco_hipe_special). +strar_mg_verify_service_change_reply_fun() -> + fun(Rep) -> + strar_mg_verify_service_change_reply(Rep) + end. +-endif. + +strar_mg_verify_service_change_reply( + {handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> + (catch strar_mg_do_verify_service_change_reply(AR)); +strar_mg_verify_service_change_reply(Crap) -> + {error, Crap, ok}. + +strar_mg_do_verify_service_change_reply(AR) -> + io:format("strar_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +-ifndef(megaco_hipe_special). +strar_mg_verify_notify_reply_fun() -> + fun(Rep) -> + strar_mg_verify_notify_reply(Rep) + end. +-endif. + +strar_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("strar_mg_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +strar_mg_verify_notify_reply(Else) -> + io:format("strar_mg_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +strar_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +strar_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +single_trans_req_and_reply_sendopts(suite) -> + []; +single_trans_req_and_reply_sendopts(doc) -> + ["Receive a (single) transaction request and then send a " + "reply with handle_ack and a reply_timer in sendoptions. " + "The MGC is a megaco instance (megaco event sequence) and the " + "MG is emulated (tcp event sequence)"]; +single_trans_req_and_reply_sendopts(Config) when is_list(Config) -> + %% <CONDITIONAL-SKIP> + Skippable = [{unix, [darwin, linux]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, straro), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = straro_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = straro_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId], 30000), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(straro_mgc_verify_handle_connect_fun(), + {?MODULE, straro_mgc_verify_handle_connect, []}). +-define(straro_mgc_verify_service_change_req_fun(Mid), + {?MODULE, straro_mgc_verify_service_change_req, [Mid]}). +-define(straro_mgc_verify_notify_req_fun(), + {?MODULE, straro_mgc_verify_notify_request, []}). +-define(straro_mgc_verify_handle_trans_ack_fun(), + {?MODULE, straro_mgc_verify_handle_trans_ack, []}). +-else. +-define(straro_mgc_verify_handle_connect_fun(), + fun straro_mgc_verify_handle_connect/1). +-define(straro_mgc_verify_service_change_req_fun(Mid), + straro_mgc_verify_service_change_req_fun(Mid)). +-define(straro_mgc_verify_notify_req_fun(), + straro_mgc_verify_notify_request_fun()). +-define(straro_mgc_verify_handle_trans_ack_fun(), + straro_mgc_verify_handle_trans_ack_fun()). +-endif. + +straro_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?straro_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?straro_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?straro_mgc_verify_notify_req_fun(), + TransAckVerify = ?straro_mgc_verify_handle_trans_ack_fun(), +%% ConnectVerify = fun straro_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = straro_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = straro_mgc_verify_notify_request_fun(), +%% TransAckVerify = straro_mgc_verify_handle_trans_ack_fun(), + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, TransAckVerify}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +straro_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("straro_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +straro_mgc_verify_handle_connect(Else) -> + io:format("straro_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +-ifndef(megaco_hipe_special). +straro_mgc_verify_service_change_req_fun(Mid) -> + fun(Req) -> + straro_mgc_verify_service_change_req(Req, Mid) + end. +-endif. + +straro_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + (catch straro_mgc_do_verify_service_change_req(AR, Mid)); +straro_mgc_verify_service_change_req(Crap, _Mid) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +straro_mgc_do_verify_service_change_req(AR, Mid) -> + io:format("straro_mgc_do_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionRequest'{commandRequests = [CmdReq]} -> + CmdReq; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Err4 = {invalid_termination_id, Tid}, + ED4 = cre_ErrDesc(Tid), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + case Parms of + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + AckData = [straro_mgc_service_change_reply_ar(Mid, 1)], + Reply = {discard_ack, AckData}, + {ok, AR, Reply}; + _ -> + Err5 = {invalid_SCP, Parms}, + ED5 = cre_ErrDesc(Parms), + ErrReply5 = {discard_ack, ED5}, + {error, Err5, ErrReply5} + end. + +-ifndef(megaco_hipe_special). +straro_mgc_verify_notify_request_fun() -> + fun(Req) -> + straro_mgc_verify_notify_request(Req) + end. +-endif. + +straro_mgc_verify_notify_request({handle_trans_request, _, ?VERSION, [AR]}) -> + (catch straro_mgc_do_verify_notify_request(AR)); +straro_mgc_verify_notify_request(Crap) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +straro_mgc_do_verify_notify_request(AR) -> + io:format("straro_mgc_do_verify_notify_request -> ok" + "~n AR: ~p~n", [AR]), + {Cid, CR} = + case AR of + #'ActionRequest'{contextId = CtxID, + commandRequests = [CmdReq]} when (CtxID == 1) or + (CtxID == 2) -> + {CtxID, CmdReq}; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + {Tid, OED} = + case NR of + #'NotifyRequest'{terminationID = [TermID], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + {TermID, ObsEvsDesc}; + _ -> + Err4 = {invalid_NR, NR}, + ED4 = cre_ErrDesc(NR), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + Err5 = {invalid_OED, OED}, + ED5 = cre_ErrDesc(NR), + ErrReply5 = {discard_ack, ED5}, + throw({error, Err5, ErrReply5}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + Replies = [straro_mgc_notify_reply_ar(Cid, Tid)], + SendOpts = [{protocol_version, 99}], + Reply = {{handle_ack, get(tc)}, Replies, SendOpts}, + {ok, AR, Reply}; + _ -> + Err6 = {invalid_OE, OE}, + ED6 = cre_ErrDesc(OE), + ErrReply6 = {discard_ack, ED6}, + {error, Err6, ErrReply6} + end. + +-ifndef(megaco_hipe_special). +straro_mgc_verify_handle_trans_ack_fun() -> + fun(Ack) -> + straro_mgc_verify_handle_trans_ack(Ack) + end. +-endif. + +straro_mgc_verify_handle_trans_ack( + {handle_trans_ack, _CH, ?VERSION, AS, _AD}) -> + (catch straro_mgc_do_verify_handle_trans_ack(AS)); +straro_mgc_verify_handle_trans_ack(Crap) -> + io:format("straro_mgc_verify_handle_trans_ack -> entry with" + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + +straro_mgc_do_verify_handle_trans_ack({error, {EM, EF, [EC, Version, Msg], Reason}}) -> + io:format("straro_mgc_do_handle_verify_handle_trans_ack -> entry with" + "~n EM: ~p" + "~n EF: ~p" + "~n EC: ~p" + "~n Version: ~p" + "~n Msg: ~p" + "~n Reason: ~p" + "~n", [EM, EF, EC, Version, Msg, Reason]), + case Reason of + {bad_version, 99} -> + {ok, Reason, ok}; + _ -> + {error, {unexpected_reason, Reason}, ok} + end; +straro_mgc_do_verify_handle_trans_ack(Else) -> + io:format("straro_mgc_verify_handle_trans_ack -> unknown" + "~n Else: ~p" + "~n", [Else]), + {error, Else, ok}. + +%% straro_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> +%% io:format("straro_mgc_verify_handle_disconnect -> ok" +%% "~n CH: ~p" +%% "~n R: ~p" +%% "~n", [CH, R]), +%% {ok, CH, ok}; +%% straro_mgc_verify_handle_disconnect(Else) -> +%% io:format("straro_mgc_verify_handle_disconnect -> unknown" +%% "~n Else: ~p~n", [Else]), +%% {error, Else, ok}. + + +straro_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +straro_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +%% straro_mgc_notify_reply(Mid, TransId, Cid, TermId) -> +%% AR = straro_mgc_notify_reply_ar(Cid, TermId), +%% TRes = cre_transResult([AR]), +%% TR = cre_transReply(TransId, TRes), +%% Trans = cre_transaction(TR), +%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), +%% cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(straro_mg_verify_handle_connect_fun(), + {?MODULE, straro_mg_verify_handle_connect, []}). +-define(straro_mg_verify_service_change_reply_fun(), + {?MODULE, straro_mg_verify_service_change_reply, []}). +-define(straro_mg_verify_handle_disconnect_fun(), + {?MODULE, straro_mg_verify_handle_disconnect, []}). +-else. +-define(straro_mg_verify_handle_connect_fun(), + straro_mg_verify_handle_connect_fun()). +-define(straro_mg_verify_service_change_reply_fun(), + straro_mg_verify_service_change_reply_fun()). +-define(straro_mg_verify_handle_disconnect_fun(), + fun straro_mg_verify_handle_disconnect/1). +-endif. + +straro_mg_event_sequence(text, tcp) -> + Mid = {deviceName, "mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [straro_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [straro_mg_notify_request_ar(Rid, Tid, Cid)] + end, + ConnectVerify = ?straro_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?straro_mg_verify_service_change_reply_fun(), + DiscoVerify = ?straro_mg_verify_handle_disconnect_fun(), +%% ConnectVerify = straro_mg_verify_handle_connect_fun(), +%% DiscoVerify = fun straro_mg_verify_handle_disconnect/1, +%% ServiceChangeReplyVerify = straro_mg_verify_service_change_reply_fun(), + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_conn_info, all}, + {megaco_cast, NR(1,1), []}, + {megaco_callback, handle_disconnect, DiscoVerify}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +-ifndef(megaco_hipe_special). +straro_mg_verify_handle_connect_fun() -> + fun(Ev) -> + straro_mg_verify_handle_connect(Ev) + end. +-endif. + +straro_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("straro_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +straro_mg_verify_handle_connect(Else) -> + io:format("straro_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +straro_mg_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("straro_mg_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +straro_mg_verify_handle_disconnect(Else) -> + io:format("straro_mg_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +-ifndef(megaco_hipe_special). +straro_mg_verify_service_change_reply_fun() -> + fun(Rep) -> + straro_mg_verify_service_change_reply(Rep) + end. +-endif. + +straro_mg_verify_service_change_reply( + {handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> + (catch straro_mg_do_verify_service_change_reply(AR)); +straro_mg_verify_service_change_reply(Crap) -> + {error, Crap, ok}. + +straro_mg_do_verify_service_change_reply(AR) -> + io:format("straro_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +%% -ifndef(megaco_hipe_special). +%% straro_mg_verify_notify_reply_fun() -> +%% fun(Rep) -> +%% straro_mg_verify_notify_reply(Rep) +%% end. +%% -endif. + +%% straro_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, +%% {ok, [AR]}, _}) -> +%% io:format("straro_mg_verify_notify_reply -> ok" +%% "~n AR: ~p~n", [AR]), +%% {ok, AR, ok}; +%% straro_mg_verify_notify_reply(Else) -> +%% io:format("straro_mg_verify_notify_reply -> unknown" +%% "~n Else: ~p~n", [Else]), +%% {error, Else, ok}. + +straro_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +straro_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +request_and_reply_and_ack(suite) -> + []; +request_and_reply_and_ack(doc) -> + ["This test case tests that megaco correctly handles three-way-handshake"]; +request_and_reply_and_ack(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, raraa), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = raraa_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_tcp_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = raraa_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_tcp_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_tcp_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% + +-ifdef(megaco_hipe_special). +-define(raraa_mgc_verify_handle_connect_fun(), + {?MODULE, raraa_mgc_verify_handle_connect, []}). +-define(raraa_mgc_verify_service_change_req_fun(Mid), + {?MODULE, raraa_mgc_verify_service_change_req, [Mid]}). +-define(raraa_mgc_verify_notify_req_fun(), + {?MODULE, raraa_mgc_verify_notify_req, []}). +-define(raraa_mgc_verify_handle_trans_ack_fun(), + {?MODULE, raraa_mgc_verify_handle_trans_ack, []}). +-define(raraa_mgc_verify_handle_disconnect_fun(), + {?MODULE, raraa_mgc_verify_handle_disconnect, []}). +-else. +-define(raraa_mgc_verify_handle_connect_fun(), + fun raraa_mgc_verify_handle_connect/1). +-define(raraa_mgc_verify_service_change_req_fun(Mid), + raraa_mgc_verify_service_change_req_fun(Mid)). +-define(raraa_mgc_verify_notify_req_fun(), + raraa_mgc_verify_notify_req_fun()). +-define(raraa_mgc_verify_handle_trans_ack_fun(), + raraa_mgc_verify_handle_trans_ack_fun()). +-define(raraa_mgc_verify_handle_disconnect_fun(), + fun raraa_mgc_verify_handle_disconnect/1). +-endif. + +raraa_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?raraa_mgc_verify_handle_connect_fun(), + ScrVerify = ?raraa_mgc_verify_service_change_req_fun(Mid), + NrVerify = ?raraa_mgc_verify_notify_req_fun(), + AckVerify = ?raraa_mgc_verify_handle_trans_ack_fun(), + DiscoVerify = ?raraa_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun raraa_mgc_verify_handle_connect/1, +%% ScrVerify = raraa_mgc_verify_service_change_req_fun(Mid), +%% NrVerify = raraa_mgc_verify_notify_request_fun(), +%% AckVerify = raraa_mgc_verify_trans_ack_fun(), +%% DiscoVerify = fun raraa_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, sent_pending_limit, 100}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_conn_info, all}, + {megaco_callback, handle_trans_request, ScrVerify}, + {megaco_callback, handle_trans_request, NrVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + +%% Connect verification +raraa_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + {ok, CH, ok}; +raraa_mgc_verify_handle_connect(Else) -> + {error, Else, ok}. + +%% Service Change verification +-ifndef(megaco_hipe_special). +raraa_mgc_verify_service_change_req_fun(Mid) -> + fun(Req) -> + raraa_mgc_verify_service_change_req(Req, Mid) + end. +-endif. + +raraa_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + (catch raraa_do_verify_service_change_req(AR, Mid)); +raraa_mgc_verify_service_change_req(Crap, _Mid) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +raraa_do_verify_service_change_req(AR, Mid) -> + io:format("raraa_mgc_verify_service_change_req -> entry with" + "~n AR: ~p" + "~n Mid: ~p" + "~n", [AR, Mid]), + CR = + case AR of + #'ActionRequest'{commandRequests = [CmdReq]} -> + CmdReq; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Err4 = {invalid_termination_id, Tid}, + ED4 = cre_ErrDesc(Tid), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + case Parms of + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + AckData = [raraa_mgc_service_change_reply_ar(Mid, 1)], + Reply = {discard_ack, AckData}, + {ok, AR, Reply}; + _ -> + Err5 = {invalid_SCP, Parms}, + ED5 = cre_ErrDesc(Parms), + ErrReply5 = {discard_ack, ED5}, + {error, Err5, ErrReply5} + end. + + +%% Notify Request verification +-ifndef(megaco_hipe_special). +raraa_mgc_verify_notify_req_fun() -> + fun(Req) -> + raraa_mgc_verify_notify_req(Req) + end. +-endif. + +raraa_mgc_verify_notify_req({handle_trans_request, _, ?VERSION, [AR]}) -> + (catch raraa_mgc_do_verify_notify_req(AR)); +raraa_mgc_verify_notify_req(Crap) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +raraa_mgc_do_verify_notify_req(AR) -> + io:format("raraa_mgc_verify_notify_req -> entry with" + "~n AR: ~p" + "~n", [AR]), + {Cid, CR} = + case AR of + #'ActionRequest'{contextId = CtxID, + commandRequests = [CmdReq]} -> + {CtxID, CmdReq}; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + {Tid, OED} = + case NR of + #'NotifyRequest'{terminationID = [TermID], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + {TermID, ObsEvsDesc}; + _ -> + Err4 = {invalid_NR, NR}, + ED4 = cre_ErrDesc(NR), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + Err5 = {invalid_OED, OED}, + ED5 = cre_ErrDesc(NR), + ErrReply5 = {discard_ack, ED5}, + throw({error, Err5, ErrReply5}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + AckData = raraa, + Replies = [raraa_mgc_notify_reply_ar(Cid, Tid)], + Reply = {{handle_ack, AckData}, Replies}, + {ok, AR, Reply}; + _ -> + Err6 = {invalid_OE, OE}, + ED6 = cre_ErrDesc(OE), + ErrReply6 = {discard_ack, ED6}, + throw({error, Err6, ErrReply6}) + end. + + +-ifndef(megaco_hipe_special). +raraa_mgc_verify_handle_trans_ack_fun() -> + fun(Ack) -> + raraa_mgc_verify_handle_trans_ack(Ack) + end. +-endif. + +raraa_mgc_verify_handle_trans_ack( + {handle_trans_ack, CH, ?VERSION, ok, raraa}) -> + io:format("raraa_mgc_verify_handle_trans_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +raraa_mgc_verify_handle_trans_ack(Crap) -> + io:format("raraa_mgc_verify_handle_trans_ack -> unknown" + "~n Crap: ~p~n", [Crap]), + {error, Crap, ok}. + + +%% Disconnect verification +raraa_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, _R}) -> + {ok, CH, ok}; +raraa_mgc_verify_handle_disconnect(Else) -> + {error, Else, ok}. + +raraa_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + AR. + +raraa_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(raraa_mg_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(raraa_mg_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(raraa_mg_verify_service_change_rep_msg_fun(), + {?MODULE, raraa_mg_verify_service_change_rep_msg, []}). +-define(raraa_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), + {?MODULE, raraa_mg_verify_notify_rep_msg, [TermId, TransId, ReqId, CtxId]}). +-else. +-define(raraa_mg_decode_msg_fun(Mod, Conf), + raraa_mg_decode_msg_fun(Mod, Conf)). +-define(raraa_mg_encode_msg_fun(Mod, Conf), + raraa_mg_encode_msg_fun(Mod, Conf)). +-define(raraa_mg_verify_service_change_rep_msg_fun(), + raraa_mg_verify_service_change_rep_msg_fun()). +-define(raraa_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), + raraa_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId)). +-endif. + +raraa_mg_event_sequence(text, tcp) -> + DecodeFun = ?raraa_mg_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ?raraa_mg_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mg"}, + ServiceChangeReq = raraa_mg_service_change_request_msg(Mid, 1, 0), + TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + TransId = 2, + ReqId = 1, + CtxId = 1, + NotifyReq = raraa_mg_notify_request_msg(Mid, TermId, + TransId, ReqId, CtxId), + TransAck = raraa_mg_trans_ack_msg(Mid, TransId), + ScrVerifyFun = ?raraa_mg_verify_service_change_rep_msg_fun(), + NrVerifyFun = ?raraa_mg_verify_notify_rep_msg_fun(TermId, + TransId, ReqId, CtxId), +%% ScrVerifyFun = raraa_mg_verify_service_change_rep_msg_fun(), +%% NrVerifyFun = raraa_mg_verify_notify_rep_msg_fun(TermId, +%% TransId, ReqId, CtxId), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {connect, 2944}, + {send, "service-change-request", ServiceChangeReq}, + {expect_receive, "service-change-reply", {ScrVerifyFun, 10000}}, + {send, "notify request", NotifyReq}, + {expect_receive, "notify-reply", {NrVerifyFun, 10000}}, + {send, "transaction-ack", TransAck}, + {expect_nothing, 11000}, + disconnect + ], + EvSeq. + +-ifndef(megaco_hipe_special). +raraa_mg_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +raraa_mg_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +raraa_mg_verify_service_change_rep_msg_fun() -> + fun(Msg) -> + (catch raraa_mg_verify_service_change_rep_msg(Msg)) + end. +-endif. + +raraa_mg_verify_service_change_rep_msg(#'MegacoMessage'{mess = Mess} = M) -> + Body = + case Mess of + #'Message'{version = _V, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = _Tid, + immAckRequired = asn1_NOVALUE, + transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = _Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + SCRes = + case SCR of + #'ServiceChangeReply'{terminationID = _TermID, + serviceChangeResult = ServChRes} -> + ServChRes; + _ -> + throw({error, {invalid_serviceChangeReply, SCR}}) + end, + SCRP = + case SCRes of + {serviceChangeResParms, Parms} -> + Parms; + _ -> + throw({error, {invalid_serviceChangeResult, SCRes}}) + end, + case SCRP of + #'ServiceChangeResParm'{serviceChangeMgcId = _MgcMid} -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeResParms, SCRP}} + end; +raraa_mg_verify_service_change_rep_msg(Crap) -> + {error, {invalid_message, Crap}}. + +-ifndef(megaco_hipe_special). +raraa_mg_verify_notify_rep_msg_fun(TermId, TransId, Rid, Cid) -> + fun(Msg) -> + (catch raraa_mg_verify_notify_rep_msg(Msg, + TermId, TransId, Rid, Cid)) + end. +-endif. + +raraa_mg_verify_notify_rep_msg(#'MegacoMessage'{mess = Mess} = M, + TermId, TransId, Rid, Cid) -> + io:format("raraa_mg_verify_notify_rep_msg -> entry with" + "~n M: ~p" + "~n TermId: ~p" + "~n TransId: ~p" + "~n Rid: ~p" + "~n Cid: ~p" + "~n", [M, TermId, TransId, Rid, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = TransId, + immAckRequired = 'NULL', + transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + case NR of + #'NotifyReply'{terminationID = [TermId], + errorDescriptor = asn1_NOVALUE} -> + {ok, M}; + _ -> + {error, {invalid_notifyReply, NR}} + end; +raraa_mg_verify_notify_rep_msg(Crap, _TermId, _TransId, _Rid, _Cid) -> + {error, {invalid_message, Crap}}. + +raraa_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +raraa_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = raraa_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +raraa_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +raraa_mg_notify_request_msg(Mid, TermId, TransId, Rid, Cid) -> + AR = raraa_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +raraa_mg_trans_ack_msg(Mid, TransId) -> + TR = cre_transRespAck(cre_transAck(TransId)), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +request_and_reply_and_no_ack(suite) -> + []; +request_and_reply_and_no_ack(doc) -> + ["This test case tests that megaco handles a failed three-way-handshake," + " i.e. when the ack never arrives"]; +request_and_reply_and_no_ack(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, rarana), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = rarana_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_tcp_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = rarana_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_tcp_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_tcp_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% + +-ifdef(megaco_hipe_special). +-define(rarana_mgc_verify_handle_connect_fun(), + {?MODULE, rarana_mgc_verify_handle_connect, []}). +-define(rarana_mgc_verify_service_change_req_fun(Mid), + {?MODULE, rarana_mgc_verify_service_change_req, [Mid]}). +-define(rarana_mgc_verify_notify_req_fun(), + {?MODULE, rarana_mgc_verify_notify_req, []}). +-define(rarana_mgc_verify_handle_trans_ack_fun(), + {?MODULE, rarana_mgc_verify_handle_trans_ack, []}). +-define(rarana_mgc_verify_handle_disconnect_fun(), + {?MODULE, rarana_mgc_verify_handle_disconnect, []}). +-else. +-define(rarana_mgc_verify_handle_connect_fun(), + fun rarana_mgc_verify_handle_connect/1). +-define(rarana_mgc_verify_service_change_req_fun(Mid), + rarana_mgc_verify_service_change_req_fun(Mid)). +-define(rarana_mgc_verify_notify_req_fun(), + rarana_mgc_verify_notify_req_fun()). +-define(rarana_mgc_verify_handle_trans_ack_fun(), + rarana_mgc_verify_handle_trans_ack_fun()). +-define(rarana_mgc_verify_handle_disconnect_fun(), + fun rarana_mgc_verify_handle_disconnect/1). +-endif. + +rarana_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?rarana_mgc_verify_handle_connect_fun(), + ScrVerify = ?rarana_mgc_verify_service_change_req_fun(Mid), + NrVerify = ?rarana_mgc_verify_notify_req_fun(), + AckVerify = ?rarana_mgc_verify_handle_trans_ack_fun(), + DiscoVerify = ?rarana_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun rarana_mgc_verify_handle_connect/1, +%% ScrVerify = rarana_mgc_verify_service_change_req_fun(Mid), +%% NrVerify = rarana_mgc_verify_notify_request_fun(), +%% AckVerify = rarana_mgc_verify_trans_ack_fun(), +%% DiscoVerify = fun rarana_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, sent_pending_limit, 100}, + {megaco_update_user_info, reply_timer, 9000}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_conn_info, all}, + {megaco_callback, handle_trans_request, ScrVerify}, + {megaco_callback, handle_trans_request, NrVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + %% {megaco_callback, nocall, 8000}, + {megaco_callback, handle_disconnect, DiscoVerify}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + +%% Connect verification +rarana_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + {ok, CH, ok}; +rarana_mgc_verify_handle_connect(Else) -> + {error, Else, ok}. + +%% Service Change verification +-ifndef(megaco_hipe_special). +rarana_mgc_verify_service_change_req_fun(Mid) -> + fun(Req) -> + rarana_mgc_verify_service_change_req(Req, Mid) + end. +-endif. + +rarana_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + (catch rarana_do_verify_service_change_req(AR, Mid)); +rarana_mgc_verify_service_change_req(Crap, _Mid) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +rarana_do_verify_service_change_req(AR, Mid) -> + CR = + case AR of + #'ActionRequest'{commandRequests = [CmdReq]} -> + CmdReq; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Err4 = {invalid_termination_id, Tid}, + ED4 = cre_ErrDesc(Tid), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + case Parms of + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + AckData = [rarana_mgc_service_change_reply_ar(Mid, 1)], + Reply = {discard_ack, AckData}, + {ok, AR, Reply}; + _ -> + Err5 = {invalid_SCP, Parms}, + ED5 = cre_ErrDesc(Parms), + ErrReply5 = {discard_ack, ED5}, + {error, Err5, ErrReply5} + end. + + +%% Notify Request verification +-ifndef(megaco_hipe_special). +rarana_mgc_verify_notify_req_fun() -> + fun(Req) -> + rarana_mgc_verify_notify_req(Req) + end. +-endif. + +rarana_mgc_verify_notify_req({handle_trans_request, _, ?VERSION, [AR]}) -> + (catch rarana_mgc_do_verify_notify_req(AR)); +rarana_mgc_verify_notify_req(Crap) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +rarana_mgc_do_verify_notify_req(AR) -> + {Cid, CR} = + case AR of + #'ActionRequest'{contextId = CtxID, + commandRequests = [CmdReq]} -> + {CtxID, CmdReq}; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + {Tid, OED} = + case NR of + #'NotifyRequest'{terminationID = [TermID], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + {TermID, ObsEvsDesc}; + _ -> + Err4 = {invalid_NR, NR}, + ED4 = cre_ErrDesc(NR), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + Err5 = {invalid_OED, OED}, + ED5 = cre_ErrDesc(NR), + ErrReply5 = {discard_ack, ED5}, + throw({error, Err5, ErrReply5}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + AckData = rarana, + Replies = [rarana_mgc_notify_reply_ar(Cid, Tid)], + Reply = {{handle_ack, AckData}, Replies}, + {ok, AR, Reply}; + _ -> + Err6 = {invalid_OE, OE}, + ED6 = cre_ErrDesc(OE), + ErrReply6 = {discard_ack, ED6}, + throw({error, Err6, ErrReply6}) + end. + + +-ifndef(megaco_hipe_special). +rarana_mgc_verify_handle_trans_ack_fun() -> + fun(Ack) -> + rarana_mgc_verify_handle_trans_ack(Ack) + end. +-endif. + +rarana_mgc_verify_handle_trans_ack({handle_trans_ack, CH, ?VERSION, + {error, timeout}, rarana}) -> + io:format("rarana_mgc_verify_handle_trans_ack -> expected error: ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +rarana_mgc_verify_handle_trans_ack(Crap) -> + io:format("rarana_mgc_verify_trans_ack -> unknown" + "~n Crap: ~p~n", [Crap]), + {error, Crap, ok}. + + +%% Disconnect verification +rarana_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, _R}) -> + {ok, CH, ok}; +rarana_mgc_verify_handle_disconnect(Else) -> + {error, Else, ok}. + +rarana_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + AR. + +rarana_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(rarana_mg_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(rarana_mg_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(rarana_mg_verify_service_change_rep_msg_fun(), + {?MODULE, rarana_mg_verify_service_change_rep_msg, []}). +-define(rarana_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), + {?MODULE, rarana_mg_verify_notify_rep_msg, [TermId, TransId, ReqId, CtxId]}). +-else. +-define(rarana_mg_decode_msg_fun(Mod, Conf), + rarana_mg_decode_msg_fun(Mod, Conf)). +-define(rarana_mg_encode_msg_fun(Mod, Conf), + rarana_mg_encode_msg_fun(Mod, Conf)). +-define(rarana_mg_verify_service_change_rep_msg_fun(), + rarana_mg_verify_service_change_rep_msg_fun()). +-define(rarana_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), + rarana_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId)). +-endif. + +rarana_mg_event_sequence(text, tcp) -> + DecodeFun = ?rarana_mg_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ?rarana_mg_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mg"}, + ServiceChangeReq = rarana_mg_service_change_request_msg(Mid, 1, 0), + TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + TransId = 2, + ReqId = 1, + CtxId = 1, + NotifyReq = rarana_mg_notify_request_msg(Mid, TermId, + TransId, ReqId, CtxId), + ScrVerifyFun = ?rarana_mg_verify_service_change_rep_msg_fun(), + NrVerifyFun = ?rarana_mg_verify_notify_rep_msg_fun(TermId, + TransId, ReqId, CtxId), +%% ScrVerifyFun = rarana_mg_verify_service_change_rep_msg_fun(), +%% NrVerifyFun = rarana_mg_verify_notify_rep_msg_fun(TermId, +%% TransId, ReqId, CtxId), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {connect, 2944}, + {send, "service-change-request", ServiceChangeReq}, + {expect_receive, "service-change-reply", {ScrVerifyFun, 10000}}, + {send, "notify request", NotifyReq}, + {expect_receive, "notify-reply", {NrVerifyFun, 10000}}, + {expect_nothing, 11000}, + disconnect + ], + EvSeq. + +-ifndef(megaco_hipe_special). +rarana_mg_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +rarana_mg_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +rarana_mg_verify_service_change_rep_msg_fun() -> + fun(Msg) -> + (catch rarana_mg_verify_service_change_rep_msg(Msg)) + end. +-endif. + +rarana_mg_verify_service_change_rep_msg(#'MegacoMessage'{mess = Mess} = M) -> + Body = + case Mess of + #'Message'{version = _V, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = _Tid, + immAckRequired = asn1_NOVALUE, + transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = _Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + SCRes = + case SCR of + #'ServiceChangeReply'{terminationID = _TermID, + serviceChangeResult = ServChRes} -> + ServChRes; + _ -> + throw({error, {invalid_serviceChangeReply, SCR}}) + end, + SCRP = + case SCRes of + {serviceChangeResParms, Parms} -> + Parms; + _ -> + throw({error, {invalid_serviceChangeResult, SCRes}}) + end, + case SCRP of + #'ServiceChangeResParm'{serviceChangeMgcId = _MgcMid} -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeResParms, SCRP}} + end; +rarana_mg_verify_service_change_rep_msg(Crap) -> + {error, {invalid_message, Crap}}. + +-ifndef(megaco_hipe_special). +rarana_mg_verify_notify_rep_msg_fun(TermId, TransId, Rid, Cid) -> + fun(Msg) -> + (catch rarana_mg_verify_notify_rep_msg(Msg, + TermId, TransId, Rid, Cid)) + end. +-endif. + +rarana_mg_verify_notify_rep_msg(#'MegacoMessage'{mess = Mess} = M, + TermId, TransId, Rid, Cid) -> + io:format("rarana_mg_verify_notify_rep_msg -> entry with" + "~n M: ~p" + "~n TermId: ~p" + "~n TransId: ~p" + "~n Rid: ~p" + "~n Cid: ~p" + "~n", [M, TermId, TransId, Rid, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = TransId, + immAckRequired = 'NULL', + transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + case NR of + #'NotifyReply'{terminationID = [TermId], + errorDescriptor = asn1_NOVALUE} -> + {ok, M}; + _ -> + {error, {invalid_notifyReply, NR}} + end; +rarana_mg_verify_notify_rep_msg(Crap, _TermId, _TransId, _Rid, _Cid) -> + {error, {invalid_message, Crap}}. + +rarana_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +rarana_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = rarana_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +rarana_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +rarana_mg_notify_request_msg(Mid, TermId, TransId, Rid, Cid) -> + AR = rarana_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +request_and_reply_and_late_ack(suite) -> + []; +request_and_reply_and_late_ack(doc) -> + ["This test case tests that megaco handles three-way-handshake " + "when the ack is late (and requeire a retransmission)"]; +request_and_reply_and_late_ack(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, rarala), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = rarala_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_tcp_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = rarala_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_tcp_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_tcp_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% + +-ifdef(megaco_hipe_special). +-define(rarala_mgc_verify_handle_connect_fun(), + {?MODULE, rarala_mgc_verify_handle_connect, []}). +-define(rarala_mgc_verify_service_change_req_fun(Mid), + {?MODULE, rarala_mgc_verify_service_change_req, [Mid]}). +-define(rarala_mgc_verify_notify_req_fun(), + {?MODULE, rarala_mgc_verify_notify_req, []}). +-define(rarala_mgc_verify_handle_trans_ack_fun(), + {?MODULE, rarala_mgc_verify_handle_trans_ack, []}). +-define(rarala_mgc_verify_handle_disconnect_fun(), + {?MODULE, rarala_mgc_verify_handle_disconnect, []}). +-else. +-define(rarala_mgc_verify_handle_connect_fun(), + fun rarala_mgc_verify_handle_connect/1). +-define(rarala_mgc_verify_service_change_req_fun(Mid), + rarala_mgc_verify_service_change_req_fun(Mid)). +-define(rarala_mgc_verify_notify_req_fun(), + rarala_mgc_verify_notify_req_fun()). +-define(rarala_mgc_verify_handle_trans_ack_fun(), + rarala_mgc_verify_handle_trans_ack_fun()). +-define(rarala_mgc_verify_handle_disconnect_fun(), + fun rarala_mgc_verify_handle_disconnect/1). +-endif. + +rarala_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + RepTmr = #megaco_incr_timer{wait_for = 3000, + factor = 1, + incr = 0, + max_retries = 2 + }, + ConnectVerify = ?rarala_mgc_verify_handle_connect_fun(), + ScrVerify = ?rarala_mgc_verify_service_change_req_fun(Mid), + NrVerify = ?rarala_mgc_verify_notify_req_fun(), + AckVerify = ?rarala_mgc_verify_handle_trans_ack_fun(), + DiscoVerify = ?rarala_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun rarala_mgc_verify_handle_connect/1, +%% ScrVerify = rarala_mgc_verify_service_change_req_fun(Mid), +%% NrVerify = rarala_mgc_verify_notify_request_fun(), +%% AckVerify = rarala_mgc_verify_trans_ack_fun(), +%% DiscoVerify = fun rarala_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, sent_pending_limit, 100}, + {megaco_update_user_info, reply_timer, RepTmr}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_conn_info, all}, + {megaco_callback, handle_trans_request, ScrVerify}, + {megaco_callback, handle_trans_request, NrVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + +%% Connect verification +rarala_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + {ok, CH, ok}; +rarala_mgc_verify_handle_connect(Else) -> + {error, Else, ok}. + +%% Service Change verification +-ifndef(megaco_hipe_special). +rarala_mgc_verify_service_change_req_fun(Mid) -> + fun(Req) -> + rarala_mgc_verify_service_change_req(Req, Mid) + end. +-endif. + +rarala_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + (catch rarala_do_verify_service_change_req(AR, Mid)); +rarala_mgc_verify_service_change_req(Crap, _Mid) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +rarala_do_verify_service_change_req(AR, Mid) -> + io:format("rarala_mgc_do_verify_service_change_req -> entry with" + "~n AR: ~p" + "~n Mid: ~p" + "~n", [AR, Mid]), + CR = + case AR of + #'ActionRequest'{commandRequests = [CmdReq]} -> + CmdReq; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Err4 = {invalid_termination_id, Tid}, + ED4 = cre_ErrDesc(Tid), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + case Parms of + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + AckData = [rarala_mgc_service_change_reply_ar(Mid, 1)], + Reply = {discard_ack, AckData}, + {ok, AR, Reply}; + _ -> + Err5 = {invalid_SCP, Parms}, + ED5 = cre_ErrDesc(Parms), + ErrReply5 = {discard_ack, ED5}, + {error, Err5, ErrReply5} + end. + + +%% Notify Request verification +-ifndef(megaco_hipe_special). +rarala_mgc_verify_notify_req_fun() -> + fun(Req) -> + rarala_mgc_verify_notify_req(Req) + end. +-endif. + +rarala_mgc_verify_notify_req({handle_trans_request, _, ?VERSION, [AR]}) -> + (catch rarala_mgc_do_verify_notify_req(AR)); +rarala_mgc_verify_notify_req(Crap) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +rarala_mgc_do_verify_notify_req(AR) -> + io:format("rarala_mgc_do_verify_notify_req -> entry with" + "~n AR: ~p" + "~n", [AR]), + {Cid, CR} = + case AR of + #'ActionRequest'{contextId = CtxID, + commandRequests = [CmdReq]} -> + {CtxID, CmdReq}; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + {Tid, OED} = + case NR of + #'NotifyRequest'{terminationID = [TermID], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + {TermID, ObsEvsDesc}; + _ -> + Err4 = {invalid_NR, NR}, + ED4 = cre_ErrDesc(NR), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + Err5 = {invalid_OED, OED}, + ED5 = cre_ErrDesc(NR), + ErrReply5 = {discard_ack, ED5}, + throw({error, Err5, ErrReply5}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + AckData = rarala, + Replies = [rarala_mgc_notify_reply_ar(Cid, Tid)], + Reply = {{handle_ack, AckData}, Replies}, + {ok, AR, Reply}; + _ -> + Err6 = {invalid_OE, OE}, + ED6 = cre_ErrDesc(OE), + ErrReply6 = {discard_ack, ED6}, + throw({error, Err6, ErrReply6}) + end. + + +-ifndef(megaco_hipe_special). +rarala_mgc_verify_handle_trans_ack_fun() -> + fun(Ack) -> + rarala_mgc_verify_handle_trans_ack(Ack) + end. +-endif. + +rarala_mgc_verify_handle_trans_ack( + {handle_trans_ack, CH, ?VERSION, ok, rarala}) -> + io:format("rarala_mgc_verify_handle_trans_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +rarala_mgc_verify_handle_trans_ack(Crap) -> + io:format("rarala_mgc_verify_handle_trans_ack -> unknown" + "~n Crap: ~p~n", [Crap]), + {error, Crap, ok}. + + +%% Disconnect verification +rarala_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, _R}) -> + {ok, CH, ok}; +rarala_mgc_verify_handle_disconnect(Else) -> + {error, Else, ok}. + +rarala_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + AR. + +rarala_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(rarala_mg_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(rarala_mg_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(rarala_mg_verify_service_change_rep_msg_fun(), + {?MODULE, rarala_mg_verify_service_change_rep_msg, []}). +-define(rarala_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), + {?MODULE, rarala_mg_verify_notify_rep_msg, [TermId, TransId, ReqId, CtxId]}). +-else. +-define(rarala_mg_decode_msg_fun(Mod, Conf), + rarala_mg_decode_msg_fun(Mod, Conf)). +-define(rarala_mg_encode_msg_fun(Mod, Conf), + rarala_mg_encode_msg_fun(Mod, Conf)). +-define(rarala_mg_verify_service_change_rep_msg_fun(), + rarala_mg_verify_service_change_rep_msg_fun()). +-define(rarala_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), + rarala_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId)). +-endif. + +rarala_mg_event_sequence(text, tcp) -> + DecodeFun = ?rarala_mg_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ?rarala_mg_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mg"}, + ServiceChangeReq = rarala_mg_service_change_request_msg(Mid, 1, 0), + TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + TransId = 2, + ReqId = 1, + CtxId = 1, + NotifyReq = rarala_mg_notify_request_msg(Mid, TermId, + TransId, ReqId, CtxId), + TransAck = rarala_mg_trans_ack_msg(Mid, TransId), + ScrVerifyFun = ?rarala_mg_verify_service_change_rep_msg_fun(), + NrVerifyFun = ?rarala_mg_verify_notify_rep_msg_fun(TermId, + TransId, ReqId, CtxId), +%% ScrVerifyFun = rarala_mg_verify_service_change_rep_msg_fun(), +%% NrVerifyFun = rarala_mg_verify_notify_rep_msg_fun(TermId, +%% TransId, ReqId, CtxId), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {connect, 2944}, + {send, "service-change-request", ServiceChangeReq}, + {expect_receive, "service-change-reply", {ScrVerifyFun, 10000}}, + {send, "notify request", NotifyReq}, + {expect_receive, "notify-reply", {NrVerifyFun, 4000}}, + {expect_receive, "notify-reply", {NrVerifyFun, 4000}}, + {expect_receive, "notify-reply", {NrVerifyFun, 4000}}, + {send, "transaction-ack", TransAck}, + {expect_nothing, 11000}, + disconnect + ], + EvSeq. + +-ifndef(megaco_hipe_special). +rarala_mg_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +rarala_mg_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +rarala_mg_verify_service_change_rep_msg_fun() -> + fun(Msg) -> + (catch rarala_mg_verify_service_change_rep_msg(Msg)) + end. +-endif. + +rarala_mg_verify_service_change_rep_msg(#'MegacoMessage'{mess = Mess} = M) -> + Body = + case Mess of + #'Message'{version = _V, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = _Tid, + immAckRequired = asn1_NOVALUE, + transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = _Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + SCRes = + case SCR of + #'ServiceChangeReply'{terminationID = _TermID, + serviceChangeResult = ServChRes} -> + ServChRes; + _ -> + throw({error, {invalid_serviceChangeReply, SCR}}) + end, + SCRP = + case SCRes of + {serviceChangeResParms, Parms} -> + Parms; + _ -> + throw({error, {invalid_serviceChangeResult, SCRes}}) + end, + case SCRP of + #'ServiceChangeResParm'{serviceChangeMgcId = _MgcMid} -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeResParms, SCRP}} + end; +rarala_mg_verify_service_change_rep_msg(Crap) -> + {error, {invalid_message, Crap}}. + +-ifndef(megaco_hipe_special). +rarala_mg_verify_notify_rep_msg_fun(TermId, TransId, Rid, Cid) -> + fun(Msg) -> + (catch rarala_mg_verify_notify_rep_msg(Msg, + TermId, TransId, Rid, Cid)) + end. +-endif. + +rarala_mg_verify_notify_rep_msg(#'MegacoMessage'{mess = Mess} = M, + TermId, TransId, Rid, Cid) -> + io:format("rarala_mg_verify_notify_rep_msg -> entry with" + "~n M: ~p" + "~n TermId: ~p" + "~n TransId: ~p" + "~n Rid: ~p" + "~n Cid: ~p" + "~n", [M, TermId, TransId, Rid, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = TransId, + immAckRequired = 'NULL', + transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + case NR of + #'NotifyReply'{terminationID = [TermId], + errorDescriptor = asn1_NOVALUE} -> + {ok, M}; + _ -> + {error, {invalid_notifyReply, NR}} + end; +rarala_mg_verify_notify_rep_msg(Crap, _TermId, _TransId, _Rid, _Cid) -> + {error, {invalid_message, Crap}}. + +rarala_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +rarala_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = rarala_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +rarala_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +rarala_mg_notify_request_msg(Mid, TermId, TransId, Rid, Cid) -> + AR = rarala_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +rarala_mg_trans_ack_msg(Mid, TransId) -> + TR = cre_transRespAck(cre_transAck(TransId)), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +trans_req_and_reply_and_req(suite) -> + []; +trans_req_and_reply_and_req(doc) -> + ["Receive a transaction request, send a reply (discard ack)" + "then receive the same reply again after the timeout. " + "The MGC is a megaco instance (megaco event sequence) and the " + "MG is emulated (tcp event sequence)"]; +trans_req_and_reply_and_req(Config) when is_list(Config) -> + %% <CONDITIONAL-SKIP> + Skippable = [{unix, [darwin, linux]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, trarar), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = trarar_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_tcp_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = trarar_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_tcp_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId], 60000), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_tcp_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(trarar_mgc_verify_handle_connect_fun(), + {?MODULE, trarar_mgc_verify_handle_connect, []}). +-define(trarar_mgc_verify_service_change_req_fun(Mid), + {?MODULE, trarar_mgc_verify_service_change_req, [Mid]}). +-define(trarar_mgc_verify_notify_req_fun(Cid), + {?MODULE, trarar_mgc_verify_notify_req, [Cid]}). +-define(trarar_mgc_verify_handle_disconnect_fun(), + {?MODULE, trarar_mgc_verify_handle_disconnect, []}). +-else. +-define(trarar_mgc_verify_handle_connect_fun(), + fun trarar_mgc_verify_handle_connect/1). +-define(trarar_mgc_verify_service_change_req_fun(Mid), + trarar_mgc_verify_service_change_req_fun(Mid)). +-define(trarar_mgc_verify_notify_req_fun(Cid), + trarar_mgc_verify_notify_req_fun(Cid)). +-define(trarar_mgc_verify_handle_disconnect_fun(), + fun trarar_mgc_verify_handle_disconnect/1). +-endif. + +trarar_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], +%% Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, +%% ReqTmr = #megaco_incr_timer{wait_for = 500, +%% factor = 1, +%% max_retries = 1}, + ConnectVerify = ?trarar_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?trarar_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify1 = ?trarar_mgc_verify_notify_req_fun(1), + NotifyReqVerify2 = ?trarar_mgc_verify_notify_req_fun(2), + NotifyReqVerify3 = ?trarar_mgc_verify_notify_req_fun(3), + NotifyReqVerify4 = ?trarar_mgc_verify_notify_req_fun(4), + DiscoVerify = ?trarar_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun trarar_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = trarar_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify1 = trarar_mgc_verify_notify_request_fun(1), +%% NotifyReqVerify2 = trarar_mgc_verify_notify_request_fun(2), +%% NotifyReqVerify3 = trarar_mgc_verify_notify_request_fun(3), +%% NotifyReqVerify4 = trarar_mgc_verify_notify_request_fun(4), +%% DiscoVerify = fun trarar_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, reply_timer, 2000}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify1}, + {megaco_callback, handle_trans_request, NotifyReqVerify2}, + {megaco_update_conn_info, reply_timer, 4000}, + {megaco_callback, handle_trans_request, NotifyReqVerify3}, + {megaco_callback, handle_trans_request, NotifyReqVerify4}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +trarar_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("trarar_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +trarar_mgc_verify_handle_connect(Else) -> + io:format("trarar_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +-ifndef(megaco_hipe_special). +trarar_mgc_verify_service_change_req_fun(Mid) -> + fun(Req) -> + trarar_mgc_verify_service_change_req(Req, Mid) + end. +-endif. + +trarar_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + (catch trarar_mgc_do_verify_service_change_req(AR, Mid)); +trarar_mgc_verify_service_change_req(Crap, _Mid) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +trarar_mgc_do_verify_service_change_req(AR, Mid) -> + io:format("trarar_mgc_verify_service_change_req -> ok" + "~n AR: ~p" + "~n Mid: ~p" + "~n", [AR, Mid]), + CR = + case AR of + #'ActionRequest'{commandRequests = [CmdReq]} -> + CmdReq; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Err4 = {invalid_termination_id, Tid}, + ED4 = cre_ErrDesc(Tid), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + case Parms of + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + AckData = [trarar_mgc_service_change_reply_ar(Mid, 1)], + Reply = {discard_ack, AckData}, + {ok, AR, Reply}; + _ -> + Err5 = {invalid_SCP, Parms}, + ED5 = cre_ErrDesc(Parms), + ErrReply5 = {discard_ack, ED5}, + {error, Err5, ErrReply5} + end. + +-ifndef(megaco_hipe_special). +trarar_mgc_verify_notify_req_fun(Cid) -> + fun(Req) -> + trarar_mgc_verify_notify_req(Req, Cid) + end. +-endif. + +trarar_mgc_verify_notify_req({handle_trans_request, _, ?VERSION, [AR]}, Cid) -> + (catch trarar_mgc_do_verify_notify_req(AR, Cid)); +trarar_mgc_verify_notify_req(Crap, _Cid) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +trarar_mgc_do_verify_notify_req(AR, Cid) -> + io:format("trarar_mgc_do_verify_notify_req -> entry with" + "~n AR: ~p" + "~n Cid: ~p" + "~n", [AR, Cid]), + {ContextID, CR} = + case AR of + #'ActionRequest'{contextId = CtxID, + commandRequests = [CmdReq]} when (CtxID == Cid) -> + {CtxID, CmdReq}; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + {Tid, OED} = + case NR of + #'NotifyRequest'{terminationID = [TermID], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + {TermID, ObsEvsDesc}; + _ -> + Err4 = {invalid_NR, NR}, + ED4 = cre_ErrDesc(NR), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + Err5 = {invalid_OED, OED}, + ED5 = cre_ErrDesc(NR), + ErrReply5 = {discard_ack, ED5}, + throw({error, Err5, ErrReply5}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + Replies = [trarar_mgc_notify_reply_ar(ContextID, Tid)], + Reply = {discard_ack, Replies}, + {ok, AR, Reply}; + _ -> + Err6 = {invalid_OE, OE}, + ED6 = cre_ErrDesc(OE), + ErrReply6 = {discard_ack, ED6}, + {error, Err6, ErrReply6} + end. + +trarar_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("trarar_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +trarar_mgc_verify_handle_disconnect(Else) -> + io:format("trarar_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +trarar_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +trarar_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +%% trarar_mgc_notify_reply(Mid, TransId, Cid, TermId) -> +%% AR = trarar_mgc_notify_reply_ar(Cid, TermId), +%% TRes = cre_transResult([AR]), +%% TR = cre_transReply(TransId, TRes), +%% Trans = cre_transaction(TR), +%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), +%% cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(trarar_mg_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(trarar_mg_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(trarar_mg_verify_service_change_rep_msg_fun(), + {?MODULE, trarar_mg_verify_service_change_rep_msg, []}). +-define(trarar_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), + {?MODULE, trarar_mg_verify_notify_rep_msg, [TermId, TransId, ReqId, CtxId]}). +-else. +-define(trarar_mg_decode_msg_fun(Mod, Conf), + trarar_mg_decode_msg_fun(Mod, Conf)). +-define(trarar_mg_encode_msg_fun(Mod, Conf), + trarar_mg_encode_msg_fun(Mod, Conf)). +-define(trarar_mg_verify_service_change_rep_msg_fun(), + trarar_mg_verify_service_change_rep_msg_fun()). +-define(trarar_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), + trarar_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId)). +-endif. + +trarar_mg_event_sequence(text, tcp) -> + DecodeFun = ?trarar_mg_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ?trarar_mg_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mg"}, + ServiceChangeReq = trarar_mg_service_change_request_msg(Mid, 1, 0), + TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq1 = + trarar_mg_notify_request_msg(Mid, TermId, 2, 1, 1), + NotifyReq2 = + trarar_mg_notify_request_msg(Mid, TermId, 2, 2, 2), + NotifyReq3 = + trarar_mg_notify_request_msg(Mid, TermId, 2, 3, 3), + NotifyReq4 = + trarar_mg_notify_request_msg(Mid, TermId, 2, 4, 4), + ScrVerifyFun = ?trarar_mg_verify_service_change_rep_msg_fun(), + NrVerifyFun1 = + ?trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 1, 1), + NrVerifyFun2 = + ?trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 2, 2), + NrVerifyFun3 = + ?trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 3, 3), + NrVerifyFun4 = + ?trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 4, 4), +%% ScrVerifyFun = trarar_mg_verify_service_change_rep_msg_fun(), +%% NrVerifyFun1 = +%% trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 1, 1), +%% NrVerifyFun2 = +%% trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 2, 2), +%% NrVerifyFun3 = +%% trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 3, 3), +%% NrVerifyFun4 = +%% trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 4, 4), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {connect, 2944}, + + {send, "service-change-request", ServiceChangeReq}, + {expect_receive, "service-change-reply", {ScrVerifyFun, 10000}}, + + %% the original setting for reply timer is 2000 + {send, "notify request 1", NotifyReq1}, + {expect_receive, "notify-reply 1", {NrVerifyFun1, 2500}}, + {sleep, 1000}, + {send, "notify request 2", NotifyReq2}, + {expect_receive, "notify-reply 2 (resend of 1)", {NrVerifyFun1, 2500}}, + {sleep, 3000}, % reply timer is set to 2000 + {send, "notify request 3 (same as 2)", NotifyReq2}, + {expect_receive, "notify-reply 3", {NrVerifyFun2, 2500}}, + + %% reply timer is now set to 4000 but previous was 2000 + %% so, 3000 is enough to let the timer running with the + %% previous settings (2000) to time out + {sleep, 3000}, + {send, "notify request 4", NotifyReq3}, + {expect_receive, "notify-reply 4", {NrVerifyFun3, 4500}}, + {sleep, 5000}, + {send, "notify request 5", NotifyReq4}, + {expect_receive, "notify-reply 5", {NrVerifyFun4, 4500}}, + + {expect_nothing, 5000}, + disconnect + ], + EvSeq. + +-ifndef(megaco_hipe_special). +trarar_mg_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +trarar_mg_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +trarar_mg_verify_service_change_rep_msg_fun() -> + fun(Msg) -> + (catch trarar_mg_verify_service_change_rep_msg(Msg)) + end. +-endif. + +trarar_mg_verify_service_change_rep_msg(#'MegacoMessage'{mess = Mess} = M) -> + Body = + case Mess of + #'Message'{version = _V, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = _Tid, + immAckRequired = asn1_NOVALUE, + transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = _Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + SCRes = + case SCR of + #'ServiceChangeReply'{terminationID = _TermID, + serviceChangeResult = ServChRes} -> + ServChRes; + _ -> + throw({error, {invalid_serviceChangeReply, SCR}}) + end, + SCRP = + case SCRes of + {serviceChangeResParms, Parms} -> + Parms; + _ -> + throw({error, {invalid_serviceChangeResult, SCRes}}) + end, + case SCRP of + #'ServiceChangeResParm'{serviceChangeMgcId = _MgcMid} -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeResParms, SCRP}} + end; +trarar_mg_verify_service_change_rep_msg(Crap) -> + {error, {invalid_message, Crap}}. + +-ifndef(megaco_hipe_special). +trarar_mg_verify_notify_rep_msg_fun(TermId, TransId, Rid, Cid) -> + fun(Msg) -> + (catch trarar_mg_verify_notify_rep_msg(Msg, + TermId, TransId, Rid, Cid)) + end. +-endif. + +trarar_mg_verify_notify_rep_msg(#'MegacoMessage'{mess = Mess} = M, + TermId, TransId, Rid, Cid) -> + io:format("trarar_mg_verify_notify_rep_msg -> entry with" + "~n M: ~p" + "~n TermId: ~p" + "~n TransId: ~p" + "~n Rid: ~p" + "~n Cid: ~p" + "~n", [M, TermId, TransId, Rid, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + io:format("trarar_mg_verify_notify_rep_msg -> " + "~n Body: ~p" + "~n", [Body]), + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + io:format("trarar_mg_verify_notify_rep_msg -> " + "~n Trans: ~p" + "~n", [Trans]), + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + io:format("trarar_mg_verify_notify_rep_msg -> " + "~n TR: ~p" + "~n", [TR]), + TRes = + case TR of + #'TransactionReply'{transactionId = TransId, + immAckRequired = asn1_NOVALUE, + transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + io:format("trarar_mg_verify_notify_rep_msg -> " + "~n TRes: ~p" + "~n", [TRes]), + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + io:format("trarar_mg_verify_notify_rep_msg -> " + "~n AR: ~p" + "~n", [AR]), + CR = + case AR of + #'ActionReply'{contextId = Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + case NR of + #'NotifyReply'{terminationID = [TermId], + errorDescriptor = asn1_NOVALUE} -> + {ok, M}; + _ -> + {error, {invalid_notifyReply, NR}} + end; +trarar_mg_verify_notify_rep_msg(Crap, _TermId, _TransId, _Rid, _Cid) -> + {error, {invalid_message, Crap}}. + +trarar_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +trarar_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = trarar_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +trarar_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +trarar_mg_notify_request_msg(Mid, TermId, TransId, Rid, Cid) -> + AR = trarar_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +%% trarar_mg_trans_ack_msg(Mid, TransId) -> +%% TR = cre_transRespAck(cre_transAck(TransId)), +%% Trans = cre_transaction(TR), +%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), +%% cre_megacoMessage(Mess). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +pending_ack_plain(suite) -> + []; +pending_ack_plain(doc) -> + ["Receive a request and handle it as a long request, " + "i.e. return with {pending, _} and expect a call to the " + "long request function"]; +pending_ack_plain(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, pap), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = pap_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_tcp_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = pap_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_tcp_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_tcp_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% + +-ifdef(megaco_hipe_special). +-define(pap_mgc_verify_handle_connect_fun(), + {?MODULE, pap_mgc_verify_handle_connect, []}). +-define(pap_mgc_verify_service_change_req_fun(Mid), + {?MODULE, pap_mgc_verify_service_change_req, [Mid]}). +-define(pap_mgc_verify_notify_req_fun(), + {?MODULE, pap_mgc_verify_notify_req, []}). +-define(pap_mgc_verify_notify_req_long_fun(), + {?MODULE, pap_mgc_verify_notify_req_long, []}). +-define(pap_mgc_verify_handle_trans_ack_fun(), + {?MODULE, pap_mgc_verify_handle_trans_ack, []}). +-define(pap_mgc_verify_handle_disconnect_fun(), + {?MODULE, pap_mgc_verify_handle_disconnect, []}). +-else. +-define(pap_mgc_verify_handle_connect_fun(), + fun pap_mgc_verify_handle_connect/1). +-define(pap_mgc_verify_service_change_req_fun(Mid), + pap_mgc_verify_service_change_req_fun(Mid)). +-define(pap_mgc_verify_notify_req_fun(), + pap_mgc_verify_notify_req_fun()). +-define(pap_mgc_verify_notify_req_long_fun(), + pap_mgc_verify_notify_req_long_fun()). +-define(pap_mgc_verify_handle_trans_ack_fun(), + pap_mgc_verify_handle_trans_ack_fun()). +-define(pap_mgc_verify_handle_disconnect_fun(), + fun pap_mgc_verify_handle_disconnect/1). +-endif. + +pap_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?pap_mgc_verify_handle_connect_fun(), + ScrVerify = ?pap_mgc_verify_service_change_req_fun(Mid), + NrVerify1 = ?pap_mgc_verify_notify_req_fun(), + NrVerify2 = ?pap_mgc_verify_notify_req_long_fun(), + AckVerify = ?pap_mgc_verify_handle_trans_ack_fun(), + DiscoVerify = ?pap_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun pap_mgc_verify_handle_connect/1, +%% ScrVerify = pap_mgc_verify_service_change_req_fun(Mid), +%% NrVerify1 = pap_mgc_verify_notify_request_fun(), +%% NrVerify2 = pap_mgc_verify_notify_request_long_fun(), +%% AckVerify = pap_mgc_verify_trans_ack_fun(), +%% DiscoVerify = fun pap_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, sent_pending_limit, 100}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_conn_info, all}, + {megaco_callback, handle_trans_request, ScrVerify}, + {megaco_callback, handle_trans_request, NrVerify1}, + {megaco_callback, handle_trans_long_request, NrVerify2}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + +%% Connect verification +pap_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + {ok, CH, ok}; +pap_mgc_verify_handle_connect(Else) -> + {error, Else, ok}. + +%% Service Change verification +-ifndef(megaco_hipe_special). +pap_mgc_verify_service_change_req_fun(Mid) -> + fun(Req) -> + pap_mgc_verify_service_change_req(Req, Mid) + end. +-endif. + +pap_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + (catch pap_do_verify_service_change_req(AR, Mid)); +pap_mgc_verify_service_change_req(Crap, _Mid) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +pap_do_verify_service_change_req(AR, Mid) -> + CR = + case AR of + #'ActionRequest'{commandRequests = [CmdReq]} -> + CmdReq; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Err4 = {invalid_termination_id, Tid}, + ED4 = cre_ErrDesc(Tid), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + case Parms of + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + AckData = [pap_mgc_service_change_reply_ar(Mid, 1)], + Reply = {discard_ack, AckData}, + {ok, AR, Reply}; + _ -> + Err5 = {invalid_SCP, Parms}, + ED5 = cre_ErrDesc(Parms), + ErrReply5 = {discard_ack, ED5}, + {error, Err5, ErrReply5} + end. + + +%% Notify Request verification +-ifndef(megaco_hipe_special). +pap_mgc_verify_notify_req_fun() -> + fun(Req) -> + pap_mgc_verify_notify_req(Req) + end. +-endif. + +pap_mgc_verify_notify_req({handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("pap_mgc_verify_notify_req -> entry with" + "~n AR: ~p" + "~n", [AR]), + Reply = {pending, AR}, + {ok, AR, Reply}; +pap_mgc_verify_notify_req(Crap) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +%% Notify Request verification +-ifndef(megaco_hipe_special). +pap_mgc_verify_notify_req_long_fun() -> + fun(Req) -> + pap_mgc_verify_notify_req_long(Req) + end. +-endif. + +pap_mgc_verify_notify_req_long( + {handle_trans_long_request, _, ?VERSION, AR}) -> + (catch pap_mgc_do_verify_notify_req_long(AR)); +pap_mgc_verify_notify_req_long(Crap) -> + ED = cre_ErrDesc(Crap), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + +pap_mgc_do_verify_notify_req_long(AR) -> + io:format("pap_mgc_do_verify_notify_req_long -> entry with" + "~n AR: ~p" + "~n", [AR]), + {Cid, CR} = + case AR of + #'ActionRequest'{contextId = CtxID, + commandRequests = [CmdReq]} -> + {CtxID, CmdReq}; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + {Tid, OED} = + case NR of + #'NotifyRequest'{terminationID = [TermID], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + {TermID, ObsEvsDesc}; + _ -> + Err4 = {invalid_NR, NR}, + ED4 = cre_ErrDesc(NR), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + Err5 = {invalid_OED, OED}, + ED5 = cre_ErrDesc(NR), + ErrReply5 = {discard_ack, ED5}, + throw({error, Err5, ErrReply5}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + AckData = pap, + Replies = [pap_mgc_notify_reply_ar(Cid, Tid)], + Reply = {{handle_ack, AckData}, Replies}, + {ok, AR, Reply}; + _ -> + Err6 = {invalid_OE, OE}, + ED6 = cre_ErrDesc(OE), + ErrReply6 = {discard_ack, ED6}, + throw({error, Err6, ErrReply6}) + end. + + +-ifndef(megaco_hipe_special). +pap_mgc_verify_handle_trans_ack_fun() -> + fun(Ack) -> + pap_mgc_verify_handle_trans_ack(Ack) + end. +-endif. + +pap_mgc_verify_handle_trans_ack({handle_trans_ack, CH, ?VERSION, ok, pap}) -> + io:format("pap_mgc_verify_handle_trans_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +pap_mgc_verify_handle_trans_ack(Crap) -> + io:format("pap_mgc_verify_handle_trans_ack -> unknown" + "~n Crap: ~p~n", [Crap]), + {error, Crap, ok}. + + +%% Disconnect verification +pap_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, _R}) -> + {ok, CH, ok}; +pap_mgc_verify_handle_disconnect(Else) -> + {error, Else, ok}. + +pap_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + AR. + +pap_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(pap_mg_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(pap_mg_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(pap_mg_verify_service_change_rep_msg_fun(), + {?MODULE, pap_mg_verify_service_change_rep_msg, []}). +-define(pap_mg_verify_pending_msg_fun(TransId), + {?MODULE, pap_mg_verify_pending_msg, [TransId]}). +-define(pap_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), + {?MODULE, pap_mg_verify_notify_rep_msg, [TermId, TransId, ReqId, CtxId]}). +-else. +-define(pap_mg_decode_msg_fun(Mod, Conf), + pap_mg_decode_msg_fun(Mod, Conf)). +-define(pap_mg_encode_msg_fun(Mod, Conf), + pap_mg_encode_msg_fun(Mod, Conf)). +-define(pap_mg_verify_service_change_rep_msg_fun(), + pap_mg_verify_service_change_rep_msg_fun()). +-define(pap_mg_verify_pending_msg_fun(TransId), + pap_mg_verify_pending_msg_fun(TransId)). +-define(pap_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), + pap_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId)). +-endif. + +pap_mg_event_sequence(text, tcp) -> + DecodeFun = ?pap_mg_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ?pap_mg_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mg"}, + ServiceChangeReq = pap_mg_service_change_request_msg(Mid, 1, 0), + TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + TransId = 2, + ReqId = 1, + CtxId = 1, + NotifyReq = + pap_mg_notify_request_msg(Mid, TermId, TransId, ReqId, CtxId), + TransAck = pap_mg_trans_ack_msg(Mid, TransId), + ScrVerifyFun = ?pap_mg_verify_service_change_rep_msg_fun(), + PendingVerifyFun = + ?pap_mg_verify_pending_msg_fun(TransId), + NrVerifyFun = + ?pap_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), +%% ScrVerifyFun = pap_mg_verify_service_change_rep_msg_fun(), +%% PendingVerifyFun = +%% pap_mg_verify_pending_msg_fun(TransId), +%% NrVerifyFun = +%% pap_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {connect, 2944}, + {send, "service-change-request", ServiceChangeReq}, + {expect_receive, "service-change-reply", {ScrVerifyFun, 10000}}, + {send, "notify request", NotifyReq}, + {expect_receive, "pending", {PendingVerifyFun, 4000}}, + {expect_receive, "notify-reply", {NrVerifyFun, 4000}}, + {send, "transaction-ack", TransAck}, + {expect_nothing, 11000}, + disconnect + ], + EvSeq. + +-ifndef(megaco_hipe_special). +pap_mg_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +pap_mg_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +pap_mg_verify_service_change_rep_msg_fun() -> + fun(Msg) -> + (catch pap_mg_verify_service_change_rep_msg(Msg)) + end. +-endif. + +pap_mg_verify_service_change_rep_msg(#'MegacoMessage'{mess = Mess} = M) -> + Body = + case Mess of + #'Message'{version = _V, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = _Tid, + immAckRequired = asn1_NOVALUE, + transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = _Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + SCRes = + case SCR of + #'ServiceChangeReply'{terminationID = _TermID, + serviceChangeResult = ServChRes} -> + ServChRes; + _ -> + throw({error, {invalid_serviceChangeReply, SCR}}) + end, + SCRP = + case SCRes of + {serviceChangeResParms, Parms} -> + Parms; + _ -> + throw({error, {invalid_serviceChangeResult, SCRes}}) + end, + case SCRP of + #'ServiceChangeResParm'{serviceChangeMgcId = _MgcMid} -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeResParms, SCRP}} + end; +pap_mg_verify_service_change_rep_msg(Crap) -> + {error, {invalid_message, Crap}}. + +-ifndef(megaco_hipe_special). +pap_mg_verify_pending_msg_fun(TransId) -> + fun(Msg) -> + (catch pap_mg_verify_pending_msg(Msg, TransId)) + end. +-endif. + +pap_mg_verify_pending_msg(#'MegacoMessage'{mess = Mess} = M, TransId) -> + io:format("pap_mg_verify_pending_msg -> entry with" + "~n M: ~p" + "~n TransId: ~p" + "~n", [M, TransId]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TP = + case Trans of + {transactionPending, TransPending} -> + TransPending; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + case TP of + #'TransactionPending'{transactionId = TransId} -> + {ok, M}; + _ -> + {error, {invalid_transactionPending, TP}} + end; +pap_mg_verify_pending_msg(Crap, _TransId) -> + {error, {invalid_message, Crap}}. + +-ifndef(megaco_hipe_special). +pap_mg_verify_notify_rep_msg_fun(TermId, TransId, Rid, Cid) -> + fun(Msg) -> + (catch pap_mg_verify_notify_rep_msg(Msg, + TermId, TransId, Rid, Cid)) + end. +-endif. + +pap_mg_verify_notify_rep_msg(#'MegacoMessage'{mess = Mess} = M, + TermId, TransId, Rid, Cid) -> + io:format("pap_mg_verify_notify_rep_msg -> entry with" + "~n M: ~p" + "~n TermId: ~p" + "~n TransId: ~p" + "~n Rid: ~p" + "~n Cid: ~p" + "~n", [M, TermId, TransId, Rid, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = TransId, + immAckRequired = 'NULL', + transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + case NR of + #'NotifyReply'{terminationID = [TermId], + errorDescriptor = asn1_NOVALUE} -> + {ok, M}; + _ -> + {error, {invalid_notifyReply, NR}} + end; +pap_mg_verify_notify_rep_msg(Crap, _TermId, _TransId, _Rid, _Cid) -> + {error, {invalid_message, Crap}}. + +pap_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +pap_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = pap_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +pap_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +pap_mg_notify_request_msg(Mid, TermId, TransId, Rid, Cid) -> + AR = pap_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +pap_mg_trans_ack_msg(Mid, TransId) -> + TR = cre_transRespAck(cre_transAck(TransId)), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +request_and_pending_and_late_reply(suite) -> + []; +request_and_pending_and_late_reply(doc) -> + ["Receive a request and handle it as a long request, " + "i.e. return with {pending, _}. Then, expect the sender " + "to keep re-sending the request until the reply is sent."]; +request_and_pending_and_late_reply(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, rapalr), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = rapalr_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = rapalr_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% + +-ifdef(megaco_hipe_special). +-define(rapalr_mgc_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(rapalr_mgc_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(rapalr_mgc_verify_service_change_req_msg_fun(), + {?MODULE, rapalr_mgc_verify_service_change_req_msg, []}). +-define(rapalr_mgc_verify_notify_req_msg_fun(TermId, TransId, ReqId, CtxId), + {?MODULE, rapalr_mgc_verify_notify_req_msg, [TermId, TransId, ReqId, CtxId]}). +-define(rapalr_mgc_verify_trans_ack_msg_fun(TransId), + {?MODULE, rapalr_mgc_verify_trans_ack_msg, [TransId]}). +-else. +-define(rapalr_mgc_decode_msg_fun(Mod, Conf), + rapalr_mgc_decode_msg_fun(Mod, Conf)). +-define(rapalr_mgc_encode_msg_fun(Mod, Conf), + rapalr_mgc_encode_msg_fun(Mod, Conf)). +-define(rapalr_mgc_verify_service_change_req_msg_fun(), + rapalr_mgc_verify_service_change_req_msg_fun()). +-define(rapalr_mgc_verify_notify_req_msg_fun(TermId, TransId, ReqId, CtxId), + rapalr_mgc_verify_notify_req_msg_fun(TermId, TransId, ReqId, CtxId)). +-define(rapalr_mgc_verify_trans_ack_msg_fun(TransId), + rapalr_mgc_verify_trans_ack_msg_fun(TransId)). +-endif. + +rapalr_mgc_event_sequence(text, tcp) -> + DecodeFun = ?rapalr_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ?rapalr_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mgc"}, + ServiceChangeRep = rapalr_mgc_service_change_reply_msg(Mid, 1), + TermId = + #megaco_term_id{id = ["00000000","00000000","01101101"]}, + TransId = 2, + ReqId = 1, + CtxId = 1, + Pending = rapalr_mgc_trans_pending_msg(Mid, TransId), + NotifyRep = rapalr_mgc_notify_reply_msg(Mid, TransId, + CtxId, TermId), + ScrVerifyFun = ?rapalr_mgc_verify_service_change_req_msg_fun(), + NrVerifyFun = + ?rapalr_mgc_verify_notify_req_msg_fun(TermId, TransId, ReqId, CtxId), + AckVerifyFun = ?rapalr_mgc_verify_trans_ack_msg_fun(TransId), +%% ScrVerifyFun = rapalr_mgc_verify_service_change_req_msg_fun(), +%% NrVerifyFun = +%% rapalr_mgc_verify_notify_req_msg_fun(TermId, TransId, ReqId, CtxId), +%% AckVerifyFun = rapalr_mgc_verify_trans_ack_msg_fun(TransId), + EvSeq = [{debug, false}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-request", {ScrVerifyFun, 5000}}, + {send, "service-change-reply", ServiceChangeRep}, + {expect_receive, "notify-request(1)", {NrVerifyFun, 4000}}, + {send, "pending", Pending}, + {expect_receive, "notify-request(2)", {NrVerifyFun, 4000}}, + {expect_receive, "notify-request(3)", {NrVerifyFun, 4000}}, + {send, "notify reply", NotifyRep}, + {expect_receive, "ack", {AckVerifyFun, 4000}}, + {sleep, 1000}, + disconnect + ], + EvSeq. + +-ifndef(megaco_hipe_special). +rapalr_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +rapalr_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +rapalr_mgc_verify_service_change_req_msg_fun() -> + fun(Msg) -> + (catch rapalr_mgc_verify_service_change_req_msg(Msg)) + end. +-endif. + +rapalr_mgc_verify_service_change_req_msg(#'MegacoMessage'{mess = Mess} = M) -> + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = _TransId, + actions = [ActionReq]} -> + ActionReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + CR = + case AR of + #'ActionRequest'{contextId = _Cid, + commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_action, AR}}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + throw({error, {invalid_terminationID, Tid}}) + end, + case Parms of + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeParms, Parms}} + end. + +-ifndef(megaco_hipe_special). +rapalr_mgc_verify_notify_req_msg_fun(TermId, TransId, Rid, Cid) -> + fun(Msg) -> + (catch rapalr_mgc_verify_notify_req_msg(Msg, + TermId, + TransId, Rid, Cid)) + end. +-endif. + +rapalr_mgc_verify_notify_req_msg(#'MegacoMessage'{mess = Mess} = M, + TermId, TransId, Rid, Cid) -> + io:format("rapalr_mgc_verify_notify_req_msg -> entry with" + "~n M: ~p" + "~n TermId: ~p" + "~n TransId: ~p" + "~n Rid: ~p" + "~n Cid: ~p" + "~n", [M, TermId, TransId, Rid, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = TransId, + actions = [ActReq]} -> + ActReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + CR = + case AR of + #'ActionRequest'{contextId = Cid, + commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_actions, AR}}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequests, CR}}) + end, + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + OED = + case NR of + #'NotifyRequest'{terminationID = [TermId], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + ObsEvsDesc; + _ -> + throw({error, {invalid_notifyReq, NR}}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + throw({error, {invalid_observedEventsDescriptor, OED}}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + {ok, M}; + _ -> + throw({error, {invalid_observedEventLst, OE}}) + end; +rapalr_mgc_verify_notify_req_msg(Crap, _TermId, _TransId, _Rid, _Cid) -> + {error, {invalid_MegacoMessage, Crap}}. + +-ifndef(megaco_hipe_special). +rapalr_mgc_verify_trans_ack_msg_fun(TransId) -> + fun(Msg) -> + (catch rapalr_mgc_verify_trans_ack_msg(Msg, TransId)) + end. +-endif. + +rapalr_mgc_verify_trans_ack_msg(#'MegacoMessage'{mess = Mess} = M, + TransId) -> + io:format("rapalr_mgc_verify_trans_ack_msg -> entry with" + "~n M: ~p" + "~n TransId: ~p" + "~n", [M, TransId]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TA = + case Trans of + {transactionResponseAck, [TransAck]} -> + TransAck; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + case TA of + #'TransactionAck'{firstAck = TransId, + lastAck = asn1_NOVALUE} -> + {ok, M}; + _ -> + throw({error, {invalid_transactionResponseAck, TA}}) + end; +rapalr_mgc_verify_trans_ack_msg(Crap, _TransId) -> + {error, {invalid_MegacoMessage, Crap}}. + +rapalr_mgc_service_change_reply_msg(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + TRes = cre_transResult([AR]), + TR = cre_transReply(1, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +rapalr_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +rapalr_mgc_notify_reply_msg(Mid, TransId, Cid, TermId) -> + AR = rapalr_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, 'NULL', TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +rapalr_mgc_trans_pending_msg(Mid, TransId) -> + TP = #'TransactionPending'{transactionId = TransId}, + Body = {transactions, [{transactionPending, TP}]}, + Mess = #'Message'{version = 1, + mId = Mid, + messageBody = Body}, + #'MegacoMessage'{mess = Mess}. + + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(rapalr_mg_verify_handle_connect_fun(), + {?MODULE, rapalr_mg_verify_handle_connect, []}). +-define(rapalr_mg_verify_service_change_rep_fun(), + {?MODULE, rapalr_mg_verify_service_change_rep, []}). +-define(rapalr_mg_verify_notify_rep_fun(), + {?MODULE, rapalr_mg_verify_notify_rep, []}). +-else. +-define(rapalr_mg_verify_handle_connect_fun(), + rapalr_mg_verify_handle_connect_fun()). +-define(rapalr_mg_verify_service_change_rep_fun(), + rapalr_mg_verify_service_change_rep_fun()). +-define(rapalr_mg_verify_notify_rep_fun(), + rapalr_mg_verify_notify_rep_fun()). +-endif. + +rapalr_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + LReqTmr = #megaco_incr_timer{wait_for = 3000, + factor = 1, + incr = 0, + max_retries = 2 + }, + ServiceChangeReq = rapalr_mg_service_change_request_ar(Mid, 1), + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq = rapalr_mg_notify_request_ar(1, Tid, 1), + ConnectVerify = ?rapalr_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?rapalr_mg_verify_service_change_rep_fun(), + NotifyReplyVerify = ?rapalr_mg_verify_notify_rep_fun(), +%% ConnectVerify = rapalr_mg_verify_handle_connect_fun(), +%% ServiceChangeReplyVerify = rapalr_mg_verify_service_change_reply_fun(), +%% NotifyReplyVerify = rapalr_mg_verify_notify_reply_fun(), + EvSeq = [ + {debug, false}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {megaco_update_user_info, long_request_resend, true}, + {megaco_update_user_info, long_request_timer, LReqTmr}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_cast, [NotifyReq], []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +-ifndef(megaco_hipe_special). +rapalr_mg_verify_handle_connect_fun() -> + fun(Ev) -> + rapalr_mg_verify_handle_connect(Ev) + end. +-endif. + +rapalr_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("rapalr_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +rapalr_mg_verify_handle_connect(Else) -> + io:format("rapalr_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +-ifndef(megaco_hipe_special). +rapalr_mg_verify_service_change_rep_fun() -> + fun(Rep) -> + rapalr_mg_verify_service_change_rep(Rep) + end. +-endif. + +rapalr_mg_verify_service_change_rep( + {handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> + (catch rapalr_mg_do_verify_service_change_rep(AR)); +rapalr_mg_verify_service_change_rep(Crap) -> + {error, Crap, ok}. + +rapalr_mg_do_verify_service_change_rep(AR) -> + io:format("rapalr_mg_verify_service_change_rep -> ok" + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +-ifndef(megaco_hipe_special). +rapalr_mg_verify_notify_rep_fun() -> + fun(Rep) -> + rapalr_mg_verify_notify_rep(Rep) + end. +-endif. + +rapalr_mg_verify_notify_rep({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("rapalr_mg_verify_notify_rep -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +rapalr_mg_verify_notify_rep(Else) -> + io:format("rapalr_mg_verify_notify_rep -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +rapalr_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +rapalr_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + + + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +dist(suite) -> + []; +dist(Config) when is_list(Config) -> + [_Local, Dist] = ?ACQUIRE_NODES(2, Config), + d("dist -> start proxy",[]), + megaco_mess_user_test:start_proxy(), + + PrelMid = preliminary_mid, + MgMid = ipv4_mid(4711), + MgcMid = ipv4_mid(), + UserMod = megaco_mess_user_test, + d("dist -> start megaco app",[]), + ?VERIFY(ok, application:start(megaco)), + UserConfig = [{user_mod, UserMod}, {send_mod, UserMod}, + {request_timer, infinity}, {reply_timer, infinity}], + + d("dist -> start megaco user MG (~p)",[MgMid]), + ?VERIFY(ok, megaco:start_user(MgMid, UserConfig)), + + d("dist -> start megaco user MGC (~p)",[MgcMid]), + ?VERIFY(ok, megaco:start_user(MgcMid, UserConfig)), + + d("dist -> retrieve (user info) receive_handle for MG",[]), + MgRH = user_info(MgMid, receive_handle), + + d("dist -> retrieve (user info) receive_handle for MGC",[]), + MgcRH = user_info(MgcMid, receive_handle), + + d("dist -> start transport",[]), + {ok, MgPid, MgSH} = + ?VERIFY({ok, _, _}, UserMod:start_transport(MgRH, MgcRH)), + PrelMgCH = #megaco_conn_handle{local_mid = MgMid, + remote_mid = preliminary_mid}, + MgCH = #megaco_conn_handle{local_mid = MgMid, + remote_mid = MgcMid}, + MgcCH = #megaco_conn_handle{local_mid = MgcMid, + remote_mid = MgMid}, + + d("dist -> (MG) connect",[]), + ?SEND(megaco:connect(MgRH, PrelMid, MgSH, MgPid)), % Mg prel + + d("dist -> (MG) await connect",[]), + ?USER({connect, PrelMgCH, _V, []}, ok), + ?RECEIVE([{res, _, {ok, PrelMgCH}}]), + + d("dist -> (MG) send service change request",[]), + Req = service_change_request(), + ?SEND(megaco:call(PrelMgCH, [Req], [])), + + d("dist -> (MGC) await auto-connect",[]), + ?USER({connect, MgcCH, _V, []}, ok), % Mgc auto + + + Rep = service_change_reply(MgcMid), + d("dist -> (MGC) " + "await service change request and send reply when received",[]), + ?USER({request, MgcCH, _V, [[Req]]}, {discard_ack, [Rep]}), + + d("dist -> (MG) await connect",[]), + ?USER({connect, MgCH, _V, []}, ok), % Mg confirm + + d("dist -> (MG) await service change reply",[]), + ?RECEIVE([{res, _, {1, {ok, [Rep]}}}]), + + %% Dist + d("dist -> start megaco on ~p", [Dist]), + ?VERIFY(ok, rpc:call(Dist, megaco, start, [])), + + d("dist -> start megaco user on ~p", [Dist]), + ?VERIFY(ok, rpc:call(Dist, megaco, start_user, [MgcMid, UserConfig])), + + d("dist -> (MG) connect to MGC", []), + MgcPid = self(), + MgcSH = {element(2, MgSH), element(1, MgSH)}, + ?SEND(rpc:call(Dist, megaco, connect, [MgcRH, MgMid, MgcSH, MgcPid])), % Mgc dist + + d("dist -> (MGC) await auto-connect (from MG on ~p)", [Dist]), + ?USER({connect, MgcCH, _V, []}, ok), % Mgc dist auto + ?RECEIVE([{res, _, {ok, MgcCH}}]), + + d("dist -> (~p:MG) send service change request",[Dist]), + ?SEND(rpc:call(Dist, megaco, call, [MgcCH, [Req], []])), + + d("dist -> (MG????????) " + "await service change request and send reply when received",[]), + ?USER({request, MgCH, _V, [[Req]]}, {discard_ack, [Rep]}), + ?RECEIVE([{res, _, {1, {ok, [Rep]}}}]), + + d("dist -> retreive some info",[]), + connections([MgCH, MgcCH]), + ?VERIFY([MgCH], megaco:user_info(MgMid, connections)), + ?VERIFY([MgcCH], megaco:user_info(MgcMid, connections)), + + ?VERIFY([MgcCH], rpc:call(Dist, megaco, system_info, [connections])), + ?VERIFY([], rpc:call(Dist, megaco, user_info, [MgMid, connections])), + ?VERIFY([MgcCH], rpc:call(Dist, megaco, user_info, [MgcMid, connections])), + + %% Shutdown + + d("dist -> close down the shop...",[]), + Reason = shutdown, + ?SEND(megaco:disconnect(MgCH, Reason)), + ?USER({disconnect, MgCH, _V, [{user_disconnect, Reason}]}, ok), + ?RECEIVE([{res, _, ok}]), + ?VERIFY(ok, megaco:stop_user(MgMid)), + + ?SEND(megaco:disconnect(MgcCH, Reason)), + ?USER({disconnect, MgcCH, _V, [{user_disconnect, Reason}]}, ok), + ?USER({disconnect, MgcCH, _V, [{user_disconnect, Reason}]}, ok), + ?RECEIVE([{res, _, ok}]), + ?VERIFY(ok, megaco:stop_user(MgcMid)), + + ?VERIFY(ok, application:stop(megaco)), + ?RECEIVE([]), + d("dist -> done",[]), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_4359(suite) -> + []; +otp_4359(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Mid = {deviceName, "dummy_mid"}, + + io:format("otp_4359 -> start megaco application~n", []), + ?VERIFY(ok, application:start(megaco)), + + %% megaco:enable_trace(max, io), + io:format("otp_4359 -> start and configure megaco user~n", []), + ?VERIFY(ok, megaco:start_user(Mid, [{send_mod, ?MODULE}, + {request_timer, infinity}, + {reply_timer, infinity}])), + + io:format("otp_4359 -> update user info: user_mod -> ~p~n", [?MODULE]), + ?VERIFY(ok, megaco:update_user_info(Mid, user_mod, ?MODULE)), + io:format("otp_4359 -> update user info: user_args -> ~p~n", [self()]), + ?VERIFY(ok, megaco:update_user_info(Mid, user_args, [self()])), + io:format("otp_4359 -> retreive receive_handle~n", []), + RH0 = user_info(Mid, receive_handle), + io:format("otp_4359 -> RH0: ~p~n", [RH0]), + RH1 = RH0#megaco_receive_handle{send_mod = ?MODULE, + encoding_mod = megaco_compact_text_encoder, + encoding_config = []}, + + %% First an erroneous transaction (missing the transaction id number) + %% then an valid transaction. + M = "!/1 ml2 " + "T={C=${A=${M{O {MO=SR,RG=OFF,RV=OFF}}}}}" + "T=1{C=${A=${M{O {MO=SR,RG=OFF,RV=OFF}}}}}", + + %% Simulate incomming message + %% Will result in an (auto) connect first + io:format("otp_4359 -> simulate receive message~n", []), + megaco:receive_message(RH1, self(), self(), list_to_binary(M)), + io:format("otp_4359 -> await actions~n", []), + Actions = otp_4359_await_actions([{handle_connect, ignore}, + {send_message, ?megaco_bad_request}, + {handle_trans_request, ignore}, + {send_message, ?megaco_not_implemented}]), + io:format("otp_4359 -> analyze actions~n", []), + otp_4359_analyze_result(RH1, Actions), + + Conns = megaco:system_info(connections), + io:format("otp_4359 -> connections~n~p~n", [Conns]), + OKs = lists:duplicate(length(Conns),ok), + io:format("otp_4359 -> verify (all) connection disconnect~n", []), + ?VERIFY(OKs, [megaco:disconnect(CH, test_complete) || CH <- Conns]), + io:format("otp_4359 -> stop user (~p)~n", [Mid]), + stop_user(Mid), + io:format("otp_4359 -> stop megaco application~n", []), + ?VERIFY(ok, application:stop(megaco)), + io:format("otp_4359 -> make sure we have nothing in the message queue~n", []), + ?RECEIVE([]), + io:format("otp_4359 -> done~n", []), + ok. + + +otp_4359_await_actions(Exp) -> + otp_4359_await_actions(Exp, []). + +otp_4359_await_actions([], Rep) -> + lists:reverse(Rep); +otp_4359_await_actions([{M,I}|R] = _All, Rep) -> + receive + {M, Info} -> + io:format("otp_4359 -> received expected event [~w]~n", [M]), + otp_4359_await_actions(R, [{M, I, Info}|Rep]) +%% Else -> +%% exit({received_unexpected_message, M, Else}) +%% %% io:format("received unexpected: ~p~n", [Else]), +%% %% otp_4359_await_actions(All, Rep) + after 10000 -> + exit({timeout,megaco_test_lib:flush()} ) + end. + +otp_4359_analyze_result(_RH, []) -> + ok; +otp_4359_analyze_result(RH, + [{send_message, ExpErrorCode, EncodedMessage}|L]) -> + io:format("otp_4359_analyze_result -> send_message: ", []), + otp_4359_analyze_encoded_message(RH, ExpErrorCode, EncodedMessage), + otp_4359_analyze_result(RH,L); +otp_4359_analyze_result(RH, [{M,ignore,_}|T]) -> + io:format("otp_4359_analyze_result -> ignoring ~p~n", [M]), + otp_4359_analyze_result(RH,T). + +otp_4359_analyze_encoded_message(RH, ExpErrorCode, M) + when is_record(RH, megaco_receive_handle) andalso is_binary(M) -> + #megaco_receive_handle{encoding_mod = Mod, + encoding_config = Conf} = RH, + case (catch Mod:decode_message(Conf, M)) of + {ok, #'MegacoMessage'{mess = #'Message'{messageBody = Body}}} -> + case Body of + {transactions, [{transactionReply,Reply}]} -> + case Reply of + #'TransactionReply'{transactionResult = Result} -> + case Result of + {transactionError,ED} when is_record(ED, 'ErrorDescriptor') -> + case ED#'ErrorDescriptor'.errorCode of + ExpErrorCode -> + io:format("error code ~p ok~n", [ExpErrorCode]), + ok; + Code -> + io:format("error code ~p erroneous~n", [Code]), + exit({unexpected_error_code, ExpErrorCode, Code}) + end; + _ -> + io:format("unexpected trans result~n", []), + exit({unexpected_trans_result, Result}) + end; + _ -> + io:format("unexpected trans reply~n", []), + exit({unexpected_trans_reply, Reply}) + end; + _ -> + io:format("unexpected body~n", []), + exit({unexpected_body, Body}) + end; + + Else -> + io:format("unexpected decode result~n", []), + exit({unexpected_decode_result, Else}) + end. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_4836(suite) -> + []; +otp_4836(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, otp_4836), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("start the MGC simulator (generator)"), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("create the MGC event sequence"), + MgcEvSeq = otp_4836_mgc_event_sequence(text, tcp), + + d("start the MGC simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("[MG] start"), + MgMid = {deviceName, "mg"}, + ReqTmr = #megaco_incr_timer{wait_for = 3000, + factor = 1, + incr = 0, + max_retries = 3}, + %% 5000, %% Does not matter since we will not use this anyway... + LongReqTmr = #megaco_incr_timer{wait_for = 3000, + factor = 1, + incr = 0, + max_retries = 3}, + PendingTmr = 10000, + ReplyTmr = 16000, + MgConfig = [{request_timer, ReqTmr}, + {long_request_timer, LongReqTmr}, + {pending_timer, PendingTmr}, + {reply_timer, ReplyTmr}], + {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY), + + i("[MG] connect to the MGC (service change)"), + ServChRes = ?MG_SERV_CHANGE(Mg), + d("service change result: ~p", [ServChRes]), + + d("[MG] send the notify"), + {ok, Reply} = (catch ?MG_NOTIF_RAR(Mg)), + {1, {ok, [AR]}} = Reply, + d("[MG] ActionReply: ~p", [AR]), + + d("await the generator reply"), + await_completion([MgcId]), + + %% Tell MG to stop + i("[MG] stop"), + ?MG_STOP(Mg), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + i("done", []), + ok. + + +-ifdef(megaco_hipe_special). +-define(otp_4836_mgc_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(otp_4836_mgc_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(otp_4836_mgc_verify_service_change_req_msg_fun(), + {?MODULE, otp_4836_mgc_verify_service_change_req_msg, []}). +-define(otp_4836_mgc_verify_notify_req_msg_fun(), + {?MODULE, otp_4836_mgc_verify_notify_req_msg, []}). +-else. +-define(otp_4836_mgc_decode_msg_fun(Mod, Conf), + otp_4836_mgc_decode_msg_fun(Mod, Conf)). +-define(otp_4836_mgc_encode_msg_fun(Mod, Conf), + otp_4836_mgc_encode_msg_fun(Mod, Conf)). +-define(otp_4836_mgc_verify_service_change_req_msg_fun(), + otp_4836_mgc_verify_service_change_req_msg_fun()). +-define(otp_4836_mgc_verify_notify_req_msg_fun(), + otp_4836_mgc_verify_notify_req_msg_fun()). +-endif. + +otp_4836_mgc_event_sequence(text, tcp) -> + DecodeFun = ?otp_4836_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ?otp_4836_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"ctrl"}, + ServiceChangeReply = otp_4836_service_change_reply_msg(Mid, 1, 0), + TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReply = otp_4836_notify_reply_msg(Mid, 2, 0, TermId), + Pending = otp_4836_pending_msg(Mid,2), + ServiceChangeVerifyFun = ?otp_4836_mgc_verify_service_change_req_msg_fun(), + NotifyReqVerifyFun = ?otp_4836_mgc_verify_notify_req_msg_fun(), + MgcEvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-request", {ServiceChangeVerifyFun, 10000}}, + {send, "service-change-reply", ServiceChangeReply}, + {expect_receive, "notify-request", {NotifyReqVerifyFun, 10000}}, + {send, "pending 1", Pending}, + {sleep, 100}, + {send, "pending 2", Pending}, + {sleep, 500}, + {send, "notify-reply", NotifyReply}, + {sleep, 2000} + ], + MgcEvSeq. + +otp_4836_service_change_reply_msg(Mid, TransId, Cid) -> + SCRP = #'ServiceChangeResParm'{serviceChangeMgcId = Mid}, + SCRPs = {serviceChangeResParms,SCRP}, + Root = #megaco_term_id{id = ["root"]}, + SCR = #'ServiceChangeReply'{terminationID = [Root], + serviceChangeResult = SCRPs}, + CR = {serviceChangeReply, SCR}, + otp_4836_msg(Mid, TransId, CR, Cid). + +otp_4836_notify_reply_msg(Mid, TransId, Cid, TermId) -> + NR = #'NotifyReply'{terminationID = [TermId]}, + CR = {notifyReply, NR}, + otp_4836_msg(Mid, TransId, CR, Cid). + +otp_4836_msg(Mid, TransId, CR, Cid) -> + AR = #'ActionReply'{contextId = Cid, + commandReply = [CR]}, + ARs = {actionReplies, [AR]}, + TR = #'TransactionReply'{transactionId = TransId, + transactionResult = ARs}, + Body = {transactions, [{transactionReply, TR}]}, + Mess = #'Message'{version = 1, + mId = Mid, + messageBody = Body}, + #'MegacoMessage'{mess = Mess}. + + +otp_4836_pending_msg(Mid, TransId) -> + TP = #'TransactionPending'{transactionId = TransId}, + Body = {transactions, [{transactionPending, TP}]}, + Mess = #'Message'{version = 1, + mId = Mid, + messageBody = Body}, + #'MegacoMessage'{mess = Mess}. + + +-ifndef(megaco_hipe_special). +otp_4836_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. +-endif. +%% otp_4836_mgc_encode_msg_fun(Mod, Conf, Ver) -> +%% fun(M) -> +%% encode_msg(M, Mod, Conf, Ver) +%% end. + +-ifndef(megaco_hipe_special). +otp_4836_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. +%% otp_4836_mgc_decode_msg_fun(Mod, Conf, Ver) -> +%% fun(M) -> +%% decode_msg(M, Mod, Conf, Ver) +%% end. + +%% otp_4836_verify_msg_fun() -> +%% fun(M) -> +%% {ok, M} +%% end. + +-ifndef(megaco_hipe_special). +otp_4836_mgc_verify_service_change_req_msg_fun() -> + fun(M) -> + otp_4836_mgc_verify_service_change_req_msg(M) + end. +-endif. + +otp_4836_mgc_verify_service_change_req_msg( + #'MegacoMessage'{mess = Mess} = M) -> + #'Message'{version = _V, + mId = _Mid, + messageBody = Body} = Mess, + {transactions, [Trans]} = Body, + {transactionRequest, TR} = Trans, + #'TransactionRequest'{transactionId = _Tid, + actions = [AR]} = TR, + #'ActionRequest'{contextId = _Cid, + contextRequest = _CtxReq, + contextAttrAuditReq = _CtxAar, + commandRequests = [CR]} = AR, + #'CommandRequest'{command = Cmd, + optional = _Opt, + wildcardReturn = _WR} = CR, + {serviceChangeReq, SCR} = Cmd, + #'ServiceChangeRequest'{terminationID = _TermID, + serviceChangeParms = SCP} = SCR, + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} = SCP, + {ok, M}; +otp_4836_mgc_verify_service_change_req_msg(M) -> + {error, {invalid_message, M}}. + +-ifndef(megaco_hipe_special). +otp_4836_mgc_verify_notify_req_msg_fun() -> + fun(M) -> + otp_4836_mgc_verify_notify_req_msg(M) + end. +-endif. + +otp_4836_mgc_verify_notify_req_msg(#'MegacoMessage'{mess = Mess} = M) -> + #'Message'{messageBody = Body} = Mess, + {transactions, [Trans]} = Body, + {transactionRequest, TR} = Trans, + #'TransactionRequest'{actions = [AR]} = TR, + #'ActionRequest'{commandRequests = [CR1,CR2]} = AR, + #'CommandRequest'{command = Cmd1} = CR1, + {notifyReq, NR1} = Cmd1, + #'NotifyRequest'{observedEventsDescriptor = OED1} = NR1, + #'ObservedEventsDescriptor'{observedEventLst = [OE1]} = OED1, + #'ObservedEvent'{eventName = "al/of"} = OE1, + #'CommandRequest'{command = Cmd2} = CR2, + {notifyReq, NR2} = Cmd2, + #'NotifyRequest'{observedEventsDescriptor = OED2} = NR2, + #'ObservedEventsDescriptor'{observedEventLst = [OE2]} = OED2, + #'ObservedEvent'{eventName = "al/of"} = OE2, + {ok, M}; +otp_4836_mgc_verify_notify_req_msg(M) -> + {error, {invalid_message, M}}. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_5805(suite) -> + []; +otp_5805(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, otp_5805), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = otp_5805_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = + megaco_test_megaco_generator:exec(Mgc, MgcEvSeq, timer:minutes(1)), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("start the MG simulator (generator)"), + {ok, Mg} = megaco_test_tcp_generator:start_link("MG", MgNode), + + d("create the MG event sequence"), + MgEvSeq = otp_5805_mg_event_sequence(text, tcp), + + d("start the MG simulation"), + {ok, MgId} = + megaco_test_tcp_generator:exec(Mg, MgEvSeq, timer:minutes(1)), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_tcp_generator:stop(Mg), + + i("done", []), + ok. + + +-ifdef(megaco_hipe_special). +-define(otp_5805_mg_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(otp_5805_mg_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(otp_5805_mg_verify_service_change_rep_msg_fun(), + {?MODULE, otp_5805_mg_verify_service_change_rep_msg, []}). +-define(otp_5805_mg_verify_error_descriptor_msg_fun(), + {?MODULE, otp_5805_mg_verify_error_descriptor_msg, []}). +-else. +-define(otp_5805_mg_decode_msg_fun(Mod, Conf), + otp_5805_mg_decode_msg_fun(Mod, Conf)). +-define(otp_5805_mg_encode_msg_fun(Mod, Conf), + otp_5805_mg_encode_msg_fun(Mod, Conf)). +-define(otp_5805_mg_verify_service_change_rep_msg_fun(), + otp_5805_mg_verify_service_change_rep_msg_fun()). +-define(otp_5805_mg_verify_error_descriptor_msg_fun(), + otp_5805_mg_verify_error_descriptor_msg_fun()). +-endif. + +otp_5805_mg_event_sequence(text, tcp) -> + DecodeFun = ?otp_5805_mg_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ?otp_5805_mg_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mg"}, + ServiceChangeReq = otp_5805_mg_service_change_request_msg(Mid, 1, 0), + NotifyReqNNV = otp_5805_mg_notify_request_msg("1"), + NotifyReqUV = otp_5805_mg_notify_request_msg("4"), + ServiceChangeReplyVerifyFun = + ?otp_5805_mg_verify_service_change_rep_msg_fun(), + EDVerify = + ?otp_5805_mg_verify_error_descriptor_msg_fun(), +%% ServiceChangeReplyVerifyFun = +%% otp_5805_mg_verify_service_change_rep_msg_fun(), +%% EDVerify = otp_5805_mg_verify_error_descriptor_msg_fun(), + MgEvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {connect, 2944}, + + {send, "service-change-request", ServiceChangeReq}, + {expect_receive, "service-change-reply", {ServiceChangeReplyVerifyFun, 5000}}, + {sleep, 1000}, + {send, "notify request (not negotiated version)", NotifyReqNNV}, + {expect_receive, "error-descriptor", EDVerify}, + {sleep, 1000}, + {send, "notify request (unsupported version)", NotifyReqUV}, + {expect_receive, "error-descriptor", EDVerify}, + + {expect_nothing, 4000}, + disconnect + ], + MgEvSeq. + +-ifndef(megaco_hipe_special). +otp_5805_mg_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +otp_5805_mg_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +otp_5805_mg_verify_service_change_rep_msg_fun() -> + fun(M) -> + otp_5805_mg_verify_service_change_rep_msg(M) + end. +-endif. + +otp_5805_mg_verify_service_change_rep_msg(#'MegacoMessage'{mess = Mess} = M) -> + case Mess of + #'Message'{version = 1, + mId = _MgMid, + messageBody = Body} -> + case Body of + {transactions, [Trans]} -> + case Trans of + {transactionReply, TR} -> + case TR of + #'TransactionReply'{transactionId = _Tid, + immAckRequired = asn1_NOVALUE, + transactionResult = Res} -> + case Res of + {actionReplies, [AR]} -> + case AR of + #'ActionReply'{contextId = _Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CR]} -> + case CR of + {serviceChangeReply, SCR} -> + case SCR of + #'ServiceChangeReply'{ + terminationID = _TermID, + serviceChangeResult = SCRes} -> + case SCRes of + {serviceChangeResParms, SCRP} -> + case SCRP of + #'ServiceChangeResParm'{ + serviceChangeMgcId = _MgcMid, + serviceChangeVersion = 2} -> + {ok, M}; + _ -> + {error, {invalid_scrp, SCRP}} + end; + _ -> + {error, {invalid_scres, SCRes}} + end; + _ -> + {error, {invalid_scr, SCR}} + end; + _ -> + {error, {invalid_cr, CR}} + end; + _ -> + {error, {invalid_ar, AR}} + end; + _ -> + {error, {invalid_tres, Res}} + end; + _ -> + {error, {invalid_tr, TR}} + end; + _ -> + {error, {invalid_trans, Trans}} + end; + _ -> + {error, {invalid_body, Body}} + end; + _ -> + {error, {invalid_mess, Mess}} + end; +otp_5805_mg_verify_service_change_rep_msg(M) -> + {error, {invalid_message, M}}. + + +-ifndef(megaco_hipe_special). +otp_5805_mg_verify_error_descriptor_msg_fun() -> + fun(M) -> + otp_5805_mg_verify_error_descriptor_msg(M) + end. +-endif. + +otp_5805_mg_verify_error_descriptor_msg(#'MegacoMessage'{mess = Mess} = M) -> + case Mess of + #'Message'{version = 2, + mId = _MgMid, + messageBody = Body} -> + io:format("otp_5805_mg_verify_error_descriptor_msg_fun -> ok" + "~n Body: ~p" + "~n", [Body]), + case Body of + {messageError, ED} -> + case ED of + #'ErrorDescriptor'{ + errorCode = ?megaco_version_not_supported} -> + {ok, M}; + _ -> + {error, {invalid_ed, ED}} + end; + _ -> + {error, {invalid_body, Body}} + end; + _ -> + {error, {invalid_mess, Mess}} + end; +otp_5805_mg_verify_error_descriptor_msg(M) -> + {error, {invalid_message, M}}. + +otp_5805_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, 2, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp_5805_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = otp_5805_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(1, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +%% otp_5805_mg_notify_request_ar(Rid, Tid, Cid) -> +%% TT = cre_timeNotation("19990729", "22000000"), +%% Ev = cre_obsEvent("al/of", TT), +%% EvsDesc = cre_obsEvsDesc(Rid, [Ev]), +%% NR = cre_notifyReq([Tid], EvsDesc), +%% CMD = cre_command(NR), +%% CR = cre_cmdReq(CMD), +%% cre_actionReq(Cid, [CR]). + +otp_5805_mg_notify_request_msg(V) -> + M = +"MEGACO/" ++ V ++ " mg +Transaction = 2 { + Context = 1 { + Notify = 00000000/00000000/01101101 { + ObservedEvents = 1 { + 19990729T22000000:al/of + } + } + } +}", + list_to_binary(M). + + +%% +%% MGC generator stuff +%% + +-ifdef(megaco_hipe_special). +-define(otp_5805_mgc_verify_handle_connect_fun(), + {?MODULE, otp_5805_mgc_verify_handle_connect, []}). +-define(otp_5805_mgc_verify_service_change_req_fun(Mid), + {?MODULE, otp_5805_mgc_verify_service_change_req, [Mid]}). +-define(otp_5805_mgc_verify_handle_syntax_error_fun(), + {?MODULE, otp_5805_mgc_verify_handle_syntax_error, []}). +-define(otp_5805_mgc_verify_handle_disconnect_fun(), + {?MODULE, otp_5805_mgc_verify_handle_disconnect, []}). +-else. +-define(otp_5805_mgc_verify_handle_connect_fun(), + fun otp_5805_mgc_verify_handle_connect/1). +-define(otp_5805_mgc_verify_service_change_req_fun(Mid), + otp_5805_mgc_verify_service_change_req_fun(Mid)). +-define(otp_5805_mgc_verify_handle_syntax_error_fun(), + fun otp_5805_mgc_verify_handle_syntax_error/1). +-define(otp_5805_mgc_verify_handle_disconnect_fun(), + fun otp_5805_mgc_verify_handle_disconnect/1). +-endif. + +otp_5805_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?otp_5805_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?otp_5805_mgc_verify_service_change_req_fun(Mid), + SyntaxErrorVerify1 = ?otp_5805_mgc_verify_handle_syntax_error_fun(), + SyntaxErrorVerify2 = ?otp_5805_mgc_verify_handle_syntax_error_fun(), + DiscoVerify = ?otp_5805_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun otp_5805_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = otp_5805_mgc_verify_service_change_req_fun(Mid), +%% SyntaxErrorVerify1 = fun otp_5805_mgc_verify_handle_syntax_error/1, +%% SyntaxErrorVerify2 = fun otp_5805_mgc_verify_handle_syntax_error/1, +%% DiscoVerify = fun otp_5805_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_conn_info, all}, + {megaco_callback, handle_trans_request_sc, ServiceChangeReqVerify}, + {megaco_update_conn_info, protocol_version, 2}, + {megaco_callback, handle_syntax_error, SyntaxErrorVerify1}, + {megaco_callback, handle_syntax_error, SyntaxErrorVerify2}, + {megaco_callback, handle_disconnect, DiscoVerify}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + +otp_5805_mgc_verify_handle_connect({handle_connect, CH, 1}) -> + io:format("otp_5805_mgc_verify_handle_connect -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +otp_5805_mgc_verify_handle_connect({handle_connect, CH, V}) -> + io:format("otp_5805_mgc_verify_handle_connect -> unexpected version" + "~n CH: ~p" + "~n V: ~p" + "~n", [CH, V]), + {error, {unexpected_version, V}, ok}; +otp_5805_mgc_verify_handle_connect(Else) -> + {error, Else, ok}. + + +-ifndef(megaco_hipe_special). +otp_5805_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + otp_5805_mgc_verify_service_change_req(Ev, Mid) + end. +-endif. + +otp_5805_mgc_verify_service_change_req({handle_trans_request, _, V, [AR]}, + Mid) -> + io:format("otp_5805_mgc_verify_service_change_req -> ok so far" + "~n V: ~p" + "~n", [V]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeVersion = 2, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [otp_5805_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = otp_5805_err_desc(Parms), + ErrReply = + {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = otp_5805_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = otp_5805_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = otp_5805_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = otp_5805_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +otp_5805_mgc_verify_service_change_req(Else, _Mid) -> + ED = otp_5805_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +otp_5805_mgc_verify_handle_syntax_error({handle_syntax_error, CH, _, ED}) + when is_record(ED, 'ErrorDescriptor') -> + io:format("otp_5805_mgc_verify_handle_syntax_error -> ok so far" + "~n CH: ~p" + "~n ED: ~p" + "~n", [CH, ED]), + case ED of + #'ErrorDescriptor'{errorCode = ?megaco_version_not_supported} -> + {ok, CH, reply}; + #'ErrorDescriptor'{errorCode = Code} -> + {error, {invalid_errorCode, Code}, ok} + end; +otp_5805_mgc_verify_handle_syntax_error(Else) -> + io:format("otp_5805_mgc_verify_handle_syntax_error -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp_5805_mgc_verify_handle_disconnect({handle_disconnect, CH, V, _R}) -> + io:format("otp_5805_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n V: ~p" + "~n _R: ~p" + "~n", [CH, V, _R]), + {ok, CH, ok}; +otp_5805_mgc_verify_handle_disconnect(Else) -> + io:format("otp_5805_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp_5805_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid, 2), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +%% otp_5805_mgc_notify_reply_ar(Cid, TermId) -> +%% NR = cre_notifyReply([TermId]), +%% CR = cre_cmdReply(NR), +%% cre_actionReply(Cid, [CR]). + + +otp_5805_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_5881(suite) -> + []; +otp_5881(Config) when is_list(Config) -> + ?SKIP("deprecated by OTP-5887"), + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, otp_5881), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("start the MGC simulator (generator)"), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("create the MGC event sequence"), + MgcEvSeq = otp_5881_mgc_event_sequence(text, tcp), + + d("start the MGC simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("[MG] start"), + MgMid = {deviceName, "mg"}, + ReqTmr = #megaco_incr_timer{wait_for = 3000, + factor = 1, + incr = 0, + max_retries = 3}, + %% 5000, %% Does not matter since we will not use this anyway... + LongReqTmr = #megaco_incr_timer{wait_for = 3000, + factor = 1, + incr = 0, + max_retries = 3}, + PendingTmr = 10000, + ReplyTmr = 16000, + MgConfig = [{request_timer, ReqTmr}, + {long_request_timer, LongReqTmr}, + {pending_timer, PendingTmr}, + {reply_timer, ReplyTmr}], + {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY), + + i("[MG] verify transaction-id: undefined_serial"), + otp_5881_verify_trans_id(Mg, undefined_serial), + + i("[MG] connect to the MGC (service change)"), + ServChRes = ?MG_SERV_CHANGE(Mg), + d("service change result: ~p", [ServChRes]), + + i("[MG] verify transaction-id: 1"), + otp_5881_verify_trans_id(Mg, 1), + + d("[MG] send the notify"), + {ok, Reply} = (catch ?MG_NOTIF_RAR(Mg)), + {1, {ok, [AR]}} = Reply, + d("[MG] ActionReply: ~p", [AR]), + + i("[MG] verify transaction-id: 2"), + otp_5881_verify_trans_id(Mg, 2), + + d("await the generator reply"), + await_completion([MgcId]), + + %% Tell MG to stop + i("[MG] stop"), + ?MG_STOP(Mg), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + i("done", []), + ok. + +otp_5881_verify_trans_id(Mg, Expected) -> + case ?MG_CONN_INFO(Mg, trans_id) of + Expected -> + ok; + ErroneousValue -> + throw({unexpected_transaction_id_value, ErroneousValue, Expected}) + end. + + +-ifdef(megaco_hipe_special). +-define(otp_5881_mgc_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(otp_5881_mgc_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(otp_5881_mgc_verify_service_change_req_msg_fun(), + {?MODULE, otp_5881_mgc_verify_service_change_req_msg, []}). +-define(otp_5881_mgc_verify_notify_req_msg_fun(), + {?MODULE, otp_5881_mgc_verify_notify_req_msg, []}). +-else. +-define(otp_5881_mgc_decode_msg_fun(Mod, Conf), + otp_5881_mgc_decode_msg_fun(Mod, Conf)). +-define(otp_5881_mgc_encode_msg_fun(Mod, Conf), + otp_5881_mgc_encode_msg_fun(Mod, Conf)). +-define(otp_5881_mgc_verify_service_change_req_msg_fun(), + otp_5881_mgc_verify_service_change_req_msg_fun()). +-define(otp_5881_mgc_verify_notify_req_msg_fun(), + otp_5881_mgc_verify_notify_req_msg_fun()). +-endif. + +otp_5881_mgc_event_sequence(text, tcp) -> + DecodeFun = ?otp_5881_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ?otp_5881_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"ctrl"}, + ServiceChangeReply = otp_5881_service_change_reply_msg(Mid, 1, 0), + TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReply = otp_5881_notify_reply_msg(Mid, 2, 0, TermId), + %% Pending = otp_5881_pending_msg(Mid,2), + ServiceChangeVerifyFun = ?otp_5881_mgc_verify_service_change_req_msg_fun(), + NotifyReqVerifyFun = ?otp_5881_mgc_verify_notify_req_msg_fun(), +%% ServiceChangeVerifyFun = otp_5881_verify_service_change_req_msg_fun(), +%% NotifyReqVerifyFun = otp_5881_verify_notify_request_fun(), + MgcEvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-request", {ServiceChangeVerifyFun, 10000}}, + {send, "service-change-reply", ServiceChangeReply}, + {expect_receive, "notify-request", {NotifyReqVerifyFun, 10000}}, + {send, "notify-reply", NotifyReply}, + {sleep, 2000} + ], + MgcEvSeq. + +-ifndef(megaco_hipe_special). +otp_5881_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +otp_5881_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. + +otp_5881_service_change_reply_msg(Mid, TransId, Cid) -> + SCRP = #'ServiceChangeResParm'{serviceChangeMgcId = Mid}, + SCRPs = {serviceChangeResParms,SCRP}, + Root = #megaco_term_id{id = ["root"]}, + SCR = #'ServiceChangeReply'{terminationID = [Root], + serviceChangeResult = SCRPs}, + CR = {serviceChangeReply, SCR}, + otp_5881_msg(Mid, TransId, CR, Cid). + +otp_5881_notify_reply_msg(Mid, TransId, Cid, TermId) -> + NR = #'NotifyReply'{terminationID = [TermId]}, + CR = {notifyReply, NR}, + otp_5881_msg(Mid, TransId, CR, Cid). + +otp_5881_msg(Mid, TransId, CR, Cid) -> + AR = #'ActionReply'{contextId = Cid, + commandReply = [CR]}, + ARs = {actionReplies, [AR]}, + TR = #'TransactionReply'{transactionId = TransId, + transactionResult = ARs}, + Body = {transactions, [{transactionReply, TR}]}, + Mess = #'Message'{version = 1, + mId = Mid, + messageBody = Body}, + #'MegacoMessage'{mess = Mess}. + + +%% otp_5881_pending_msg(Mid, TransId) -> +%% TP = #'TransactionPending'{transactionId = TransId}, +%% Body = {transactions, [{transactionPending, TP}]}, +%% Mess = #'Message'{version = 1, +%% mId = Mid, +%% messageBody = Body}, +%% #'MegacoMessage'{mess = Mess}. + + +-ifndef(megaco_hipe_special). +otp_5881_mgc_verify_service_change_req_msg_fun() -> + fun(M) -> + otp_5881_mgc_verify_service_change_req_msg(M) + end. +-endif. + +otp_5881_mgc_verify_service_change_req_msg( + #'MegacoMessage'{mess = Mess} = M) -> + #'Message'{version = _V, + mId = _Mid, + messageBody = Body} = Mess, + {transactions, [Trans]} = Body, + {transactionRequest, TR} = Trans, + #'TransactionRequest'{transactionId = _Tid, + actions = [AR]} = TR, + #'ActionRequest'{contextId = _Cid, + contextRequest = _CtxReq, + contextAttrAuditReq = _CtxAar, + commandRequests = [CR]} = AR, + #'CommandRequest'{command = Cmd, + optional = _Opt, + wildcardReturn = _WR} = CR, + {serviceChangeReq, SCR} = Cmd, + #'ServiceChangeRequest'{terminationID = _TermID, + serviceChangeParms = SCP} = SCR, + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} = SCP, + {ok, M}; +otp_5881_mgc_verify_service_change_req_msg(M) -> + {error, {invalid_message, M}}. + +-ifndef(megaco_hipe_special). +otp_5881_mgc_verify_notify_req_msg_fun() -> + fun(M) -> + otp_5881_mgc_verify_notify_req_msg(M) + end. +-endif. + +otp_5881_mgc_verify_notify_req_msg(#'MegacoMessage'{mess = Mess} = M) -> + #'Message'{messageBody = Body} = Mess, + {transactions, [Trans]} = Body, + {transactionRequest, TR} = Trans, + #'TransactionRequest'{actions = [AR]} = TR, + #'ActionRequest'{commandRequests = [CR1,CR2]} = AR, + #'CommandRequest'{command = Cmd1} = CR1, + {notifyReq, NR1} = Cmd1, + #'NotifyRequest'{observedEventsDescriptor = OED1} = NR1, + #'ObservedEventsDescriptor'{observedEventLst = [OE1]} = OED1, + #'ObservedEvent'{eventName = "al/of"} = OE1, + #'CommandRequest'{command = Cmd2} = CR2, + {notifyReq, NR2} = Cmd2, + #'NotifyRequest'{observedEventsDescriptor = OED2} = NR2, + #'ObservedEventsDescriptor'{observedEventLst = [OE2]} = OED2, + #'ObservedEvent'{eventName = "al/of"} = OE2, + {ok, M}; +otp_5881_mgc_verify_notify_req_msg(M) -> + {error, {invalid_message, M}}. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_5887(suite) -> + []; +otp_5887(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, otp_5887), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("start the MGC simulator (generator)"), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("create the MGC event sequence"), + MgcEvSeq = otp_5887_mgc_event_sequence(text, tcp), + + d("start the MGC simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("[MG] start"), + MgMid = {deviceName, "mg"}, + ReqTmr = #megaco_incr_timer{wait_for = 3000, + factor = 1, + incr = 0, + max_retries = 3}, + %% 5000, %% Does not matter since we will not use this anyway... + LongReqTmr = #megaco_incr_timer{wait_for = 3000, + factor = 1, + incr = 0, + max_retries = 3}, + PendingTmr = 10000, + ReplyTmr = 16000, + MgConfig = [{request_timer, ReqTmr}, + {long_request_timer, LongReqTmr}, + {pending_timer, PendingTmr}, + {reply_timer, ReplyTmr}], + {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY), + + i("[MG] conn info: ~n~p", [?MG_CONN_INFO(Mg, all)]), + + i("[MG] verify conn transaction-id: 1"), + otp_5887_verify_conn_trans_id(Mg, 1), + + i("[MG] user info: ~n~p", [?MG_USER_INFO(Mg, all)]), + + i("[MG] verify user transaction-id: undefined_serial"), + otp_5887_verify_user_trans_id(Mg, undefined_serial), + + i("[MG] connect to the MGC (service change)"), + ServChRes = ?MG_SERV_CHANGE(Mg), + d("service change result: ~p", [ServChRes]), + + i("[MG] conn info: ~n~p", [?MG_CONN_INFO(Mg, all)]), + + i("[MG] verify conn transaction-id: 2"), + otp_5887_verify_conn_trans_id(Mg, 2), + + i("[MG] user info: ~n~p", [?MG_USER_INFO(Mg, all)]), + + i("[MG] verify user transaction-id: 1"), + otp_5887_verify_user_trans_id(Mg, 1), + + d("[MG] send the notify"), + {ok, Reply} = (catch ?MG_NOTIF_RAR(Mg)), + {1, {ok, [AR]}} = Reply, + d("[MG] ActionReply: ~p", [AR]), + + i("[MG] conn info: ~n~p", [?MG_CONN_INFO(Mg, all)]), + + i("[MG] verify conn transaction-id: 3"), + otp_5887_verify_conn_trans_id(Mg, 3), + + i("[MG] user info: ~n~p", [?MG_USER_INFO(Mg, all)]), + + i("[MG] verify user transaction-id: 2"), + otp_5887_verify_user_trans_id(Mg, 2), + + d("await the generator reply"), + await_completion([MgcId]), + + %% Tell MG to stop + i("[MG] stop"), + ?MG_STOP(Mg), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + i("done", []), + ok. + + +otp_5887_verify_conn_trans_id(Mg, Expected) -> + F = fun() -> (catch ?MG_CONN_INFO(Mg, trans_id)) end, + otp_5887_verify_trans_id(F, Expected). + +otp_5887_verify_user_trans_id(Mg, Expected) -> + F = fun() -> (catch ?MG_USER_INFO(Mg, trans_id)) end, + otp_5887_verify_trans_id(F, Expected). + +otp_5887_verify_trans_id(F, Expected) -> + case F() of + Expected -> + ok; + ErroneousValue -> + throw({unexpected_transaction_id_value, ErroneousValue, Expected}) + end. + + +-ifdef(megaco_hipe_special). +-define(otp_5887_mgc_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(otp_5887_mgc_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(otp_5887_mgc_verify_service_change_req_msg_fun(), + {?MODULE, otp_5887_mgc_verify_service_change_req_msg, []}). +-define(otp_5887_mgc_verify_notify_req_msg_fun(), + {?MODULE, otp_5887_mgc_verify_notify_req_msg, []}). +-else. +-define(otp_5887_mgc_decode_msg_fun(Mod, Conf), + otp_5887_mgc_decode_msg_fun(Mod, Conf)). +-define(otp_5887_mgc_encode_msg_fun(Mod, Conf), + otp_5887_mgc_encode_msg_fun(Mod, Conf)). +-define(otp_5887_mgc_verify_service_change_req_msg_fun(), + otp_5887_mgc_verify_service_change_req_msg_fun()). +-define(otp_5887_mgc_verify_notify_req_msg_fun(), + otp_5887_mgc_verify_notify_req_msg_fun()). +-endif. + +otp_5887_mgc_event_sequence(text, tcp) -> + DecodeFun = ?otp_5887_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ?otp_5887_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"ctrl"}, + ServiceChangeReply = otp_5887_service_change_reply_msg(Mid, 1, 0), + TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReply = otp_5887_notify_reply_msg(Mid, 2, 0, TermId), + ServiceChangeVerifyFun = ?otp_5887_mgc_verify_service_change_req_msg_fun(), + NotifyReqVerifyFun = ?otp_5887_mgc_verify_notify_req_msg_fun(), +%% ServiceChangeVerifyFun = otp_5887_verify_service_change_req_msg_fun(), +%% NotifyReqVerifyFun = otp_5887_verify_notify_request_fun(), + MgcEvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-request", {ServiceChangeVerifyFun, 10000}}, + {send, "service-change-reply", ServiceChangeReply}, + {expect_receive, "notify-request", {NotifyReqVerifyFun, 10000}}, + {send, "notify-reply", NotifyReply}, + {sleep, 2000} + ], + MgcEvSeq. + +otp_5887_service_change_reply_msg(Mid, TransId, Cid) -> + SCRP = #'ServiceChangeResParm'{serviceChangeMgcId = Mid}, + SCRPs = {serviceChangeResParms,SCRP}, + Root = #megaco_term_id{id = ["root"]}, + SCR = #'ServiceChangeReply'{terminationID = [Root], + serviceChangeResult = SCRPs}, + CR = {serviceChangeReply, SCR}, + otp_5887_msg(Mid, TransId, CR, Cid). + +otp_5887_notify_reply_msg(Mid, TransId, Cid, TermId) -> + NR = #'NotifyReply'{terminationID = [TermId]}, + CR = {notifyReply, NR}, + otp_5887_msg(Mid, TransId, CR, Cid). + +otp_5887_msg(Mid, TransId, CR, Cid) -> + AR = #'ActionReply'{contextId = Cid, + commandReply = [CR]}, + ARs = {actionReplies, [AR]}, + TR = #'TransactionReply'{transactionId = TransId, + transactionResult = ARs}, + Body = {transactions, [{transactionReply, TR}]}, + Mess = #'Message'{version = 1, + mId = Mid, + messageBody = Body}, + #'MegacoMessage'{mess = Mess}. + + +%% otp_5887_pending_msg(Mid, TransId) -> +%% TP = #'TransactionPending'{transactionId = TransId}, +%% Body = {transactions, [{transactionPending, TP}]}, +%% Mess = #'Message'{version = 1, +%% mId = Mid, +%% messageBody = Body}, +%% #'MegacoMessage'{mess = Mess}. + + +-ifndef(megaco_hipe_special). +otp_5887_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. +-endif. +%% otp_5887_mgc_encode_msg_fun(Mod, Conf, Ver) -> +%% fun(M) -> +%% encode_msg(M, Mod, Conf, Ver) +%% end. + +-ifndef(megaco_hipe_special). +otp_5887_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. +%% otp_5887_mgc_decode_msg_fun(Mod, Conf, Ver) -> +%% fun(M) -> +%% decode_msg(M, Mod, Conf, Ver) +%% end. + +-ifndef(megaco_hipe_special). +otp_5887_mgc_verify_service_change_req_msg_fun() -> + fun(M) -> + otp_5887_mgc_verify_service_change_req_msg(M) + end. +-endif. + +otp_5887_mgc_verify_service_change_req_msg( + #'MegacoMessage'{mess = Mess} = M) -> + #'Message'{version = _V, + mId = _Mid, + messageBody = Body} = Mess, + {transactions, [Trans]} = Body, + {transactionRequest, TR} = Trans, + #'TransactionRequest'{transactionId = _Tid, + actions = [AR]} = TR, + #'ActionRequest'{contextId = _Cid, + contextRequest = _CtxReq, + contextAttrAuditReq = _CtxAar, + commandRequests = [CR]} = AR, + #'CommandRequest'{command = Cmd, + optional = _Opt, + wildcardReturn = _WR} = CR, + {serviceChangeReq, SCR} = Cmd, + #'ServiceChangeRequest'{terminationID = _TermID, + serviceChangeParms = SCP} = SCR, + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} = SCP, + {ok, M}; +otp_5887_mgc_verify_service_change_req_msg(M) -> + {error, {invalid_message, M}}. + + +-ifndef(megaco_hipe_special). +otp_5887_mgc_verify_notify_req_msg_fun() -> + fun(M) -> + otp_5887_mgc_verify_notify_req_msg(M) + end. +-endif. + +otp_5887_mgc_verify_notify_req_msg(#'MegacoMessage'{mess = Mess} = M) -> + #'Message'{messageBody = Body} = Mess, + {transactions, [Trans]} = Body, + {transactionRequest, TR} = Trans, + #'TransactionRequest'{actions = [AR]} = TR, + #'ActionRequest'{commandRequests = [CR1,CR2]} = AR, + #'CommandRequest'{command = Cmd1} = CR1, + {notifyReq, NR1} = Cmd1, + #'NotifyRequest'{observedEventsDescriptor = OED1} = NR1, + #'ObservedEventsDescriptor'{observedEventLst = [OE1]} = OED1, + #'ObservedEvent'{eventName = "al/of"} = OE1, + #'CommandRequest'{command = Cmd2} = CR2, + {notifyReq, NR2} = Cmd2, + #'NotifyRequest'{observedEventsDescriptor = OED2} = NR2, + #'ObservedEventsDescriptor'{observedEventLst = [OE2]} = OED2, + #'ObservedEvent'{eventName = "al/of"} = OE2, + {ok, M}; +otp_5887_mgc_verify_notify_req_msg(M) -> + {error, {invalid_message, M}}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_6253(suite) -> + []; +otp_6253(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + + put(verbosity, debug), + put(tc, otp_6253), + + d("otp_6253 -> start test case controller",[]), + ok = megaco_tc_controller:start_link(), + + PrelMid = preliminary_mid, + MgMid = ipv4_mid(4711), + + ?VERIFY(ok, application:start(megaco)), + ?VERIFY(ok, megaco:start_user(MgMid, [{send_mod, megaco_mess_user_test}, + {request_timer, infinity}, + {reply_timer, infinity}])), + + MgRH = user_info(MgMid, receive_handle), + {ok, PrelCH} = ?VERIFY({ok, _}, megaco:connect(MgRH, PrelMid, sh, self())), + + connections([PrelCH]), + ?VERIFY([PrelCH], megaco:user_info(MgMid, connections)), + + SC = service_change_request(), + + %% Instruct the transport module to fail all send_message + d("otp_6253 -> instruct transport module to fail message send",[]), + ok = megaco_tc_controller:insert(allow_send_message, {fail, otp_6253}), + + ?VERIFY({1, {error, {send_message_failed, otp_6253}}}, + megaco:call(PrelCH, [SC], [])), + + sleep(1000), + + %% Instruct the transport module to cancel all send_message + d("otp_6253 -> instruct transport module to cancel message send",[]), + ok = megaco_tc_controller:insert(allow_send_message, {cancel, otp_6253}), + + ?VERIFY({1, {error, {send_message_cancelled, otp_6253}}}, + megaco:call(PrelCH, [SC], [])), + + ?VERIFY(ok, megaco:disconnect(PrelCH, shutdown)), + + ?VERIFY(ok, megaco:stop_user(MgMid)), + ?VERIFY(ok, application:stop(megaco)), + ?RECEIVE([]), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_6275(suite) -> + []; +otp_6275(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, otp_6275), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("start the MGC simulator (generator)"), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("create the MGC event sequence"), + MgcEvSeq = otp_6275_mgc_event_sequence(text, tcp), + + d("start the MGC simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = otp_6275_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("[MGC] await the generator reply"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp_6275_mg_verify_handle_connect_fun(), + {?MODULE, otp_6275_mg_verify_handle_connect, []}). +-define(otp_6275_mg_verify_notify_req_fun(), + {?MODULE, otp_6275_mg_verify_notify_req, []}). +-define(otp_6275_mg_verify_handle_trans_rep_fun(), + {?MODULE, otp_6275_mg_verify_handle_trans_rep, []}). +-else. +-define(otp_6275_mg_verify_handle_connect_fun(), + otp_6275_mg_verify_handle_connect_fun()). +-define(otp_6275_mg_verify_notify_req_fun(), + otp_6275_mg_verify_notify_req_fun()). +-define(otp_6275_mg_verify_handle_trans_rep_fun(), + otp_6275_mg_verify_handle_trans_rep_fun()). +-endif. + +otp_6275_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + otp_6275_mg_event_sequence2(Mid, RI). + +otp_6275_mg_event_sequence2(Mid, RI) -> + ServiceChangeReq = [otp_6275_mg_service_change_request_ar(Mid, 1)], + _Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + ConnectVerify = ?otp_6275_mg_verify_handle_connect_fun(), + NotifyReqVerify = ?otp_6275_mg_verify_notify_req_fun(), + TransReplyVerify = ?otp_6275_mg_verify_handle_trans_rep_fun(), +%% ConnectVerify = otp_6275_mg_verify_handle_connect_fun(), +%% NotifyReqVerify = otp_6275_mg_verify_notify_request_fun(), +%% TransReplyVerify = otp_6275_mg_verify_trans_reply_fun(), + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + %% {megaco_update_user_info, recv_pending_limit, 4}, + {megaco_update_user_info, request_timer, 3000}, + start_transport, + {megaco_trace, disable}, %%100}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_reply, TransReplyVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +-ifndef(megaco_hipe_special). +otp_6275_mg_verify_handle_connect_fun() -> + fun(Event) -> + (catch otp_6275_mg_verify_handle_connect(Event)) + end. +-endif. + +otp_6275_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("otp_6275_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +otp_6275_mg_verify_handle_connect(Else) -> + io:format("otp_6275_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +-ifndef(megaco_hipe_special). +otp_6275_mg_verify_notify_req_fun() -> + fun(Event) -> + (catch otp_6275_mg_verify_notify_req(Event)) + end. +-endif. + +otp_6275_mg_verify_notify_req( + {handle_trans_request, _CH, ?VERSION, [AR]}) -> + io:format("otp_6275_mg_verify_notify_req -> entry with" + "~n AR: ~p" + "~n", [AR]), + CR = + case AR of + #'ActionRequest'{commandRequests = [CmdReq]} -> + CmdReq; + _ -> + ET1 = lists:flatten( + io_lib:format("Invalid action request: ~w", [AR])), + EC1 = ?megaco_internal_gateway_error, + ED1 = #'ErrorDescriptor'{errorCode = EC1, + errorText = ET1}, + throw({error, {invalid_ActionRequest, AR}, {discard_ack, ED1}}) + end, + + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + ET2 = lists:flatten( + io_lib:format("Invalid command request: ~w", [CR])), + EC2 = ?megaco_internal_gateway_error, + ED2 = #'ErrorDescriptor'{errorCode = EC2, + errorText = ET2}, + throw({error, {invalid_CommandRequest, CR}, {discard_ack, ED2}}) + end, + + case Cmd of + {notifyReq, NotifyReq} -> + ET3 = "Unexpected request", + EC3 = ?megaco_transaction_req_received_before_servicechange_reply, + ED3 = #'ErrorDescriptor'{errorCode = EC3, + errorText = ET3}, + throw({ok, {ok, NotifyReq}, {discard_ack, ED3}}); + _ -> + ET4 = lists:flatten( + io_lib:format("Invalid command: ~w", [Cmd])), + EC4 = ?megaco_internal_gateway_error, + ED4 = #'ErrorDescriptor'{errorCode = EC4, + errorText = ET4}, + throw({error, {invalid_command, Cmd}, {discard_ack, ED4}}) + end; +otp_6275_mg_verify_notify_req({Tag, CH, Version, ARs}) -> + io:format("otp_6275_mg_verify_notify_req -> ok" + "~n Tag: ~p" + "~n CH: ~p" + "~n Version: ~p" + "~n ARs: ~p" + "~n", [Tag, CH, Version, ARs]), + {error, {invalid_event, {Tag, CH, Version, ARs}}, ok}; +otp_6275_mg_verify_notify_req(Else) -> + io:format("otp_6275_mg_verify_notify_req -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +-ifndef(megaco_hipe_special). +otp_6275_mg_verify_handle_trans_rep_fun() -> + fun(Event) -> + (catch otp_6275_mg_verify_handle_trans_rep(Event)) + end. +-endif. + +otp_6275_mg_verify_handle_trans_rep( + {handle_trans_reply, CH, ?VERSION, {error, timeout} = Error, _}) -> + io:format("otp_6275_mg_verify_trans_rep -> expected error" + "~n", []), + case CH of + #megaco_conn_handle{remote_mid = preliminary_mid} -> + {ok, Error, error}; + _ -> + {error, {unexpected_connection, CH}, error} + end; +otp_6275_mg_verify_handle_trans_rep( + {handle_trans_reply, _CH, ?VERSION, Error, _}) -> + io:format("otp_6275_mg_verify_handle_trans_rep -> unexpected error" + "~n Error: ~p" + "~n", [Error]), + {error, Error, error}; +otp_6275_mg_verify_handle_trans_rep(Else) -> + io:format("otp_6275_mg_verify_handle_trans_rep -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, error}. + +otp_6275_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp_6275_mgc_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(otp_6275_mgc_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(otp_6275_mgc_verify_service_change_req_msg_fun(), + {?MODULE, otp_6275_mgc_verify_service_change_req_msg, []}). +-define(otp_6275_mgc_verify_notify_rep_msg_fun(), + {?MODULE, otp_6275_mgc_verify_notify_rep_msg, []}). +-else. +-define(otp_6275_mgc_decode_msg_fun(Mod, Conf), + otp_6275_mgc_decode_msg_fun(Mod, Conf)). +-define(otp_6275_mgc_encode_msg_fun(Mod, Conf), + otp_6275_mgc_encode_msg_fun(Mod, Conf)). +-define(otp_6275_mgc_verify_service_change_req_msg_fun(), + otp_6275_mgc_verify_service_change_req_msg_fun()). +-define(otp_6275_mgc_verify_notify_rep_msg_fun(), + otp_6275_mgc_verify_notify_rep_msg_fun()). +-endif. + +otp_6275_mgc_event_sequence(text, tcp) -> + DecodeFun = ?otp_6275_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ?otp_6275_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"ctrl"}, + TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq = otp_6275_mgc_notify_request_msg(Mid, 2, 1, TermId, 1), + SCRVerifyFun = ?otp_6275_mgc_verify_service_change_req_msg_fun(), + NotifyReplyVerifyFun = ?otp_6275_mgc_verify_notify_rep_msg_fun(), +%% SCRVerifyFun = otp_6275_mgc_verify_service_change_req_fun(), +%% NotifyReplyVerifyFun = otp_6275_mgc_verify_notify_reply_fun(), + MgcEvSeq = + [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + + {expect_accept, any}, + {expect_receive, "service-change-request", {SCRVerifyFun, 5000}}, + {sleep, 1000}, %% Do _not_ send SC reply + {send, "notify-request", NotifyReq}, + {expect_receive, "request before sc reply", {NotifyReplyVerifyFun, 5000}}, + {sleep, 2000} + ], + MgcEvSeq. + +-ifndef(megaco_hipe_special). +otp_6275_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. +-endif. + +%% otp_6275_mgc_encode_msg_fun(Mod, Conf, Ver) -> +%% fun(M) -> +%% encode_msg(M, Mod, Conf, Ver) +%% end. + +-ifndef(megaco_hipe_special). +otp_6275_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. + +%% otp_6275_mgc_decode_msg_fun(Mod, Conf, Ver) -> +%% fun(M) -> +%% decode_msg(M, Mod, Conf, Ver) +%% end. + +-ifndef(megaco_hipe_special). +otp_6275_mgc_verify_service_change_req_msg_fun() -> + fun(M) -> + (catch otp_6275_mgc_verify_service_change_req_msg(M)) + end. +-endif. + +otp_6275_mgc_verify_service_change_req_msg( + #'MegacoMessage'{mess = Mess} = M) -> + io:format("otp_6275_mgc_verify_service_change_req_msg -> entry with" + "~n M: ~p" + "~n", [M]), + Body = + case Mess of + #'Message'{messageBody = MB} -> + MB; + _ -> + throw({error, {invalid_mess, Mess}}) + end, + + Trans = + case Body of + {transactions, [Transaction]} -> + Transaction; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + + TR = + case Trans of + {transactionRequest, TransReq} -> + TransReq; + _ -> + throw({error, {invalid_transaction, Trans}}) + end, + + AR = + case TR of + #'TransactionRequest'{actions = [ActionReq]} -> + ActionReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + + CR = + case AR of + #'ActionRequest'{commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_TransactionRequest, AR}}) + end, + + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_ActionRequest, CR}}) + end, + + SCR = + case Cmd of + {serviceChangeReq, ServiceChangeReq} -> + ServiceChangeReq; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + + SCP = + case SCR of + #'ServiceChangeRequest'{serviceChangeParms = ServiceChangeParms} -> + ServiceChangeParms; + _ -> + throw({error, {invalid_serviceChangeReq, SCR}}) + end, + + case SCP of + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeParms, SCP}} + end; +otp_6275_mgc_verify_service_change_req_msg(Crap) -> + {error, {invalid_MegacoMessage, Crap}}. + +-ifndef(megaco_hipe_special). +otp_6275_mgc_verify_notify_rep_msg_fun() -> + fun(M) -> + (catch otp_6275_mgc_verify_notify_rep_msg(M)) + end. +-endif. + +otp_6275_mgc_verify_notify_rep_msg(#'MegacoMessage'{mess = Mess} = M) -> + io:format("otp_6275_mgc_verify_notify_rep_msg -> entry with" + "~n M: ~p" + "~n", [M]), + Body = + case Mess of + #'Message'{messageBody = MB} -> + MB; + _ -> + throw({error, {invalid_mess, Mess}}) + end, + + Trans = + case Body of + {transactions, [Transaction]} -> + Transaction; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transaction, Trans}}) + end, + + Res = + case TR of + #'TransactionReply'{transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + + ED = + case Res of + {transactionError, ErrorDesc} -> + ErrorDesc; + _ -> + throw({error, {invalid_TransactionReply, Res}}) + end, + + case ED of + #'ErrorDescriptor'{errorCode = ?megaco_transaction_req_received_before_servicechange_reply} -> + ok; + _ -> + throw({error, {invalid_transactionError, ED}}) + end, + {ok, M}; +otp_6275_mgc_verify_notify_rep_msg(Crap) -> + {error, {invalid_MegacoMessage, Crap}}. + + +otp_6275_mgc_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp_6275_mgc_notify_request_msg(Mid, TransId, Cid, TermId, Rid) -> + AR = otp_6275_mgc_notify_request_ar(Rid, TermId, Cid), + otp_6275_msg(Mid, TransId, AR). + + +%% -- + +otp_6275_msg(Mid, TransId, AR) -> + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(1, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% This test case can only be run with the stack compiled with +%% the MEGACO_TEST_CODE flag. Therefor there is no point in +%% including this test case in the usual test suite +-ifdef(MEGACO_TEST_CODE). +otp_6276(suite) -> + []; +otp_6276(doc) -> + "OTP-6276: Cancel when receiving reply raise condition"; +otp_6276(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, otp_6276), + i("starting"), + + d("create sequence controller"), + CtrlPid = otp_6276_sequence_controller_start(), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = otp_6276_mgc_event_sequence(text, tcp, CtrlPid), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the tcp-simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("send start order to sequence controller"), + CtrlPid ! {start, self(), Mgc, Mg}, + + d("[MG] create the event sequence"), + MgEvSeq = otp_6276_mg_event_sequence(text, tcp, CtrlPid), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the megaco-simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +otp_6276_sequence_controller_start() -> + Self = self(), + erlang:spawn(fun() -> otp_6276_sequence_controller(Self) end). + +otp_6276_sequence_controller(Parent) -> + io:format("otp_6276_sequence_controller -> entry with" + "~n Parent: ~p" + "~n self(): ~p" + "~n", [Parent, self()]), + + d("start tc controller"), + put(dbg,true), + ok = megaco_tc_controller:start_link(), + + + %% Await MGC announcement + Mgc = + receive + {announce_mgc, MgcPid} -> + MgcPid + end, + io:format("otp_6276_sequence_controller -> MGC announced: " + "~n Mgc: ~p" + "~n", [Mgc]), + + %% Await MG announcement + Mg = + receive + {announce_mg, MgPid} -> + MgPid + end, + io:format("otp_6276_sequence_controller -> MG announced: " + "~n Mg: ~p" + "~n", [Mg]), + + %% Await request_received notification + receive + {notify_request_received, Mgc} -> + io:format("otp_6276_sequence_controller -> " + "request received from MGC (~p)" + "~n", [Mgc]), + ok + end, + + %% Make sure the cancel operation gets blocked midway: + megaco_tc_controller:insert(block_on_cancel, {cancel_block, self()}), + + %% Send start cancel order + io:format("otp_6276_sequence_controller -> " + "send cancel start order to MG (~p)" + "~n", [Mg]), + Mg ! {start_cancel, self()}, + receive + {started_cancel, Mg} -> + ok + end, + io:format("otp_6276_sequence_controller -> " + "cancel started - now await blocked" + "~n", []), + + receive + {cancel_block, Mg} -> + ok + end, + io:format("otp_6276_sequence_controller -> " + "cancel blocked - now instruct MGC to send notify reply" + "~n", []), + + %% Make sure the cancel operation gets blocked midway: + megaco_tc_controller:insert(block_on_reply, {reply_block, self()}), + + %% Send NR-send order + Mgc ! {notify_reply_send, self()}, + io:format("otp_6276_sequence_controller -> " + "NR-send order sent - now await notify reply blocked received" + "~n", []), + + ReplyPid = + receive + {reply_block, Pid, true} -> + io:format("otp_6276_sequence_controller -> " + "notify reply blocked received from ~p (true) - " + "now unblock cancel" + "~n", [Pid]), + %% Pid ! {reply_block, self()}, + Pid; + {reply_block, Pid, Info} -> + io:format("otp_6276_sequence_controller -> " + "notify reply blocked received from ~p: ~p" + "~n", [Pid, Info]), + Pid ! {reply_block, self()}, + exit({unexpected_reply_block_info, Info}) + end, + + %% Send cancel continue (unblock) order + Mg ! {cancel_block, self()}, + io:format("otp_6276_sequence_controller -> " + "cancel unblocked - now await notify-request cancelled" + "~n", []), + + %% Await request cancelled + receive + {notify_request_cancelled, Mg} -> + ok; + {notify_request_cancelled, Pid} -> + io:format("otp_6276_sequence_controller -> " + "notify-request cancelled - from ~p" + "~n", [Pid]), + ok + end, + io:format("otp_6276_sequence_controller -> " + "notify-request cancelled - now unblock notify-reply" + "~n", []), + + %% await notify reply result + ReplyPid ! {reply_block, self()}, + io:format("otp_6276_sequence_controller -> " + "notify-reply unblocked - now await unexpected trans" + "~n", []), + + %% Await unexpected trans + receive + {unexpected_trans, Mg, _Trans} -> + ok; + {unexpected_trans, Pid, _Trans} -> + io:format("otp_6276_sequence_controller -> " + "unexpected_trans - from ~p" + "~n", [Pid]), + ok + end, + io:format("otp_6276_sequence_controller -> " + "unexpected transaction received" + "~n", []), + + %% Await unexpected trans + Mgc ! {done, self()}, + receive + {done, Mgc} -> + ok + end, + io:format("otp_6276_sequence_controller -> MGC instructed we are done" + "~n", []), + + d("stop tc controller"), + megaco_tc_controller:stop(), + + io:format("otp_6276_sequence_controller -> done~n", []), + + exit(normal). + + +%% +%% MGC generator stuff +%% +otp_6276_mgc_event_sequence(text, tcp, Ctrl) -> + Mid = {deviceName,"ctrl"}, + EM = megaco_pretty_text_encoder, + EC = [], + otp_6276_mgc_event_sequence2(Mid, EM, EC, Ctrl). + +otp_6276_mgc_event_sequence2(Mid, EM, EC, Ctrl) -> + DecodeFun = otp_6276_mgc_decode_msg_fun(EM, EC), + EncodeFun = otp_6276_mgc_encode_msg_fun(EM, EC), + AnnounceMe = otp_6276_mgc_announce_fun(Ctrl), + ServiceChangeReqVerify = + otp_6276_mgc_verify_service_change_req_fun(Mid), + ServiceChangeReply = + otp_6276_mgc_service_change_reply_msg(Mid, 1, 0), + NotifyReqVerify = otp_6276_mgc_verify_notify_request_fun(Ctrl), + TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + AwaitNrSendOrder = otp_6276_mgc_await_notify_reply_send_order_fun(Ctrl), + NotifyReply = otp_6276_mgc_notify_reply_msg(Mid, 2, 0, TermId), + AwaitDoneOrder = otp_6276_mgc_await_done_order_fun(Ctrl), + EvSeq = + [ + {trigger, AnnounceMe}, + {debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-req", + {ServiceChangeReqVerify, 10000}}, + {send, "service-change-reply", ServiceChangeReply}, + {expect_receive, "notify-request", {NotifyReqVerify, 5000}}, + + {trigger, AwaitNrSendOrder}, + + {send, "notify-reply", NotifyReply}, + + {trigger, AwaitDoneOrder}, + + disconnect + ], + EvSeq. + +otp_6276_mgc_announce_fun(Pid) -> + fun() -> + Pid ! {announce_mgc, self()} + end. + +otp_6276_mgc_await_notify_reply_send_order_fun(Pid) -> + fun() -> + receive + {notify_reply_send, Pid} -> + Pid ! {notify_reply_send, self()} + end + end. + +otp_6276_mgc_await_done_order_fun(Pid) -> + fun() -> + receive + {done, Pid} -> + Pid ! {done, self()} + end + end. + +otp_6276_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:encode_message(Conf, M) + end. + +otp_6276_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:decode_message(Conf, M) + end. + +otp_6276_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + SCRP = #'ServiceChangeResParm'{serviceChangeMgcId = Mid}, + SCRPs = {serviceChangeResParms,SCRP}, + Root = #megaco_term_id{id = ["root"]}, + SCR = #'ServiceChangeReply'{terminationID = [Root], + serviceChangeResult = SCRPs}, + CR = {serviceChangeReply, SCR}, + otp_6276_mgc_msg(Mid, TransId, CR, Cid). + +otp_6276_mgc_notify_reply_msg(Mid, TransId, Cid, TermId) -> + NR = #'NotifyReply'{terminationID = [TermId]}, + CR = {notifyReply, NR}, + otp_6276_mgc_msg(Mid, TransId, CR, Cid). + +otp_6276_mgc_msg(Mid, TransId, CR, Cid) -> + AR = #'ActionReply'{contextId = Cid, + commandReply = [CR]}, + ARs = {actionReplies, [AR]}, + TR = #'TransactionReply'{transactionId = TransId, + transactionResult = ARs}, + Body = {transactions, [{transactionReply, TR}]}, + Mess = #'Message'{version = 1, + mId = Mid, + messageBody = Body}, + #'MegacoMessage'{mess = Mess}. + +otp_6276_mgc_pending_msg(Mid, TransId) -> + TP = #'TransactionPending'{transactionId = TransId}, + Body = {transactions, [{transactionPending, TP}]}, + Mess = #'Message'{version = 1, + mId = Mid, + messageBody = Body}, + #'MegacoMessage'{mess = Mess}. + +otp_6276_mgc_verify_service_change_req_fun(_) -> + fun(#'MegacoMessage'{mess = Mess} = M) -> + #'Message'{version = _V, + mId = _Mid, + messageBody = Body} = Mess, + {transactions, [Trans]} = Body, + {transactionRequest, TR} = Trans, + #'TransactionRequest'{transactionId = _Tid, + actions = [AR]} = TR, + #'ActionRequest'{contextId = _Cid, + contextRequest = _CtxReq, + contextAttrAuditReq = _CtxAar, + commandRequests = [CR]} = AR, + #'CommandRequest'{command = Cmd, + optional = _Opt, + wildcardReturn = _WR} = CR, + {serviceChangeReq, SCR} = Cmd, + #'ServiceChangeRequest'{terminationID = _TermID, + serviceChangeParms = SCP} = SCR, + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} = SCP, + {ok, M}; + (M) -> + {error, {invalid_message, M}} + end. + +otp_6276_mgc_verify_notify_request_fun(Pid) -> + fun(M) -> + (catch otp_6276_mgc_verify_notify_request(M, Pid)) + end. + +otp_6276_mgc_verify_notify_request(#'MegacoMessage'{mess = Mess} = M, + Pid) -> + io:format("otp_6276_mgc_verify_notify_request -> entry with" + "~n M: ~p" + "~n", [M]), + Body = + case Mess of + #'Message'{messageBody = MessageBody} -> + MessageBody; + _ -> + throw({error, {invalid_mess, Mess}}) + end, + + Trans = + case Body of + {transactions, [Transaction]} -> + Transaction; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + + TR = + case Trans of + {transactionRequest, TransReq} -> + TransReq; + _ -> + throw({error, {invalid_transaction, Trans}}) + end, + + AR = + case TR of + #'TransactionRequest'{actions = [Action]} -> + Action; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + + io:format("otp_6276_mgc_verify_notify_request -> " + "~n AR: ~p" + "~n", [AR]), + + CR = + case AR of + #'ActionRequest'{commandRequests = [CommandReq]} -> + CommandReq; + _ -> + throw({error, {invalid_TransactionRequest, AR}}) + end, + + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_ActionRequest, CR}}) + end, + + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + throw({error, {invalid_CommandRequest, Cmd}}) + end, + + OED = + case NR of + #'NotifyRequest'{observedEventsDescriptor = ObsEvDesc} -> + ObsEvDesc; + _ -> + throw({error, {invalid_notifyReq, NR}}) + end, + + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEv]} -> + ObsEv; + _ -> + throw({error, {invalid_NotifyRequest, OED}}) + end, + + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + ok; + _ -> + throw({error, {invalid_ObservedEventsDescriptor, OE}}) + end, + io:format("otp_6276_mgc_verify_notify_request -> " + "send notify_request received to " + "~n Pid: ~p" + "~n self(): ~p" + "~n", [Pid, self()]), + Pid ! {notify_request_received, self()}, + {ok, M}; +otp_6276_mgc_verify_notify_request(M, _Pid) -> + {error, {invalid_message, M}}. + + +%% +%% MG generator stuff +%% +otp_6276_mg_event_sequence(text, tcp, Ctrl) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + otp_6276_mg_event_sequence2(Mid, RI, Ctrl). + +otp_6276_mg_event_sequence2(Mid, RI, Ctrl) -> + AnnounceMe = otp_6276_mg_announce_fun(Ctrl), + ServiceChangeReq = [otp_6276_mg_service_change_request_ar(Mid, 1)], + ConnectVerify = fun otp_6276_mg_verify_handle_connect/1, + ServiceChangeReplyVerify = + fun otp_6276_mg_verify_service_change_reply/1, + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq = [otp_6276_mg_notify_request_ar(1, Tid, 1)], + AwaitCancelOrder = otp_6276_mg_await_cancel_order_fun(Ctrl), + TransReplyVerify = otp_6276_mg_verify_trans_reply_fun(Ctrl), + UnexpTransVerify = otp_6276_mg_verify_unexpected_trans_fun(Ctrl), + EvSeq = [ + {trigger, AnnounceMe}, + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, recv_pending_limit, 4}, + start_transport, + {megaco_trace, disable}, %%100}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_cast, NotifyReq, []}, + + {trigger, AwaitCancelOrder}, + + {megaco_cancel, otp_6276}, + + {megaco_callback, handle_trans_reply, TransReplyVerify}, + {megaco_callback, handle_unexpected_trans, UnexpTransVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +otp_6276_mg_announce_fun(Pid) -> + fun() -> + Pid ! {announce_mg, self()} + end. + +otp_6276_mg_await_cancel_order_fun(Pid) -> + fun() -> + io:format("otp_6276_mg_await_cancel_order_fun -> entry with" + "~n Pid: ~p" + "~n self(): ~p" + "~n", [Pid, self()]), + receive + {start_cancel, Pid} -> + io:format("otp_6276_mg_await_cancel_order_fun -> " + "received cancel start order" + "~n Pid: ~p" + "~n self(): ~p" + "~n", [Pid, self()]), + Pid ! {started_cancel, self()} + end + end. + +otp_6276_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("otp_6276_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +otp_6276_mg_verify_handle_connect(Else) -> + io:format("otp_6276_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp_6276_mg_verify_service_change_reply({handle_trans_reply, _CH, + ?VERSION, + {ok, [AR]}, _}) -> + io:format("otp_6276_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +otp_6276_mg_verify_service_change_reply(Else) -> + io:format("otp_6276_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp_6276_mg_verify_trans_reply_fun(Pid) -> + fun(Event) -> + otp_6276_mg_verify_trans_reply(Pid, Event) + end. + +otp_6276_mg_verify_trans_reply(Pid, + {handle_trans_reply, _CH, ?VERSION, + {error, {user_cancel, otp_6276}} = E, _}) -> + io:format("otp_6276_mg_verify_trans_reply -> expected error" + "~n", []), + Pid ! {notify_request_cancelled, self()}, + {ok, E, error}; +otp_6276_mg_verify_trans_reply(_Pid, + {handle_trans_reply, _CH, ?VERSION, + {error, Reason} = E, _}) -> + io:format("otp_6276_mg_verify_trans_reply -> unexpected error" + "~n Reason: ~p" + "~n", [Reason]), + {error, E, error}; +otp_6276_mg_verify_trans_reply(_Pid, + {handle_trans_reply, _CH, ?VERSION, Result, _}) -> + io:format("otp_6276_mg_verify_trans_reply -> unexpected result" + "~n Result: ~p" + "~n", [Result]), + {error, Result, error}; +otp_6276_mg_verify_trans_reply(_Pid, Else) -> + io:format("otp_6276_mg_verify_trans_reply -> unknown event" + "~n Else: ~p" + "~n", [Else]), + {error, Else, error}. + +otp_6276_mg_verify_unexpected_trans_fun(Pid) -> + fun(Event) -> + otp_6276_mg_verify_unexpected_trans(Pid, Event) + end. + +otp_6276_mg_verify_unexpected_trans(Pid, + {handle_unexpected_trans, RH, ?VERSION, Trans}) -> + io:format("otp_6276_mg_verify_unexpected_trans -> expected event" + "~n RH: ~p" + "~n Trans: ~p" + "~n", [RH, Trans]), + Pid ! {unexpected_trans, self(), Trans}, + {ok, Trans, error}; +otp_6276_mg_verify_unexpected_trans(_Pid, Else) -> + io:format("otp_6276_mg_verify_unexpected_trans -> unknown event" + "~n Else: ~p" + "~n", [Else]), + {error, Else, error}. + +otp_6276_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp_6276_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + + +-else. % -ifdef(MEGACO_TEST_CODE). + +otp_6276(suite) -> + []; +otp_6276(doc) -> + "OTP-6276"; +otp_6276(Config) when is_list(Config) -> + + ?SKIP("included only if compiled with USE_MEGACO_TEST_CODE=true"). + +-endif. % -ifdef(MEGACO_TEST_CODE). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +otp_6442_resend_request1(suite) -> + []; +otp_6442_resend_request1(Config) when is_list(Config) -> + put(verbosity, debug), + put(sname, "TEST"), + put(tc, otp6442rreq1), + i("starting"), + + MgNode = make_node_name(mg), + d("start (MG) node: ~p", [MgNode]), + ok = megaco_test_lib:start_nodes([MgNode], ?FILE, ?LINE), + + d("[MG] start the simulator "), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgMid = {deviceName,"mg"}, + MgEvSeq = otp_6442_resend_request1_mg_event_sequence(MgMid), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + i("await the transport module service change send_message event"), + Pid = otp_6442_expect(fun otp_6442_rsrq1_verify_scr_msg/1, 5000), + + i("wait some before issuing the service change reply"), + sleep(500), + + i("send the service change reply"), + MgcMid = {deviceName,"mgc"}, + ServiceChangeReply = otp_6442_mgc_service_change_reply_msg(MgcMid, 1, 1), + megaco_test_generic_transport:incomming_message(Pid, ServiceChangeReply), + + i("await the transport module " + "notify-request send_message event from MG: " + "ignore"), + ok = otp_6442_expect(fun otp_6442_rsrq1_verify_first_nr_msg/1, 5000), + + i("await the transport module " + "notify-request resend_message event from MG: " + "reply"), + {TransId2, Cid2, TermId2} = + otp_6442_expect(fun otp_6442_rsrq1_verify_second_nr_msg/1, 10000), + + i("wait some before issuing the notify reply"), + sleep(500), + + i("send the notify reply"), + NotifyReply = + otp_6442_mgc_notify_reply_msg(MgcMid, TransId2, Cid2, TermId2), + megaco_test_generic_transport:incomming_message(Pid, NotifyReply), + + d("await the generator reply"), + await_completion([MgId]), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +otp_6442_expect(Verify, Timeout) when (Timeout > 0) -> + T = mtime(), + receive + Msg -> + case (catch Verify(Msg)) of + {ok, Result} -> + d("verified after ~p msec", [mtime() - T]), + Result; + skip -> + otp_6442_expect(Verify, to(Timeout, T)); + {error, Reason} -> + exit({verification_failed, Reason}) + end + after Timeout -> + exit(timeout) + end; +otp_6442_expect(_, _Timeout) -> + exit(timeout). + +otp_6442_rsrq1_verify_scr_msg( + {transport_event, {send_message, _SH, {message, Msg}}, Pid}) + when is_record(Msg, 'MegacoMessage') -> + d("received expected service change request message: " + "~n Msg: ~p", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + {ok, Pid}; +otp_6442_rsrq1_verify_scr_msg( + {transport_event, {send_message, _SH, BadMsg}, _Pid}) -> + io:format("otp_6442_rsrq1_verify_scr_msg -> error: " + "~n BadMsg: ~p" + "~n", [BadMsg]), + {error, {invalid_message, BadMsg}}; +otp_6442_rsrq1_verify_scr_msg({transport_event, BadEvent, _Pid}) -> + io:format("otp_6442_rsrq1_verify_scr_msg -> error: " + "~n BadEvent: ~p" + "~n", [BadEvent]), + {error, {invalid_message, BadEvent}}; +otp_6442_rsrq1_verify_scr_msg(Msg) -> + io:format("otp_6442_rsrq1_verify_scr_msg -> error: " + "~n Msg: ~p" + "~n", [Msg]), + {error, {invalid_message, Msg}}. + +otp_6442_rsrq1_verify_first_nr_msg( + {transport_event, {send_message, _SH, {message, Msg}}, Pid}) + when is_record(Msg, 'MegacoMessage') -> + d("received expected first notify request send message: " + "~n Msg: ~p", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + {ok, ok}; +otp_6442_rsrq1_verify_first_nr_msg(Msg) -> + io:format("otp_6442_rsrq1_verify_nr_msg -> error: " + "~n Msg: ~p" + "~n", [Msg]), + {error, {invalid_message, Msg}}. + +otp_6442_rsrq1_verify_second_nr_msg( + {transport_event, {send_message, _SH, {message, Msg}}, Pid}) + when is_record(Msg, 'MegacoMessage') -> + io:format("otp_6442_rsrq1_verify_second_nr_msg -> " + "entry when received expected message with" + "~n Msg: ~p" + "~n", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + #'MegacoMessage'{mess = Mess} = Msg, + #'Message'{mId = _Mid, + messageBody = Body} = Mess, + {transactions, Transactions} = Body, + [Transaction] = Transactions, + {transactionRequest, TransReq} = Transaction, + #'TransactionRequest'{transactionId = TransId, + actions = Actions} = TransReq, + [Action] = Actions, + #'ActionRequest'{contextId = Cid, + commandRequests = CmdReqs} = Action, + [CmdReq] = CmdReqs, + #'CommandRequest'{command = Cmd} = CmdReq, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [TermId]} = NR, + {ok, {TransId, Cid, TermId}}; +otp_6442_rsrq1_verify_second_nr_msg(Msg) -> + io:format("otp_6442_rsrq1_verify_second_nr_msg -> entry when error with" + "~n Msg: ~p" + "~n", [Msg]), + {error, {invalid_message, Msg}}. + + +otp_6442_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + SCRP = #'ServiceChangeResParm'{serviceChangeMgcId = Mid}, + SCRPs = {serviceChangeResParms, SCRP}, + Root = #megaco_term_id{id = ["root"]}, + SCR = #'ServiceChangeReply'{terminationID = [Root], + serviceChangeResult = SCRPs}, + CR = {serviceChangeReply, SCR}, + otp_6442_mgc_reply_msg(Mid, TransId, CR, Cid). + +otp_6442_mgc_notify_reply_msg(Mid, TransId, Cid, TermId) -> + NR = #'NotifyReply'{terminationID = [TermId]}, + CR = {notifyReply, NR}, + otp_6442_mgc_reply_msg(Mid, TransId, CR, Cid). + +otp_6442_mgc_reply_msg(Mid, TransId, CR, Cid) -> + AR = #'ActionReply'{contextId = Cid, + commandReply = [CR]}, + ARs = {actionReplies, [AR]}, + TR = #'TransactionReply'{transactionId = TransId, + transactionResult = ARs}, + Body = {transactions, [{transactionReply, TR}]}, + Mess = #'Message'{version = 1, + mId = Mid, + messageBody = Body}, + #'MegacoMessage'{mess = Mess}. + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp_6442_resend_request1_mg_verify_handle_connect_fun(), + {?MODULE, otp_6442_resend_request1_mg_verify_handle_connect, []}). +-define(otp_6442_resend_request1_mg_verify_service_change_rep_fun(), + {?MODULE, otp_6442_resend_request1_mg_verify_service_change_rep, []}). +-define(otp_6442_resend_request1_mg_verify_notify_rep_fun(), + {?MODULE, otp_6442_resend_request1_mg_verify_notify_rep, []}). +-else. +-define(otp_6442_resend_request1_mg_verify_handle_connect_fun(), + otp_6442_resend_request1_mg_verify_handle_connect_fun()). +-define(otp_6442_resend_request1_mg_verify_service_change_rep_fun(), + otp_6442_resend_request1_mg_verify_service_change_rep_fun()). +-define(otp_6442_resend_request1_mg_verify_notify_rep_fun(), + otp_6442_resend_request1_mg_verify_notify_rep_fun()). +-endif. + +otp_6442_resend_request1_mg_event_sequence(Mid) -> + RI = [ + {port, self()}, % This is just a trick to get my pid to the transport module + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_test_generic_transport} + ], + ServiceChangeReq = + otp_6442_resend_request1_mg_service_change_request_ar(Mid, 1), + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq = otp_6442_resend_request1_mg_notify_request_ar(1, Tid, 1), + ConnectVerify = + ?otp_6442_resend_request1_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = + ?otp_6442_resend_request1_mg_verify_service_change_rep_fun(), + NotifyReplyVerify = + ?otp_6442_resend_request1_mg_verify_notify_rep_fun(), + %% ConnectVerify = + %% otp_6442_resend_request1_mg_verify_handle_connect_fun(), + %% ServiceChangeReplyVerify = + %% otp_6442_resend_request1_mg_verify_service_change_reply_fun(), + %% NotifyReplyVerify = otp_6442_resend_request1_mg_verify_notify_reply_fun(), + EvSeq = [ + {debug, false}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, resend_indication, false}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_cast, [NotifyReq], []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +-ifndef(megaco_hipe_special). +otp_6442_resend_request1_mg_verify_handle_connect_fun() -> + fun(Ev) -> + otp_6442_resend_request1_mg_verify_handle_connect(Ev) + end. +-endif. + +otp_6442_resend_request1_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("otp_6442_resend_request1_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +otp_6442_resend_request1_mg_verify_handle_connect(Else) -> + io:format("otp_6442_resend_request1_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +-ifndef(megaco_hipe_special). +otp_6442_resend_request1_mg_verify_service_change_rep_fun() -> + fun(Rep) -> + otp_6442_resend_request1_mg_verify_service_change_rep(Rep) + end. +-endif. + +otp_6442_resend_request1_mg_verify_service_change_rep( + {handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> + (catch otp_6442_resend_request1_mg_do_verify_service_change_rep(AR)); +otp_6442_resend_request1_mg_verify_service_change_rep(Crap) -> + {error, Crap, ok}. + +otp_6442_resend_request1_mg_do_verify_service_change_rep(AR) -> + io:format("otp_6442_resend_request1_mg_verify_service_change_rep -> ok" + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +-ifndef(megaco_hipe_special). +otp_6442_resend_request1_mg_verify_notify_rep_fun() -> + fun(Rep) -> + otp_6442_resend_request1_mg_verify_notify_rep(Rep) + end. +-endif. + +otp_6442_resend_request1_mg_verify_notify_rep( + {handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> + io:format("otp_6442_resend_request1_mg_verify_notify_rep -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +otp_6442_resend_request1_mg_verify_notify_rep(Else) -> + io:format("otp_6442_resend_request1_mg_verify_notify_rep -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +otp_6442_resend_request1_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp_6442_resend_request1_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_6442_resend_request2(suite) -> + []; +otp_6442_resend_request2(Config) when is_list(Config) -> + put(verbosity, debug), + put(sname, "TEST"), + put(tc, otp6442rreq2), + i("starting"), + + MgNode = make_node_name(mg), + d("start (MG) node: ~p", [MgNode]), + ok = megaco_test_lib:start_nodes([MgNode], ?FILE, ?LINE), + + d("[MG] start the simulator "), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + Mid = {deviceName,"mg"}, + MgcMid = {deviceName,"mgc"}, + MgEvSeq = otp_6442_resend_request2_mg_event_sequence(Mid), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + i("await the transport module service change send_message event"), + Pid = otp_6442_expect(fun otp_6442_rsrq2_verify_scr_msg/1, 5000), + + i("wait some before issuing the service change reply"), + sleep(500), + + i("send the service change reply"), + ServiceChangeReply = otp_6442_mgc_service_change_reply_msg(MgcMid, 1, 1), + megaco_test_generic_transport:incomming_message(Pid, ServiceChangeReply), + + i("await the transport module notify-request send_message event from MG: ignore"), + ok = otp_6442_expect(fun otp_6442_rsrq2_verify_first_nr_msg/1, 5000), + + i("await the transport module notify-request resend_message event from MG: reply"), + {TransId2, Cid2, TermId2} = + otp_6442_expect(fun otp_6442_rsrq2_verify_second_nr_msg/1, 10000), + + i("wait some before issuing the notify reply"), + sleep(500), + + i("send the notify reply"), + NotifyReply = otp_6442_mgc_notify_reply_msg(MgcMid, TransId2, Cid2, TermId2), + megaco_test_generic_transport:incomming_message(Pid, NotifyReply), + + d("await the generator reply"), + await_completion([MgId]), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +otp_6442_rsrq2_verify_scr_msg( + {transport_event, {send_message, _SH, {message, Msg}}, Pid}) + when is_record(Msg, 'MegacoMessage') -> + d("received expected service change request message: " + "~n Msg: ~p", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + {ok, Pid}; +otp_6442_rsrq2_verify_scr_msg(Msg) -> + io:format("otp_6442_rsrq2_verify_nr_msg -> error: " + "~n Msg: ~p" + "~n", [Msg]), + {error, {invalid_message, Msg}}. + +otp_6442_rsrq2_verify_first_nr_msg( + {transport_event, {send_message, _SH, {message, Msg}}, Pid}) + when is_record(Msg, 'MegacoMessage') -> + d("received expected first notify request message: " + "~n Msg: ~p", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + {ok, ok}; +otp_6442_rsrq2_verify_first_nr_msg(Msg) -> + {error, {invalid_message, Msg}}. + +otp_6442_rsrq2_verify_second_nr_msg( + {transport_event, {resend_message, _SH, {message, Msg}}, Pid}) + when is_record(Msg, 'MegacoMessage') -> + d("received expected second notify request message: " + "~n Msg: ~p", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + #'MegacoMessage'{mess = Mess} = Msg, + #'Message'{mId = _Mid, + messageBody = Body} = Mess, + {transactions, Transactions} = Body, + [Transaction] = Transactions, + {transactionRequest, TransReq} = Transaction, + #'TransactionRequest'{transactionId = TransId, + actions = Actions} = TransReq, + [Action] = Actions, + #'ActionRequest'{contextId = Cid, + commandRequests = CmdReqs} = Action, + [CmdReq] = CmdReqs, + #'CommandRequest'{command = Cmd} = CmdReq, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [TermId]} = NR, + {ok, {TransId, Cid, TermId}}; +otp_6442_rsrq2_verify_second_nr_msg(Msg) -> + {error, {invalid_message, Msg}}. + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp_6442_resend_request2_mg_verify_handle_connect_fun(), + {?MODULE, otp_6442_resend_request2_mg_verify_handle_connect, []}). +-define(otp_6442_resend_request2_mg_verify_service_change_rep_fun(), + {?MODULE, otp_6442_resend_request2_mg_verify_service_change_rep, []}). +-define(otp_6442_resend_request2_mg_verify_notify_rep_fun(), + {?MODULE, otp_6442_resend_request2_mg_verify_notify_rep, []}). +-else. +-define(otp_6442_resend_request2_mg_verify_handle_connect_fun(), + otp_6442_resend_request2_mg_verify_handle_connect_fun()). +-define(otp_6442_resend_request2_mg_verify_service_change_rep_fun(), + otp_6442_resend_request2_mg_verify_service_change_rep_fun()). +-define(otp_6442_resend_request2_mg_verify_notify_rep_fun(), + otp_6442_resend_request2_mg_verify_notify_rep_fun()). +-endif. + +otp_6442_resend_request2_mg_event_sequence(Mid) -> + RI = [ + {port, self()}, % This is just a trick to get my pid to the transport module + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_test_generic_transport} + ], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq = otp_6442_resend_request2_mg_notify_request_ar(1, Tid, 1), + ServiceChangeReq = + otp_6442_resend_request2_mg_service_change_request_ar(Mid, 1), + ConnectVerify = + ?otp_6442_resend_request2_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = + ?otp_6442_resend_request2_mg_verify_service_change_rep_fun(), + NotifyReplyVerify = + ?otp_6442_resend_request2_mg_verify_notify_rep_fun(), +%% ConnectVerify = +%% otp_6442_resend_request2_mg_verify_handle_connect_fun(), +%% ServiceChangeReplyVerify = +%% otp_6442_resend_request2_mg_verify_service_change_reply_fun(), +%% NotifyReplyVerify = otp_6442_resend_request2_mg_verify_notify_reply_fun(), + EvSeq = [ + {debug, false}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, resend_indication, true}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_cast, [NotifyReq], []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +-ifndef(megaco_hipe_special). +otp_6442_resend_request2_mg_verify_handle_connect_fun() -> + fun(Ev) -> + otp_6442_resend_request2_mg_verify_handle_connect(Ev) + end. +-endif. + +otp_6442_resend_request2_mg_verify_handle_connect( + {handle_connect, CH, ?VERSION}) -> + io:format("otp_6442_resend_request2_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +otp_6442_resend_request2_mg_verify_handle_connect(Else) -> + io:format("otp_6442_resend_request2_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +-ifndef(megaco_hipe_special). +otp_6442_resend_request2_mg_verify_service_change_rep_fun() -> + fun(Rep) -> + otp_6442_resend_request2_mg_verify_service_change_rep(Rep) + end. +-endif. + +otp_6442_resend_request2_mg_verify_service_change_rep( + {handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> + (catch otp_6442_resend_request2_mg_do_verify_service_change_rep(AR)); +otp_6442_resend_request2_mg_verify_service_change_rep(Crap) -> + {error, Crap, ok}. + +otp_6442_resend_request2_mg_do_verify_service_change_rep(AR) -> + io:format("otp_6442_resend_request2_mg_verify_service_change_rep -> ok" + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +-ifndef(megaco_hipe_special). +otp_6442_resend_request2_mg_verify_notify_rep_fun() -> + fun(Rep) -> + otp_6442_resend_request2_mg_verify_notify_rep(Rep) + end. +-endif. + +otp_6442_resend_request2_mg_verify_notify_rep( + {handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> + io:format("otp_6442_resend_request2_mg_verify_notify_rep -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +otp_6442_resend_request2_mg_verify_notify_rep(Else) -> + io:format("otp_6442_resend_request2_mg_verify_notify_rep -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +otp_6442_resend_request2_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp_6442_resend_request2_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_6442_resend_reply1(suite) -> + []; +otp_6442_resend_reply1(Config) when is_list(Config) -> + put(sname, "TEST"), + put(verbosity, debug), + put(tc, otp6442rrep1), + i("starting"), + + MgNode = make_node_name(mg), + d("start (MG) node: ~p", [MgNode]), + ok = megaco_test_lib:start_nodes([MgNode], ?FILE, ?LINE), + + d("[MG] start the simulator "), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + Mid = {deviceName,"mg"}, + MgcMid = {deviceName,"mgc"}, + TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + MgEvSeq = otp_6442_resend_reply1_mg_event_sequence(Mid, TermId), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + i("await the transport module service change send_message event"), + Pid = otp_6442_expect(fun otp_6442_rsrp1_verify_scr_msg/1, 5000), + + i("wait some before issuing the service change reply"), + sleep(500), + + i("simulate MGC sending the service change reply"), + ServiceChangeReply = otp_6442_mgc_service_change_reply_msg(MgcMid, 1, 1), + megaco_test_generic_transport:incomming_message(Pid, ServiceChangeReply), + + + i("wait some before issuing the notify request"), + sleep(500), + + i("simulate MGC sending the notify request"), + NotifyRequest = otp_6442_mgc_notify_request_msg(MgcMid, TermId, 2, 1), + megaco_test_generic_transport:incomming_message(Pid, NotifyRequest), + + i("await the transport module first notify-reply send_message event from MG: " + "ignore"), + otp_6442_expect(fun otp_6442_rsrp1_verify_first_nr_msg/1, 5000), + + i("await the transport module second notify-reply send_message event from MG: " + "ack"), + {TransId, _, _} = otp_6442_expect(fun otp_6442_rsrp1_verify_second_nr_msg/1, 10000), + + i("wait some before issuing the ack"), + sleep(500), + + i("simulate MGC sending the ack"), + Ack = otp_6442_mgc_ack_msg(MgcMid, TransId), + megaco_test_generic_transport:incomming_message(Pid, Ack), + + + d("await the generator reply"), + await_completion([MgId]), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +otp_6442_rsrp1_verify_scr_msg( + {transport_event, {send_message, _SH, {message, Msg}}, Pid}) + when is_record(Msg, 'MegacoMessage') -> + d("received expected service change request message: " + "~n Msg: ~p", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + {ok, Pid}; +otp_6442_rsrp1_verify_scr_msg(Msg) -> + {error, {invalid_message, Msg}}. + +otp_6442_rsrp1_verify_first_nr_msg( + {transport_event, {send_message, _SH, {message, Msg}}, Pid}) + when is_record(Msg, 'MegacoMessage') -> + d("received expected first notify reply message: " + "~n Msg: ~p", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + {ok, ok}; +otp_6442_rsrp1_verify_first_nr_msg(Msg) -> + {error, {invalid_message, Msg}}. + +otp_6442_rsrp1_verify_second_nr_msg( + {transport_event, {send_message, _SH, {message, Msg}}, Pid}) + when is_record(Msg, 'MegacoMessage') -> + d("received expected second notify reply message: " + "~n Msg: ~p", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + #'MegacoMessage'{mess = Mess} = Msg, + #'Message'{mId = _Mid, + messageBody = Body} = Mess, + {transactions, Transactions} = Body, + [Transaction] = Transactions, + {transactionReply, TransRep} = Transaction, + #'TransactionReply'{transactionId = TransId, + immAckRequired = 'NULL', + transactionResult = TransRes} = TransRep, + {actionReplies, ActReps} = TransRes, + [ActRep] = ActReps, + #'ActionReply'{contextId = Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = asn1_NOVALUE, + commandReply = CmdReps} = ActRep, + [CmdRep] = CmdReps, + {notifyReply, NR} = CmdRep, + #'NotifyReply'{terminationID = TermId} = NR, + {ok, {TransId, Cid, TermId}}; +otp_6442_rsrp1_verify_second_nr_msg(Msg) -> + {error, {invalid_message, Msg}}. + + +otp_6442_mgc_notify_request_msg(Mid, TermId, TransId, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(1, [Ev]), + NR = cre_notifyReq([TermId], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + AR = cre_actionReq(Cid, [CR]), + ARs = [AR], + TR = cre_transReq(TransId, ARs), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +otp_6442_mgc_ack_msg(Mid, TransId) -> + TR = cre_transRespAck(cre_transAck(TransId)), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp_6442_resend_reply1_mg_verify_handle_connect_fun(), + {?MODULE, otp_6442_resend_reply1_mg_verify_handle_connect, []}). +-define(otp_6442_resend_reply1_mg_verify_service_change_rep_fun(), + {?MODULE, otp_6442_resend_reply1_mg_verify_service_change_rep, []}). +-define(otp_6442_resend_reply1_mg_verify_notify_req_fun(TermId), + {?MODULE, otp_6442_resend_reply1_mg_verify_notify_req, [TermId]}). +-define(otp_6442_resend_reply1_mg_verify_ack_fun(), + {?MODULE, otp_6442_resend_reply1_mg_verify_ack, []}). +-else. +-define(otp_6442_resend_reply1_mg_verify_handle_connect_fun(), + otp_6442_resend_reply1_mg_verify_handle_connect_fun()). +-define(otp_6442_resend_reply1_mg_verify_service_change_rep_fun(), + otp_6442_resend_reply1_mg_verify_service_change_rep_fun()). +-define(otp_6442_resend_reply1_mg_verify_notify_req_fun(TermId), + otp_6442_resend_reply1_mg_verify_notify_req_fun(TermId)). +-define(otp_6442_resend_reply1_mg_verify_ack_fun(), + otp_6442_resend_reply1_mg_verify_ack_fun()). +-endif. + +otp_6442_resend_reply1_mg_event_sequence(Mid, TermId) -> + RI = [ + {port, self()}, % This is just a trick to get my pid to the transport module + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_test_generic_transport} + ], + ServiceChangeReq = + otp_6442_resend_reply1_mg_service_change_request_ar(Mid, 1), + RepTmr = #megaco_incr_timer{wait_for = 2000, + factor = 1, + max_retries = 1}, + ConnectVerify = + ?otp_6442_resend_reply1_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = + ?otp_6442_resend_reply1_mg_verify_service_change_rep_fun(), + NotifyReqVerify = + ?otp_6442_resend_reply1_mg_verify_notify_req_fun(TermId), + AckVerify = + ?otp_6442_resend_reply1_mg_verify_ack_fun(), +%% ConnectVerify = +%% otp_6442_resend_reply1_mg_verify_handle_connect_fun(), +%% ServiceChangeReplyVerify = +%% otp_6442_resend_reply1_mg_verify_service_change_reply_fun(), +%% NotifyReqVerify = +%% otp_6442_resend_reply1_mg_verify_notify_request_fun(TermId), +%% AckVerify = +%% otp_6442_resend_reply1_mg_verify_ack_fun(), + EvSeq = [ + {debug, false}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, resend_indication, false}, + {megaco_update_user_info, reply_timer, RepTmr}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +-ifndef(megaco_hipe_special). +otp_6442_resend_reply1_mg_verify_handle_connect_fun() -> + fun(Ev) -> + otp_6442_resend_reply1_mg_verify_handle_connect(Ev) + end. +-endif. + +otp_6442_resend_reply1_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("otp_6442_resend_reply1_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +otp_6442_resend_reply1_mg_verify_handle_connect(Else) -> + io:format("otp_6442_resend_reply1_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +-ifndef(megaco_hipe_special). +otp_6442_resend_reply1_mg_verify_service_change_rep_fun() -> + fun(Rep) -> + otp_6442_resend_reply1_mg_verify_service_change_rep(Rep) + end. +-endif. + +otp_6442_resend_reply1_mg_verify_service_change_rep( + {handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> + (catch otp_6442_resend_reply1_mg_do_verify_service_change_rep(AR)); +otp_6442_resend_reply1_mg_verify_service_change_rep(Crap) -> + {error, Crap, ok}. + +otp_6442_resend_reply1_mg_do_verify_service_change_rep(AR) -> + io:format("otp_6442_resend_reply1_mg_verify_service_change_rep -> ok" + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +-ifndef(megaco_hipe_special). +otp_6442_resend_reply1_mg_verify_notify_req_fun(TermId) -> + fun(Req) -> + otp_6442_resend_reply1_mg_verify_notify_req(Req, TermId) + end. +-endif. + +otp_6442_resend_reply1_mg_verify_notify_req( + {handle_trans_request, _, ?VERSION, [AR]}, TermId) -> + io:format("otp_6442_resend_reply1_mg_verify_notify_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [TermId], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + HandleAck = {handle_ack, otp_6442_resend_reply1}, + Reply = {HandleAck, + [otp_6442_resend_reply1_mg_notify_reply_ar(Cid, TermId)]}, + {ok, AR, Reply}; + _ -> + ED = otp_6442_resend_reply1_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +otp_6442_resend_reply1_mg_verify_notify_req(Else, TermId) -> + io:format("otp_6442_resend_reply1_mg_verify_notify_request -> unknown" + "~n Else: ~p" + "~n TermId: ~p" + "~n", [Else, TermId]), + ED = otp_6442_resend_reply1_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +otp_6442_resend_reply1_mg_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +-ifndef(megaco_hipe_special). +otp_6442_resend_reply1_mg_verify_ack_fun() -> + fun(Ack) -> + otp_6442_resend_reply1_mg_verify_ack(Ack) + end. +-endif. + +otp_6442_resend_reply1_mg_verify_ack( + {handle_trans_ack, CH, ?VERSION, ok, otp_6442_resend_reply1}) -> + io:format("otp_6442_resend_reply1_verify_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +otp_6442_resend_reply1_mg_verify_ack(Else) -> + io:format("otp_6442_resend_reply1_verify_ack -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +otp_6442_resend_reply1_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp_6442_resend_reply1_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_6442_resend_reply2(suite) -> + []; +otp_6442_resend_reply2(Config) when is_list(Config) -> + put(sname, "TEST"), + put(verbosity, debug), + put(tc, otp6442rrep2), + i("starting"), + + MgNode = make_node_name(mg), + d("start (MG) node: ~p", [MgNode]), + ok = megaco_test_lib:start_nodes([MgNode], ?FILE, ?LINE), + + d("[MG] start the simulator "), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + Mid = {deviceName,"mg"}, + MgcMid = {deviceName,"mgc"}, + TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + MgEvSeq = otp_6442_resend_reply2_mg_event_sequence(Mid, TermId), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + i("await the transport module service change send_message event"), + Pid = otp_6442_expect(fun otp_6442_rsrp2_verify_scr_msg/1, 5000), + + i("wait some before issuing the service change reply"), + sleep(500), + + i("simulate MGC sending the service change reply"), + ServiceChangeReply = otp_6442_mgc_service_change_reply_msg(MgcMid, 1, 1), + megaco_test_generic_transport:incomming_message(Pid, ServiceChangeReply), + + + i("wait some before issuing the notify request"), + sleep(500), + + i("simulate MGC sending the notify request"), + NotifyRequest = otp_6442_mgc_notify_request_msg(MgcMid, TermId, 2, 1), + megaco_test_generic_transport:incomming_message(Pid, NotifyRequest), + + i("await the transport module notify-reply send_message event from MG: ignore"), + otp_6442_expect(otp_6442_rsrp2_verify_first_nr_msg_fun(), 5000), + + i("await the transport module notify-reply resend_message event from MG: ack"), + {TransId, _, _} = + otp_6442_expect(otp_6442_rsrp2_verify_second_nr_msg_fun(), 10000), + + i("wait some before issuing the ack"), + sleep(500), + + i("simulate MGC sending the ack"), + Ack = otp_6442_mgc_ack_msg(MgcMid, TransId), + megaco_test_generic_transport:incomming_message(Pid, Ack), + + + d("await the generator reply"), + await_completion([MgId]), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +otp_6442_rsrp2_verify_scr_msg( + {transport_event, {send_message, _SH, {message, Msg}}, Pid}) + when is_record(Msg, 'MegacoMessage') -> + d("received expected service change request message: " + "~n Msg: ~p", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + {ok, Pid}; +otp_6442_rsrp2_verify_scr_msg(Msg) -> + {error, {invalid_message, Msg}}. + +otp_6442_rsrp2_verify_first_nr_msg_fun() -> + fun(E) -> + otp_6442_rsrp2_verify_first_nr_msg(E) + end. + +otp_6442_rsrp2_verify_first_nr_msg( + {transport_event, {send_message, _SH, {message, Msg}}, Pid}) + when is_record(Msg, 'MegacoMessage') -> + d("received expected first notify reply message: " + "~n Msg: ~p", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + {ok, ok}; +otp_6442_rsrp2_verify_first_nr_msg(Msg) -> + {error, {invalid_message, Msg}}. + +otp_6442_rsrp2_verify_second_nr_msg_fun() -> + fun(E) -> + otp_6442_rsrp2_verify_second_nr_msg(E) + end. + +otp_6442_rsrp2_verify_second_nr_msg( + {transport_event, {resend_message, _SH, {message, Msg}}, Pid}) + when is_record(Msg, 'MegacoMessage') -> + d("received expected second notify reply message: " + "~n Msg: ~p", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + #'MegacoMessage'{mess = Mess} = Msg, + #'Message'{mId = _Mid, + messageBody = Body} = Mess, + {transactions, Transactions} = Body, + [Transaction] = Transactions, + {transactionReply, TransRep} = Transaction, + #'TransactionReply'{transactionId = TransId, + immAckRequired = 'NULL', + transactionResult = TransRes} = TransRep, + {actionReplies, ActReps} = TransRes, + [ActRep] = ActReps, + #'ActionReply'{contextId = Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = asn1_NOVALUE, + commandReply = CmdReps} = ActRep, + [CmdRep] = CmdReps, + {notifyReply, NR} = CmdRep, + #'NotifyReply'{terminationID = TermId} = NR, + {ok, {TransId, Cid, TermId}}; +otp_6442_rsrp2_verify_second_nr_msg(Msg) -> + d("received expected bad second notify reply message: " + "~n Msg: ~p", [Msg]), + {error, {invalid_message, Msg}}. + + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp_6442_resend_reply2_mg_verify_handle_connect_fun(), + {?MODULE, otp_6442_resend_reply2_mg_verify_handle_connect, []}). +-define(otp_6442_resend_reply2_mg_verify_service_change_rep_fun(), + {?MODULE, otp_6442_resend_reply2_mg_verify_service_change_rep, []}). +-define(otp_6442_resend_reply2_mg_verify_notify_req_fun(TermId), + {?MODULE, otp_6442_resend_reply2_mg_verify_notify_req, [TermId]}). +-define(otp_6442_resend_reply2_mg_verify_ack_fun(), + {?MODULE, otp_6442_resend_reply2_mg_verify_ack, []}). +-else. +-define(otp_6442_resend_reply2_mg_verify_handle_connect_fun(), + otp_6442_resend_reply2_mg_verify_handle_connect_fun()). +-define(otp_6442_resend_reply2_mg_verify_service_change_rep_fun(), + otp_6442_resend_reply2_mg_verify_service_change_rep_fun()). +-define(otp_6442_resend_reply2_mg_verify_notify_req_fun(TermId), + otp_6442_resend_reply2_mg_verify_notify_req_fun(TermId)). +-define(otp_6442_resend_reply2_mg_verify_ack_fun(), + otp_6442_resend_reply2_mg_verify_ack_fun()). +-endif. + +otp_6442_resend_reply2_mg_event_sequence(Mid, TermId) -> + RI = [ + {port, self()}, % This is just a trick to get my pid to the transport module + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_test_generic_transport} + ], + ServiceChangeReq = + otp_6442_resend_reply2_mg_service_change_request_ar(Mid, 1), + RepTmr = #megaco_incr_timer{wait_for = 2000, + factor = 1, + max_retries = 1}, + ConnectVerify = + ?otp_6442_resend_reply2_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = + ?otp_6442_resend_reply2_mg_verify_service_change_rep_fun(), + NotifyReqVerify = + ?otp_6442_resend_reply2_mg_verify_notify_req_fun(TermId), + AckVerify = + ?otp_6442_resend_reply2_mg_verify_ack_fun(), +%% ConnectVerify = +%% otp_6442_resend_reply2_mg_verify_handle_connect_fun(), +%% ServiceChangeReplyVerify = +%% otp_6442_resend_reply2_mg_verify_service_change_reply_fun(), +%% NotifyReqVerify = +%% otp_6442_resend_reply2_mg_verify_notify_request_fun(TermId), +%% AckVerify = +%% otp_6442_resend_reply2_mg_verify_ack_fun(), + EvSeq = [ + {debug, false}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, resend_indication, true}, + {megaco_update_user_info, reply_timer, RepTmr}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +-ifndef(megaco_hipe_special). +otp_6442_resend_reply2_mg_verify_handle_connect_fun() -> + fun(Ev) -> + otp_6442_resend_reply2_mg_verify_handle_connect(Ev) + end. +-endif. + +otp_6442_resend_reply2_mg_verify_handle_connect( + {handle_connect, CH, ?VERSION}) -> + io:format("otp_6442_resend_reply2_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +otp_6442_resend_reply2_mg_verify_handle_connect(Else) -> + io:format("otp_6442_resend_reply2_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +-ifndef(megaco_hipe_special). +otp_6442_resend_reply2_mg_verify_service_change_rep_fun() -> + fun(Rep) -> + otp_6442_resend_reply2_mg_verify_service_change_rep(Rep) + end. +-endif. + +otp_6442_resend_reply2_mg_verify_service_change_rep( + {handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> + (catch otp_6442_resend_reply2_mg_do_verify_service_change_rep(AR)); +otp_6442_resend_reply2_mg_verify_service_change_rep(Crap) -> + {error, Crap, ok}. + +otp_6442_resend_reply2_mg_do_verify_service_change_rep(AR) -> + io:format("otp_6442_resend_reply2_mg_verify_service_change_rep -> ok" + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +-ifndef(megaco_hipe_special). +otp_6442_resend_reply2_mg_verify_notify_req_fun(TermId) -> + fun(Req) -> + otp_6442_resend_reply2_mg_verify_notify_req(Req, TermId) + end. +-endif. + +otp_6442_resend_reply2_mg_verify_notify_req( + {handle_trans_request, _, ?VERSION, [AR]}, TermId) -> + io:format("otp_6442_resend_reply2_mg_verify_notify_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [TermId], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + HandleAck = {handle_ack, otp_6442_resend_reply2}, + Reply = {HandleAck, + [otp_6442_resend_reply2_mg_notify_reply_ar(Cid, TermId)]}, + {ok, AR, Reply}; + _ -> + ED = otp_6442_resend_reply2_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +otp_6442_resend_reply2_mg_verify_notify_req(Else, TermId) -> + io:format("otp_6442_resend_reply2_mg_verify_notify_req -> unknown" + "~n Else: ~p" + "~n TermId: ~p" + "~n", [Else, TermId]), + ED = otp_6442_resend_reply2_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +otp_6442_resend_reply2_mg_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + + +-ifndef(megaco_hipe_special). +otp_6442_resend_reply2_mg_verify_ack_fun() -> + fun(Ack) -> + otp_6442_resend_reply2_mg_verify_ack(Ack) + end. +-endif. + +otp_6442_resend_reply2_mg_verify_ack( + {handle_trans_ack, CH, ?VERSION, ok, otp_6442_resend_reply2}) -> + io:format("otp_6442_resend_reply2_verify_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +otp_6442_resend_reply2_mg_verify_ack(Else) -> + io:format("otp_6442_resend_reply2_verify_ack -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +otp_6442_resend_reply2_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + + +otp_6442_resend_reply2_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_6865_request_and_reply_plain_extra1(suite) -> + []; +otp_6865_request_and_reply_plain_extra1(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + + put(sname, "TEST"), + put(verbosity, debug), + put(tc, otp6865e1), + i("starting"), + + d("start test case controller",[]), + ok = megaco_tc_controller:start_link(), + + %% Instruct the transport module to fail all send_message + d("instruct transport module to provide extra info: ",[]), + ExtraInfo = otp_6865_extra_info, + ok = megaco_tc_controller:insert(extra_transport_info, ExtraInfo), + + d("start proxy",[]), + megaco_mess_user_test:start_proxy(), + + PrelMid = preliminary_mid, + MgMid = ipv4_mid(4711), + MgcMid = ipv4_mid(), + UserMod = megaco_mess_user_test, + d("start megaco app",[]), + ?VERIFY(ok, application:start(megaco)), + UserConfig = [{user_mod, UserMod}, {send_mod, UserMod}, + {request_timer, infinity}, {reply_timer, infinity}], + d("start (MG) user ~p",[MgMid]), + ?VERIFY(ok, megaco:start_user(MgMid, UserConfig)), + + d("start (MGC) user ~p",[MgcMid]), + ?VERIFY(ok, megaco:start_user(MgcMid, UserConfig)), + + d("get receive info for ~p",[MgMid]), + MgRH = user_info(MgMid, receive_handle), + d("get receive info for ~p",[MgcMid]), + MgcRH = user_info(MgcMid, receive_handle), + d("start transport",[]), + {ok, MgPid, MgSH} = + ?VERIFY({ok, _, _}, UserMod:start_transport(MgRH, MgcRH)), + PrelMgCH = #megaco_conn_handle{local_mid = MgMid, + remote_mid = preliminary_mid}, + MgCH = #megaco_conn_handle{local_mid = MgMid, + remote_mid = MgcMid}, + MgcCH = #megaco_conn_handle{local_mid = MgcMid, + remote_mid = MgMid}, + d("(MG) try connect to MGC",[]), + ?SEND(megaco:connect(MgRH, PrelMid, MgSH, MgPid)), % Mg prel + d("await connect from MG",[]), + ?USER({connect, PrelMgCH, _V, []}, ok), + ?RECEIVE([{res, _, {ok, PrelMgCH}}]), + + d("(MG) send service change request",[]), + Req = service_change_request(), + ?SEND(megaco:call(PrelMgCH, [Req], [])), + + d("(MGC) send service change reply",[]), + ?USER({connect, MgcCH, _V, [ExtraInfo]}, ok), % Mgc auto + Rep = service_change_reply(MgcMid), + ?USER({request, MgcCH, _V, [[Req], ExtraInfo]}, {discard_ack, [Rep]}), + ?USER({connect, MgCH, _V, [ExtraInfo]}, ok), % Mg confirm + ?RECEIVE([{res, _, {1, {ok, [Rep], ExtraInfo}}}]), + + d("get (system info) connections",[]), + connections([MgCH, MgcCH]), + d("get (~p) connections",[MgMid]), + ?VERIFY([MgCH], megaco:user_info(MgMid, connections)), + d("get (~p) connections",[MgcMid]), + ?VERIFY([MgcCH], megaco:user_info(MgcMid, connections)), + + Reason = shutdown, + d("(MG) disconnect",[]), + ?SEND(megaco:disconnect(MgCH, Reason)), + ?USER({disconnect, MgCH, _V, [{user_disconnect, Reason}]}, ok), + ?RECEIVE([{res, _, ok}]), + ?VERIFY(ok, megaco:stop_user(MgMid)), + + d("(MGC) disconnect",[]), + ?SEND(megaco:disconnect(MgcCH, Reason)), + ?USER({disconnect, MgcCH, _V, [{user_disconnect, Reason}]}, ok), + ?RECEIVE([{res, _, ok}]), + ?VERIFY(ok, megaco:stop_user(MgcMid)), + + d("stop megaco app",[]), + ?VERIFY(ok, application:stop(megaco)), + ?RECEIVE([]), + + d("stop test case controller",[]), + ok = megaco_tc_controller:stop(), + + d("done",[]), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_6865_request_and_reply_plain_extra2(suite) -> + []; +otp_6865_request_and_reply_plain_extra2(doc) -> + []; +otp_6865_request_and_reply_plain_extra2(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, otp6865e2), + i("starting"), + + d("start tc controller"), + ok = megaco_tc_controller:start_link(), + + %% Instruct the transport module to fail all send_message + d("instruct transport module to provide extra info: ", []), + ExtraInfo = otp6865e2_extra_info, + ok = megaco_tc_controller:insert(extra_transport_info, ExtraInfo), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = otp6865e2_mgc_event_sequence(ExtraInfo, text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_tcp_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = otp6865e2_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_tcp_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId], 60000), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_tcp_generator:stop(Mg), + + i("stop tc controller"), + ok = megaco_tc_controller:stop(), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp6865e2_mgc_verify_handle_connect_fun(ExtraInfo), + {?MODULE, otp6865e2_mgc_verify_handle_connect, [ExtraInfo]}). +-define(otp6865e2_mgc_verify_service_change_req_fun(Mid, ExtraInfo), + {?MODULE, otp6865e2_mgc_verify_service_change_req, [Mid, ExtraInfo]}). +-define(otp6865e2_mgc_verify_notify_req_fun(Cid, ExtraInfo, RequireAck), + {?MODULE, otp6865e2_mgc_verify_notify_req, [Cid, ExtraInfo, RequireAck]}). +-define(otp6865e2_mgc_verify_reply_ack_fun(ExtraInfo), + {?MODULE, otp6865e2_mgc_verify_reply_ack, [ExtraInfo]}). +-define(otp6865e2_mgc_verify_notify_reply_fun(ExtraInfo), + {?MODULE, otp6865e2_mgc_verify_notify_reply, [ExtraInfo]}). +-define(otp6865e2_mgc_verify_handle_disconnect_fun(), + {?MODULE, otp6865e2_mgc_verify_handle_disconnect, []}). +-else. +-define(otp6865e2_mgc_verify_handle_connect_fun(ExtraInfo), + otp6865e2_mgc_verify_handle_connect(ExtraInfo)). +-define(otp6865e2_mgc_verify_service_change_req_fun(Mid, ExtraInfo), + otp6865e2_mgc_verify_service_change_req_fun(Mid, ExtraInfo)). +-define(otp6865e2_mgc_verify_notify_req_fun(Cid, ExtraInfo, RequireAck), + otp6865e2_mgc_verify_notify_req_fun(Cid, ExtraInfo, RequireAck)). +-define(otp6865e2_mgc_verify_reply_ack_fun(ExtraInfo), + otp6865e2_mgc_verify_reply_ack_fun(ExtraInfo)). +-define(otp6865e2_mgc_verify_notify_reply_fun(ExtraInfo), + otp6865e2_mgc_verify_notify_reply_fun(ExtraInfo)). +-define(otp6865e2_mgc_verify_handle_disconnect_fun(), + fun otp6865e2_mgc_verify_handle_disconnect/1). +-endif. + +otp6865e2_mgc_event_sequence(ExtraInfo, text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = + ?otp6865e2_mgc_verify_handle_connect_fun(ExtraInfo), + ServiceChangeReqVerify = + ?otp6865e2_mgc_verify_service_change_req_fun(Mid, ExtraInfo), + NotifyReqVerify1 = + ?otp6865e2_mgc_verify_notify_req_fun(1, ExtraInfo, false), + NotifyReqVerify2 = + ?otp6865e2_mgc_verify_notify_req_fun(2, ExtraInfo, true), + AckVerify = ?otp6865e2_mgc_verify_reply_ack_fun(ExtraInfo), + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq = [otp6865e2_mgc_notify_request_ar(1, Tid, 1)], + NotifyReplyVerify = ?otp6865e2_mgc_verify_notify_reply_fun(ExtraInfo), + DiscoVerify = + ?otp6865e2_mgc_verify_handle_disconnect_fun(), + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify1}, + {megaco_callback, handle_trans_request, NotifyReqVerify2}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_cast, NotifyReq, []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +-ifndef(megaco_hipe_special). +otp6865e2_mgc_verify_handle_connect(ExtraInfo) -> + fun(Req) -> + otp6865e2_mgc_verify_handle_connect(Req, ExtraInfo) + end. +-endif. + +otp6865e2_mgc_verify_handle_connect({handle_connect, CH, ?VERSION, ExtraInfo}, + ExtraInfo) -> + io:format("otp6865e2_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +otp6865e2_mgc_verify_handle_connect(Else, ExtraInfo) -> + io:format("otp6865e2_mgc_verify_handle_connect -> unknown" + "~n Else: ~p" + "~n ExtraInfo: ~p" + "~n", [Else, ExtraInfo]), + {error, {Else, ExtraInfo}, ok}. + +-ifndef(megaco_hipe_special). +otp6865e2_mgc_verify_service_change_req_fun(Mid, ExtraInfo) -> + fun(Req) -> + otp6865e2_mgc_verify_service_change_req(Req, Mid, ExtraInfo) + end. +-endif. + +otp6865e2_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR], ExtraInfo}, Mid, ExtraInfo) -> + (catch otp6865e2_mgc_do_verify_service_change_req(AR, Mid)); +otp6865e2_mgc_verify_service_change_req(Crap, _Mid, ExtraInfo) -> + ED = cre_ErrDesc({Crap, ExtraInfo}), + ErrReply = {discard_ack, ED}, + {error, {Crap, ExtraInfo}, ErrReply}. + +otp6865e2_mgc_do_verify_service_change_req(AR, Mid) -> + io:format("otp6865e2_mgc_verify_service_change_req -> ok" + "~n AR: ~p" + "~n Mid: ~p" + "~n", [AR, Mid]), + CR = + case AR of + #'ActionRequest'{commandRequests = [CmdReq]} -> + CmdReq; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Err4 = {invalid_termination_id, Tid}, + ED4 = cre_ErrDesc(Tid), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + case Parms of + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + AckData = [otp6865e2_mgc_service_change_reply_ar(Mid, 1)], + Reply = {discard_ack, AckData}, + {ok, AR, Reply}; + _ -> + Err5 = {invalid_SCP, Parms}, + ED5 = cre_ErrDesc(Parms), + ErrReply5 = {discard_ack, ED5}, + {error, Err5, ErrReply5} + end. + +-ifndef(megaco_hipe_special). +otp6865e2_mgc_verify_notify_req_fun(Cid, ExtraInfo, RequireAck) -> + fun(Req) -> + otp6865e2_mgc_verify_notify_req(Req, Cid, ExtraInfo, RequireAck) + end. +-endif. + +otp6865e2_mgc_verify_notify_req( + {handle_trans_request, _, ?VERSION, [AR], ExtraInfo}, + Cid, ExtraInfo, RequireAck) -> + (catch otp6865e2_mgc_do_verify_notify_req(AR, Cid, RequireAck)); +otp6865e2_mgc_verify_notify_req(Crap, _Cid, ExtraInfo, _RequireAck) -> + ED = cre_ErrDesc({Crap, ExtraInfo}), + ErrReply = {discard_ack, ED}, + {error, {Crap, ExtraInfo}, ErrReply}. + +otp6865e2_mgc_do_verify_notify_req(AR, Cid, RequireAck) -> + io:format("otp6865e2_mgc_do_verify_notify_req -> entry with" + "~n AR: ~p" + "~n Cid: ~p" + "~n RequireAck: ~p" + "~n", [AR, Cid, RequireAck]), + {ContextID, CR} = + case AR of + #'ActionRequest'{contextId = CtxID, + commandRequests = [CmdReq]} when (CtxID == Cid) -> + {CtxID, CmdReq}; + _ -> + Err1 = {invalid_action_request, AR}, + ED1 = cre_ErrDesc(AR), + ErrReply1 = {discard_ack, ED1}, + throw({error, Err1, ErrReply1}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + Err2 = {invalid_command_request, CR}, + ED2 = cre_ErrDesc(CR), + ErrReply2 = {discard_ack, ED2}, + throw({error, Err2, ErrReply2}) + end, + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + Err3 = {invalid_command, Cmd}, + ED3 = cre_ErrDesc(Cmd), + ErrReply3 = {discard_ack, ED3}, + throw({error, Err3, ErrReply3}) + end, + {Tid, OED} = + case NR of + #'NotifyRequest'{terminationID = [TermID], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + {TermID, ObsEvsDesc}; + _ -> + Err4 = {invalid_NR, NR}, + ED4 = cre_ErrDesc(NR), + ErrReply4 = {discard_ack, ED4}, + throw({error, Err4, ErrReply4}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + Err5 = {invalid_OED, OED}, + ED5 = cre_ErrDesc(NR), + ErrReply5 = {discard_ack, ED5}, + throw({error, Err5, ErrReply5}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + Replies = [otp6865e2_mgc_notify_reply_ar(ContextID, Tid)], + Reply = + case RequireAck of + true -> + {{handle_ack, otp6865e2}, Replies}; + false -> + {discard_ack, Replies} + end, + {ok, AR, Reply}; + _ -> + Err6 = {invalid_OE, OE}, + ED6 = cre_ErrDesc(OE), + ErrReply6 = {discard_ack, ED6}, + {error, Err6, ErrReply6} + end. + +%% Ack verification +-ifndef(megaco_hipe_special). +otp6865e2_mgc_verify_reply_ack_fun(ExtraInfo) -> + fun(M) -> + otp6865e2_mgc_verify_reply_ack(M, ExtraInfo) + end. +-endif. + +otp6865e2_mgc_verify_reply_ack( + {handle_trans_ack, _, ?VERSION, ok, otp6865e2, ExtraInfo}, ExtraInfo) -> + io:format("otp6865e2_mgc_verify_reply_ack -> ok~n", []), + {ok, ok, ok}; +otp6865e2_mgc_verify_reply_ack( + {handle_trans_ack, _, ?VERSION, AS, AD, ExtraInfo1} = Crap, ExtraInfo2) -> + io:format("otp6865e2_mgc_verify_reply_ack -> incorrect ack-status:" + "~n AS: ~p" + "~n AD: ~p" + "~n ExtraInfo1: ~p" + "~n ExtraInfo2: ~p" + "~n", [AS, AD, ExtraInfo1, ExtraInfo2]), + ED = cre_ErrDesc({invalid_ack_status, + {AS, AD, ExtraInfo1, ExtraInfo2}}), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}; +otp6865e2_mgc_verify_reply_ack(Crap, ExtraInfo) -> + io:format("otp6865e2_mgc_verify_reply_ack -> invalid ack:" + "~n Crap: ~p" + "~n ExtraInfo: ~p" + "~n", [Crap, ExtraInfo]), + ED = cre_ErrDesc({Crap, ExtraInfo}), + ErrReply = {discard_ack, ED}, + {error, Crap, ErrReply}. + + +%% Notify reply verification +-ifndef(megaco_hipe_special). +otp6865e2_mgc_verify_notify_reply_fun(ExtraInfo) -> + fun(Rep) -> + otp6865e2_mgc_verify_notify_reply(Rep, ExtraInfo) + end. +-endif. + +otp6865e2_mgc_verify_notify_reply( + {handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _, ExtraInfo}, ExtraInfo) -> + io:format("otp6865e2_mgc_verify_notify_reply -> ok" + "~n AR: ~p" + "~n ExtraInfo: ~p" + "~n", [AR, ExtraInfo]), + {ok, AR, ok}; +otp6865e2_mgc_verify_notify_reply(Else, ExtraInfo) -> + io:format("otp6865e2_mgc_verify_notify_reply -> received unknown event" + "~n Else: ~p" + "~n ExtraInfo: ~p" + "~n", [Else, ExtraInfo]), + {error, {Else, ExtraInfo}, ok}. + + +%% Disconnect verification +otp6865e2_mgc_verify_handle_disconnect( + {handle_disconnect, CH, ?VERSION, R}) -> + io:format("otp6865e2_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +otp6865e2_mgc_verify_handle_disconnect(Else) -> + io:format("otp6865e2_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +otp6865e2_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +otp6865e2_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +otp6865e2_mgc_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp6865e2_mg_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(otp6865e2_mg_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(otp6865e2_mg_verify_service_change_rep_msg_fun(), + {?MODULE, otp6865e2_mg_verify_service_change_rep_msg, []}). +-define(otp6865e2_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId, AckRequired), + {?MODULE, otp6865e2_mg_verify_notify_rep_msg, [TermId, TransId, ReqId, CtxId, AckRequired]}). +-define(otp6865e2_mg_verify_notify_req_msg_fun(), + {?MODULE, otp6865e2_mg_verify_notify_req_msg, []}). +-else. +-define(otp6865e2_mg_decode_msg_fun(Mod, Conf), + otp6865e2_mg_decode_msg_fun(Mod, Conf)). +-define(otp6865e2_mg_encode_msg_fun(Mod, Conf), + otp6865e2_mg_encode_msg_fun(Mod, Conf)). +-define(otp6865e2_mg_verify_service_change_rep_msg_fun(), + otp6865e2_mg_verify_service_change_rep_msg_fun()). +-define(otp6865e2_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId, AckRequired), + otp6865e2_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId, AckRequired)). +-define(otp6865e2_mg_verify_notify_req_msg_fun(), + otp6865e2_mg_verify_notify_req_msg_fun()). +-endif. + +otp6865e2_mg_event_sequence(text, tcp) -> + DecodeFun = ?otp6865e2_mg_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ?otp6865e2_mg_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mg"}, + ServiceChangeReq = otp6865e2_mg_service_change_request_msg(Mid, 1, 0), + ScrVerifyFun = ?otp6865e2_mg_verify_service_change_rep_msg_fun(), + TermId1 = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + TermId2 = #megaco_term_id{id = ["00000000","00000000","10010010"]}, + NotifyReq1 = + otp6865e2_mg_notify_request_msg(Mid, TermId1, 2, 1, 1), + NrVerifyFun1 = + ?otp6865e2_mg_verify_notify_rep_msg_fun(TermId1, 2, 1, 1, false), + NotifyReq2 = + otp6865e2_mg_notify_request_msg(Mid, TermId2, 3, 2, 2), + NrVerifyFun2 = + ?otp6865e2_mg_verify_notify_rep_msg_fun(TermId2, 3, 2, 2, true), + TransAck = otp6865e2_mg_trans_ack_msg(Mid, 3), + NotifyReqVerifyFun = ?otp6865e2_mg_verify_notify_req_msg_fun(), + NotifyReply = otp6865e2_mg_notify_reply_msg(Mid, 1, 0, TermId1), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {connect, 2944}, + + {send, "service-change-request", ServiceChangeReq}, + {expect_receive, "service-change-reply", {ScrVerifyFun, 10000}}, + + %% the original setting for reply timer is 2000 + {send, "notify request 1", NotifyReq1}, + {expect_receive, "notify-reply 1", {NrVerifyFun1, 2500}}, + {sleep, 1000}, + {send, "notify request 2", NotifyReq2}, + {expect_receive, "notify-reply 2", {NrVerifyFun2, 2500}}, + {sleep, 100}, + {send, "transacktion-ack", TransAck}, + {expect_receive, "notify-request", {NotifyReqVerifyFun, 2500}}, + {sleep, 100}, + {send, "notify-reply", NotifyReply}, + + {expect_nothing, 5000}, + disconnect + ], + EvSeq. + +-ifndef(megaco_hipe_special). +otp6865e2_mg_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +otp6865e2_mg_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +otp6865e2_mg_verify_service_change_rep_msg_fun() -> + fun(Msg) -> + (catch otp6865e2_mg_verify_service_change_rep_msg(Msg)) + end. +-endif. + +otp6865e2_mg_verify_service_change_rep_msg(#'MegacoMessage'{mess = Mess} = M) -> + Body = + case Mess of + #'Message'{version = _V, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = _Tid, + immAckRequired = asn1_NOVALUE, + transactionResult = TransRes} -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = _Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + SCRes = + case SCR of + #'ServiceChangeReply'{terminationID = _TermID, + serviceChangeResult = ServChRes} -> + ServChRes; + _ -> + throw({error, {invalid_serviceChangeReply, SCR}}) + end, + SCRP = + case SCRes of + {serviceChangeResParms, Parms} -> + Parms; + _ -> + throw({error, {invalid_serviceChangeResult, SCRes}}) + end, + case SCRP of + #'ServiceChangeResParm'{serviceChangeMgcId = _MgcMid} -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeResParms, SCRP}} + end; +otp6865e2_mg_verify_service_change_rep_msg(Crap) -> + {error, {invalid_message, Crap}}. + +-ifndef(megaco_hipe_special). +otp6865e2_mg_verify_notify_rep_msg_fun(TermId, TransId, Rid, Cid, + AckRequired) -> + fun(Msg) -> + (catch otp6865e2_mg_verify_notify_rep_msg(Msg, + TermId, TransId, + Rid, Cid, + AckRequired)) + end. +-endif. + +otp6865e2_mg_verify_notify_rep_msg(#'MegacoMessage'{mess = Mess} = M, + TermId, TransId, Rid, Cid, AckRequired) -> + io:format("otp6865e2_mg_verify_notify_rep_msg -> entry with" + "~n M: ~p" + "~n TermId: ~p" + "~n TransId: ~p" + "~n Rid: ~p" + "~n Cid: ~p" + "~n", [M, TermId, TransId, Rid, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + io:format("otp6865e2_mg_verify_notify_rep_msg -> " + "~n Body: ~p" + "~n", [Body]), + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + io:format("otp6865e2_mg_verify_notify_rep_msg -> " + "~n Trans: ~p" + "~n", [Trans]), + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + io:format("otp6865e2_mg_verify_notify_rep_msg -> " + "~n TR: ~p" + "~n", [TR]), + TRes = + case TR of + #'TransactionReply'{transactionId = TransId, + immAckRequired = asn1_NOVALUE, + transactionResult = TransRes} when (AckRequired == false) -> + TransRes; + #'TransactionReply'{transactionId = TransId, + immAckRequired = 'NULL', + transactionResult = TransRes} when (AckRequired == true) -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + io:format("otp6865e2_mg_verify_notify_rep_msg -> " + "~n TRes: ~p" + "~n", [TRes]), + AR = + case TRes of + {actionReplies, [ActRes]} -> + ActRes; + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + io:format("otp6865e2_mg_verify_notify_rep_msg -> " + "~n AR: ~p" + "~n", [AR]), + CR = + case AR of + #'ActionReply'{contextId = Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CmdRep]} -> + CmdRep; + _ -> + throw({error, {invalid_actionReplies, AR}}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + case NR of + #'NotifyReply'{terminationID = [TermId], + errorDescriptor = asn1_NOVALUE} -> + {ok, M}; + _ -> + {error, {invalid_notifyReply, NR}} + end; +otp6865e2_mg_verify_notify_rep_msg(Crap, _TermId, _TransId, _Rid, _Cid, _AckRequired) -> + {error, {invalid_message, Crap}}. + +-ifndef(megaco_hipe_special). +otp6865e2_mg_verify_notify_req_msg_fun() -> + fun(M) -> + otp6865e2_mg_verify_notify_req_msg(M) + end. +-endif. + +otp6865e2_mg_verify_notify_req_msg(#'MegacoMessage'{mess = Mess} = M) -> + io:format("otp6865e2_mg_verify_notify_req_msg -> entry with" + "~n M: ~p" + "~n", [M]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + io:format("otp6865e2_mg_verify_notify_req_msg -> " + "~n Body: ~p" + "~n", [Body]), + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + io:format("otp6865e2_mg_verify_notify_req_msg -> " + "~n Trans: ~p" + "~n", [Trans]), + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + io:format("otp6865e2_mg_verify_notify_req_msg -> " + "~n TR: ~p" + "~n", [TR]), + AR = + case TR of + #'TransactionRequest'{transactionId = _TransId, + actions = [ActReq]} -> + ActReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + io:format("otp6865e2_mg_verify_notify_req_msg -> " + "~n AR: ~p" + "~n", [AR]), + CR = + case AR of + #'ActionRequest'{contextId = _Cid, + commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_actions, AR}}) + end, + io:format("otp6865e2_mg_verify_notify_req_msg -> " + "~n CR: ~p" + "~n", [CR]), + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequests, CR}}) + end, + io:format("otp6865e2_mg_verify_notify_req_msg -> " + "~n Cmd: ~p" + "~n", [Cmd]), + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + io:format("otp6865e2_mg_verify_notify_req_msg -> " + "~n NR: ~p" + "~n", [NR]), + OED = + case NR of + #'NotifyRequest'{terminationID = [_TermId], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + ObsEvsDesc; + _ -> + throw({error, {invalid_notifyReq, NR}}) + end, + io:format("otp6865e2_mg_verify_notify_req_msg -> " + "~n OED: ~p" + "~n", [OED]), + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + throw({error, {invalid_observedEventsDescriptor, OED}}) + end, + io:format("otp6865e2_mg_verify_notify_req_msg -> " + "~n OE: ~p" + "~n", [OE]), + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + io:format("otp6865e2_mg_verify_notify_req_msg -> verifyed" + "~n", []), + {ok, M}; + _ -> + throw({error, {invalid_observedEventLst, OE}}) + end; +otp6865e2_mg_verify_notify_req_msg(M) -> + {error, {invalid_message, M}}. + +otp6865e2_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp6865e2_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = otp6865e2_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +otp6865e2_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp6865e2_mg_notify_request_msg(Mid, TermId, TransId, Rid, Cid) -> + AR = otp6865e2_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +otp6865e2_mg_notify_reply_msg(Mid, TransId, Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + AR = cre_actionReply(Cid, [CR]), + TRes = {actionReplies, [AR]}, + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +otp6865e2_mg_trans_ack_msg(Mid, TransId) -> + TR = cre_transRespAck(cre_transAck(TransId)), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_7189(suite) -> + []; +otp_7189(doc) -> + "..."; +otp_7189(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, otp_7189), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = otp_7189_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_tcp_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = otp_7189_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_tcp_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId], 60000), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_tcp_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp_7189_mgc_verify_handle_connect_fun(), + {?MODULE, otp_7189_mgc_verify_handle_connect, []}). +-define(otp_7189_mgc_verify_service_change_req_fun(Mid), + {?MODULE, otp_7189_mgc_verify_service_change_req, [Mid]}). +-define(otp_7189_mgc_verify_handle_trans_rep_fun(), + {?MODULE, otp_7189_mgc_verify_handle_trans_rep, []}). +-define(otp_7189_mgc_verify_handle_disconnect_fun(), + {?MODULE, otp_7189_mgc_verify_handle_disconnect, []}). +-else. +-define(otp_7189_mgc_verify_handle_connect_fun(), + otp_7189_mgc_verify_handle_connect_fun()). +-define(otp_7189_mgc_verify_service_change_req_fun(Mid), + otp_7189_mgc_verify_service_change_req_fun(Mid)). +-define(otp_7189_mgc_verify_handle_trans_rep_fun(), + otp_7189_mgc_verify_handle_trans_rep_fun()). +-define(otp_7189_mgc_verify_handle_disconnect_fun(), + fun otp_7189_mgc_verify_handle_disconnect/1). +-endif. + +otp_7189_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq = [otp_7189_mgc_notify_req_ar(1, Tid, 1)], + ConnectVerify = ?otp_7189_mgc_verify_handle_connect_fun(), + ScrVerify = ?otp_7189_mgc_verify_service_change_req_fun(Mid), + TransReplyVerify = ?otp_7189_mgc_verify_handle_trans_rep_fun(), + PendingCountersVerify1 = + fun([{Counter, 1}]) -> + io:format("received expected recv pending counter:" + "~n Counter: ~p" + "~n", [Counter]), + ok; + (BadCounters) -> + io:format("ERROR: " + "received unexpected number of " + "recv pending counters " + "(expected one with counter value 1):" + "~n BadCounters: ~p" + "~n", [BadCounters]), + {error, {invalid_pending_counters, BadCounters}} + end, + PendingCountersVerify2 = + fun([]) -> + io:format("received expected number of recv pending counters (none)" + "~n", []), + ok; + (BadCounters) -> + io:format("ERROR: " + "received unexpected number of " + "recv pending counters " + "(expected none):" + "~n BadCounters: ~p" + "~n", [BadCounters]), + {error, {invalid_pending_counters, BadCounters}} + end, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, recv_pending_limit, 10}, + + {megaco_update_user_info, long_request_timer, timer:seconds(10)}, + {megaco_user_info, all}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_conn_info, all}, + {megaco_callback, handle_trans_request, ScrVerify}, + {sleep, 500}, + {megaco_cast, NotifyReq, []}, + + %% Wait for 5 seconds to make sure we are on track + {megaco_callback, nocall, timer:seconds(5)}, + {megaco_system_info, recv_pending_counters, PendingCountersVerify1}, + + %% Now wait for the timeout to hit + {megaco_callback, handle_trans_reply, TransReplyVerify}, + {megaco_system_info, recv_pending_counters, PendingCountersVerify2}, + + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +-ifndef(megaco_hipe_special). +otp_7189_mgc_verify_handle_connect_fun() -> + fun(M) -> + otp_7189_mgc_verify_handle_connect(M) + end. +-endif. + +otp_7189_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + {ok, CH, ok}; +otp_7189_mgc_verify_handle_connect(Else) -> + {error, Else, ok}. + +-ifndef(megaco_hipe_special). +otp_7189_mgc_verify_service_change_req_fun(Mid) -> + fun(Req) -> + otp_7189_mgc_verify_service_change_req(Req, Mid) + end. +-endif. + +otp_7189_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("otp_7189_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [otp_7189_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = otp_7189_err_desc(Parms), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = otp_7189_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = otp_7189_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = otp_7189_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = otp_7189_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +otp_7189_mgc_verify_service_change_req(Else, _Mid) -> + io:format("otp_7189_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = otp_7189_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +otp_7189_mgc_notify_req_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp_7189_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + AR. + +-ifndef(megaco_hipe_special). +otp_7189_mgc_verify_handle_trans_rep_fun() -> + fun(Event) -> + (catch otp_7189_mgc_verify_handle_trans_rep(Event)) + end. +-endif. + +otp_7189_mgc_verify_handle_trans_rep( + {handle_trans_reply, CH, ?VERSION, {error, timeout} = Error, _}) -> + io:format("otp_6275_mgc_verify_trans_rep -> expected error" + "~n CH: ~p" + "~n", [CH]), + {ok, Error, error}; +otp_7189_mgc_verify_handle_trans_rep( + {handle_trans_reply, _CH, ?VERSION, Error, _}) -> + io:format("otp_6275_mgc_verify_handle_trans_rep -> unexpected error" + "~n Error: ~p" + "~n", [Error]), + {error, Error, error}; +otp_7189_mgc_verify_handle_trans_rep(Else) -> + io:format("otp_6275_mg_verify_handle_trans_rep -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, error}. + + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp_7189_mg_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(otp_7189_mg_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(otp_7189_mg_verify_service_change_rep_msg_fun(), + {?MODULE, otp_7189_mg_verify_service_change_rep_msg, []}). +-define(otp_7189_mg_verify_notify_req_msg_fun(TermId, TransId, ReqId, CtxId), + {?MODULE, otp_7189_mg_verify_notify_req_msg, [TermId, TransId, ReqId, CtxId]}). +-else. +-define(otp_7189_mg_decode_msg_fun(Mod, Conf), + otp_7189_mg_decode_msg_fun(Mod, Conf)). +-define(otp_7189_mg_encode_msg_fun(Mod, Conf), + otp_7189_mg_encode_msg_fun(Mod, Conf)). +-define(otp_7189_mg_verify_service_change_rep_msg_fun(), + otp_7189_mg_verify_service_change_rep_msg_fun()). +-define(otp_7189_mg_verify_notify_req_msg_fun(TermId, TransId, ReqId, CtxId), + otp_7189_mg_verify_notify_req_msg_fun(TermId, TransId, ReqId, CtxId)). +-endif. + +otp_7189_mg_event_sequence(text, tcp) -> + DecodeFun = ?otp_7189_mg_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ?otp_7189_mg_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mg"}, + ServiceChangeReq = otp_7189_mg_service_change_request_msg(Mid, 1, 0), + TermId = + #megaco_term_id{id = ["00000000","00000000","01101101"]}, + TransId = 1, + ReqId = 1, + CtxId = 1, + Pending = otp_7189_mg_trans_pending_msg(Mid, TransId), + ServiceChangeReplyVerifyFun = + ?otp_7189_mg_verify_service_change_rep_msg_fun(), + NotifyReqVerify = ?otp_7189_mg_verify_notify_req_msg_fun(TermId, TransId, ReqId, CtxId), + EvSeq = [ + {debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {connect, 2944}, + {send, "service-change-request", ServiceChangeReq}, + {expect_receive, "service-change-reply", {ServiceChangeReplyVerifyFun, 2000}}, + {expect_receive, "notify request", {NotifyReqVerify, 2000}}, + {sleep, 100}, + {send, "pending", Pending}, + {expect_closed, timer:seconds(120)}, + disconnect + ], + EvSeq. + +otp_7189_mg_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. + +otp_7189_mg_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. + +otp_7189_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp_7189_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = otp_7189_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +-ifndef(megaco_hipe_special). +otp_7189_mg_verify_service_change_rep_msg_fun() -> + fun(M) -> + otp_7189_mg_verify_service_change_rep_msg(M) + end. +-endif. + +otp_7189_mg_verify_service_change_rep_msg( + #'MegacoMessage'{mess = Mess} = M) -> + io:format("otp_7189_mg_verify_service_change_rep_msg -> " + "ok so far~n",[]), + #'Message'{version = _V, + mId = _MgMid, + messageBody = Body} = Mess, + {transactions, [Trans]} = Body, + {transactionReply, TR} = Trans, + #'TransactionReply'{transactionId = _Tid, + immAckRequired = asn1_NOVALUE, + transactionResult = Res} = TR, + {actionReplies, [AR]} = Res, + #'ActionReply'{contextId = _Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CR]} = AR, + {serviceChangeReply, SCR} = CR, + #'ServiceChangeReply'{terminationID = _TermID, + serviceChangeResult = SCRes} = SCR, + {serviceChangeResParms, SCRP} = SCRes, + #'ServiceChangeResParm'{serviceChangeMgcId = _MgcMid} = SCRP, + {ok, M}; +otp_7189_mg_verify_service_change_rep_msg(M) -> + {error, {invalid_message, M}}. + +-ifndef(megaco_hipe_special). +otp_7189_mg_verify_notify_req_msg_fun(TermId, TransId, Rid, Cid) -> + fun(Msg) -> + (catch otp_7189_mg_verify_notify_req_msg(Msg, + TermId, + TransId, Rid, Cid)) + end. +-endif. + +otp_7189_mg_verify_notify_req_msg(#'MegacoMessage'{mess = Mess} = M, + TermId, TransId, Rid, Cid) -> + io:format("otp_7189_mgc_verify_notify_req_msg -> entry with" + "~n M: ~p" + "~n TermId: ~p" + "~n TransId: ~p" + "~n Rid: ~p" + "~n Cid: ~p" + "~n", [M, TermId, TransId, Rid, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = TransId, + actions = [ActReq]} -> + ActReq; + _ -> + throw({error, {invalid_transactionRequest, TR, TransId}}) + end, + CR = + case AR of + #'ActionRequest'{contextId = Cid, + commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_actions, AR}}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequests, CR}}) + end, + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + OED = + case NR of + #'NotifyRequest'{terminationID = [TermId], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + ObsEvsDesc; + _ -> + throw({error, {invalid_notifyReq, NR}}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + throw({error, {invalid_observedEventsDescriptor, OED}}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + {ok, M}; + _ -> + throw({error, {invalid_observedEventLst, OE}}) + end; +otp_7189_mg_verify_notify_req_msg(Crap, _TermId, _TransId, _Rid, _Cid) -> + {error, {invalid_MegacoMessage, Crap}}. + + +otp_7189_mg_trans_pending_msg(Mid, TransId) -> + TP = #'TransactionPending'{transactionId = TransId}, + Body = {transactions, [{transactionPending, TP}]}, + Mess = #'Message'{version = 1, + mId = Mid, + messageBody = Body}, + #'MegacoMessage'{mess = Mess}. + + +otp_7189_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +otp_7259(suite) -> + []; +otp_7259(doc) -> + ["This is a variant of ticket OTP-6442"]; +otp_7259(Config) when is_list(Config) -> + put(verbosity, debug), + put(sname, "TEST"), + put(tc, otp7259rr), + i("starting"), + + MgNode = make_node_name(mg), + d("start (MG) node: ~p", [MgNode]), + ok = megaco_test_lib:start_nodes([MgNode], ?FILE, ?LINE), + + d("[MG] start the simulator "), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgMid = {deviceName,"mg"}, + MgEvSeq = otp_7259_mg_event_sequence(MgMid), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + i("await the transport module service change send_message event"), + Pid = otp_7259_expect(fun otp_7259_verify_scr_msg/1, 5000), + + i("wait some before issuing the service change reply"), + sleep(500), + + i("send the service change reply"), + MgcMid = {deviceName,"mgc"}, + ServiceChangeReply = otp_7259_mgc_service_change_reply_msg(MgcMid, 1, 1), + megaco_test_generic_transport:incomming_message(Pid, ServiceChangeReply), + + i("await the transport module " + "notify-request send_message event from MG: " + "ignore"), + ok = otp_7259_expect(fun otp_7259_verify_first_nr_msg/1, 5000), + + i("await the transport module " + "notify-request resend_message event from MG: " + "reply"), + {TransId2, Cid2, TermId2} = + otp_7259_expect(fun otp_7259_verify_second_nr_msg/1, 10000), + + i("wait some before issuing the notify reply"), + sleep(500), + + i("send the notify reply"), + NotifyReply = + otp_7259_mgc_notify_reply_msg(MgcMid, TransId2, Cid2, TermId2), + megaco_test_generic_transport:incomming_message(Pid, NotifyReply), + + d("[MG] await the generator reply"), + await_completion([MgId], 5000), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +otp_7259_expect(Verify, Timeout) when (Timeout > 0) -> + T = mtime(), + receive + Msg -> + case (catch Verify(Msg)) of + {ok, Result} -> + d("verified after ~p msec", [mtime() - T]), + Result; + skip -> + otp_7259_expect(Verify, to(Timeout, T)); + {error, Reason} -> + exit({verification_failed, Reason}) + end + after Timeout -> + exit(timeout) + end; +otp_7259_expect(_, _Timeout) -> + exit(timeout). + +otp_7259_verify_scr_msg( + {transport_event, {send_message, _SH, {message, Msg, Resend}}, Pid}) + when is_record(Msg, 'MegacoMessage') andalso ((Resend =:= true) orelse (Resend =:= false)) -> + d("received expected service change request message: " + "~n Msg: ~p" + "~n Resend: ~p", [Msg, Resend]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + {ok, Pid}; +otp_7259_verify_scr_msg(Msg) -> + {error, {invalid_message, Msg}}. + +otp_7259_verify_first_nr_msg( + {transport_event, {send_message, _SH, {message, Msg, Resend}}, Pid}) + when is_record(Msg, 'MegacoMessage') andalso ((Resend =:= true) orelse (Resend =:= false)) -> + d("received expected first notify request send message: " + "~n Msg: ~p", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + {ok, ok}; +otp_7259_verify_first_nr_msg(Msg) -> + {error, {invalid_message, Msg}}. + +otp_7259_verify_second_nr_msg( + {transport_event, {send_message, _SH, {message, Msg, Resend}}, Pid}) + when is_record(Msg, 'MegacoMessage') andalso ((Resend =:= true) orelse (Resend =:= false)) -> + d("received expected second notify request send message: " + "~n Msg: ~p", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + #'MegacoMessage'{mess = Mess} = Msg, + #'Message'{mId = _Mid, + messageBody = Body} = Mess, + {transactions, Transactions} = Body, + [Transaction] = Transactions, + {transactionRequest, TransReq} = Transaction, + #'TransactionRequest'{transactionId = TransId, + actions = Actions} = TransReq, + [Action] = Actions, + #'ActionRequest'{contextId = Cid, + commandRequests = CmdReqs} = Action, + [CmdReq] = CmdReqs, + #'CommandRequest'{command = Cmd} = CmdReq, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [TermId]} = NR, + {ok, {TransId, Cid, TermId}}; +otp_7259_verify_second_nr_msg(Msg) -> + {error, {invalid_message, Msg}}. + + +otp_7259_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + SCRP = #'ServiceChangeResParm'{serviceChangeMgcId = Mid}, + SCRPs = {serviceChangeResParms, SCRP}, + Root = #megaco_term_id{id = ["root"]}, + SCR = #'ServiceChangeReply'{terminationID = [Root], + serviceChangeResult = SCRPs}, + CR = {serviceChangeReply, SCR}, + otp_7259_mgc_reply_msg(Mid, TransId, CR, Cid). + +otp_7259_mgc_notify_reply_msg(Mid, TransId, Cid, TermId) -> + NR = #'NotifyReply'{terminationID = [TermId]}, + CR = {notifyReply, NR}, + otp_7259_mgc_reply_msg(Mid, TransId, CR, Cid). + +otp_7259_mgc_reply_msg(Mid, TransId, CR, Cid) -> + AR = #'ActionReply'{contextId = Cid, + commandReply = [CR]}, + ARs = {actionReplies, [AR]}, + TR = #'TransactionReply'{transactionId = TransId, + transactionResult = ARs}, + Body = {transactions, [{transactionReply, TR}]}, + Mess = #'Message'{version = 1, + mId = Mid, + messageBody = Body}, + #'MegacoMessage'{mess = Mess}. + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp_7259_mg_verify_handle_connect_fun(), + {?MODULE, otp_7259_mg_verify_handle_connect, []}). +-define(otp_7259_mg_verify_service_change_rep_fun(), + {?MODULE, otp_7259_mg_verify_service_change_rep, []}). +-define(otp_7259_mg_verify_notify_rep_fun(), + {?MODULE, otp_7259_mg_verify_notify_rep, []}). +-else. +-define(otp_7259_mg_verify_handle_connect_fun(), + otp_7259_mg_verify_handle_connect_fun()). +-define(otp_7259_mg_verify_service_change_rep_fun(), + otp_7259_mg_verify_service_change_rep_fun()). +-define(otp_7259_mg_verify_notify_rep_fun(), + otp_7259_mg_verify_notify_rep_fun()). +-endif. + +otp_7259_mg_event_sequence(Mid) -> + RI = [ + {port, self()}, % This is just a trick to get my pid to the transport module + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_test_generic_transport} + ], + ServiceChangeReq = + otp_7259_mg_service_change_request_ar(Mid, 1), + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq = otp_7259_mg_notify_request_ar(1, Tid, 1), + ConnectVerify = + ?otp_7259_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = + ?otp_7259_mg_verify_service_change_rep_fun(), + NotifyReplyVerify = + ?otp_7259_mg_verify_notify_rep_fun(), + EvSeq = [ + {debug, false}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, resend_indication, flag}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_cast, [NotifyReq], []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +-ifndef(megaco_hipe_special). +otp_7259_mg_verify_handle_connect_fun() -> + fun(Ev) -> + otp_7259_mg_verify_handle_connect(Ev) + end. +-endif. + +otp_7259_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("otp_7259_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +otp_7259_mg_verify_handle_connect(Else) -> + io:format("otp_7259_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +-ifndef(megaco_hipe_special). +otp_7259_mg_verify_service_change_rep_fun() -> + fun(Rep) -> + otp_7259_mg_verify_service_change_rep(Rep) + end. +-endif. + +otp_7259_mg_verify_service_change_rep( + {handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> + (catch otp_7259_mg_do_verify_service_change_rep(AR)); +otp_7259_mg_verify_service_change_rep(Crap) -> + {error, Crap, ok}. + +otp_7259_mg_do_verify_service_change_rep(AR) -> + io:format("otp_7259_mg_verify_service_change_rep -> ok" + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +-ifndef(megaco_hipe_special). +otp_7259_mg_verify_notify_rep_fun() -> + fun(Rep) -> + otp_7259_mg_verify_notify_rep(Rep) + end. +-endif. + +otp_7259_mg_verify_notify_rep( + {handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> + io:format("otp_7259_mg_verify_notify_rep -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +otp_7259_mg_verify_notify_rep(Else) -> + io:format("otp_7259_mg_verify_notify_rep -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +otp_7259_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp_7259_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_7713(suite) -> + []; +otp_7713(doc) -> + []; +otp_7713(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + + put(verbosity, debug), + put(sname, "TEST"), + put(tc, otp7713), + i("starting"), + + d("start proxy",[]), + megaco_mess_user_test:start_proxy(), + + Extra = otp7713_extra, + PrelMid = preliminary_mid, + MgMid = ipv4_mid(4711), + MgcMid = ipv4_mid(), + UserMod = megaco_mess_user_test, + d("start megaco app",[]), + ?VERIFY(ok, application:start(megaco)), + UserConfig = [{user_mod, UserMod}, {send_mod, UserMod}, + {request_timer, infinity}, {reply_timer, infinity}], + d("start (MG) user ~p",[MgMid]), + ?VERIFY(ok, megaco:start_user(MgMid, UserConfig)), + + d("start (MGC) user ~p",[MgcMid]), + ?VERIFY(ok, megaco:start_user(MgcMid, UserConfig)), + + d("get receive info for ~p",[MgMid]), + MgRH = user_info(MgMid, receive_handle), + d("get receive info for ~p",[MgcMid]), + MgcRH = user_info(MgcMid, receive_handle), + d("start transport",[]), + {ok, MgPid, MgSH} = + ?VERIFY({ok, _, _}, UserMod:start_transport(MgRH, MgcRH)), + PrelMgCH = #megaco_conn_handle{local_mid = MgMid, + remote_mid = preliminary_mid}, + MgCH = #megaco_conn_handle{local_mid = MgMid, + remote_mid = MgcMid}, + MgcCH = #megaco_conn_handle{local_mid = MgcMid, + remote_mid = MgMid}, + d("(MG) try connect to MGC",[]), + ?SEND(megaco:connect(MgRH, PrelMid, MgSH, MgPid, Extra)), % Mg prel + d("await connect from MG", []), + ?USER({connect, PrelMgCH, _V, [Extra]}, ok), + ?RECEIVE([{res, _, {ok, PrelMgCH}}]), + + d("(MG) send service change request",[]), + Req = service_change_request(), + ?SEND(megaco:call(PrelMgCH, [Req], [])), + + d("(MGC) send service change reply",[]), + ?USER({connect, MgcCH, _V, []}, ok), % Mgc auto + Rep = service_change_reply(MgcMid), + ?USER({request, MgcCH, _V, [[Req]]}, {discard_ack, [Rep]}), + ?USER({connect, MgCH, _V, []}, ok), % Mg confirm + ?RECEIVE([{res, _, {1, {ok, [Rep]}}}]), + + d("get (system info) connections",[]), + connections([MgCH, MgcCH]), + d("get (~p) connections",[MgMid]), + ?VERIFY([MgCH], megaco:user_info(MgMid, connections)), + d("get (~p) connections",[MgcMid]), + ?VERIFY([MgcCH], megaco:user_info(MgcMid, connections)), + + Reason = shutdown, + d("(MG) disconnect",[]), + ?SEND(megaco:disconnect(MgCH, Reason)), + ?USER({disconnect, MgCH, _V, [{user_disconnect, Reason}]}, ok), + ?RECEIVE([{res, _, ok}]), + ?VERIFY(ok, megaco:stop_user(MgMid)), + + d("(MGC) disconnect",[]), + ?SEND(megaco:disconnect(MgcCH, Reason)), + ?USER({disconnect, MgcCH, _V, [{user_disconnect, Reason}]}, ok), + ?RECEIVE([{res, _, ok}]), + ?VERIFY(ok, megaco:stop_user(MgcMid)), + + d("stop megaco app",[]), + ?VERIFY(ok, application:stop(megaco)), + ?RECEIVE([]), + + d("done",[]), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_8183_request1(suite) -> + []; +otp_8183_request1(Config) when is_list(Config) -> + put(verbosity, debug), + put(sname, "TEST"), + put(tc, otp8183r1), + i("starting"), + + MgNode = make_node_name(mg), + d("start (MG) node: ~p", [MgNode]), + ok = megaco_test_lib:start_nodes([MgNode], ?FILE, ?LINE), + + d("[MG] start the simulator "), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgMid = {deviceName,"mg"}, + MgEvSeq = otp_8183_r1_mg_event_sequence(MgMid), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + i("await the transport module service change send_message event"), + Pid = otp_8183_expect(fun(Ev) -> otp_8183_r1_verify_scr_msg(Ev) end, 5000), + + i("wait some before issuing the service change reply"), + sleep(500), + + i("send the service change reply"), + MgcMid = {deviceName,"mgc"}, + ServiceChangeReply = otp_8183_r1_mgc_service_change_reply_msg(MgcMid, 1, 1), + megaco_test_generic_transport:incomming_message(Pid, ServiceChangeReply), + + i("await the transport module " + "notify-request send_message event from MG: " + "ignore"), + {TransId2, Cid2, TermId2} = + otp_8183_expect(fun(Ev) -> otp_8183_r1_verify_nr_msg(Ev) end, 5000), + + i("wait some before issuing the notify reply (twice)"), + sleep(500), + + i("send the notify reply, twice times"), + NotifyReply = + otp_8183_r1_mgc_notify_reply_msg(MgcMid, TransId2, Cid2, TermId2), + megaco_test_generic_transport:incomming_message(Pid, NotifyReply), + megaco_test_generic_transport:incomming_message(Pid, NotifyReply), + + d("await the generator reply"), + await_completion([MgId]), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +otp_8183_expect(Verify, Timeout) when (Timeout > 0) -> + T = mtime(), + receive + Msg -> + case (catch Verify(Msg)) of + {ok, Result} -> + d("verified after ~p msec", [mtime() - T]), + Result; + skip -> + otp_8183_expect(Verify, to(Timeout, T)); + {error, Reason} -> + exit({verification_failed, Reason}) + end + after Timeout -> + exit(timeout) + end; +otp_8183_expect(_, _Timeout) -> + exit(timeout). + +otp_8183_r1_verify_scr_msg( + {transport_event, {send_message, _SH, {message, Msg}}, Pid}) + when is_record(Msg, 'MegacoMessage') -> + d("received expected service change request message: " + "~n Msg: ~p", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + {ok, Pid}; +otp_8183_r1_verify_scr_msg( + {transport_event, {send_message, _SH, BadMsg}, _Pid}) -> + io:format("otp_8183_r1_verify_scr_msg -> error: " + "~n BadMsg: ~p" + "~n", [BadMsg]), + {error, {invalid_message, BadMsg}}; +otp_8183_r1_verify_scr_msg({transport_event, BadEvent, _Pid}) -> + io:format("otp_8183_r1_verify_scr_msg -> error: " + "~n BadEvent: ~p" + "~n", [BadEvent]), + {error, {invalid_message, BadEvent}}; +otp_8183_r1_verify_scr_msg(Msg) -> + io:format("otp_8183_r1_verify_scr_msg -> error: " + "~n Msg: ~p" + "~n", [Msg]), + {error, {invalid_message, Msg}}. + +otp_8183_r1_verify_nr_msg( + {transport_event, {send_message, _SH, {message, Msg}}, Pid}) + when is_record(Msg, 'MegacoMessage') -> + io:format("otp_8183_r1_verify_nr_msg -> " + "entry when received expected message with" + "~n Msg: ~p" + "~n", [Msg]), + Reply = ok, + Pid ! {transport_reply, Reply, self()}, + #'MegacoMessage'{mess = Mess} = Msg, + #'Message'{mId = _Mid, + messageBody = Body} = Mess, + {transactions, Transactions} = Body, + [Transaction] = Transactions, + {transactionRequest, TransReq} = Transaction, + #'TransactionRequest'{transactionId = TransId, + actions = Actions} = TransReq, + [Action] = Actions, + #'ActionRequest'{contextId = Cid, + commandRequests = CmdReqs} = Action, + [CmdReq] = CmdReqs, + #'CommandRequest'{command = Cmd} = CmdReq, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [TermId]} = NR, + {ok, {TransId, Cid, TermId}}; +otp_8183_r1_verify_nr_msg(Msg) -> + io:format("otp_8183_r1_verify_nr_msg -> entry when error with" + "~n Msg: ~p" + "~n", [Msg]), + {error, {invalid_message, Msg}}. + +otp_8183_r1_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + SCRP = #'ServiceChangeResParm'{serviceChangeMgcId = Mid}, + SCRPs = {serviceChangeResParms, SCRP}, + Root = #megaco_term_id{id = ["root"]}, + SCR = #'ServiceChangeReply'{terminationID = [Root], + serviceChangeResult = SCRPs}, + CR = {serviceChangeReply, SCR}, + otp_8183_r1_mgc_reply_msg(Mid, TransId, CR, Cid). + +otp_8183_r1_mgc_notify_reply_msg(Mid, TransId, Cid, TermId) -> + NR = #'NotifyReply'{terminationID = [TermId]}, + CR = {notifyReply, NR}, + otp_8183_r1_mgc_reply_msg(Mid, TransId, CR, Cid). + +otp_8183_r1_mgc_reply_msg(Mid, TransId, CR, Cid) -> + AR = #'ActionReply'{contextId = Cid, + commandReply = [CR]}, + ARs = {actionReplies, [AR]}, + TR = #'TransactionReply'{transactionId = TransId, + transactionResult = ARs}, + Body = {transactions, [{transactionReply, TR}]}, + Mess = #'Message'{version = 1, + mId = Mid, + messageBody = Body}, + #'MegacoMessage'{mess = Mess}. + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp_8183_r1_mg_verify_handle_connect_fun(), + {?MODULE, otp_8183_r1_mg_verify_handle_connect, []}). +-define(otp_8183_r1_mg_verify_service_change_rep_fun(), + {?MODULE, otp_8183_r1_mg_verify_service_change_rep, []}). +-define(otp_8183_r1_mg_verify_notify_rep_fun(Nr + {?MODULE, otp_8183_r1_mg_verify_notify_rep, [Nr). +-else. +-define(otp_8183_r1_mg_verify_handle_connect_fun(), + otp_8183_r1_mg_verify_handle_connect_fun()). +-define(otp_8183_r1_mg_verify_service_change_rep_fun(), + otp_8183_r1_mg_verify_service_change_rep_fun()). +-define(otp_8183_r1_mg_verify_notify_rep_fun(Nr), + otp_8183_r1_mg_verify_notify_rep_fun(Nr)). +-endif. + +otp_8183_r1_mg_event_sequence(Mid) -> + RI = [ + {port, self()}, % This is just a trick to get my pid to the transport module + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_test_generic_transport} + ], + ServiceChangeReq = + otp_8183_r1_mg_service_change_request_ar(Mid, 1), + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq = otp_8183_r1_mg_notify_request_ar(1, Tid, 1), + ConnectVerify = + ?otp_8183_r1_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = + ?otp_8183_r1_mg_verify_service_change_rep_fun(), + NotifyReplyVerify = + fun(Nr) -> + ?otp_8183_r1_mg_verify_notify_rep_fun(Nr) + end, + EvSeq = [ + {debug, true}, % false}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + + {sleep, 1000}, + {megaco_cast, [NotifyReq], [{request_keep_alive_timeout, 5000}]}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify(1)}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify(2)}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +-ifndef(megaco_hipe_special). +otp_8183_r1_mg_verify_handle_connect_fun() -> + fun(Ev) -> + otp_8183_r1_mg_verify_handle_connect(Ev) + end. +-endif. + +otp_8183_r1_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("otp_8183_r1_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +otp_8183_r1_mg_verify_handle_connect(Else) -> + io:format("otp_8183_r1_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +-ifndef(megaco_hipe_special). +otp_8183_r1_mg_verify_service_change_rep_fun() -> + fun(Rep) -> + otp_8183_r1_mg_verify_service_change_rep(Rep) + end. +-endif. + +otp_8183_r1_mg_verify_service_change_rep( + {handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> + (catch otp_8183_r1_mg_do_verify_service_change_rep(AR)); +otp_8183_r1_mg_verify_service_change_rep(Crap) -> + io:format("otp_8183_r1_mg_verify_service_change_rep -> crap" + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + +otp_8183_r1_mg_do_verify_service_change_rep(AR) -> + io:format("otp_8183_r1_mg_do_verify_service_change_rep -> ok" + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +-ifndef(megaco_hipe_special). +otp_8183_r1_mg_verify_notify_rep_fun(Nr) -> + fun(Rep) -> + otp_8183_r1_mg_verify_notify_rep(Nr, Rep) + end. +-endif. + +otp_8183_r1_mg_verify_notify_rep(Nr, + {handle_trans_reply, _CH, ?VERSION, {ok, Nr, [AR]}, _}) -> + io:format("otp_8183_r1_mg_verify_notify_rep -> ok" + "~n Nr: ~p" + "~n AR: ~p" + "~n", [Nr, AR]), + {ok, AR, ok}; +otp_8183_r1_mg_verify_notify_rep(Nr, Else) -> + io:format("otp_8183_r1_mg_verify_notify_rep -> unknown" + "~n Nr: ~p" + "~n Else: ~p" + "~n", [Nr, Else]), + {error, Else, ok}. + + +otp_8183_r1_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp_8183_r1_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp8212_scr(MidStr) -> + Msg = "!/1 " ++ MidStr ++ " T=19731{C=-{SC=ROOT{SV{MT=RS,RE=\"901\"}}}}", + list_to_binary(Msg). + +otp_8212(suite) -> + []; +otp_8212(doc) -> + []; +otp_8212(Config) when is_list(Config) -> + %% ?ACQUIRE_NODES(1, Config), + + put(verbosity, debug), + put(sname, "TEST"), + put(tc, otp8212), + i("starting"), + + Extra = otp8212_extra, + NoMid = preliminary_mid, + LocalMid = {deviceName, "MGC"}, + RemoteMidStr1 = "bgf1", + RemoteMid1 = {deviceName, RemoteMidStr1}, + RemoteMidStr2 = "bgf2", + RemoteMid2 = {deviceName, RemoteMidStr2}, + UserMod = megaco_mess_otp8212_test, + + d("set megaco trace level to max",[]), + megaco:enable_trace(max, io), + + d("start megaco app",[]), + ?VERIFY(ok, application:start(megaco)), + + d("start local user (MGC) ~p", [LocalMid]), + UserConfig = [{user_mod, UserMod}, {send_mod, UserMod}], + ?VERIFY(ok, megaco:start_user(LocalMid, UserConfig)), + + d("get (MGC) receive info for ~p", [LocalMid]), + RH0 = user_info(LocalMid, receive_handle), + RH = RH0#megaco_receive_handle{encoding_mod = megaco_mess_otp8212_test, + encoding_config = []}, + + d("do a pre-connect for ~p", [LocalMid]), + ControlPid = self(), + SendHandle = {RH, ControlPid, RemoteMidStr1, RemoteMidStr2}, + ?VERIFY({ok, _}, megaco:connect(RH, NoMid, SendHandle, ControlPid)), + + d("simulate incomming service change message from ~p", + [RemoteMidStr1]), + ?VERIFY(ok, + megaco:process_received_message(RH, ControlPid, + otp8212_scr, + otp8212_scr(RemoteMidStr1))), + + d("get the updated connection handle", []), + [CH] = megaco:user_info(LocalMid, connections), + + d("verify connection with ~p", [RemoteMidStr1]), + ?VERIFY(RemoteMid1, megaco:conn_info(CH, remote_mid)), + + d("send a request to ~p but receive no reply but an unexpected call", + [RemoteMidStr1]), + Res = megaco:call(CH, ["action request"], [{request_timer, 2000}]), + d("request result: ~p", [Res]), + ?VERIFY({1, [{error, {wrong_mid, RemoteMid2, RemoteMid1, _}, {Extra, _}}]}, Res), + + Conns = disconnect_all(LocalMid), + await_disconnected(Conns), + + d("stop megaco user ~p",[LocalMid]), + ok = await_stopped_user(LocalMid), + + d("stop megaco app",[]), + ?VERIFY(ok, application:stop(megaco)), + ?RECEIVE([]), + + d("done",[]), + ok. + +disconnect_all(LocalMid) -> + Conns = megaco:user_info(LocalMid, connections), + d("[~p] disconnect from all connections: ~n~p", [LocalMid, Conns]), + lists:foreach( + fun(Conn) -> + d("[~p] disconnect from connection ~p", [LocalMid, Conn]), + DiscoRes = megaco:disconnect(Conn, {otp8212_done, self()}), + d("[~p] disconnect result: ~p", [LocalMid, DiscoRes]) + end, + Conns), + Conns. + +await_disconnected([]) -> + ok; +await_disconnected(Conns) -> + receive + {disconnected, Conn} -> + d("disconnected: ~p", [Conn]), + Conns2 = lists:delete(Conn, Conns), + await_disconnected(Conns2) + end. + + +await_stopped_user(LocalMid) -> + await_stopped_user(LocalMid, 10). + +await_stopped_user(LocalMid, N) when N =< 0 -> + ?ERROR({failed_stopping_user, LocalMid}); +await_stopped_user(LocalMid, N) -> + case megaco:stop_user(LocalMid) of + ok -> + d("user stopped(~w)", [N]), + ok; + {error, {active_connections, _}} -> + d("still active connections when N = ~w", [N]), + Conns = disconnect_all(LocalMid), + await_disconnected(Conns), + ?SLEEP(500), + await_stopped_user(LocalMid, N-1) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +cre_ErrDesc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +cre_serviceChangeParm(M,R,P) -> + #'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeReason = R, + serviceChangeProfile = P}. + +cre_serviceChangeParm(M, V, R, P) -> + #'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeVersion = V, + serviceChangeReason = R, + serviceChangeProfile = P}. + +cre_serviceChangeReq(Tid, Parms) -> + #'ServiceChangeRequest'{terminationID = Tid, + serviceChangeParms = Parms}. + +cre_timeNotation(D,T) -> + #'TimeNotation'{date = D, time = T}. + +cre_obsEvent(Name, Not) -> + #'ObservedEvent'{eventName = Name, + timeNotation = Not}. + +cre_obsEvsDesc(Id, EvList) -> + #'ObservedEventsDescriptor'{requestId = Id, + observedEventLst = EvList}. + +cre_notifyReq(Tid, EvsDesc) -> + #'NotifyRequest'{terminationID = Tid, + observedEventsDescriptor = EvsDesc}. + +cre_command(R) when is_record(R, 'NotifyRequest') -> + {notifyReq, R}; +cre_command(R) when is_record(R, 'ServiceChangeRequest') -> + {serviceChangeReq, R}. + +cre_cmdReq(Cmd) -> + #'CommandRequest'{command = Cmd}. + +cre_actionReq(CtxId, CmdReqs) when is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxId, + commandRequests = CmdReqs}. + +cre_transReq(TransId, ARs) when is_list(ARs) -> + #'TransactionRequest'{transactionId = TransId, + actions = ARs}. + +cre_transResult(ED) when is_record(ED, 'ErrorDescriptor') -> + {transactionError, ED}; +cre_transResult([AR|_] = ARs) when is_record(AR, 'ActionReply') -> + {actionReplies, ARs}. + +cre_transReply(TransId, Res) -> + #'TransactionReply'{transactionId = TransId, + transactionResult = Res}. + +cre_transReply(TransId, IAR, Res) -> + #'TransactionReply'{transactionId = TransId, + immAckRequired = IAR, + transactionResult = Res}. + + +%% -- + +cre_serviceChangeResParm(Mid) -> + cre_serviceChangeResParm(Mid, ?VERSION). + +cre_serviceChangeResParm(Mid, V) -> + #'ServiceChangeResParm'{serviceChangeMgcId = Mid, + serviceChangeVersion = V}. + +cre_serviceChangeResult(SCRP) when is_record(SCRP, 'ServiceChangeResParm') -> + {serviceChangeResParms, SCRP}; +cre_serviceChangeResult(ED) when is_record(ED, 'ErrorDescriptor') -> + {errorDescriptor, ED}. + +cre_serviceChangeReply(Tid, Res) -> + #'ServiceChangeReply'{terminationID = Tid, + serviceChangeResult = Res}. + +cre_cmdReply(R) when is_record(R, 'NotifyReply') -> + {notifyReply, R}; +cre_cmdReply(R) when is_record(R, 'ServiceChangeReply') -> + {serviceChangeReply, R}. + +cre_transRespAck(TransAck) when is_record(TransAck, 'TransactionAck') -> + [TransAck]; +cre_transRespAck(TRA) when is_list(TRA) -> + TRA. + +cre_transAck(TransId) -> + #'TransactionAck'{firstAck = TransId}. + +cre_notifyReply(Tid) -> + #'NotifyReply'{terminationID = Tid}. + +cre_actionReply(CtxId, CmdRep) -> + #'ActionReply'{contextId = CtxId, + commandReply = CmdRep}. + +cre_serviceChangeProf(Name, Ver) when is_list(Name) andalso is_integer(Ver) -> + #'ServiceChangeProfile'{profileName = Name, + version = Ver}. + +cre_transaction(Trans) when is_record(Trans, 'TransactionRequest') -> + {transactionRequest, Trans}; +cre_transaction(Trans) when is_record(Trans, 'TransactionPending') -> + {transactionPending, Trans}; +cre_transaction(Trans) when is_record(Trans, 'TransactionReply') -> + {transactionReply, Trans}; +cre_transaction(Trans) when is_list(Trans) -> + {transactionResponseAck, Trans}. + +cre_transactions(Trans) when is_list(Trans) -> + {transactions, Trans}. + +cre_message(Version, Mid, Body) -> + #'Message'{version = Version, + mId = Mid, + messageBody = Body}. + +cre_megacoMessage(Mess) -> + #'MegacoMessage'{mess = Mess}. + +service_change_request() -> + Parm = #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [?megaco_cold_boot]}, + SCR = #'ServiceChangeRequest'{terminationID = [?megaco_root_termination_id], + serviceChangeParms = Parm}, + CR = #'CommandRequest'{command = {serviceChangeReq, SCR}}, + #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}. + +service_change_reply(MgcMid) -> + Res = {serviceChangeResParms, #'ServiceChangeResParm'{serviceChangeMgcId = MgcMid}}, + SCR = #'ServiceChangeReply'{terminationID = [?megaco_root_termination_id], + serviceChangeResult = Res}, + #'ActionReply'{contextId = ?megaco_null_context_id, + commandReply = [{serviceChangeReply, SCR}]}. + +local_ip_address() -> + {ok, Hostname} = inet:gethostname(), + {ok, {A1, A2, A3, A4}} = inet:getaddr(Hostname, inet), + {A1, A2, A3, A4}. + +ipv4_mid() -> + ipv4_mid(asn1_NOVALUE). + +ipv4_mid(Port) -> + IpAddr = local_ip_address(), + Ip = tuple_to_list(IpAddr), + {ip4Address, #'IP4Address'{address = Ip, portNumber = Port}}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%% ------------------------------------------------------------------------------- +%%% Megaco user callback interface +%%% ------------------------------------------------------------------------------- + +handle_connect(ConnHandle, ProtocolVersion, Pid) -> + Pid ! {handle_connect, {ConnHandle, ProtocolVersion}}, + ok. + +handle_disconnect(_, _, {user_disconnect, test_complete}, _) -> + ok; +handle_disconnect(ConnHandle, ProtocolVersion, Reason, Pid) -> + Pid ! {handle_disconnect, {ConnHandle, ProtocolVersion, Reason}}, + ok. + +handle_syntax_error(ConnHandle, ProtocolVersion, ErrorDescriptor, Pid) -> + Pid ! {handle_syntax_error,{ConnHandle, ProtocolVersion, ErrorDescriptor}}, + reply. + +handle_message_error(ConnHandle, ProtocolVersion, ErrorDescriptor, Pid) -> + Pid ! {handle_message_error,{ConnHandle, ProtocolVersion, ErrorDescriptor}}, + reply. + +handle_trans_request(ConnHandle, ProtocolVersion, ActionRequests, Pid) -> + Pid ! {handle_trans_request,{ConnHandle, ProtocolVersion, ActionRequests}}, + ED = #'ErrorDescriptor'{errorCode = ?megaco_not_implemented, + errorText = "not implemented yet"}, + {discard_ack, ED}. + +handle_trans_long_request(ConnHandle, ProtocolVersion, Data, Pid) -> + Pid ! {handle_trans_long_request,{ConnHandle, ProtocolVersion, Data}}, + ED = #'ErrorDescriptor'{errorCode = ?megaco_not_implemented, + errorText = "not implemented yet"}, + {discard_ack, ED}. + +handle_trans_reply(ConnHandle, ProtocolVersion, ActualReply, Data, Pid) -> + Pid ! {handle_trans_reply,{ConnHandle, ProtocolVersion, ActualReply, Data}}, + ok. + +handle_trans_ack(ConnHandle, ProtocolVersion, Status, Data, Pid) -> + Pid ! {handle_trans_ack,{ConnHandle, ProtocolVersion, Status, Data}}, + ok. + +handle_unexpected_trans(ReceiveHandle, ProtocolVersion, Trans, Pid) -> + Pid ! {handle_unexpected_trans, + {ReceiveHandle, ProtocolVersion, Trans, Pid}}, + ok. + +handle_trans_request_abort(ReceiveHandle, ProtocolVersion, TransNo, HandlerPid, Pid) -> + Pid ! {handle_trans_request_abort, + {ReceiveHandle, ProtocolVersion, TransNo, HandlerPid}}, + ok. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +encode_msg(M, Mod, Conf) -> + Mod:encode_message(Conf, M). + +%% encode_msg(M, Mod, Conf, Ver) -> +%% Mod:encode_message(Conf, Ver, M). + +decode_msg(M, Mod, Conf) -> + Mod:decode_message(Conf, M). + +%% decode_msg(M, Mod, Conf, Ver) -> +%% Mod:decode_message(Conf, Ver, M). + + + +%%% ------------------------------------------------------------------------------- +%%% Megaco transport module interface +%%% ------------------------------------------------------------------------------- + +send_message(Pid, Data) -> + Pid ! {send_message, Data}, + ok. + +% block(Pid) -> +% Pid ! {block, dummy}, +% ok. + +unblock(Pid) -> + Pid ! {unblock, dummy}, + ok. + +% close(Pid) -> +% Pid ! {close, dummy}, +% ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +make_node_name(Name) -> + case string:tokens(atom_to_list(node()), [$@]) of + [_,Host] -> + list_to_atom(lists:concat([atom_to_list(Name) ++ "@" ++ Host])); + _ -> + exit("Test node must be started with '-sname'") + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +user_info(Mid, Key) -> + case (catch megaco:user_info(Mid, Key)) of + {'EXIT', _} = Error -> + ?ERROR(Error); + Val -> + ?LOG("user_info -> ok: " + "~n ~p" + "~n", [Val]), + Val + end. + + +stop_user(Mid) -> + case (catch megaco:stop_user(Mid)) of + {'EXIT', _} = Error -> + ?ERROR(Error); + Val -> + ?LOG("stop_user -> ok:" + "~n ~p" + "~n", [Val]), + Val + end. + +connections() -> + system_info(connections). + +connections(Conns0) -> + Conns1 = lists:sort(Conns0), + case lists:sort(connections()) of + Conns1 -> + ?LOG("connections -> ok:" + "~n ~p" + "~n", [Conns1]), + Conns1; + Conns2 -> + ?ERROR({Conns1, Conns2}), + Conns2 + end. + +system_info(Key) -> + megaco:system_info(Key). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +await_completion(Ids) -> + case megaco_test_generator_lib:await_completion(Ids) of + {ok, Reply} -> + d("OK => Reply: ~n~p", [Reply]), + ok; + {error, Reply} -> + d("ERROR => Reply: ~n~p", [Reply]), + ?ERROR({failed, Reply}) + end. + +await_completion(Ids, Timeout) -> + case megaco_test_generator_lib:await_completion(Ids, Timeout) of + {ok, Reply} -> + d("OK => Reply: ~n~p", [Reply]), + ok; + {error, Reply} -> + d("ERROR => Reply: ~n~p", [Reply]), + ?ERROR({failed, Reply}) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +sleep(X) -> receive after X -> ok end. + +% error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +i(F) -> + i(F, []). + +i(F, A) -> + print(info, get(verbosity), now(), get(tc), "INF", F, A). + + +d(F) -> + d(F, []). + +d(F, A) -> + print(debug, get(verbosity), now(), get(tc), "DBG", F, A). + + +printable(_, debug) -> true; +printable(info, info) -> true; +printable(_,_) -> false. + +print(Severity, Verbosity, Ts, Tc, P, F, A) -> + print(printable(Severity,Verbosity), Ts, Tc, P, F, A). + +print(true, Ts, Tc, P, F, A) -> + io:format("*** [~s] ~s ~p ~s:~w ***" + "~n " ++ F ++ "~n", + [format_timestamp(Ts), P, self(), get(sname), Tc | A]); +print(_, _, _, _, _, _) -> + ok. + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +to(To, Start) -> + To - (mtime() - Start). + +%% Time in milli seconds +mtime() -> + {A,B,C} = erlang:now(), + A*1000000000+B*1000+(C div 1000). + +%% random_init() -> +%% {A,B,C} = now(), +%% random:seed(A,B,C). + +%% random() -> +%% 10 * random:uniform(50). + diff --git a/lib/megaco/test/megaco_mess_user_test.erl b/lib/megaco/test/megaco_mess_user_test.erl new file mode 100644 index 0000000000..50284be549 --- /dev/null +++ b/lib/megaco/test/megaco_mess_user_test.erl @@ -0,0 +1,309 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: A fun implementation of user callbacks +%%---------------------------------------------------------------------- + +-module(megaco_mess_user_test). + +-behaviour(megaco_user). + +-export([ + handle_connect/2, handle_connect/3, + handle_disconnect/3, + handle_syntax_error/3, handle_syntax_error/4, + handle_message_error/3, handle_message_error/4, + handle_trans_request/3, handle_trans_request/4, + handle_trans_long_request/3, handle_trans_long_request/4, + handle_trans_reply/4, handle_trans_reply/5, + handle_trans_ack/4, handle_trans_ack/5, + handle_unexpected_trans/3, handle_unexpected_trans/4, + handle_trans_request_abort/4, handle_trans_request_abort/5, + handle_segment_reply/5, handle_segment_reply/6 + ]). + +-export([ + start_proxy/0, + stop_proxy/0, + apply_proxy/1, + reply/3, + + start_transport/2, + loop_transport/1, % Internal only + send_message/2, + resend_message/2 + ]). + +-include("megaco_test_lib.hrl"). +-define(SERVER, ?MODULE). + +start_proxy() -> + yes = global:register_name(?SERVER, self()), + Pid = megaco_test_lib:proxy_start(?MODULE), + put(?MODULE, Pid), + Pid. + +stop_proxy() -> + global:unregister_name(?SERVER), + Pid = erase(?MODULE), + unlink(Pid), + exit(Pid, shutdown). + +whereis_proxy() -> + case get(?MODULE) of + undefined -> + exit(no_server, ?MODULE); + Pid when is_pid(Pid) -> + Pid + end. + +apply_proxy(Fun) -> + Pid = whereis_proxy(), + ?APPLY(Pid, Fun), + ok. + +reply(Mod, Line, Fun) when is_function(Fun) -> + receive + {?MODULE, Pid, UserCallback} -> + UserReply = Fun(UserCallback), + Pid ! {?MODULE, self(), UserReply}, + UserReply; + Other -> + megaco_test_lib:error(Other, Mod, Line), + {error, Other} +%% after 1000 -> +%% megaco_test_lib:error(timeout, Mod, Line), +%% {error, timeout} + end. + +call(UserCallback) -> + Request = {?MODULE, self(), UserCallback}, + case global:whereis_name(?SERVER) of + undefined -> + exit({no_server, ?SERVER, Request}); + Pid when is_pid(Pid) -> + ?LOG("call[~p] -> bang request: " + "~n ~p" + "~n", [Pid, Request]), + Pid ! Request, + call_await_reply(Pid) + end. + +call_await_reply(Pid) -> + receive + {?MODULE, Pid, UserReply} = _Reply -> + case UserReply of + {ok, Good} -> Good; + {error, Bad} -> exit(Bad) + end; + {'EXIT', Pid, Reason} = Bad -> + ?LOG("receive test case exit: ~p~n", [Bad]), + exit(Reason); + {'EXIT', _, _Reason} = Bad -> + ?LOG("receive unknown exit: ~p~n", [Bad]), + call_await_reply(Pid); + Bad -> + ?LOG("receive other: ~p~n", [Bad]), + exit(Bad) + end. + +%%---------------------------------------------------------------------- +%% Megaco user callback +%%---------------------------------------------------------------------- + +%% -- handle_connect/2 -- + +handle_connect(ConnHandle, ProtocolVersion) -> +%% io:format("~p~p[~p]: handle_connect -> entry with" +%% "~n ConnHandle: ~p" +%% "~n ProtocolVersion: ~p" +%% "~n", +%% [self(), ?MODULE, ?LINE, ConnHandle, ProtocolVersion]), + call({connect, ConnHandle, ProtocolVersion, []}). + +handle_connect(ConnHandle, ProtocolVersion, Extra) -> +%% io:format(user,"~p~p[~p]: handle_connect -> entry with" +%% "~n ConnHandle: ~p" +%% "~n ProtocolVersion: ~p" +%% "~n Extra: ~p" +%% "~n", +%% [self(), ?MODULE, ?LINE, ConnHandle, ProtocolVersion, Extra]), + call({connect, ConnHandle, ProtocolVersion, [Extra]}). + + +%% -- handle_disconnect/3 -- + +handle_disconnect(ConnHandle, ProtocolVersion, Reason) -> + %% io:format("~w:~w:~p:handle_disconnect -> entry with" + %% "~n ConnHandle: ~p" + %% "~n ProtocolVersion: ~p" + %% "~n Reason: ~p" + %% "~n", + %% [?MODULE, ?LINE, self(), ConnHandle, ProtocolVersion, Reason]), + call({disconnect, ConnHandle, ProtocolVersion, [Reason]}). + + +%% -- handle_syntax_error/3,4 -- + +handle_syntax_error(ReceiveHandle, ProtocolVersion, ErrorDescriptor) -> + call({syntax_error, ReceiveHandle, ProtocolVersion, [ErrorDescriptor]}). + +handle_syntax_error(ReceiveHandle, ProtocolVersion, ErrorDescriptor, Extra) -> + call({syntax_error, ReceiveHandle, ProtocolVersion, [ErrorDescriptor, Extra]}). + + +%% -- handle_message_error/3,4 -- + +handle_message_error(ConnHandle, ProtocolVersion, ErrorDescriptor) -> + call({message_error, ConnHandle, ProtocolVersion, [ErrorDescriptor]}). + +handle_message_error(ConnHandle, ProtocolVersion, ErrorDescriptor, Extra) -> + call({message_error, ConnHandle, ProtocolVersion, [ErrorDescriptor, Extra]}). + + +%% -- handle_trans_request/3,4 -- + +handle_trans_request(ConnHandle, ProtocolVersion, ActionRequests) -> + call({request, ConnHandle, ProtocolVersion, [ActionRequests]}). + +handle_trans_request(ConnHandle, ProtocolVersion, ActionRequests, Extra) -> + call({request, ConnHandle, ProtocolVersion, [ActionRequests, Extra]}). + +%% -- handle_trans_long_request/3,4 -- + +handle_trans_long_request(ConnHandle, ProtocolVersion, RequestData) -> + call({long_request, ConnHandle, ProtocolVersion, [RequestData]}). + +handle_trans_long_request(ConnHandle, ProtocolVersion, RequestData, Extra) -> + call({long_request, ConnHandle, ProtocolVersion, [RequestData, Extra]}). + + +%% -- handle_trans_relpy/4,5 -- + +handle_trans_reply(ConnHandle, ProtocolVersion, UserReply, UserData) -> + call({reply, ConnHandle, ProtocolVersion, [UserReply, UserData]}). + +handle_trans_reply(ConnHandle, ProtocolVersion, UserReply, UserData, Extra) -> + call({reply, ConnHandle, ProtocolVersion, [UserReply, UserData, Extra]}). + + +%% -- handle_trans_relpy/4,5 -- + +handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData) -> + call({ack, ConnHandle, ProtocolVersion, [AckStatus, AckData]}). + +handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData, Extra) -> + call({ack, ConnHandle, ProtocolVersion, [AckStatus, AckData, Extra]}). + + +%% -- handle_unexpected_trans/3,4 -- + +handle_unexpected_trans(ConnHandle, ProtocolVersion, Trans) -> + call({unepected_trans, ConnHandle, ProtocolVersion, [Trans]}). + +handle_unexpected_trans(ConnHandle, ProtocolVersion, Trans, Extra) -> + call({unepected_trans, ConnHandle, ProtocolVersion, [Trans, Extra]}). + + +%% -- handle_trans_request_abort/4,5 -- + +handle_trans_request_abort(ConnHandle, ProtocolVersion, TransId, Pid) -> + call({request_abort, ConnHandle, ProtocolVersion, [TransId, Pid]}). + +handle_trans_request_abort(ConnHandle, ProtocolVersion, TransId, Pid, Extra) -> + call({request_abort, ConnHandle, ProtocolVersion, [TransId, Pid, Extra]}). + + +%% -- handle_segment_reply/5,6 -- + +handle_segment_reply(ConnHandle, ProtocolVersion, TransId, SN, SC) -> + call({segment_reply, ConnHandle, ProtocolVersion, [TransId, SN, SC]}). + +handle_segment_reply(ConnHandle, ProtocolVersion, TransId, SN, SC, Extra) -> + call({segment_reply, ConnHandle, ProtocolVersion, [TransId, SN, SC, Extra]}). + + +%%---------------------------------------------------------------------- +%% The ultimate Megaco transport callback +%%---------------------------------------------------------------------- + +start_transport(MgReceiveHandle, MgcReceiveHandle) -> + MgControlPid = spawn_link(?MODULE, loop_transport, [self()]), + MgSendHandle = {MgcReceiveHandle, MgControlPid}, + MgcControlPid = spawn_link(?MODULE, loop_transport, [self()]), + MgcSendHandle = {MgReceiveHandle, MgcControlPid}, + SendHandle = {MgSendHandle, MgcSendHandle}, + {ok, MgControlPid, SendHandle}. + +loop_transport(Parent) -> + receive + {'EXIT', _Pid, Reason} = Error -> + ok = io:format("transport stopped: ~p~n", [{Parent, Error}]), + exit(Reason) + end. + +send_message(Handles, Bin) -> + ?LOG("send_message -> entry with" + "~n Handles: ~p" + "~n", [Handles]), + case megaco_tc_controller:lookup(allow_send_message) of + {value, ok} -> + do_send_message(Handles, Bin); + {value, {fail, Reason}} -> + {error, Reason}; + {value, {cancel, Reason}} -> + {cancel, Reason}; + {value, {skip, Result}} -> + Result; + false -> + do_send_message(Handles, Bin) + end. + +resend_message(Handles, Bin) -> + ?LOG("resend_message -> entry with" + "~n Handles: ~p" + "~n", [Handles]), + case megaco_tc_controller:lookup(allow_resend_message) of + {value, ok} -> + do_send_message(Handles, Bin); + {value, {fail, Reason}} -> + {error, Reason}; + {value, {cancel, Reason}} -> + {cancel, Reason}; + {value, {skip, Result}} -> + Result; + false -> + do_send_message(Handles, Bin) + end. + +do_send_message({{RH, Pid} = LocalSendHandle, RemoteSendHandle}, Bin) -> + ?LOG("do_send_message -> entry with" + "~n RH: ~p" + "~n Pid: ~p" + "~n RemoteSendHandle: ~p" + "~n", [RH, Pid, RemoteSendHandle]), + SwappedSendHandle = {RemoteSendHandle, LocalSendHandle}, + case megaco_tc_controller:lookup(extra_transport_info) of + {value, Extra} -> + megaco:receive_message(RH, Pid, SwappedSendHandle, Bin, Extra); + _ -> + megaco:receive_message(RH, Pid, SwappedSendHandle, Bin) + end. diff --git a/lib/megaco/test/megaco_mib_test.erl b/lib/megaco/test/megaco_mib_test.erl new file mode 100644 index 0000000000..2da6aa3bf3 --- /dev/null +++ b/lib/megaco/test/megaco_mib_test.erl @@ -0,0 +1,1619 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Verify the application specifics of the Megaco application +%%---------------------------------------------------------------------- +-module(megaco_mib_test). + +-compile(export_all). + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). + +-define(TEST_VERBOSITY, info). % silence | info | debug +-define(MGC_VERBOSITY, info). +-define(MG_VERBOSITY, info). + +-define(LOAD_COUNTER_START, 100). +-define(A4444, ["11111111", "00000000", "00000000"]). + +-record(mgc, {parent = undefined, + tcp_sup = undefined, + udp_sup = undefined, + mid = undefined, + mg = []}). +-record(mg, {parent = undefined, + mid = undefined, + conn_handle = undefined, + state = initiated, + load_counter = 0}). + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + + +%% Test server callbacks +init_per_testcase(Case, Config) -> + process_flag(trap_exit, true), + case Case of + traffic -> + Conf0 = lists:keydelete(tc_timeout, 1, Config), + Conf = [{tc_timeout, timer:minutes(5)}|Conf0], + megaco_test_lib:init_per_testcase(Case, Conf); + _ -> + megaco_test_lib:init_per_testcase(Case, Config) + end. + +fin_per_testcase(Case, Config) -> + process_flag(trap_exit, false), + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all(suite) -> + Cases = + [ + plain, + connect, + traffic + ], + Cases. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +plain(suite) -> + []; +plain(doc) -> + ["Test case for the basic statistics counter handling. "]; +plain(Config) when is_list(Config) -> + io:format("create test table 1~n", []), + Tab1 = megaco_test_cnt1, + megaco_stats:init(Tab1), + + io:format("~ncreate test table 2~n", []), + Tab2 = megaco_test_cnt2, + megaco_stats:init(Tab2, [kalle, hobbe]), + + io:format("~ntable 1 increments~n", []), + H1 = #megaco_conn_handle{local_mid = {deviceName, "a"}, + remote_mid = {deviceName, "b"}}, + H2 = #megaco_conn_handle{local_mid = {deviceName, "a"}, + remote_mid = {deviceName, "c"}}, + 1 = megaco_stats:inc(Tab1, H1, sune), + 2 = megaco_stats:inc(Tab1, H2, sune, 2), + 3 = megaco_stats:inc(Tab1, H1, gurka, 3), + 4 = megaco_stats:inc(Tab1, H2, sune, 2), + 4 = megaco_stats:inc(Tab1, H1, gurka), + + io:format("~ntable 2 increments~n", []), + H3 = #megaco_conn_handle{local_mid = {deviceName, "e"}, + remote_mid = {deviceName, "c"}}, + H4 = #megaco_conn_handle{local_mid = {deviceName, "e"}, + remote_mid = {deviceName, "d"}}, + 1 = megaco_stats:inc(Tab2, H3, tomat), + 4 = megaco_stats:inc(Tab2, H3, tomat, 3), + 5 = megaco_stats:inc(Tab2, H4, paprika, 5), + + io:format("~ntable 2 global increments~n", []), + 1 = megaco_stats:inc(Tab2, kalle), + 1 = megaco_stats:inc(Tab2, hobbe), + 2 = megaco_stats:inc(Tab2, hobbe), + 2 = megaco_stats:inc(Tab2, kalle), + 3 = megaco_stats:inc(Tab2, kalle), + 4 = megaco_stats:inc(Tab2, hobbe, 2), + + io:format("~ntable 1 stats~n", []), + {ok, Stats1} = megaco_stats:get_stats(Tab1), + io:format("Stats1 = ~p~n", [Stats1]), + {value, {H1, H1Stats}} = lists:keysearch(H1, 1, Stats1), + Stats1_2 = lists:keydelete(H1, 1, Stats1), + {value, {H2, H2Stats}} = lists:keysearch(H2, 1, Stats1_2), + Stats1_3 = lists:keydelete(H2, 1, Stats1_2), + [] = Stats1_3, + io:format("H1Stats = ~p~n", [H1Stats]), + io:format("H2Stats = ~p~n", [H2Stats]), + + {value, {sune, 1}} = lists:keysearch(sune, 1, H1Stats), + H1Stats_2 = lists:keydelete(sune, 1, H1Stats), + {value, {gurka, 4}} = lists:keysearch(gurka, 1, H1Stats_2), + H1Stats_3 = lists:keydelete(gurka, 1, H1Stats_2), + [] = H1Stats_3, + + {value, {sune, 4}} = lists:keysearch(sune, 1, H2Stats), + H2Stats_2 = lists:keydelete(sune, 1, H2Stats), + [] = H2Stats_2, + + + %% -- + io:format("~ntable 2 stats~n", []), + {ok, Stats2} = megaco_stats:get_stats(Tab2), + io:format("Stats2 = ~p~n", [Stats2]), + {ok, 3} = megaco_stats:get_stats(Tab2, kalle), + {ok, 4} = megaco_stats:get_stats(Tab2, hobbe), + + + %% -- + io:format("~ntable 1 reset stats for ~p~n", [H1]), + megaco_stats:reset_stats(Tab1, H1), + {ok, Stats1_4} = megaco_stats:get_stats(Tab1), + io:format("Stats1_4 = ~p~n", [Stats1_4]), + {ok, 0} = megaco_stats:get_stats(Tab1, H1, sune), + {ok, 0} = megaco_stats:get_stats(Tab1, H1, gurka), + + + %% -- + io:format("~ntable 2 reset stats for kalle and ~p~n", [H4]), + megaco_stats:reset_stats(Tab2, kalle), + megaco_stats:reset_stats(Tab2, H4), + {ok, Stats2_2} = megaco_stats:get_stats(Tab2), + io:format("Stats2_2 = ~p~n", [Stats2_2]), + {ok, 0} = megaco_stats:get_stats(Tab2, kalle), + {ok, 4} = megaco_stats:get_stats(Tab2, hobbe), + {ok, 4} = megaco_stats:get_stats(Tab2, H3, tomat), + {ok, 0} = megaco_stats:get_stats(Tab2, H4, paprika), + {ok, Stats4_4} = megaco_stats:get_stats(Tab2, H4), + io:format("Stats4_4 = ~p~n", [Stats4_4]), + + %% -- + io:format("~ntable 2 stats for nonexisting counters~n", []), + {error, _} = megaco_stats:get_stats(Tab2, kalla), + {error, _} = megaco_stats:get_stats(Tab2, H3, paprika), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +connect(suite) -> + []; +connect(doc) -> + []; +connect(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + i("connect -> starting"), + MgcNode = make_node_name(mgc), + Mg1Node = make_node_name(mg1), + Mg2Node = make_node_name(mg2), + d("connect -> Nodes: " + "~n MgcNode: ~p" + "~n Mg1Node: ~p" + "~n Mg2Node: ~p", [MgcNode, Mg1Node, Mg2Node]), + ok = megaco_test_lib:start_nodes([MgcNode, Mg1Node, Mg2Node], + ?FILE, ?LINE), + + %% Start the MGC and MGs + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + {ok, Mgc} = + start_mgc(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY), + {ok, Mg1} = + start_mg(Mg1Node, {deviceName, "mg1"}, text, tcp, ?MG_VERBOSITY), + {ok, Mg2} = + start_mg(Mg2Node, {deviceName, "mg2"}, binary, udp, ?MG_VERBOSITY), + + %% Collect the initial statistics (should be zero if anything) + {ok, Mg1Stats0} = get_stats(Mg1, 1), + d("connect -> stats for Mg1: ~n~p", [Mg1Stats0]), + {ok, Mg2Stats0} = get_stats(Mg2, 1), + d("connect -> stats for Mg2: ~n~p", [Mg2Stats0]), + {ok, MgcStats0} = get_stats(Mgc, 1), + d("connect -> stats for Mgc: ~n~p", [MgcStats0]), + + %% Ask Mg1 to do a service change + {ok, Res1} = service_change(Mg1), + d("connect -> (Mg1) service change result: ~p", [Res1]), + + %% Collect the statistics + {ok, Mg1Stats1} = get_stats(Mg1, 1), + d("connect -> stats for Mg1: ~n~p", [Mg1Stats1]), + {ok, MgcStats1} = get_stats(Mgc, 1), + d("connect -> stats (1) for Mgc: ~n~p", [MgcStats1]), + {ok, MgcStats2} = get_stats(Mgc, 2), + d("connect -> stats (2) for Mgc: ~n~p", [MgcStats2]), + + %% Ask Mg2 to do a service change + {ok, Res2} = service_change(Mg2), + d("connect -> (Mg2) service change result: ~p", [Res2]), + + %% Collect the statistics + {ok, Mg2Stats1} = get_stats(Mg2, 1), + d("connect -> stats for Mg1: ~n~p", [Mg2Stats1]), + {ok, MgcStats3} = get_stats(Mgc, 1), + d("connect -> stats (1) for Mgc: ~n~p", [MgcStats3]), + {ok, MgcStats4} = get_stats(Mgc, 2), + d("connect -> stats (2) for Mgc: ~n~p", [MgcStats4]), + + %% Tell Mg1 to stop + stop(Mg1), + + %% Collect the statistics + {ok, MgcStats5} = get_stats(Mgc, 1), + d("connect -> stats (1) for Mgc: ~n~p", [MgcStats5]), + {ok, MgcStats6} = get_stats(Mgc, 2), + d("connect -> stats (2) for Mgc: ~n~p", [MgcStats6]), + + %% Tell Mg2 to stop + stop(Mg2), + + %% Collect the statistics + {ok, MgcStats7} = get_stats(Mgc, 1), + d("connect -> stats (1) for Mgc: ~n~p", [MgcStats7]), + {ok, MgcStats8} = get_stats(Mgc, 2), + d("connect -> stats (2) for Mgc: ~n~p", [MgcStats8]), + + %% Tell Mgc to stop + stop(Mgc), + + i("connect -> done", []), + ok. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +traffic(suite) -> + []; +traffic(doc) -> + []; +traffic(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + i("traffic -> starting"), + MgcNode = make_node_name(mgc), + Mg1Node = make_node_name(mg1), + Mg2Node = make_node_name(mg2), + Mg3Node = make_node_name(mg3), + Mg4Node = make_node_name(mg4), + d("traffic -> Nodes: " + "~n MgcNode: ~p" + "~n Mg1Node: ~p" + "~n Mg2Node: ~p" + "~n Mg3Node: ~p" + "~n Mg4Node: ~p", + [MgcNode, Mg1Node, Mg2Node, Mg3Node, Mg4Node]), + ok = megaco_test_lib:start_nodes([MgcNode, + Mg1Node, Mg2Node, Mg3Node, Mg4Node], + ?FILE, ?LINE), + + %% Start the MGC and MGs + i("traffic -> start the MGC"), + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + {ok, Mgc} = + start_mgc(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY), + + i("traffic -> start and connect the MGs"), + MgConf0 = [{Mg1Node, "mg1", text, tcp}, + {Mg2Node, "mg2", text, udp}, + {Mg3Node, "mg3", binary, tcp}, + {Mg4Node, "mg4", binary, udp}], + MgConf = traffic_connect_mg(MgConf0, []), + + %% Collect and check the MGs statistics + i("traffic -> collect and check the MGs stats"), + traffic_verify_mg_stats(MgConf, 1, 1), + + %% Collect and check the MGC statistics + i("traffic -> collect and check the MGC stats"), + {ok, MgcStats1} = get_stats(Mgc, 1), + d("traffic -> stats (1) for Mgc: ~n~p~n", [MgcStats1]), + traffic_verify_mgc_stats(Mgc, 1, 1), + + + sleep(1000), + + + %% And apply some load + i("traffic -> apply traffic load"), + ok = traffic_apply_load(MgConf), + + %% Await completion of load part and the collect traffic + i("traffic -> await load competion"), + ok = traffic_await_load_complete(MgConf), + + + sleep(1000), + + + i("traffic -> collect and check the MGs statistics"), + traffic_verify_mg_stats(MgConf, + 1 + ?LOAD_COUNTER_START, + 1 + ?LOAD_COUNTER_START), + + i("traffic -> collect and check the MGC statistics"), + {ok, MgcStats3} = get_stats(Mgc, 1), + d("traffic -> stats (1) for Mgc: ~n~p~n", [MgcStats3]), + traffic_verify_mgc_stats(Mgc, + 1 + ?LOAD_COUNTER_START, + 1 + ?LOAD_COUNTER_START), + + + sleep(1000), + + + %% Reset counters + i("traffic -> reset the MGs statistics"), + traffic_reset_mg_stats(MgConf), + i("traffic -> collect and check the MGs statistics"), + traffic_verify_mg_stats(MgConf, 0, 0), + + i("traffic -> reset the MGC statistics"), + traffic_reset_mgc_stats(Mgc), + i("traffic -> collect and check the MGC statistics"), + traffic_verify_mgc_stats(Mgc, 0, 0), + + + sleep(1000), + + + %% And apply some load + i("traffic -> apply traffic load"), + ok = traffic_apply_load(MgConf), + + %% Await completion of load part and the collect traffic + i("traffic -> await load competion"), + ok = traffic_await_load_complete(MgConf), + + + sleep(1000), + + + i("traffic -> collect and check the MGs statistics"), + traffic_verify_mg_stats(MgConf, + ?LOAD_COUNTER_START, + ?LOAD_COUNTER_START), + + i("traffic -> collect and check the MGC statistics"), + traffic_verify_mgc_stats(Mgc, + ?LOAD_COUNTER_START, + ?LOAD_COUNTER_START), + + + sleep(1000), + + + %% Tell MGs to stop + i("traffic -> stop the MGs"), + traffic_stop_mg(MgConf), + + + sleep(1000), + + + %% Collect the statistics + i("traffic -> collect the MGC statistics"), + {ok, MgcStats7} = get_stats(Mgc, 1), + d("traffic -> stats (1) for Mgc: ~n~p~n", [MgcStats7]), + {ok, MgcStats8} = get_stats(Mgc, 2), + d("traffic -> stats (2) for Mgc: ~n~p~n", [MgcStats8]), + + %% Tell Mgc to stop + i("traffic -> stop the MGC"), + stop(Mgc), + + i("traffic -> done", []), + ok. + + +traffic_verify_mgc_stats(Pid, Out, In) + when is_pid(Pid) andalso is_integer(Out) andalso is_integer(In) -> + d("traffic_verify_mgc_stats -> entry with" + "~n Out: ~p" + "~n In: ~p", [Out, In]), + {ok, Stats} = get_stats(Pid, 2), + d("traffic_verify_mgc_stats -> stats (2) for Mgc: ~n~p~n", [Stats]), + traffic_verify_mgc_stats(Stats, Out, In); + +traffic_verify_mgc_stats(Stats, Out, In) when is_list(Stats) -> + d("traffic_verify_mgc_stats -> checking stats"), + Gen = traffic_verify_get_stats(gen, Stats), + Trans = traffic_verify_get_stats(trans, Stats), + traffic_verify_mgc_stats_gen(Gen), + traffic_verify_mgc_stats_trans(Trans, Out, In). + +traffic_verify_mgc_stats_gen([]) -> + d("traffic_verify_mgc_stats_gen -> done"), + ok; +traffic_verify_mgc_stats_gen([{medGwyGatewayNumErrors, 0}|Stats]) -> + traffic_verify_mgc_stats_gen(Stats); +traffic_verify_mgc_stats_gen([{medGwyGatewayNumErrors, Val}|_]) -> + exit({global_error_counter, Val, mgc}); +traffic_verify_mgc_stats_gen([{Handle, Counters}|Stats]) -> + N = {mgc, Handle, Handle}, + traffic_verify_counter(N, medGwyGatewayNumErrors, Counters, 0), + traffic_verify_mgc_stats_gen(Stats). + + +traffic_verify_mgc_stats_trans([], _Out, _In) -> + ok; +traffic_verify_mgc_stats_trans([{Mod, Stats}|MgcStats], Out, In) -> + d("traffic_verify_mgc_stats_trans -> entry with" + "~n Mod: ~p" + "~n Stats: ~p", [Mod, Stats]), + traffic_verify_mgc_stats_trans(Mod, Stats, Out, In), + traffic_verify_mgc_stats_trans(MgcStats, Out, In). + +traffic_verify_mgc_stats_trans(_Mod, [], _Out, _In) -> + ok; +traffic_verify_mgc_stats_trans(Mod, [{Handle,Counters}|Stats], Out, In) -> + N = {mgc, Mod, Handle}, + traffic_verify_counter(N, medGwyGatewayNumErrors, Counters, 0), + traffic_verify_counter(N, medGwyGatewayNumOutMessages, Counters, Out), + traffic_verify_counter(N, medGwyGatewayNumInMessages, Counters, In), + traffic_verify_mgc_stats_trans(Mod, Stats, Out, In). + + +traffic_verify_mg_stats(MgConf, Out, In) + when is_integer(Out) andalso is_integer(In) -> + d("traffic_verify_mg_stats -> entry with" + "~n Out: ~p" + "~n In: ~p", [Out, In]), + Stats = traffic_get_mg_stats(MgConf, []), + d("traffic_verify_mg_stats -> stats for MGs: ~n~p", [Stats]), + traffic_verify_mg_stats1(Stats, Out, In). + +traffic_verify_mg_stats1([], _, _) -> + ok; +traffic_verify_mg_stats1([{Name, Stats}|MgStats], Out, In) -> + d("traffic_verify_mg_stats1 -> entry with" + "~n Name: ~s" + "~n Stats: ~p", [Name, Stats]), + Gen = traffic_verify_get_stats(gen, Stats), + Trans = traffic_verify_get_stats(trans, Stats), + traffic_verify_mg_stats_gen(Name, Gen), + traffic_verify_mg_stats_trans(Name, Trans, Out, In), + traffic_verify_mg_stats1(MgStats, Out, In). + +traffic_verify_mg_stats_gen(Mg, []) -> + d("traffic_verify_mg_stats_gen -> ~s checked out OK",[Mg]), + ok; +traffic_verify_mg_stats_gen(Mg, [{medGwyGatewayNumErrors, 0}|Stats]) -> + traffic_verify_mg_stats_gen(Mg, Stats); +traffic_verify_mg_stats_gen(Mg, [{medGwyGatewayNumErrors, Val}|_]) -> + exit({global_error_counter, Val, Mg}); +traffic_verify_mg_stats_gen(Mg, [{_Handle, Counters}|Stats]) -> + traffic_verify_counter(Mg, medGwyGatewayNumErrors, Counters, 0), + traffic_verify_mg_stats_gen(Mg, Stats). + +traffic_verify_mg_stats_trans(Mg, Counters, Out, In) -> + traffic_verify_counter(Mg, medGwyGatewayNumErrors, Counters, 0), + traffic_verify_counter(Mg, medGwyGatewayNumOutMessages, Counters, Out), + traffic_verify_counter(Mg, medGwyGatewayNumInMessages, Counters, In). + + +traffic_verify_get_stats(S, Stats) -> + case lists:keysearch(S, 1, Stats) of + {value, {S, Val}} -> + Val; + false -> + exit({not_found, S, Stats}) + end. + +traffic_verify_counter(Name, Counter, Counters, Expected) -> + case lists:keysearch(Counter, 1, Counters) of + {value, {Counter, Expected}} -> + ok; + {value, {Counter, Val}} -> + exit({illegal_counter_value, Counter, Val, Expected, Name}); + false -> + exit({not_found, Counter, Counters, Name, Expected}) + end. + + +traffic_connect_mg([], Acc) -> + lists:reverse(Acc); +traffic_connect_mg([{Node, Name, Coding, Trans}|Mg], Acc) -> + Pid = traffic_connect_mg(Node, Name, Coding, Trans), + traffic_connect_mg(Mg, [{Name, Pid}|Acc]). + +traffic_connect_mg(Node, Name, Coding, Trans) -> + Mid = {deviceName, Name}, + {ok, Pid} = start_mg(Node, Mid, Coding, Trans, ?MG_VERBOSITY), + + %% Ask the MGs to do a service change + {ok, Res} = service_change(Pid), + d("traffic_connect_mg -> (~s) service change result: ~p", [Name,Res]), + + Pid. + + +traffic_stop_mg(MGs) -> + [stop(Pid) || {_Name, Pid} <- MGs]. + + +traffic_get_mg_stats([], Acc) -> + lists:reverse(Acc); +traffic_get_mg_stats([{Name, Pid}|Mgs], Acc) -> + {ok, Stats} = get_stats(Pid, 1), + d("traffic_get_mg_stats -> stats for ~s: ~n~p~n", [Name, Stats]), + traffic_get_mg_stats(Mgs, [{Name, Stats}|Acc]). + + +traffic_apply_load([]) -> + ok; +traffic_apply_load([{_,MG}|MGs]) -> + MG ! {apply_load, self(), ?LOAD_COUNTER_START}, + receive + {apply_load_ack, MG} -> + traffic_apply_load(MGs); + {'EXIT', MG, Reason} -> + exit({mg_exit, MG, Reason}) + after 10000 -> + exit({apply_load_ack_timeout, MG}) + end. + + +traffic_reset_mg_stats([]) -> + ok; +traffic_reset_mg_stats([{Name, Pid}|MGs]) -> + d("traffic_reset_mg_stats -> resetting ~s", [Name]), + traffic_reset_stats(Pid), + traffic_reset_mg_stats(MGs). + +traffic_reset_mgc_stats(Mgc) -> + d("traffic_reset_mgc_stats -> resetting ~p", [Mgc]), + traffic_reset_stats(Mgc). + +traffic_reset_stats(Pid) -> + Pid ! {reset_stats, self()}, + receive + {reset_stats_ack, Pid} -> + ok; + {'EXIT', Pid, Reason} -> + exit({client_exit, Pid, Reason}) + after 10000 -> + exit({reset_stats_ack_timeout, Pid}) + end. + + +traffic_await_load_complete([]) -> + ok; +traffic_await_load_complete(MGs0) -> + receive + {load_complete, Pid} -> + d("received load_complete from ~p", [Pid]), + MGs1 = lists:keydelete(Pid, 2, MGs0), + traffic_await_load_complete(lists:delete(Pid, MGs1)); + {'EXIT', Pid, Reason} -> + i("exit signal from ~p: ~p", [Pid, Reason]), + case lists:keymember(Pid, 2, MGs0) of + true -> + exit({mg_exit, Pid, Reason}); + false -> + MGs1 = lists:keydelete(Pid, 2, MGs0), + traffic_await_load_complete(lists:delete(Pid, MGs1)) + end + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +make_node_name(Name) -> + case string:tokens(atom_to_list(node()), [$@]) of + [_,Host] -> + list_to_atom(lists:concat([atom_to_list(Name) ++ "@" ++ Host])); + _ -> + exit("Test node must be started with '-sname'") + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_mgc(Node, Mid, ET, Verbosity) -> + d("start mgc[~p]: ~p", [Node, Mid]), + RI = {receive_info, mk_recv_info(ET)}, + Config = [{local_mid, Mid}, RI], + Pid = spawn_link(Node, ?MODULE, mgc, [self(), Verbosity, Config]), + await_started(Pid). + +mk_recv_info(ET) -> + mk_recv_info(ET, []). + +mk_recv_info([], Acc) -> + Acc; +mk_recv_info([{text,tcp}|ET], Acc) -> + RI = [{encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp}, + {port, 2944}], + mk_recv_info(ET, [RI|Acc]); +mk_recv_info([{text,udp}|ET], Acc) -> + RI = [{encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_udp}, + {port, 2944}], + mk_recv_info(ET, [RI|Acc]); +mk_recv_info([{binary,tcp}|ET], Acc) -> + RI = [{encoding_module, megaco_ber_bin_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp}, + {port, 2945}], + mk_recv_info(ET, [RI|Acc]); +mk_recv_info([{binary,udp}|ET], Acc) -> + RI = [{encoding_module, megaco_ber_bin_encoder}, + {encoding_config, []}, + {transport_module, megaco_udp}, + {port, 2945}], + mk_recv_info(ET, [RI|Acc]); +mk_recv_info([ET|_], _) -> + throw({error, {invaalid_encoding_transport, ET}}). + +mgc(Parent, Verbosity, Config) -> + process_flag(trap_exit, true), + put(verbosity, Verbosity), + put(sname, "MGC"), + i("mgc -> starting"), + {Mid, TcpSup, UdpSup} = mgc_init(Config), + notify_started(Parent), + S = #mgc{parent = Parent, + tcp_sup = TcpSup, udp_sup = UdpSup, mid = Mid}, + i("mgc -> started"), + mgc_loop(S). + +mgc_init(Config) -> + d("mgc_init -> entry"), + Mid = get_conf(local_mid, Config), + RI = get_conf(receive_info, Config), + d("mgc_init -> start megaco"), + application:start(megaco), + d("mgc_init -> start megaco user"), + megaco:start_user(Mid, []), + d("mgc_init -> update user info (user_mod)"), + megaco:update_user_info(Mid, user_mod, ?MODULE), + d("mgc_init -> update user info (user_args)"), + megaco:update_user_info(Mid, user_args, [self()]), + d("mgc_init -> get user info (receive_handle)"), + RH = megaco:user_info(Mid,receive_handle), + d("mgc_init -> parse receive info"), + ListenTo = mgc_parse_receive_info(RI, RH), + d("mgc_init -> start transports"), + {Tcp, Udp} = mgc_start_transports(ListenTo), + {Mid, Tcp, Udp}. + + +mgc_loop(S) -> + d("mgc_loop -> await request"), + receive + {stop, Parent} when S#mgc.parent == Parent -> + i("mgc_loop -> stopping", []), + Mid = S#mgc.mid, + (catch mgc_close_conns(Mid)), + megaco:stop_user(Mid), + application:stop(megaco), + i("mgc_loop -> stopped", []), + Parent ! {stopped, self()}, + exit(normal); + + + + %% Reset stats + {reset_stats, Parent} when S#mgc.parent == Parent -> + i("mgc_loop -> got request to reset stats counters"), + mgc_reset_stats(S#mgc.mid), + Parent ! {reset_stats_ack, self()}, + mgc_loop(S); + + + %% Give me statistics + {statistics, 1, Parent} when S#mgc.parent == Parent -> + i("mgc_loop -> got request for statistics 1"), + {ok, Gen} = megaco:get_stats(), + GetTrans = + fun(CH) -> + Reason = {statistics, CH}, + Pid = megaco:conn_info(CH, control_pid), + SendMod = megaco:conn_info(CH, send_mod), + SendHandle = megaco:conn_info(CH, send_handle), + {ok, Stats} = + case SendMod of + megaco_tcp -> megaco_tcp:get_stats(SendHandle); + megaco_udp -> megaco_udp:get_stats(SendHandle); + SendMod -> exit(Pid, Reason) + end, + {SendHandle, Stats} + end, + Mid = S#mgc.mid, + Trans = + lists:map(GetTrans, megaco:user_info(Mid, connections)), + Parent ! {statistics, 1, [{gen, Gen}, {trans, Trans}], self()}, + mgc_loop(S); + + + {statistics, 2, Parent} when S#mgc.parent == Parent -> + i("mgc_loop -> got request for statistics 2"), + {ok, Gen} = megaco:get_stats(), + #mgc{tcp_sup = TcpSup, udp_sup = UdpSup} = S, + TcpStats = get_trans_stats(TcpSup, megaco_tcp), + UdpStats = get_trans_stats(UdpSup, megaco_udp), + Parent ! {statistics, 2, [{gen, Gen}, {trans, [TcpStats, UdpStats]}], self()}, + mgc_loop(S); + + + %% Megaco callback messages + {request, Request, From} -> + d("mgc_loop -> received megaco request: ~n~p~n From: ~p", + [Request, From]), + Reply = mgc_handle_request(Request), + d("mgc_loop -> send request reply: ~n~p", [Reply]), + From ! {reply, Reply, self()}, + mgc_loop(S); + + + {'EXIT', Pid, Reason} -> + error_msg("MGC received unexpected exit signal from ~p:~n~p", + [Pid, Reason]), + mgc_loop(S); + + + Invalid -> + i("mgc_loop -> received invalid request: ~p", [Invalid]), + mgc_loop(S) + end. + + +mgc_reset_stats(Mid) -> + megaco:reset_stats(), + mgc_reset_trans_stats(megaco:user_info(Mid, connections), []). + +mgc_reset_trans_stats([], _Reset) -> + ok; +mgc_reset_trans_stats([CH|CHs], Reset) -> + SendMod = megaco:conn_info(CH, send_mod), + case lists:member(SendMod, Reset) of + true -> + mgc_reset_trans_stats(CHs, Reset); + false -> + SendMod:reset_stats(), + mgc_reset_trans_stats(CHs, [SendMod|Reset]) + end. + + +mgc_close_conns(Mid) -> + Reason = {self(), ignore}, + Disco = fun(CH) -> + (catch mgc_close_conn(CH, Reason)) + end, + lists:map(Disco, megaco:user_info(Mid, connections)). + +mgc_close_conn(CH, Reason) -> + d("close connection to ~p", [CH#megaco_conn_handle.remote_mid]), + Pid = megaco:conn_info(CH, control_pid), + SendMod = megaco:conn_info(CH, send_mod), + SendHandle = megaco:conn_info(CH, send_handle), + megaco:disconnect(CH, Reason), + case SendMod of + megaco_tcp -> megaco_tcp:close(SendHandle); + megaco_udp -> megaco_udp:close(SendHandle); + SendMod -> exit(Pid, Reason) + end. + +get_trans_stats(P, SendMod) when is_pid(P) -> + case (catch SendMod:get_stats()) of + {ok, Stats} -> + {SendMod, Stats}; + Else -> + {SendMod, Else} + end; +get_trans_stats(_P, SendMod) -> + {SendMod, undefined}. + +mgc_parse_receive_info([], _RH) -> + throw({error, no_receive_info}); +mgc_parse_receive_info(RI, RH) -> + mgc_parse_receive_info(RI, RH, []). + +mgc_parse_receive_info([], _RH, ListenTo) -> + ListenTo; +mgc_parse_receive_info([RI|RIs], RH, ListenTo) -> + d("mgc_parse_receive_info -> parse receive info"), + RH1 = mgc_parse_receive_info1(RI, RH), + case (catch mgc_parse_receive_info1(RI, RH)) of + {error, Reason} -> + i("failed parsing receive info: ~p~n~p", [RI, Reason]), + exit({failed_parsing_recv_info, RI, Reason}); + RH1 -> + mgc_parse_receive_info(RIs, RH, [RH1|ListenTo]) + end. + +mgc_parse_receive_info1(RI, RH) -> + d("mgc_parse_receive_info1 -> get encoding module"), + EM = get_encoding_module(RI), + d("mgc_parse_receive_info1 -> get encoding config"), + EC = get_encoding_config(RI, EM), + d("mgc_parse_receive_info1 -> get transport module"), + TM = get_transport_module(RI), + d("mgc_parse_receive_info1 -> get transport port"), + TP = get_transport_port(RI), + RH1 = RH#megaco_receive_handle{send_mod = TM, + encoding_mod = EM, + encoding_config = EC}, + {TP, RH1}. + + +mgc_start_transports([]) -> + throw({error, no_transport}); +mgc_start_transports(ListenTo) -> + mgc_start_transports(ListenTo, undefined, undefined). + + +mgc_start_transports([], TcpSup, UdpSup) -> + {TcpSup, UdpSup}; +mgc_start_transports([{Port, RH}|ListenTo], TcpSup, UdpSup) + when RH#megaco_receive_handle.send_mod == megaco_tcp -> + TcpSup1 = mgc_start_tcp(RH, Port, TcpSup), + mgc_start_transports(ListenTo, TcpSup1, UdpSup); +mgc_start_transports([{Port, RH}|ListenTo], TcpSup, UdpSup) + when RH#megaco_receive_handle.send_mod == megaco_udp -> + UdpSup1 = mgc_start_udp(RH, Port, UdpSup), + mgc_start_transports(ListenTo, TcpSup, UdpSup1); +mgc_start_transports([{_Port, RH}|_ListenTo], _TcpSup, _UdpSup) -> + throw({error, {bad_send_mod, RH#megaco_receive_handle.send_mod}}). + + +mgc_start_tcp(RH, Port, undefined) -> + d("start tcp transport"), + case megaco_tcp:start_transport() of + {ok, Sup} -> + mgc_start_tcp(RH, Port, Sup); + Else -> + throw({error, {failed_starting_tcp_transport, Else}}) + end; +mgc_start_tcp(RH, Port, Sup) when is_pid(Sup) -> + d("tcp listen on ~p", [Port]), + Opts = [{port, Port}, + {receive_handle, RH}, + {tcp_options, [{nodelay, true}]}], + mgc_tcp_create_listen(Sup, Opts, 3). + +mgc_tcp_create_listen(Sup, Opts, N) -> + mgc_tcp_create_listen(Sup, Opts, N, 1, undefined). + +mgc_tcp_create_listen(_Sup, _Opts, N, N, InitialReason) -> + d("failed creating mgc tcp listen socket after ~p tries: ~p", + [N, InitialReason]), + throw({error, {failed_starting_tcp_listen, InitialReason}}); +mgc_tcp_create_listen(Sup, Opts, MaxN, N, _InitialReason) + when is_integer(N) andalso is_integer(MaxN) andalso (MaxN > N) -> + d("try create mgc tcp listen socket [~w]", [N]), + case megaco_tcp:listen(Sup, Opts) of + ok -> + Sup; + {error, {could_not_start_listener, {gen_tcp_listen, eaddrinuse} = Reason}} -> + sleep(N * 200), + mgc_tcp_create_listen(Sup, Opts, MaxN, N + 1, Reason); + {error, Reason} -> + throw({error, {failed_starting_tcp_listen, Reason}}); + Else -> + throw({error, {failed_starting_tcp_listen, Else}}) + end. + + +mgc_start_udp(RH, Port, undefined) -> + d("start udp transport"), + case megaco_udp:start_transport() of + {ok, Sup} -> + mgc_start_udp(RH, Port, Sup); + Else -> + throw({error, {failed_starting_udp_transport, Else}}) + end; +mgc_start_udp(RH, Port, Sup) -> + d("open udp ~p", [Port]), + Opts = [{port, Port}, {receive_handle, RH}], + case megaco_udp:open(Sup, Opts) of + {ok, _SendHandle, _ControlPid} -> + Sup; + Else -> + exit({error, {failed_starting_udp_listen, Else}}) + end. + + + +%% ----------------------- +%% Handle megaco callbacks +%% + +mgc_handle_request({handle_connect, _CH, _PV}) -> + ok; +mgc_handle_request({handle_disconnect, CH, _PV, R}) -> + megaco:cancel(CH, R), % Cancel the outstanding messages + ok; +mgc_handle_request({handle_syntax_error, _RH, _PV, _ED}) -> + reply; +mgc_handle_request({handle_message_error, _CH, _PV, _ED}) -> + no_reply; +mgc_handle_request({handle_trans_request, CH, PV, ARs}) -> + ED = #'ErrorDescriptor'{errorCode = ?megaco_not_implemented, + errorText = "Only single service change on null context handled"}, + case ARs of + [AR] -> + ContextId = AR#'ActionRequest'.contextId, + case AR#'ActionRequest'.commandRequests of + [CR] when ContextId == ?megaco_null_context_id -> + case CR#'CommandRequest'.command of + {serviceChangeReq, Req} -> + Rep = mgc_service_change(CH, PV, Req), + CmdRep = [{serviceChangeReply, Rep}], + {discard_ack, + [#'ActionReply'{contextId = ContextId, + commandReply = CmdRep}]}; + _ -> + {discard_ack, ED} + end; + _ -> + {discard_ack, ED} + end; + _ -> + {discard_ack, ED} + end; +mgc_handle_request({handle_trans_long_request, _CH, _PV, _RD}) -> + ED = #'ErrorDescriptor'{errorCode = ?megaco_not_implemented, + errorText = "Long transaction requests not handled"}, + {discard_ack, ED}; +mgc_handle_request({handle_trans_reply, _CH, _PV, _AR, _RD}) -> + ok; +mgc_handle_request({handle_trans_ack, _CH, _PV, _AS, _AD}) -> + ok. + +mgc_service_change(CH, _PV, SCR) -> + SCP = SCR#'ServiceChangeRequest'.serviceChangeParms, + #'ServiceChangeParm'{serviceChangeAddress = Address, + serviceChangeProfile = Profile, + serviceChangeReason = [_Reason]} = SCP, + TermId = SCR#'ServiceChangeRequest'.terminationID, + if + TermId == [?megaco_root_termination_id] -> + MyMid = CH#megaco_conn_handle.local_mid, + Res = {serviceChangeResParms, + #'ServiceChangeResParm'{serviceChangeMgcId = MyMid, + serviceChangeAddress = Address, + serviceChangeProfile = Profile}}, + #'ServiceChangeReply'{terminationID = TermId, + serviceChangeResult = Res}; + true -> + Res = {errorDescriptor, + #'ErrorDescriptor'{errorCode = ?megaco_not_implemented, + errorText = "Only handled for root"}}, + + #'ServiceChangeReply'{terminationID = TermId, + serviceChangeResult = Res} + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_mg(Node, Mid, Encoding, Transport, Verbosity) -> + d("start mg[~p]: ~p", [Node, Mid]), + RI1 = + case Encoding of + text -> + [{encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {port,2944}]; + binary -> + [{encoding_module, megaco_ber_bin_encoder}, + {encoding_config, []}, + {port,2945}] + end, + RI2 = + case Transport of + tcp -> + [{transport_module, megaco_tcp}]; + udp -> + [{transport_module, megaco_udp}] + end, + RI = {receive_info, RI1 ++ RI2}, + Config = [{local_mid, Mid}, RI], + Pid = spawn_link(Node, ?MODULE, mg, [self(), Verbosity, Config]), + await_started(Pid). + + +mg(Parent, Verbosity, Config) -> + process_flag(trap_exit, true), + put(verbosity, Verbosity), + put(sname, "MG"), + i("mg -> starting"), + {Mid, ConnHandle} = mg_init(Config), + notify_started(Parent), + S = #mg{parent = Parent, mid = Mid, conn_handle = ConnHandle}, + i("mg -> started"), + mg_loop(S). + +mg_init(Config) -> + d("mg_init -> entry"), + random_init(), + Mid = get_conf(local_mid, Config), + RI = get_conf(receive_info, Config), + d("mg_init -> start megaco"), + application:start(megaco), + d("mg_init -> start megaco user"), + megaco:start_user(Mid, []), + d("mg_init -> update user info (user_mod)"), + megaco:update_user_info(Mid, user_mod, ?MODULE), + d("mg_init -> update user info (user_args)"), + megaco:update_user_info(Mid, user_args, [self()]), + d("mg_init -> get user info (receive_handle)"), + RH = megaco:user_info(Mid,receive_handle), + d("mg_init -> parse receive info"), + {MgcPort,RH1} = mg_parse_receive_info(RI, RH), + d("mg_init -> start transport with"), + ConnHandle = mg_start_transport(MgcPort, RH1), + {Mid, ConnHandle}. + +mg_loop(#mg{state = State} = S) -> + d("mg_loop(~p) -> await request", [State]), + receive + {stop, Parent} when S#mg.parent == Parent -> + i("mg_loop(~p) -> stopping", [State]), + mg_close_conn(S#mg.conn_handle), + megaco:stop_user(S#mg.mid), + application:stop(megaco), + i("mg_loop(~p) -> stopped", [State]), + Parent ! {stopped, self()}, + exit(normal); + + + {reset_stats, Parent} when S#mg.parent == Parent -> + i("mg_loop(~p) -> got request to reset stats counters", [State]), + %% mg_reset_stats(S#mgc.conn_handle), + mg_reset_stats(S#mg.conn_handle), + Parent ! {reset_stats_ack, self()}, + mg_loop(S); + + + + %% Give me statistics + {statistics, 1, Parent} when S#mg.parent == Parent -> + i("mg_loop(~p) -> got request for statistics 1", [State]), + {ok, Gen} = megaco:get_stats(), + CH = S#mg.conn_handle, + Reason = {statistics, CH}, + Pid = megaco:conn_info(CH, control_pid), + SendMod = megaco:conn_info(CH, send_mod), + SendHandle = megaco:conn_info(CH, send_handle), + {ok, Trans} = + case SendMod of + megaco_tcp -> megaco_tcp:get_stats(SendHandle); + megaco_udp -> megaco_udp:get_stats(SendHandle); + SendMod -> exit(Pid, Reason) + end, + Parent ! {statistics, 1, [{gen, Gen}, {trans, Trans}], self()}, + mg_loop(S); + + + %% Do a service change + {service_change, Parent} when S#mg.parent == Parent, + State == initiated -> + i("mg_loop(~p) -> received request to perform service change", + [State]), + Res = mg_service_change(S#mg.conn_handle), + d("mg_loop(~p) -> result: ~p", [State, Res]), + mg_loop(S#mg{state = connecting}); + + + %% Apply some load + {apply_load, Parent, Times} when S#mg.parent == Parent -> + i("mg_loop(~p) -> received apply_load request", [State]), + apply_load_timer(), + Parent ! {apply_load_ack, self()}, + mg_loop(S#mg{load_counter = Times - 1}); + + + apply_load_timeout -> + d("mg_loop(~p) -> received apply_load timeout [~p]", + [State, S#mg.load_counter]), + mg_apply_load(S), + mg_loop(S); + + + %% Megaco callback messages + {request, Request, From} -> + d("mg_loop(~p) -> received megaco request: ~n~p~n From: ~p", + [State, Request, From]), + {Reply, NewS} = mg_handle_request(Request, S), + d("mg_loop(~p) -> send request reply: ~n~p", + [NewS#mg.state, Reply]), + From ! {reply, Reply, self()}, + mg_loop(NewS); + + + {'EXIT', Pid, Reason} -> + error_msg("MG ~p received unexpected exit signal from ~p:~n~p", + [S#mg.mid, Pid, Reason]), + mg_loop(S); + + + Invalid -> + i("mg_loop(~p) -> received invalid request: ~p", [State, Invalid]), + mg_loop(S) + + end. + + +mg_reset_stats(CH) -> + megaco:reset_stats(), + case (catch megaco:conn_info(CH, send_mod)) of + {error, Reason} -> + error_msg("unexpected result when retrieving send module for " + "own connection ~p: ~p. " + "~nexiting...", [CH, Reason]), + exit({invalid_connection, CH, Reason}); + {'EXIT', Reason} -> + error_msg("exit signal when retrieving send module for " + "own connection ~p: ~p. " + "~nexiting...", [CH, Reason]), + exit({invalid_connection, CH, Reason}); + SendMod when is_atom(SendMod) -> + SendMod:reset_stats() + end. + + +mg_close_conn(CH) -> + Reason = {self(), ignore}, + Pid = megaco:conn_info(CH, control_pid), + SendMod = megaco:conn_info(CH, send_mod), + SendHandle = megaco:conn_info(CH, send_handle), + megaco:disconnect(CH, Reason), + case SendMod of + megaco_tcp -> megaco_tcp:close(SendHandle); + megaco_udp -> megaco_udp:close(SendHandle); + SendMod -> exit(Pid, Reason) + end. + +% display_tuple(T) when tuple(T), size(T) > 0 -> +% i("size(T): ~p", [size(T)]), +% display_tuple(T,1). + +% display_tuple(T,P) when P > size(T) -> +% ok; +% display_tuple(T,P) -> +% i("T[~p]: ~p", [P,element(P,T)]), +% display_tuple(T,P+1). + + +mg_parse_receive_info(RI, RH) -> + d("mg_parse_receive_info -> get encoding module"), + EM = get_encoding_module(RI), + d("mg_parse_receive_info -> get encoding config"), + EC = get_encoding_config(RI, EM), + d("mg_parse_receive_info -> get transport module"), + TM = get_transport_module(RI), + d("mg_parse_receive_info -> get transport port"), + TP = get_transport_port(RI), + RH1 = RH#megaco_receive_handle{send_mod = TM, + encoding_mod = EM, + encoding_config = EC}, + {TP, RH1}. + + +mg_start_transport(MgcPort, + #megaco_receive_handle{send_mod = megaco_tcp} = RH) -> + mg_start_tcp(MgcPort,RH); +mg_start_transport(MgcPort, + #megaco_receive_handle{send_mod = megaco_udp} = RH) -> + mg_start_udp(MgcPort,RH); +mg_start_transport(_, #megaco_receive_handle{send_mod = Mod}) -> + throw({error, {bad_send_mod, Mod}}). + + +mg_start_tcp(MgcPort, RH) -> + d("start tcp transport"), + case megaco_tcp:start_transport() of + {ok, Sup} -> + {ok, LocalHost} = inet:gethostname(), + Opts = [{host, LocalHost}, + {port, MgcPort}, + {receive_handle, RH}, + {tcp_options, [{nodelay, true}]}], + case megaco_tcp:connect(Sup, Opts) of + {ok, SendHandle, ControlPid} -> + PrelMgcMid = preliminary_mid, + {ok, ConnHandle} = + megaco:connect(RH, PrelMgcMid, + SendHandle, ControlPid), + ConnHandle; + {error, Reason} -> + {error, {megaco_tcp_connect, Reason}} + end; + {error, Reason} -> + {error, {megaco_tcp_start_transport, Reason}} + end. + + +mg_start_udp(MgcPort, RH) -> + d("start udp transport"), + case megaco_udp:start_transport() of + {ok, Sup} -> + {ok, LocalHost} = inet:gethostname(), + Opts = [{port, 0}, {receive_handle, RH}], + case megaco_udp:open(Sup, Opts) of + {ok, Handle, ControlPid} -> + MgcMid = preliminary_mid, + SendHandle = megaco_udp:create_send_handle(Handle, + LocalHost, + MgcPort), + {ok, ConnHandle} = + megaco:connect(RH, MgcMid, + SendHandle, ControlPid), + ConnHandle; + {error, Reason} -> + {error, {megaco_udp_open, Reason}} + end; + {error, Reason} -> + {error, {megaco_udp_start_transport, Reason}} + end. + + +mg_service_change(ConnHandle) -> + mg_service_change(ConnHandle, restart, ?megaco_cold_boot). + +mg_service_change(ConnHandle, Method, Reason) -> + SCP = #'ServiceChangeParm'{serviceChangeMethod = Method, + serviceChangeReason = [Reason]}, + TermId = [?megaco_root_termination_id], + SCR = #'ServiceChangeRequest'{terminationID = TermId, + serviceChangeParms = SCP}, + CR = #'CommandRequest'{command = {serviceChangeReq, SCR}}, + AR = #'ActionRequest'{contextId = ?megaco_null_context_id, + commandRequests = [CR]}, + megaco:cast(ConnHandle, [AR], []). + + +mg_notify_request(CH) -> + TimeStamp = cre_timeNotation("19990729", "22000000"), + Event = cre_observedEvent("al/of",TimeStamp), + Desc = cre_observedEventsDesc(2222,[Event]), + NotifyReq = cre_notifyReq([#megaco_term_id{id = ?A4444}],Desc), + CmdReq = cre_commandReq({notifyReq, NotifyReq}), + ActReq = cre_actionReq(?megaco_null_context_id, [CmdReq]), + megaco:cast(CH, [ActReq], [{reply_data, Desc}]). + +mg_apply_load(#mg{conn_handle = CH}) -> + mg_notify_request(CH). + + +cre_actionReq(Cid, Cmds) -> + #'ActionRequest'{contextId = Cid, + commandRequests = Cmds}. + +cre_commandReq(Cmd) -> + #'CommandRequest'{command = Cmd}. + +cre_notifyReq(Tid, EvsDesc) -> + #'NotifyRequest'{terminationID = Tid, observedEventsDescriptor = EvsDesc}. + +cre_observedEventsDesc(Id, EvList) -> + #'ObservedEventsDescriptor'{requestId = Id, observedEventLst = EvList}. + +cre_observedEvent(Name, Not) -> + #'ObservedEvent'{eventName = Name, timeNotation = Not}. + +cre_timeNotation(D,T) -> + #'TimeNotation'{date = D, time = T}. + +%% ----------------------- +%% Handle megaco callbacks +%% + +mg_handle_request({handle_connect, CH, _PV}, + #mg{state = connecting} = S) -> + {ok, S#mg{conn_handle = CH}}; + +mg_handle_request({handle_disconnect, CH, _PV, _R}, S) -> + {ok, S#mg{conn_handle = CH}}; + +mg_handle_request({handle_syntax_error, _RH, _PV, _ED}, S) -> + {reply, S}; + +mg_handle_request({handle_message_error, CH, _PV, _ED}, S) -> + {no_reply, S#mg{conn_handle = CH}}; + +mg_handle_request({handle_trans_request, CH, _PV, _AR}, S) -> + ED = #'ErrorDescriptor'{errorCode = ?megaco_not_implemented, + errorText = "Transaction requests not handled"}, + {{discard_ack, ED}, S#mg{conn_handle = CH}}; + +mg_handle_request({handle_trans_long_request, CH, _PV, _RD}, S) -> + ED = #'ErrorDescriptor'{errorCode = ?megaco_not_implemented, + errorText = "Long transaction requests not handled"}, + {{discard_ack, ED}, S#mg{conn_handle = CH}}; + +mg_handle_request({handle_trans_reply, CH, _PV, _AR, _RD}, + #mg{parent = Pid, state = connecting} = S) -> + %% Should really check this... + Pid ! {service_change_reply, ok, self()}, + {ok, S#mg{conn_handle = CH, state = connected}}; +mg_handle_request({handle_trans_reply, _CH, _PV, {error, ED}, RD}, + #mg{parent = Pid, load_counter = 0} = S) + when is_record(ED, 'ErrorDescriptor') andalso + is_record(RD, 'ObservedEventsDescriptor') -> + Pid ! {load_complete, self()}, + {ok, S}; +mg_handle_request({handle_trans_reply, _CH, _PV, {error, ED}, RD}, + #mg{load_counter = N} = S) + when is_record(ED, 'ErrorDescriptor') andalso + is_record(RD, 'ObservedEventsDescriptor') -> + apply_load_timer(), + {ok, S#mg{load_counter = N-1}}; + +mg_handle_request({handle_trans_ack, _CH, _PV, _AS, _AD}, S) -> + {ok, S}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +await_started(Pid) -> + receive + {started, Pid} -> + d("await_started ~p: ok", [Pid]), + {ok, Pid}; + {'EXIT', Pid, Reason} -> + i("await_started ~p: received exit signal: ~p", [Pid, Reason]), + exit({failed_starting, Pid, Reason}) + after 10000 -> + i("await_started ~p: timeout", [Pid]), + exit({error, timeout}) + end. + +stop(Pid) -> + d("stop ~p", [Pid]), + Pid ! {stop, self()}, + receive + {stopped, Pid} -> + d("stop -> received stopped from ~p", [Pid]), + ok; + {'EXIT', Pid, Reason} -> + i("stop ~p: received exit signal: ~p", [Pid, Reason]), + exit({failed_stopping, Pid, Reason}) + after 10000 -> + exit({error, timeout}) + end. + +get_stats(Pid, No) -> + d("get_stats ~p", [Pid]), + Pid ! {statistics, No, self()}, + receive + {statistics, No, Stats, Pid} -> + {ok, Stats}; + {'EXIT', Pid, Reason} -> + i("get_stats ~p: received exit signal: ~p", [Pid, Reason]), + exit({failed_getting_stats, Pid, Reason}) + after 10000 -> + exit({error, timeout}) + end. + +service_change(Pid) -> + d("service_change ~p", [Pid]), + Pid ! {service_change, self()}, + receive + {service_change_reply, Res, Pid} -> + {ok, Res}; + {'EXIT', Pid, Reason} -> + i("service_change ~p: received exit signal: ~p", [Pid, Reason]), + exit({failed_service_change, Pid, Reason}) + after 10000 -> + exit({error, timeout}) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +notify_started(Parent) -> + Parent ! {started, self()}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% The megaco user callback interface + +handle_connect(CH, PV, Pid) -> +% i("handle_connect -> entry with" +% "~n CH: ~p" +% "~n PV: ~p" +% "~n Pid: ~p", [CH, PV, Pid]), + case CH#megaco_conn_handle.remote_mid of + preliminary_mid -> + %% Avoids deadlock + ok; + _ -> + Reply = request(Pid, {handle_connect, CH, PV}), +% d("handle_connect -> Reply:~n~p", [Reply]), + Reply + end. + +handle_disconnect(_CH, _PV, + {user_disconnect, {Pid, ignore}}, + Pid) -> +% i("handle_disconnect(ignore) -> entry with" +% "~n CH: ~p" +% "~n PV: ~p", [CH, PV]), + %% Avoids deadlock + ok; +handle_disconnect(CH, PV, R, Pid) -> +% i("handle_disconnect -> entry with" +% "~n CH: ~p" +% "~n PV: ~p" +% "~n R: ~p", [CH, PV, R]), + request(Pid, {handle_disconnect, CH, PV, R}). + +handle_syntax_error(ReceiveHandle, ProtocolVersion, ErrorDescriptor, Pid) -> +% i("handle_syntax_error -> entry with" +% "~n ReceiveHandle: ~p" +% "~n ProtocolVersion: ~p" +% "~n ErrorDescriptor: ~p", +% [ReceiveHandle, ProtocolVersion, ErrorDescriptor]), + Req = {handle_syntax_error, ReceiveHandle, ProtocolVersion, + ErrorDescriptor}, + request(Pid, Req). + +handle_message_error(ConnHandle, ProtocolVersion, ErrorDescriptor, Pid) -> +% i("handle_message_error -> entry with" +% "~n ConnHandle: ~p" +% "~n ProtocolVersion: ~p" +% "~n ErrorDescriptor: ~p", +% [ConnHandle, ProtocolVersion, ErrorDescriptor]), + Req = {handle_message_error, ConnHandle, ProtocolVersion, ErrorDescriptor}, + request(Pid, Req). + +handle_trans_request(CH, PV, AR, Pid) -> +% i("handle_trans_request -> entry with" +% "~n CH: ~p" +% "~n PV: ~p" +% "~n AR: ~p" +% "~n Pid: ~p", [CH, PV, AR, Pid]), + Reply = request(Pid, {handle_trans_request, CH, PV, AR}), +% i("handle_trans_request -> Reply:~n~p", [Reply]), + Reply. + +handle_trans_long_request(ConnHandle, ProtocolVersion, ReqData, Pid) -> +% i("handle_trans_long_request -> entry with" +% "~n ConnHandle: ~p" +% "~n ProtocolVersion: ~p" +% "~n ReqData: ~p", [ConnHandle, ProtocolVersion, ReqData]), + Req = {handle_trans_long_request, ConnHandle, ProtocolVersion, ReqData}, + request(Pid, Req). + +handle_trans_reply(ConnHandle, ProtocolVersion, ActualReply, ReplyData, Pid) -> +% i("handle_trans_reply -> entry with" +% "~n ConnHandle: ~p" +% "~n ProtocolVersion: ~p" +% "~n ActualReply: ~p" +% "~n ReplyData: ~p", +% [ConnHandle, ProtocolVersion, ActualReply, ReplyData]), + Req = {handle_trans_reply, ConnHandle, ProtocolVersion, + ActualReply, ReplyData}, + request(Pid, Req). + +handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData, Pid) -> +% i("handle_trans_ack -> entry with" +% "~n ConnHandle: ~p" +% "~n ProtocolVersion: ~p" +% "~n AckStatus: ~p" +% "~n AckData: ~p", +% [ConnHandle, ProtocolVersion, AckStatus, AckData]), + Req = {handle_trans_ack, ConnHandle, ProtocolVersion, AckStatus, AckData}, + request(Pid, Req). + + +request(Pid, Request) -> + Pid ! {request, Request, self()}, + receive + {reply, Reply, Pid} -> + Reply + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +sleep(X) -> + receive after X -> ok end. + + +error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A). + + +get_encoding_module(RI) -> + case (catch get_conf(encoding_module, RI)) of + {error, _} -> + undefined; + Val -> + Val + end. + +get_encoding_config(RI, EM) -> + case text_codec(EM) of + true -> + case megaco:system_info(text_config) of + [Conf] when is_list(Conf) -> + Conf; + _ -> + [] + end; + + false -> + get_conf(encoding_config, RI) + end. + +text_codec(megaco_compact_text_encoder) -> + true; +text_codec(megaco_pretty_text_encoder) -> + true; +text_codec(_) -> + false. + + +get_transport_module(RI) -> + get_conf(transport_module, RI). + +get_transport_port(RI) -> + get_conf(port, RI). + + +get_conf(Key, Config) -> + case lists:keysearch(Key, 1, Config) of + {value, {Key, Val}} -> + Val; + _ -> + exit({error, {not_found, Key, Config}}) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +i(F) -> + i(F, []). + +i(F, A) -> + print(info, get(verbosity), "", F, A). + + +d(F) -> + d(F, []). + +d(F, A) -> + print(debug, get(verbosity), "DBG: ", F, A). + + +printable(_, debug) -> true; +printable(info, info) -> true; +printable(_,_) -> false. + +print(Severity, Verbosity, P, F, A) -> + print(printable(Severity,Verbosity), P, F, A). + +print(true, P, F, A) -> + io:format("~s~p:~s: " ++ F ++ "~n", [P, self(), get(sname) | A]); +print(_, _, _, _) -> + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +random_init() -> + {A,B,C} = now(), + random:seed(A,B,C). + +random() -> + 10 * random:uniform(50). + +apply_load_timer() -> + erlang:send_after(random(), self(), apply_load_timeout). + diff --git a/lib/megaco/test/megaco_mreq_test.erl b/lib/megaco/test/megaco_mreq_test.erl new file mode 100644 index 0000000000..676acd8a12 --- /dev/null +++ b/lib/megaco/test/megaco_mreq_test.erl @@ -0,0 +1,470 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Verify the application specifics of the Megaco application +%%---------------------------------------------------------------------- +-module(megaco_mreq_test). + +-compile(export_all). + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). + +-define(TEST_VERBOSITY, debug). +-define(MGC_VERBOSITY, debug). +-define(MG_VERBOSITY, debug). + +-define(LOAD_COUNTER_START, 10). +-define(A4444, ["11111111", "00000000", "00000000"]). +-define(A4445, ["11111111", "00000000", "11111111"]). +-define(A5555, ["11111111", "11111111", "00000000"]). +-define(A5556, ["11111111", "11111111", "11111111"]). + +-define(MGC_START(Pid, Mid, ET, Verb), + megaco_test_mgc:start(Pid, Mid, ET, Verb)). +-define(MGC_STOP(Pid), megaco_test_mgc:stop(Pid)). +-define(MGC_GET_STATS(Pid, No), megaco_test_mgc:get_stats(Pid, No)). +-define(MGC_RESET_STATS(Pid), megaco_test_mgc:reset_stats(Pid)). +-define(MGC_REQ_DISC(Pid,To), megaco_test_mgc:request_discard(Pid,To)). +-define(MGC_REQ_PEND(Pid,To), megaco_test_mgc:request_pending(Pid,To)). +-define(MGC_REQ_HAND(Pid), megaco_test_mgc:request_handle(Pid)). + +-define(MG_START(Pid, Mid, Enc, Transp, Verb), + megaco_test_mg:start(Pid, Mid, Enc, Transp, Verb)). +-define(MG_STOP(Pid), megaco_test_mg:stop(Pid)). +-define(MG_GET_STATS(Pid, No), megaco_test_mg:get_stats(Pid, No)). +-define(MG_RESET_STATS(Pid), megaco_test_mg:reset_stats(Pid)). +-define(MG_SERV_CHANGE(Pid), megaco_test_mg:service_change(Pid)). +-define(MG_NOTIF_RAR(Pid), megaco_test_mg:notify_request_and_reply(Pid)). +-define(MG_NOTIF_REQ(Pid), megaco_test_mg:notify_request(Pid)). +-define(MG_NOTIF_AR(Pid), megaco_test_mg:await_notify_reply(Pid)). +-define(MG_CANCEL(Pid,R), megaco_test_mg:cancel_request(Pid,R)). +-define(MG_APPLY_LOAD(Pid,CntStart), megaco_test_mg:apply_load(Pid,CntStart)). + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + + +%% Test server callbacks +init_per_testcase(Case, Config) -> + process_flag(trap_exit, true), + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + process_flag(trap_exit, false), + megaco_test_lib:fin_per_testcase(Case, Config). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all(suite) -> + Cases = + [ + req_and_rep, + req_and_pending, + req_and_cancel + ], + Cases. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +req_and_rep(suite) -> + []; +req_and_rep(doc) -> + []; +req_and_rep(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + i("req_and_rep -> starting"), + MgcNode = make_node_name(mgc), + Mg1Node = make_node_name(mg1), + Mg2Node = make_node_name(mg2), + Mg3Node = make_node_name(mg3), + Mg4Node = make_node_name(mg4), + d("req_and_rep -> Nodes: " + "~n MgcNode: ~p" + "~n Mg1Node: ~p" + "~n Mg2Node: ~p" + "~n Mg3Node: ~p" + "~n Mg4Node: ~p", + [MgcNode, Mg1Node, Mg2Node, Mg3Node, Mg4Node]), + ok = megaco_test_lib:start_nodes([MgcNode, + Mg1Node, Mg2Node, Mg3Node, Mg4Node], + ?FILE, ?LINE), + + %% Start the MGC and MGs + i("req_and_rep -> start the MGC"), + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + {ok, Mgc} = + ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY), + + i("req_and_rep -> start and connect the MGs"), + MgConf0 = [{Mg1Node, "mg1", text, tcp, ?MG_VERBOSITY}, + {Mg2Node, "mg2", text, udp, ?MG_VERBOSITY}, + {Mg3Node, "mg3", binary, tcp, ?MG_VERBOSITY}, + {Mg4Node, "mg4", binary, udp, ?MG_VERBOSITY}], + MgConf = req_and_rep_connect_mg(MgConf0, []), + + %% Collect the (initial) MGs statistics + Stats1 = req_and_rep_get_mg_stats(MgConf, []), + d("req_and_rep -> stats for the MGs: ~n~p", [Stats1]), + + %% Collect and check the MGC statistics + i("req_and_rep -> collect and check the MGC stats"), + {ok, MgcStats1} = ?MGC_GET_STATS(Mgc, 1), + d("req_and_rep -> stats (1) for Mgc: ~n~p~n", [MgcStats1]), + + + sleep(1000), + + + %% And apply some load + i("req_and_rep -> apply traffic load"), + ok = req_and_rep_apply_load(MgConf), + + %% Await completion of load part and the collect traffic + i("req_and_rep -> await load completion"), + ok = req_and_rep_await_load_complete(MgConf), + + + sleep(1000), + + + i("req_and_rep -> collect the MGs statistics"), + Stats2 = req_and_rep_get_mg_stats(MgConf, []), + d("req_and_rep -> stats for MGs: ~n~p", [Stats2]), + + i("req_and_rep -> collect the MGC statistics"), + {ok, MgcStats2} = ?MGC_GET_STATS(Mgc, 1), + d("req_and_rep -> stats (1) for Mgc: ~n~p~n", [MgcStats2]), + + + sleep(1000), + + + %% Reset counters + i("req_and_rep -> reset the MGs statistics"), + req_and_rep_reset_mg_stats(MgConf), + Stats3 = req_and_rep_get_mg_stats(MgConf, []), + d("req_and_rep -> stats for the MGs: ~n~p", [Stats3]), + + i("req_and_rep -> reset the MGC statistics"), + req_and_rep_reset_mgc_stats(Mgc), + {ok, MgcStats3} = ?MGC_GET_STATS(Mgc, 1), + d("req_and_rep -> stats (1) for Mgc: ~n~p~n", [MgcStats3]), + + + sleep(1000), + + + %% Tell MGs to stop + i("req_and_rep -> stop the MGs"), + req_and_rep_stop_mg(MgConf), + + + sleep(1000), + + + %% Collect the statistics + i("req_and_rep -> collect the MGC statistics"), + {ok, MgcStats4} = ?MGC_GET_STATS(Mgc, 1), + d("req_and_rep -> stats (1) for Mgc: ~n~p~n", [MgcStats4]), + {ok, MgcStats5} = ?MGC_GET_STATS(Mgc, 2), + d("req_and_rep -> stats (2) for Mgc: ~n~p~n", [MgcStats5]), + + %% Tell Mgc to stop + i("req_and_rep -> stop the MGC"), + ?MGC_STOP(Mgc), + + i("req_and_rep -> done", []), + ok. + + +req_and_rep_connect_mg([], Acc) -> + lists:reverse(Acc); +req_and_rep_connect_mg([{Node, Name, Coding, Trans, Verb}|Mg], Acc) -> + Pid = req_and_rep_connect_mg(Node, Name, Coding, Trans, Verb), + req_and_rep_connect_mg(Mg, [{Name, Pid}|Acc]). + +req_and_rep_connect_mg(Node, Name, Coding, Trans, Verb) -> + Mid = {deviceName, Name}, + {ok, Pid} = ?MG_START(Node, Mid, Coding, Trans, Verb), + + %% Ask the MGs to do a service change + Res = ?MG_SERV_CHANGE(Pid), + d("req_and_rep_connect_mg -> (~s) service change result: ~p", [Name,Res]), + + Pid. + + +req_and_rep_stop_mg(MGs) -> + [?MG_STOP(Pid) || {_Name, Pid} <- MGs]. + + +req_and_rep_get_mg_stats([], Acc) -> + lists:reverse(Acc); +req_and_rep_get_mg_stats([{Name, Pid}|Mgs], Acc) -> + {ok, Stats} = ?MG_GET_STATS(Pid, 1), + d("req_and_rep_get_mg_stats -> stats for ~s: ~n~p~n", [Name, Stats]), + req_and_rep_get_mg_stats(Mgs, [{Name, Stats}|Acc]). + + +req_and_rep_apply_load([]) -> + ok; +req_and_rep_apply_load([{_, MG}|MGs]) -> + ?MG_APPLY_LOAD(MG,?LOAD_COUNTER_START), + req_and_rep_apply_load(MGs). + + +req_and_rep_reset_mg_stats([]) -> + ok; +req_and_rep_reset_mg_stats([{Name, Pid}|MGs]) -> + d("req_and_rep_reset_mg_stats -> resetting ~s", [Name]), + ?MG_RESET_STATS(Pid), + req_and_rep_reset_mg_stats(MGs). + +req_and_rep_reset_mgc_stats(Mgc) -> + d("req_and_rep_reset_mgc_stats -> resetting ~p", [Mgc]), + ?MGC_RESET_STATS(Mgc). + + +req_and_rep_await_load_complete([]) -> + ok; +req_and_rep_await_load_complete(MGs0) -> + receive + {load_complete, Pid} -> + d("received load_complete from ~p", [Pid]), + MGs1 = lists:keydelete(Pid, 2, MGs0), + req_and_rep_await_load_complete(lists:delete(Pid, MGs1)); + {'EXIT', Pid, Reason} -> + i("exit signal from ~p: ~p", [Pid, Reason]), + case lists:keymember(Pid, 2, MGs0) of + true -> + exit({mg_exit, Pid, Reason}); + false -> + MGs1 = lists:keydelete(Pid, 2, MGs0), + req_and_rep_await_load_complete(lists:delete(Pid, MGs1)) + end + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +req_and_pending(suite) -> + []; +req_and_pending(doc) -> + []; +req_and_pending(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + i("req_and_pending -> starting"), + + MgcNode = make_node_name(mgc), + Mg1Node = make_node_name(mg1), + + d("req_and_pending -> Nodes: " + "~n MgcNode: ~p" + "~n Mg1Node: ~p", + [MgcNode, Mg1Node]), + ok = megaco_test_lib:start_nodes([MgcNode, Mg1Node], + ?FILE, ?LINE), + + %% Start the MGC and MGs + i("req_and_pending -> start the MGC"), + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + {ok, Mgc} = + ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY), + + i("req_and_pending -> start the MG"), + {ok, Mg1} = + ?MG_START(Mg1Node, {deviceName, "mg1"}, text, tcp, ?MG_VERBOSITY), + + i("req_and_pending -> connect the MG"), + Res1 = ?MG_SERV_CHANGE(Mg1), + d("req_and_pending -> service change result: ~p", [Res1]), + + sleep(1000), + + i("req_and_pending -> change request action to pending"), + {ok, _} = ?MGC_REQ_PEND(Mgc,3500), + + i("req_and_pending -> send notify request"), + {ok, Res2} = ?MG_NOTIF_RAR(Mg1), + d("req_and_pending -> notify reply: ~p",[Res2]), + + sleep(1000), + + %% Tell MGs to stop + i("req_and_rep -> stop the MGs"), + ?MG_STOP(Mg1), + + %% Tell Mgc to stop + i("req_and_pending -> stop the MGC"), + ?MGC_STOP(Mgc), + + i("req_and_pending -> done", []), + ok. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +req_and_cancel(suite) -> + []; +req_and_cancel(doc) -> + []; +req_and_cancel(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + i("req_and_cancel -> starting"), + + MgcNode = make_node_name(mgc), + Mg1Node = make_node_name(mg1), + + d("req_and_cancel -> Nodes: " + "~n MgcNode: ~p" + "~n Mg1Node: ~p", + [MgcNode, Mg1Node]), + ok = megaco_test_lib:start_nodes([MgcNode, Mg1Node], + ?FILE, ?LINE), + + %% Start the MGC and MGs + i("req_and_cancel -> start the MGC"), + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + {ok, Mgc} = + ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY), + + i("req_and_cancel -> start the MG"), + {ok, Mg1} = + ?MG_START(Mg1Node, {deviceName, "mg1"}, text, tcp, ?MG_VERBOSITY), + + i("req_and_cancel -> connect the MG"), + Res1 = ?MG_SERV_CHANGE(Mg1), + d("req_and_cancel -> service change result: ~p", [Res1]), + + + sleep(1000), + + i("req_and_cancel -> change request action to pending"), + {ok, _} = ?MGC_REQ_DISC(Mgc,5000), + + i("req_and_cancel -> send notify request"), + ?MG_NOTIF_REQ(Mg1), + + d("req_and_cancel -> wait some to get it going",[]), + sleep(1000), + + i("req_and_cancel -> now cancel the notify request"), + ok = ?MG_CANCEL(Mg1,req_and_cancel), + + i("req_and_cancel -> now await the notify request result"), + Res2 = ?MG_NOTIF_AR(Mg1), + req_and_cancel_analyze_result(Res2), + + + %% Tell MGs to stop + i("req_and_rep -> stop the MGs"), + ?MG_STOP(Mg1), + + %% Tell Mgc to stop + i("req_and_cancel -> stop the MGC"), + ?MGC_STOP(Mgc), + + i("req_and_cancel -> done", []), + ok.% ?SKIP(not_implemented_yet). + + +req_and_cancel_analyze_result({ok,{_PV,Res}}) -> + d("req_and_cancel -> notify request result: ~n ~p", [Res]), + req_and_cancel_analyze_result2(Res); +req_and_cancel_analyze_result(Unexpected) -> + exit({unexpected_result,Unexpected}). + +req_and_cancel_analyze_result2([]) -> + ok; +req_and_cancel_analyze_result2([{error,{user_cancel,req_and_cancel}}|Res]) -> + req_and_cancel_analyze_result2(Res); +req_and_cancel_analyze_result2([Unknown|_Res]) -> + exit({unknown_result,Unknown}). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +make_node_name(Name) -> + case string:tokens(atom_to_list(node()), [$@]) of + [_,Host] -> + list_to_atom(lists:concat([atom_to_list(Name) ++ "@" ++ Host])); + _ -> + exit("Test node must be started with '-sname'") + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +sleep(X) -> + receive after X -> ok end. + + +error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +i(F) -> + i(F, []). + +i(F, A) -> + print(info, get(verbosity), "", F, A). + + +d(F) -> + d(F, []). + +d(F, A) -> + print(debug, get(verbosity), "DBG: ", F, A). + + +printable(_, debug) -> true; +printable(info, info) -> true; +printable(_,_) -> false. + +print(Severity, Verbosity, P, F, A) -> + print(printable(Severity,Verbosity), P, F, A). + +print(true, P, F, A) -> + io:format("~s~p:~s: " ++ F ++ "~n", [P, self(), get(sname) | A]); +print(_, _, _, _) -> + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +random_init() -> + {A,B,C} = now(), + random:seed(A,B,C). + +random() -> + 10 * random:uniform(50). + +apply_load_timer() -> + erlang:send_after(random(), self(), apply_load_timeout). + diff --git a/lib/megaco/test/megaco_pending_limit_test.erl b/lib/megaco/test/megaco_pending_limit_test.erl new file mode 100644 index 0000000000..1ca29c195c --- /dev/null +++ b/lib/megaco/test/megaco_pending_limit_test.erl @@ -0,0 +1,2158 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Verify the application specifics of the Megaco application +%% Testing the xxxOriginatingPendingLimit property of the +%% root package +%%---------------------------------------------------------------------- +-module(megaco_pending_limit_test). + +-export([t/0, t/1]). +-export([init_per_testcase/2, fin_per_testcase/2]). +-export([all/1, + + sent/1, + sent_timer_late_reply/1, + sent_timer_exceeded/1, + sent_timer_exceeded_long/1, + sent_resend_late_reply/1, + sent_resend_exceeded/1, + sent_resend_exceeded_long/1, + + recv/1, + recv_limit_exceeded1/1, + recv_limit_exceeded2/1, + + tickets/1, + otp_4956/1, + otp_5310/1, + otp_5619/1 + + ]). + +-ifdef(megaco_hipe_special). +-export([ + %% Case: recv_limit_exceeded1 + rle1_mgc_verify_service_change_req_msg/2, + rle1_mgc_verify_notify_req_msg/1, + rle1_mg_verify_handle_connect/1, + rle1_mg_verify_service_change_rep/1, + rle1_mg_verify_trans_rep/1, + + %% Case: otp_4956 + otp_4956_mgc_verify_handle_connect/1, + otp_4956_mgc_verify_service_change_req/2, + otp_4956_mgc_verify_notify_req1/1, + otp_4956_mgc_verify_notify_req2/1, + otp_4956_mgc_verify_handle_trans_req_abort/1, + otp_4956_mgc_verify_handle_disconnect/1, + otp_4956_mg_verify_service_change_rep_msg/1, + otp_4956_mg_verify_pending_msg/1, + otp_4956_mg_verify_pending_limit_msg/1, + + %% Utility + encode_msg/3, + decode_msg/3 + ]). +-endif. + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). + +-define(TEST_VERBOSITY, debug). +-define(MGC_VERBOSITY, debug). +-define(MG_VERBOSITY, debug). + +-define(VERSION, 1). + +-define(A4444, ["11111111", "00000000", "00000000"]). +-define(A4445, ["11111111", "00000000", "11111111"]). +-define(A5555, ["11111111", "11111111", "00000000"]). +-define(A5556, ["11111111", "11111111", "11111111"]). + +-define(MGC_START(Pid, Mid, ET, Conf, Verb), + megaco_test_mgc:start(Pid, Mid, ET, Conf, Verb)). +-define(MGC_STOP(Pid), megaco_test_mgc:stop(Pid)). +-define(MGC_GET_STATS(Pid, No), megaco_test_mgc:get_stats(Pid, No)). +-define(MGC_RESET_STATS(Pid), megaco_test_mgc:reset_stats(Pid)). +-define(MGC_REQ_IGNORE(Pid), megaco_test_mgc:request_ignore(Pid)). +-define(MGC_REQ_PIGNORE(Pid), megaco_test_mgc:request_pending_ignore(Pid)). +-define(MGC_REQ_DISC(Pid,To), megaco_test_mgc:request_discard(Pid,To)). +-define(MGC_REQ_PEND(Pid,To), megaco_test_mgc:request_pending(Pid,To)). +-define(MGC_REQ_HAND(Pid, To), megaco_test_mgc:request_handle(Pid, To)). +-define(MGC_REQ_HANDS(Pid), megaco_test_mgc:request_handle_sloppy(Pid)). +-define(MGC_UPDATE_UI(Pid,Tag,Val), + megaco_test_mgc:update_user_info(Pid,Tag,Val)). +-define(MGC_UPDATE_CI(Pid,Tag,Val), + megaco_test_mgc:update_conn_info(Pid,Tag,Val)). +-define(MGC_USER_INFO(Pid,Tag), megaco_test_mgc:user_info(Pid,Tag)). +-define(MGC_CONN_INFO(Pid,Tag), megaco_test_mgc:conn_info(Pid,Tag)). +-define(MGC_ACK_INFO(Pid,To), megaco_test_mgc:ack_info(Pid,To)). +-define(MGC_ABORT_INFO(Pid,To), megaco_test_mgc:abort_info(Pid,To)). +-define(MGC_DISCO(Pid,Reason), megaco_test_mgc:disconnect(Pid,Reason)). + +-define(MG_START(Pid, Mid, Enc, Transp, Conf, Verb), + megaco_test_mg:start(Pid, Mid, Enc, Transp, Conf, Verb)). +-define(MG_STOP(Pid), megaco_test_mg:stop(Pid)). +-define(MG_GET_STATS(Pid, No), megaco_test_mg:get_stats(Pid, No)). +-define(MG_RESET_STATS(Pid), megaco_test_mg:reset_stats(Pid)). +-define(MG_SERV_CHANGE(Pid), megaco_test_mg:service_change(Pid)). +-define(MG_NOTIF_RAR(Pid), megaco_test_mg:notify_request_and_reply(Pid)). +-define(MG_NOTIF_REQ(Pid), megaco_test_mg:notify_request(Pid)). +-define(MG_NOTIF_AR(Pid), megaco_test_mg:await_notify_reply(Pid)). +-define(MG_CANCEL(Pid,R), megaco_test_mg:cancel_request(Pid,R)). +-define(MG_APPLY_LOAD(Pid,CntStart), megaco_test_mg:apply_load(Pid,CntStart)). +-define(MG_UPDATE_UI(Pid,Tag,Val), + megaco_test_mg:update_user_info(Pid,Tag,Val)). +-define(MG_UPDATE_CI(Pid,Tag,Val), + megaco_test_mg:update_conn_info(Pid,Tag,Val)). +-define(MG_USER_INFO(Pid,Tag), megaco_test_mg:user_info(Pid,Tag)). +-define(MG_CONN_INFO(Pid,Tag), megaco_test_mg:conn_info(Pid,Tag)). +-define(MG_GRP_REQ(Pid,N), megaco_test_mg:group_requests(Pid,N)). +-define(MG_ECC(Pid, M, T, F), megaco_test_mg:enable_test_code(Pid,M,T,F)). + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + + +%% Test server callbacks +init_per_testcase(Case, Config) -> + process_flag(trap_exit, true), + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + process_flag(trap_exit, false), + megaco_test_lib:fin_per_testcase(Case, Config). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all(suite) -> + [ + sent, + recv, + + %% Tickets last + tickets + ]. + +sent(suite) -> + [ + sent_timer_late_reply, + sent_timer_exceeded, + sent_timer_exceeded_long, + sent_resend_late_reply, + sent_resend_exceeded, + sent_resend_exceeded_long + + ]. + +recv(suite) -> + [ + recv_limit_exceeded1, + recv_limit_exceeded2 + ]. + +tickets(suite) -> + [ + otp_4956, + otp_5310, + otp_5619 + ]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% %%% +%%% Sent pending test cases %%% +%%% %%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +sent_timer_late_reply(suite) -> + []; +sent_timer_late_reply(doc) -> + "..."; +sent_timer_late_reply(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, sent_timer_late_reply), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + %% Start the MGC and MGs + i("[MGC] start"), + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + MgcConf = [{megaco_trace, false}], + {ok, Mgc} = + ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, MgcConf, ?MGC_VERBOSITY), + + i("[MG] start"), + MgMid = {deviceName, "mg"}, + MgConf = [{megaco_trace, io}], + {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConf, ?MG_VERBOSITY), + + d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]), + + i("[MG] connect to the MGC (service change)"), + ServChRes = ?MG_SERV_CHANGE(Mg), + d("service change result: ~p", [ServChRes]), + + d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]), + + d("[MGC] update connection info pending timer"), + PendingTimer = #megaco_incr_timer{wait_for = timer:seconds(5), + factor = 1}, + ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer), + + d("[MGC] update connection info sent pending limit"), + PendingLimit = 5, + ?MGC_UPDATE_CI(Mgc, sent_pending_limit, PendingLimit), + + d("[MGC] late reply to requests " + "(simulate that the request takes a long time)"), + {ok, _} = ?MGC_REQ_DISC(Mgc, 11000), + + d("[MG] send the notify"), + {ok, Reply} = ?MG_NOTIF_RAR(Mg), + d("[MG] Reply: ~p", [Reply]), + case Reply of + {_Version, {ok, [_ActionReply]}} -> + ok; + _ -> + ?ERROR({unexpected_reply, Reply}) + end, + + %% Tell MG to stop + i("[MG] stop"), + ?MG_STOP(Mg), + + %% Tell Mgc to stop + i("[MGC] stop"), + ?MGC_STOP(Mgc), + + i("done", []), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +sent_timer_exceeded(suite) -> + []; +sent_timer_exceeded(doc) -> + "..."; +sent_timer_exceeded(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, sent_timer_exceeded), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + %% Start the MGC and MGs + i("[MGC] start"), + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + {ok, Mgc} = + ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY), + + i("[MG] start"), + MgMid = {deviceName, "mg"}, + MgConfig = [], + {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY), + + d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]), + + i("[MG] connect to the MGC (service change)"), + ServChRes = ?MG_SERV_CHANGE(Mg), + d("service change result: ~p", [ServChRes]), + + d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]), + + d("[MGC] update connection info pending timer"), + PendingTimer = #megaco_incr_timer{wait_for = timer:seconds(5), + factor = 1}, + ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer), + + d("[MGC] update connection info sent pending limit"), + PendingLimit = 5, + ?MGC_UPDATE_CI(Mgc, sent_pending_limit, PendingLimit), + + d("[MGC] no reply to requests " + "(simulate that the request takes a __long__ time)"), + ?MGC_REQ_IGNORE(Mgc), + + d("sleep 5 seconds to align trace output"), + sleep(5000), + + d("[MG] send the notify"), + {ok, {_ProtocolVersion, {error, ED}}} = ?MG_NOTIF_RAR(Mg), + d("[MG] ED: ~p", [ED]), + ErrorCode = ?megaco_number_of_transactionpending_exceeded, + ErrorCode = ED#'ErrorDescriptor'.errorCode, + + %% Tell MG to stop + i("[MG] stop"), + ?MG_STOP(Mg), + + %% Tell Mgc to stop + i("[MGC] stop"), + ?MGC_STOP(Mgc), + + i("done", []), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +sent_timer_exceeded_long(suite) -> + []; +sent_timer_exceeded_long(doc) -> + "..."; +sent_timer_exceeded_long(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, sent_timer_exceeded_long), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + %% Start the MGC and MGs + i("[MGC] start"), + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + {ok, Mgc} = + ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY), + + i("[MG] start"), + MgMid = {deviceName, "mg"}, + MgConfig = [], + {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY), + + d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]), + + i("[MG] connect to the MGC (service change)"), + ServChRes = ?MG_SERV_CHANGE(Mg), + d("service change result: ~p", [ServChRes]), + + d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]), + + d("[MGC] update connection info pending timer"), + PendingTimer = #megaco_incr_timer{wait_for = timer:seconds(5), + factor = 1}, + ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer), + + d("[MGC] update connection info sent pending limit"), + PendingLimit = 5, + ?MGC_UPDATE_CI(Mgc, sent_pending_limit, PendingLimit), + + d("[MGC] long request with no reply ~n" + " (simulate that we know that this will " + "take a while, but takes even longer...)"), + ?MGC_REQ_PIGNORE(Mgc), + + d("[MG] send the notify"), + {ok, {_ProtocolVersion, {error, ED}}} = ?MG_NOTIF_RAR(Mg), + d("[MG] ED: ~p", [ED]), + ErrorCode = ?megaco_number_of_transactionpending_exceeded, + ErrorCode = ED#'ErrorDescriptor'.errorCode, + + %% Tell MG to stop + i("[MG] stop"), + ?MG_STOP(Mg), + + %% Tell Mgc to stop + i("[MGC] stop"), + ?MGC_STOP(Mgc), + + i("done", []), + ok. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% This test case can only be run with the stack compiled with +%% the MEGACO_TEST_CODE flag. Therefor there is no point in +%% including this test case in the usual test suite +-ifdef(MEGACO_TEST_CODE). +sent_resend_late_reply(suite) -> + []; +sent_resend_late_reply(doc) -> + "..."; +sent_resend_late_reply(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, sent_resend_late_reply), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + %% Start the MGC and MGs + i("[MGC] start"), + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + {ok, Mgc} = + ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY), + + i("[MG] start"), + MgMid = {deviceName, "mg"}, + MgConfig = [], + {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY), + + d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]), + + i("[MG] connect to the MGC (service change)"), + ServChRes = ?MG_SERV_CHANGE(Mg), + d("service change result: ~p", [ServChRes]), + + d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]), + + d("[MGC] update connection info pending timer"), + PendingTimer = infinity, + %% PendingTimer = #megaco_incr_timer{wait_for = timer:seconds(5), + %% factor = 1}, + ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer), + + d("[MGC] update connection info sent pending limit"), + PendingLimit = 5, + ?MGC_UPDATE_CI(Mgc, sent_pending_limit, PendingLimit), + + d("[MG] update connection info request timer"), + RequestTimer = #megaco_incr_timer{wait_for = timer:seconds(5), + factor = 1}, + ?MG_UPDATE_CI(Mg, request_timer, RequestTimer), + + d("[MGC] no reply to requests " + "(simulate that the request takes a __long__ time)"), + ?MGC_REQ_IGNORE(Mgc), + + d("[MG] set the 'init_request_timer' tag"), + EccRes = (catch ?MG_ECC(Mg, megaco_messenger, + init_request_timer, fun init_request_timer/1)), + d("[MG] EccRes: ~p", [EccRes]), + + d("[MGC] late reply to requests " + "(simulate that the request takes a long time)"), + ?MGC_REQ_DISC(Mgc, 11000), + + d("[MG] send the notify"), + {ok, Reply} = (catch ?MG_NOTIF_RAR(Mg)), + d("[MG] Reply: ~p", [Reply]), + {_Version, {ok, [_ActionReply]}} = Reply, + + %% Tell MG to stop + i("[MG] stop"), + ?MG_STOP(Mg), + + %% Tell Mgc to stop + i("[MGC] stop"), + ?MGC_STOP(Mgc), + + i("done", []), + ok. + +-else. + +sent_resend_late_reply(suite) -> + []; +sent_resend_late_reply(doc) -> + "..."; +sent_resend_late_reply(Config) when is_list(Config) -> + ?SKIP("included only if compiled with USE_MEGACO_TEST_CODE=true"). + +-endif. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% This test case can only be run with the stack compiled with +%% the MEGACO_TEST_CODE flag. Therefor there is no point in +%% including this test case in the usual test suite +-ifdef(MEGACO_TEST_CODE). +sent_resend_exceeded(suite) -> + []; +sent_resend_exceeded(doc) -> + "..."; +sent_resend_exceeded(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, sent_resend_exceeded), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + %% Start the MGC and MGs + i("[MGC] start"), + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + {ok, Mgc} = + ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY), + + i("[MG] start"), + MgMid = {deviceName, "mg"}, + MgConfig = [], + {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY), + + d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]), + + i("[MG] connect to the MGC (service change)"), + ServChRes = ?MG_SERV_CHANGE(Mg), + d("service change result: ~p", [ServChRes]), + + d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]), + + d("[MGC] update connection info pending timer"), + PendingTimer = infinity, + ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer), + + d("[MGC] update connection info sent pending limit"), + PendingLimit = 5, + ?MGC_UPDATE_CI(Mgc, sent_pending_limit, PendingLimit), + + d("[MG] update connection info request timer"), + RequestTimer = #megaco_incr_timer{wait_for = timer:seconds(5), + factor = 1}, + ?MG_UPDATE_CI(Mg, request_timer, RequestTimer), + + d("[MGC] no reply to requests " + "(simulate that the request takes a __long__ time)"), + ?MGC_REQ_IGNORE(Mgc), + + d("[MG] set the 'init_request_timer' tag"), + EccRes = (catch ?MG_ECC(Mg, megaco_messenger, + init_request_timer, fun init_request_timer/1)), + d("[MG] EccRes: ~p", [EccRes]), + + d("[MG] send the notify"), + ED = (catch ?MG_NOTIF_RAR(Mg)), + d("[MG] ED: ~p", [ED]), + ErrorCode = ?megaco_number_of_transactionpending_exceeded, + #'ErrorDescriptor'{errorCode = ErrorCode} = ED, + + %% Tell MG to stop + i("[MG] stop"), + ?MG_STOP(Mg), + + %% Tell Mgc to stop + i("[MGC] stop"), + ?MGC_STOP(Mgc), + + i("done", []), + ok. + + +-else. + +sent_resend_exceeded(suite) -> + []; +sent_resend_exceeded(doc) -> + "..."; +sent_resend_exceeded(Config) when is_list(Config) -> + ?SKIP("included only if compiled with USE_MEGACO_TEST_CODE=true"). + +-endif. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% This test case can only be run with the stack compiled with +%% the MEGACO_TEST_CODE flag. Therefor there is no point in +%% including this test case in the usual test suite +-ifdef(MEGACO_TEST_CODE). +sent_resend_exceeded_long(suite) -> + []; +sent_resend_exceeded_long(doc) -> + "..."; +sent_resend_exceeded_long(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, sent_resend_exceeded_long), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + %% Start the MGC and MGs + i("[MGC] start"), + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + {ok, Mgc} = + ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY), + + i("[MG] start"), + MgMid = {deviceName, "mg"}, + MgConfig = [], + {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY), + + d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]), + + i("[MG] connect to the MGC (service change)"), + ServChRes = ?MG_SERV_CHANGE(Mg), + d("service change result: ~p", [ServChRes]), + + d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]), + + d("[MGC] update connection info pending timer"), + PendingTimer = infinity, + ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer), + + d("[MGC] update connection info sent pending limit"), + PendingLimit = 5, + ?MGC_UPDATE_CI(Mgc, sent_pending_limit, PendingLimit), + + d("[MG] update connection info request timer"), + RequestTimer = #megaco_incr_timer{wait_for = timer:seconds(5), + factor = 1}, + ?MG_UPDATE_CI(Mg, request_timer, RequestTimer), + + d("[MGC] long request with no reply ~n" + " (simulate that we know that this will " + "take a while, but takes even longer...)"), + ?MGC_REQ_PIGNORE(Mgc), + + d("[MG] set the 'init_request_timer' tag"), + EccRes = (catch ?MG_ECC(Mg, megaco_messenger, + init_request_timer, fun init_request_timer/1)), + d("[MG] EccRes: ~p", [EccRes]), + + d("[MG] send the notify"), + ED = (catch ?MG_NOTIF_RAR(Mg)), + d("[MG] ED: ~p", [ED]), + ErrorCode = ?megaco_number_of_transactionpending_exceeded, + #'ErrorDescriptor'{errorCode = ErrorCode} = ED, + + %% Tell MG to stop + i("[MG] stop"), + ?MG_STOP(Mg), + + %% Tell Mgc to stop + i("[MGC] stop"), + ?MGC_STOP(Mgc), + + i("done", []), + ok. + + +-else. + +sent_resend_exceeded_long(suite) -> + []; +sent_resend_exceeded_long(doc) -> + "..."; +sent_resend_exceeded_long(Config) when is_list(Config) -> + ?SKIP("included only if compiled with USE_MEGACO_TEST_CODE=true"). + +-endif. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% %%% +%%% Received peinding test cases %%% +%%% %%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +recv_limit_exceeded1(suite) -> + []; +recv_limit_exceeded1(doc) -> + "Received pending limit exceeded (exactly)"; +recv_limit_exceeded1(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, rle1), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = rle1_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = rle1_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(rle1_mgc_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(rle1_mgc_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(rle1_mgc_verify_service_change_req_msg_fun(Mid), + {?MODULE, rle1_mgc_verify_service_change_req_msg, [Mid]}). +-define(rle1_mgc_verify_notify_req_msg_fun(), + {?MODULE, rle1_mgc_verify_notify_req_msg, []}). +-else. +-define(rle1_mgc_decode_msg_fun(Mod, Conf), + rle1_mgc_decode_msg_fun(Mod, Conf)). +-define(rle1_mgc_encode_msg_fun(Mod, Conf), + rle1_mgc_encode_msg_fun(Mod, Conf)). +-define(rle1_mgc_verify_service_change_req_msg_fun(Mid), + rle1_mgc_verify_service_change_req_msg_fun(Mid)). +-define(rle1_mgc_verify_notify_req_msg_fun(), + rle1_mgc_verify_notify_req_msg_fun()). +-endif. + +rle1_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + EM = megaco_pretty_text_encoder, + EC = [], + rle1_mgc_event_sequence2(Mid, EM, EC). + +rle1_mgc_event_sequence2(Mid, EM, EC) -> + DecodeFun = ?rle1_mgc_decode_msg_fun(EM, EC), + EncodeFun = ?rle1_mgc_encode_msg_fun(EM, EC), + ServiceChangeReply = + rle1_mgc_service_change_reply_msg(Mid, 1, 0), + Pending = rle1_mgc_pending_msg(Mid,2), + ServiceChangeReqVerify = + ?rle1_mgc_verify_service_change_req_msg_fun(Mid), + NotifyReqVerify = ?rle1_mgc_verify_notify_req_msg_fun(), +%% ServiceChangeReqVerify = +%% rle1_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = rle1_mgc_verify_notify_request_fun(), + EvSeq = + [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-req", + {ServiceChangeReqVerify, 10000}}, + {send, "service-change-reply", ServiceChangeReply}, + {expect_receive, "notify-request", {NotifyReqVerify, 5000}}, + {sleep, 100}, + {send, "pending 1", Pending}, + {sleep, 100}, + {send, "pending 2", Pending}, + {sleep, 100}, + {send, "pending 3", Pending}, + {sleep, 100}, + {send, "pending 4", Pending}, + {sleep, 100}, + {send, "pending 5", Pending}, + {sleep, 1000}, + disconnect + ], + EvSeq. + +-ifndef(megaco_hipe_special). +rle1_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. + +rle1_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. + +rle1_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + SCRP = #'ServiceChangeResParm'{serviceChangeMgcId = Mid}, + SCRPs = {serviceChangeResParms,SCRP}, + Root = #megaco_term_id{id = ["root"]}, + SCR = #'ServiceChangeReply'{terminationID = [Root], + serviceChangeResult = SCRPs}, + CR = {serviceChangeReply, SCR}, + rle1_mgc_msg(Mid, TransId, CR, Cid). + +rle1_mgc_msg(Mid, TransId, CR, Cid) -> + AR = #'ActionReply'{contextId = Cid, + commandReply = [CR]}, + ARs = {actionReplies, [AR]}, + TR = #'TransactionReply'{transactionId = TransId, + transactionResult = ARs}, + Body = {transactions, [{transactionReply, TR}]}, + Mess = #'Message'{version = 1, + mId = Mid, + messageBody = Body}, + #'MegacoMessage'{mess = Mess}. + +rle1_mgc_pending_msg(Mid, TransId) -> + TP = #'TransactionPending'{transactionId = TransId}, + Body = {transactions, [{transactionPending, TP}]}, + Mess = #'Message'{version = 1, + mId = Mid, + messageBody = Body}, + #'MegacoMessage'{mess = Mess}. + +-ifndef(megaco_hipe_special). +rle1_mgc_verify_service_change_req_msg_fun(Mid) -> + fun(M) -> + rle1_mgc_verify_service_change_req_msg(M, Mid) + end. +-endif. + +rle1_mgc_verify_service_change_req_msg(#'MegacoMessage'{mess = Mess} = M, + _Mid1) -> + io:format("rle1_mgc_verify_service_change_req_msg -> entry with" + "~n M: ~p" + "~n", [M]), + #'Message'{version = _V, + mId = _Mid2, + messageBody = Body} = Mess, + {transactions, [Trans]} = Body, + {transactionRequest, TR} = Trans, + #'TransactionRequest'{transactionId = _Tid, + actions = [AR]} = TR, + #'ActionRequest'{contextId = _Cid, + contextRequest = _CtxReq, + contextAttrAuditReq = _CtxAar, + commandRequests = [CR]} = AR, + #'CommandRequest'{command = Cmd, + optional = _Opt, + wildcardReturn = _WR} = CR, + {serviceChangeReq, SCR} = Cmd, + #'ServiceChangeRequest'{terminationID = _TermID, + serviceChangeParms = SCP} = SCR, + #'ServiceChangeParm'{serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} = SCP, + {ok, M}; +rle1_mgc_verify_service_change_req_msg(M, _Mid) -> + {error, {invalid_message, M}}. + +-ifndef(megaco_hipe_special). +rle1_mgc_verify_notify_req_msg_fun() -> + fun(M) -> + rle1_mgc_verify_notify_req_msg(M) + end. +-endif. + +rle1_mgc_verify_notify_req_msg(#'MegacoMessage'{mess = Mess} = M) -> + io:format("rle1_mgc_verify_notify_req_msg -> entry with" + "~n M: ~p" + "~n", [M]), + #'Message'{messageBody = Body} = Mess, + {transactions, [Trans]} = Body, + {transactionRequest, TR} = Trans, + #'TransactionRequest'{actions = [AR]} = TR, + io:format("rle1_mgc_verify_notify_request_fun -> AR: " + "~n~p~n", [AR]), + #'ActionRequest'{commandRequests = [CR]} = AR, + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{observedEventsDescriptor = OED} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + {ok, M}; +rle1_mgc_verify_notify_req_msg(M) -> + {error, {invalid_message, M}}. + +% rle1_err_desc(T) -> +% EC = ?megaco_internal_gateway_error, +% ET = lists:flatten(io_lib:format("~w",[T])), +% #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(rle1_mg_verify_handle_connect_fun(), + {?MODULE, rle1_mg_verify_handle_connect, []}). +-define(rle1_mg_verify_service_change_rep_fun(), + {?MODULE, rle1_mg_verify_service_change_rep, []}). +-define(rle1_mg_verify_trans_rep_fun(), + {?MODULE, rle1_mg_verify_trans_rep, []}). +-else. +-define(rle1_mg_verify_handle_connect_fun(), + fun rle1_mg_verify_handle_connect/1). +-define(rle1_mg_verify_service_change_rep_fun(), + fun rle1_mg_verify_service_change_rep/1). +-define(rle1_mg_verify_trans_rep_fun(), + fun rle1_mg_verify_trans_rep/1). +-endif. + +rle1_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + rle1_mg_event_sequence2(Mid, RI). + +rle1_mg_event_sequence2(Mid, RI) -> + ServiceChangeReq = [rle1_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq = [rle1_mg_notify_request_ar(1, Tid, 1)], + ConnectVerify = ?rle1_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?rle1_mg_verify_service_change_rep_fun(), + TransReplyVerify = ?rle1_mg_verify_trans_rep_fun(), +%% ConnectVerify = fun rle1_mg_verify_handle_connect/1, +%% ServiceChangeReplyVerify = fun rle1_mg_verify_service_change_reply/1, +%% TransReplyVerify = fun rle1_mg_verify_trans_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, recv_pending_limit, 4}, + start_transport, + {megaco_trace, disable}, %%100}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_cast, NotifyReq, []}, + {megaco_callback, handle_trans_reply, TransReplyVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +rle1_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("rle1_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +rle1_mg_verify_handle_connect(Else) -> + io:format("rle1_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +rle1_mg_verify_service_change_rep( + {handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) -> + io:format("rle1_mg_verify_service_change_rep -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +rle1_mg_verify_service_change_rep(Else) -> + io:format("rle1_mg_verify_service_change_rep -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +rle1_mg_verify_trans_rep( + {handle_trans_reply, _CH, ?VERSION, + {error, exceeded_recv_pending_limit} = E, _}) -> + io:format("rle1_mg_verify_trans_rep -> expected error~n", []), + {ok, E , error}; +rle1_mg_verify_trans_rep(Else) -> + io:format("rle1_mg_verify_trans_rep -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, error}. + +rle1_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +rle1_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + + +%% --- + +recv_limit_exceeded2(suite) -> + []; +recv_limit_exceeded2(doc) -> + "Received pending limit exceeded"; +recv_limit_exceeded2(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, rle2), + i("starting"), + + _MgcNode = make_node_name(mgc), + _MgNode = make_node_name(mg), + + ?SKIP(not_yet_implemented). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% %%% +%%% Ticket test cases %%% +%%% %%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_4956(suite) -> + []; +otp_4956(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, otp_4956), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = otp_4956_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_tcp_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = otp_4956_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_tcp_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_tcp_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp_4956_mgc_verify_handle_connect_fun(), + {?MODULE, otp_4956_mgc_verify_handle_connect, []}). +-define(otp_4956_mgc_verify_service_change_req_fun(Mid), + {?MODULE, otp_4956_mgc_verify_service_change_req, [Mid]}). +-define(otp_4956_mgc_verify_notify_req1_fun(), + {?MODULE, otp_4956_mgc_verify_notify_req1, []}). +-define(otp_4956_mgc_verify_notify_req2_fun(), + {?MODULE, otp_4956_mgc_verify_notify_req2, []}). +-define(otp_4956_mgc_verify_handle_trans_req_abort_fun(), + {?MODULE, otp_4956_mgc_verify_handle_trans_req_abort, []}). +-define(otp_4956_mgc_verify_handle_disconnect_fun(), + {?MODULE, otp_4956_mgc_verify_handle_disconnect, []}). +-else. +-define(otp_4956_mgc_verify_handle_connect_fun(), + otp_4956_mgc_verify_handle_connect_fun()). +-define(otp_4956_mgc_verify_service_change_req_fun(Mid), + otp_4956_mgc_verify_service_change_req_fun(Mid)). +-define(otp_4956_mgc_verify_notify_req1_fun(), + otp_4956_mgc_verify_notify_req1_fun()). +-define(otp_4956_mgc_verify_notify_req2_fun(), + otp_4956_mgc_verify_notify_req2_fun()). +-define(otp_4956_mgc_verify_handle_trans_req_abort_fun(), + otp_4956_mgc_verify_handle_trans_req_abort_fun()). +-define(otp_4956_mgc_verify_handle_disconnect_fun(), + fun otp_4956_mgc_verify_handle_disconnect/1). +-endif. + +otp_4956_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?otp_4956_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?otp_4956_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify1 = ?otp_4956_mgc_verify_notify_req1_fun(), + NotifyReqVerify2 = ?otp_4956_mgc_verify_notify_req2_fun(), + ReqAbortVerify = ?otp_4956_mgc_verify_handle_trans_req_abort_fun(), + DiscoVerify = ?otp_4956_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = otp_4956_mgc_verify_handle_connect_fun(), +%% ServiceChangeReqVerify = otp_4956_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify1 = otp_4956_mgc_verify_notify_request_fun1(), +%% NotifyReqVerify2 = otp_4956_mgc_verify_notify_request_fun2(), +%% ReqAbortVerify = otp_4956_mgc_verify_handle_trans_request_abort_fun(), +%% DiscoVerify = fun otp_4956_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + {megaco_update_user_info, sent_pending_limit, 4}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_conn_info, all}, + {megaco_callback, handle_trans_request_sc, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request_1, NotifyReqVerify1}, + {megaco_callback, handle_trans_request_abort, ReqAbortVerify}, + {megaco_callback, nocall, 1000}, + {megaco_callback, handle_trans_request_6, NotifyReqVerify2}, + {megaco_callback, handle_disconnect, DiscoVerify}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +-ifndef(megaco_hipe_special). +otp_4956_mgc_verify_handle_connect_fun() -> + fun(M) -> + otp_4956_mgc_verify_handle_connect(M) + end. +-endif. + +otp_4956_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + {ok, CH, ok}; +otp_4956_mgc_verify_handle_connect(Else) -> + {error, Else, ok}. + +-ifndef(megaco_hipe_special). +otp_4956_mgc_verify_service_change_req_fun(Mid) -> + fun(Req) -> + otp_4956_mgc_verify_service_change_req(Req, Mid) + end. +-endif. + +otp_4956_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("otp_4956_mgc_verify_service_change_req -> ok" + "~n AR: ~p" + "~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [otp_4956_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = otp_4956_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = otp_4956_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = otp_4956_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = otp_4956_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = otp_4956_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +otp_4956_mgc_verify_service_change_req(Else, _Mid) -> + ED = otp_4956_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +-ifndef(megaco_hipe_special). +otp_4956_mgc_verify_notify_req1_fun() -> + fun(Req) -> + otp_4956_mgc_verify_notify_req1(Req) + end. +-endif. + +otp_4956_mgc_verify_notify_req1({handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("otp_4956_mgc_verify_notify_req1 -> entry with" + "~n AR: ~p" + "~n", [AR]), + case AR of + #'ActionRequest'{contextId = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [otp_4956_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, 6500, AR, Reply}; + _ -> + ED = otp_4956_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +otp_4956_mgc_verify_notify_req1(Else) -> + io:format("otp_4956_mgc_verify_notify_req1 -> entry with" + "~n Else: ~p" + "~n", [Else]), + ED = otp_4956_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +-ifndef(megaco_hipe_special). +otp_4956_mgc_verify_notify_req2_fun() -> + fun(Ev) -> + otp_4956_mgc_verify_notify_req2(Ev) + end. +-endif. + +otp_4956_mgc_verify_notify_req2({handle_trans_request, _, ?VERSION, [AR]}) -> + case AR of + #'ActionRequest'{contextId = _Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [_Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = ignore, + {ok, 100, AR, Reply}; + _ -> + ED = otp_4956_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +otp_4956_mgc_verify_notify_req2(Else) -> + ED = otp_4956_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +-ifndef(megaco_hipe_special). +otp_4956_mgc_verify_handle_trans_req_abort_fun() -> + fun(Req) -> + otp_4956_mgc_verify_handle_trans_req_abort(Req) + end. +-endif. + +otp_4956_mgc_verify_handle_trans_req_abort({handle_trans_request_abort, + CH, ?VERSION, 2, Pid}) -> + io:format("otp_4956_mgc_verify_handle_trans_req_abort -> ok" + "~n CH: ~p" + "~n Pid: ~p" + "~n", [CH, Pid]), + {ok, {CH, Pid}, ok}; +otp_4956_mgc_verify_handle_trans_req_abort({handle_trans_request_abort, + CH, Version, TransId, Pid}) -> + io:format("otp_4956_mgc_verify_handle_trans_req_abort -> error" + "~n CH: ~p" + "~n Version: ~p" + "~n TransId: ~p" + "~n Pid: ~p" + "~n", [CH, Version, TransId, Pid]), + {error, {error, {invalid_version_trans_id, Version, TransId}}, ok}; +otp_4956_mgc_verify_handle_trans_req_abort(Else) -> + io:format("otp_4956_mgc_verify_handle_trans_req_abort -> error" + "~n Else: ~p" + "~n", [Else]), + {error, Else, ok}. + +otp_4956_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, _R}) -> + io:format("otp_4956_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n _R: ~p" + "~n", [CH, _R]), + {ok, CH, ok}; +otp_4956_mgc_verify_handle_disconnect(Else) -> + io:format("otp_4956_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp_4956_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + AR. + +%% otp_4956_mgc_service_change_reply_msg(Mid, TransId, Cid) -> +%% AR = otp_4956_mgc_service_change_reply_ar(Mid, Cid), +%% TRes = cre_transResult([AR]), +%% TR = cre_transReply(TransId, TRes), +%% Trans = cre_transaction(TR), +%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), +%% cre_megacoMessage(Mess). + +otp_4956_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +%% otp_4956_mgc_notify_reply(Mid, TransId, Cid, TermId) -> +%% AR = otp_4956_mgc_notify_reply_ar(Cid, TermId), +%% TRes = cre_transResult([AR]), +%% TR = cre_transReply(TransId, TRes), +%% Trans = cre_transaction(TR), +%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), +%% cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp_4956_mg_decode_msg_fun(Mod, Conf), + {?MODULE, decode_msg, [Mod, Conf]}). +-define(otp_4956_mg_encode_msg_fun(Mod, Conf), + {?MODULE, encode_msg, [Mod, Conf]}). +-define(otp_4956_mg_verify_service_change_rep_msg_fun(), + {?MODULE, otp_4956_mg_verify_service_change_rep_msg, []}). +-define(otp_4956_mg_verify_pending_msg_fun(), + {?MODULE, otp_4956_mg_verify_pending_msg, []}). +-define(otp_4956_mg_verify_pending_limit_msg_fun(), + {?MODULE, otp_4956_mg_verify_pending_limit_msg, []}). +-else. +-define(otp_4956_mg_decode_msg_fun(Mod, Conf), + otp_4956_mg_decode_msg_fun(Mod, Conf)). +-define(otp_4956_mg_encode_msg_fun(Mod, Conf), + otp_4956_mg_encode_msg_fun(Mod, Conf)). +-define(otp_4956_mg_verify_service_change_rep_msg_fun(), + otp_4956_mg_verify_service_change_rep_msg_fun()). +-define(otp_4956_mg_verify_pending_msg_fun(), + otp_4956_mg_verify_pending_msg_fun()). +-define(otp_4956_mg_verify_pending_limit_msg_fun(), + otp_4956_mg_verify_pending_limit_msg_fun()). +-endif. + +otp_4956_mg_event_sequence(text, tcp) -> + DecodeFun = ?otp_4956_mg_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ?otp_4956_mg_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mg"}, + ServiceChangeReq = otp_4956_mg_service_change_request_msg(Mid, 1, 0), + TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq = otp_4956_mg_notify_request_msg(Mid, 2, 1, TermId, 1), + ServiceChangeReplyVerifyFun = ?otp_4956_mg_verify_service_change_rep_msg_fun(), + PendingVerify = ?otp_4956_mg_verify_pending_msg_fun(), + PendingLimitVerify = ?otp_4956_mg_verify_pending_limit_msg_fun(), +%% ServiceChangeReplyVerifyFun = +%% otp_4956_mg_verify_service_change_rep_msg_fun(), +%% PendingVerify = otp_4956_mg_verify_pending_msg_fun(), +%% PendingLimitVerify = otp_4956_mg_verify_pending_limit_msg_fun(), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {connect, 2944}, + {send, "service-change-request", ServiceChangeReq}, + {expect_receive, "service-change-reply", {ServiceChangeReplyVerifyFun, 10000}}, + {send, "notify request (first send)", NotifyReq}, + {sleep, 100}, + {send, "notify request (resend 1)", NotifyReq}, + {expect_receive, "pending 1", {PendingVerify, 1000}}, + {sleep, 1000}, + {send, "notify request (resend 2)", NotifyReq}, + {expect_receive, "pending 2", {PendingVerify, 1000}}, + {sleep, 1000}, + {send, "notify request (resend 3)", NotifyReq}, + {expect_receive, "pending 3", {PendingVerify, 1000}}, + {sleep, 1000}, + {send, "notify request (resend 4)", NotifyReq}, + {expect_receive, "pending 4", {PendingVerify, 1000}}, + {sleep, 1000}, + {send, "notify request (resend 5)", NotifyReq}, + {expect_receive, "pending limit exceeded", + {PendingLimitVerify, 1000}}, + {sleep, 4000}, + {send, "notify request (resend 6)", NotifyReq}, + {expect_nothing, 4000}, + disconnect + ], + EvSeq. + +-ifndef(megaco_hipe_special). +otp_4956_mg_encode_msg_fun(Mod, Conf) -> + fun(M) -> + encode_msg(M, Mod, Conf) + end. + +otp_4956_mg_decode_msg_fun(Mod, Conf) -> + fun(M) -> + decode_msg(M, Mod, Conf) + end. +-endif. + +-ifndef(megaco_hipe_special). +otp_4956_mg_verify_service_change_rep_msg_fun() -> + fun(M) -> + otp_4956_mg_verify_service_change_rep_msg(M) + end. +-endif. + +otp_4956_mg_verify_service_change_rep_msg( + #'MegacoMessage'{mess = Mess} = M) -> + io:format("otp_4956_mg_verify_service_change_rep_msg -> " + "ok so far~n",[]), + #'Message'{version = _V, + mId = _MgMid, + messageBody = Body} = Mess, + {transactions, [Trans]} = Body, + {transactionReply, TR} = Trans, + #'TransactionReply'{transactionId = _Tid, + immAckRequired = asn1_NOVALUE, + transactionResult = Res} = TR, + {actionReplies, [AR]} = Res, + #'ActionReply'{contextId = _Cid, + errorDescriptor = asn1_NOVALUE, + contextReply = _CtxReq, + commandReply = [CR]} = AR, + {serviceChangeReply, SCR} = CR, + #'ServiceChangeReply'{terminationID = _TermID, + serviceChangeResult = SCRes} = SCR, + {serviceChangeResParms, SCRP} = SCRes, + #'ServiceChangeResParm'{serviceChangeMgcId = _MgcMid} = SCRP, + {ok, M}; +otp_4956_mg_verify_service_change_rep_msg(M) -> + {error, {invalid_message, M}}. + +-ifndef(megaco_hipe_special). +otp_4956_mg_verify_pending_msg_fun() -> + fun(M) -> + otp_4956_mg_verify_pending_msg(M) + end. +-endif. + +otp_4956_mg_verify_pending_msg(#'MegacoMessage'{mess = Mess} = M) -> + io:format("otp_4956_mg_verify_pending_msg -> entry with" + "~n Mess. ~p" + "~n", [Mess]), + #'Message'{messageBody = Body} = Mess, + {transactions, [Trans]} = Body, + {transactionPending, TP} = Trans, + #'TransactionPending'{transactionId = _Id} = TP, + io:format("otp_4956_mg_verify_pending_msg -> done~n", []), + {ok, M}; +otp_4956_mg_verify_pending_msg(M) -> + io:format("otp_4956_mg_verify_pending_msg -> entry with" + "~n M: ~p" + "~n", [M]), + {error, {invalid_message, M}}. + +-ifndef(megaco_hipe_special). +otp_4956_mg_verify_pending_limit_msg_fun() -> + fun(M) -> + otp_4956_mg_verify_pending_limit_msg(M) + end. +-endif. + +otp_4956_mg_verify_pending_limit_msg(#'MegacoMessage'{mess = Mess} = M) -> + io:format("otp_4956_mg_verify_pending_limit_msg -> entry with" + "~n Mess: ~p" + "~n", [Mess]), + #'Message'{messageBody = Body} = Mess, + {transactions, [Trans]} = Body, + {transactionReply, TR} = Trans, + case element(4, TR) of + {transactionError, ED} -> + EC = ?megaco_number_of_transactionpending_exceeded, + #'ErrorDescriptor'{errorCode = EC} = ED, + {ok, M}; + _ -> + {error, {invalid_transactionReply, TR}} + end; +otp_4956_mg_verify_pending_limit_msg(M) -> + io:format("otp_4956_mg_verify_pending_limit_msg -> entry with" + "~n M: ~p" + "~n", [M]), + {error, {invalid_message, M}}. + +otp_4956_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp_4956_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = otp_4956_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +otp_4956_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp_4956_mg_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = otp_4956_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +otp_4956_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_5310(suite) -> + []; +otp_5310(doc) -> + "..."; +otp_5310(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, otp_5310), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + %% Start the MGC and MGs + i("[MGC] start"), + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + {ok, Mgc} = + ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY), + + i("[MG] start"), + MgMid = {deviceName, "mg"}, + MgConfig = [], + {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY), + + d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]), + + i("[MG] connect to the MGC (service change)"), + ServChRes = ?MG_SERV_CHANGE(Mg), + d("service change result: ~p", [ServChRes]), + + d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]), + + d("[MGC] update connection info pending timer"), + PendingTimer = #megaco_incr_timer{wait_for = timer:seconds(1), + factor = 1}, + ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer), + + d("[MGC] update connection info originating pending limit"), + PendingLimit = 3, + ?MGC_UPDATE_CI(Mgc, orig_pending_limit, PendingLimit), + + ConnReps1 = ?MGC_CONN_INFO(Mgc, replies), + d("[MGC] ConnReps1: ~p", [ConnReps1]), + case filter_aborted1(ConnReps1, []) of + [{_, []}] -> + ok; + ConnFlt1 -> + ?ERROR({unexpected_reply_state, conn_info, ConnReps1, ConnFlt1}) + end, + UserReps1 = ?MGC_USER_INFO(Mgc, replies), + d("[MGC] UserReps1: ~p", [UserReps1]), + case filter_aborted1(UserReps1, []) of + [{_, []}] -> + ok; + UserFlt1 -> + ?ERROR({unexpected_reply_state, user_info, UserReps1, UserFlt1}) + end, + + %% Instruct the MGC to never reply to requests + d("[MGC] don't reply to requests"), + ?MGC_REQ_IGNORE(Mgc), + + %% We want to know when the abort comes... + d("[MGC] request abort inform"), + ?MGC_ABORT_INFO(Mgc, self()), + + %% Make MG send a request + d("[MG] send the notify"), + {ok, {_ProtocolVersion, {error, ED}}} = ?MG_NOTIF_RAR(Mg), + d("[MG] ED: ~p", [ED]), + ErrorCode = ?megaco_number_of_transactionpending_exceeded, + ErrorCode = ED#'ErrorDescriptor'.errorCode, + + %% Wait for the MGC to get aborted + d("[MGC] await the abort callback"), + {ok, TransId} = await_aborted(Mgc), + d("[MGC] aborted transaction: ~p", [TransId]), + + %% Make sure we have one in aborted state + d("[MGC] how many is aborted (should be == 1)?"), + ConnReps2 = ?MGC_CONN_INFO(Mgc, replies), + case filter_aborted1(ConnReps2, []) of + [{_, [TransId]}] -> + ok; + [{_, []}] -> + ok; % has already been cleaned up... + ConnFlt2 -> + ?ERROR({unexpected_reply_state, conn_info, ConnReps2, ConnFlt2}) + end, + d("[MGC] ConnReps2: ~p", [ConnReps2]), + UserReps2 = ?MGC_USER_INFO(Mgc, replies), + d("[MGC] UserReps2: ~p", [UserReps2]), + case filter_aborted1(UserReps2, []) of + [{_, [TransId]}] -> + ok; + [{_, []}] -> + ok; % has already been cleaned up... + UserFlt2 -> + ?ERROR({unexpected_reply_state, user_info, UserReps2, UserFlt2}) + end, + + %% do disconnect and the do cancel in the handle function + d("[MGC] disconnect"), + DiscoRes = ?MGC_DISCO(Mgc, cancel), + d("[MGC] DiscoRes: ~p", [DiscoRes]), + + %% check number of reply records (should be no in aborted). + d("[MGC] check number of replies in aborted state (should be == 1)"), + ConnReps3 = ?MGC_CONN_INFO(Mgc, replies), + d("[MGC] ConnReps3: ~p", [ConnReps3]), + UserReps3 = ?MGC_USER_INFO(Mgc, replies), + d("[MGC] UserReps3: ~p", [UserReps3]), + + %% Tell MG to stop + i("[MG] stop"), + ?MG_STOP(Mg), + + %% Tell Mgc to stop + i("[MGC] stop"), + ?MGC_STOP(Mgc), + + i("done", []), + ok. + +await_aborted(Mgc) -> + d("await_aborted"), + receive + {abort_received, Mgc, TransId} -> + {ok, TransId} + after 10000 -> + d("await_aborted - timeout"), + {error, timeout} + end. + +filter_aborted1([], Acc) -> + lists:reverse(Acc); +filter_aborted1([{CH, Ab}|T], Acc) -> + filter_aborted1(T, [{CH, filter_aborted2(Ab, [])}|Acc]). + +filter_aborted2([], Aborted) -> + lists:reverse(Aborted); +filter_aborted2([{TransId, aborted, _}|T], Aborted) -> + filter_aborted2(T, [TransId|Aborted]); +filter_aborted2([{TransId, State, _}|T], Aborted) -> + d("Transaction ~w actually in state ~w", [TransId, State]), + filter_aborted2(T, Aborted); +filter_aborted2([_|T], Aborted) -> + filter_aborted2(T, Aborted). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% The timeout times is a little odd in this test case. The (short) +%% request timer is longer then the (long) request timer. This is +%% simply to produce the effect that we want regarding max_retries = +%% infinity_restartable. Also the pending timeout has to be shorter +%% then "short" + "long" and longer then "long" + +otp_5619(suite) -> + []; +otp_5619(doc) -> + "..."; +otp_5619(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, otp_5619), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + %% Start the MGC and MGs + i("[MGC] start"), + MgcMid = {deviceName, "ctrl"}, + ET = [{text, tcp}, {text, udp}, {binary, tcp}, {binary, udp}], + {ok, Mgc} = ?MGC_START(MgcNode, MgcMid, ET, [], ?MGC_VERBOSITY), + + i("[MG] start"), + MgMid = {deviceName, "mg"}, + MgConfig = [], + {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY), + + d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]), + d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]), + + i("[MG] connect to the MGC (service change)"), + ServChRes = ?MG_SERV_CHANGE(Mg), + d("service change result: ~p", [ServChRes]), + + d("[MG] update connection info long request timer"), + LongReqTmr = #megaco_incr_timer{wait_for = timer:seconds(1), + factor = 1, + max_retries = infinity_restartable}, + ?MG_UPDATE_CI(Mg, long_request_timer, LongReqTmr), + + d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]), + + d("MGC conn info: ~p", [?MGC_CONN_INFO(Mgc, all)]), + + d("[MGC] update connection info pending timer"), + PendingTimer = #megaco_incr_timer{wait_for = timer:seconds(3), + factor = 1}, + ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer), + + d("[MGC] update connection info sent pending limit"), + PendingLimit = 5, + ?MGC_UPDATE_CI(Mgc, sent_pending_limit, PendingLimit), + + d("MGC conn info: ~p", [?MG_CONN_INFO(Mgc, all)]), + + + d("[MGC] late reply to requests " + "(simulate that the request takes a long time)"), + {ok, _} = ?MGC_REQ_DISC(Mgc, 11000), + + + d("[MG] send the notify and await the timeout"), + {ok, Reply} = ?MG_NOTIF_RAR(Mg), + case Reply of + {_Version, {error, timeout}} -> + d("[MG] expected reply (timeout) received~n", []); + _ -> + ?ERROR({unexpected_reply, Reply}) + end, + + + %% Tell MG to stop + i("[MG] stop~n"), + ?MG_STOP(Mg), + + %% Tell Mgc to stop + i("[MGC] stop~n"), + ?MGC_STOP(Mgc), + + i("done", []), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% +%% Common message creation functions +%% + +cre_serviceChangeParm(M,R,P) -> + #'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeReason = R, + serviceChangeProfile = P}. + +cre_serviceChangeReq(Tid, Parms) -> + #'ServiceChangeRequest'{terminationID = Tid, + serviceChangeParms = Parms}. + +cre_timeNotation(D,T) -> + #'TimeNotation'{date = D, time = T}. + +cre_obsEvent(Name, Not) -> + #'ObservedEvent'{eventName = Name, + timeNotation = Not}. +%% cre_obsEvent(Name, Not, Par) -> +%% #'ObservedEvent'{eventName = Name, +%% timeNotation = Not, +%% eventParList = Par}. + +cre_obsEvsDesc(Id, EvList) -> + #'ObservedEventsDescriptor'{requestId = Id, + observedEventLst = EvList}. + +cre_notifyReq(Tid, EvsDesc) -> + #'NotifyRequest'{terminationID = Tid, + observedEventsDescriptor = EvsDesc}. + +cre_command(R) when is_record(R, 'NotifyRequest') -> + {notifyReq, R}; +cre_command(R) when is_record(R, 'ServiceChangeRequest') -> + {serviceChangeReq, R}. + +cre_cmdReq(Cmd) -> + #'CommandRequest'{command = Cmd}. + +cre_actionReq(CtxId, CmdReqs) when is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxId, + commandRequests = CmdReqs}. + +cre_transReq(TransId, ARs) when is_list(ARs) -> + #'TransactionRequest'{transactionId = TransId, + actions = ARs}. + +%% -- + +cre_serviceChangeResParm(Mid) -> + cre_serviceChangeResParm(Mid, ?VERSION). + +cre_serviceChangeResParm(Mid, V) -> + #'ServiceChangeResParm'{serviceChangeMgcId = Mid, + serviceChangeVersion = V}. + +cre_serviceChangeResult(SCRP) when is_record(SCRP, 'ServiceChangeResParm') -> + {serviceChangeResParms, SCRP}; +cre_serviceChangeResult(ED) when is_record(ED, 'ErrorDescriptor') -> + {errorDescriptor, ED}. + +cre_serviceChangeReply(Tid, Res) -> + #'ServiceChangeReply'{terminationID = Tid, + serviceChangeResult = Res}. + +cre_cmdReply(R) when is_record(R, 'NotifyReply') -> + {notifyReply, R}; +cre_cmdReply(R) when is_record(R, 'ServiceChangeReply') -> + {serviceChangeReply, R}. + +cre_notifyReply(Tid) -> + #'NotifyReply'{terminationID = Tid}. + +cre_actionReply(CtxId, CmdRep) -> + #'ActionReply'{contextId = CtxId, + commandReply = CmdRep}. + +%% cre_transResult(ED) when record(ED, 'ErrorDescriptor') -> +%% {transactionError, ED}; +%% cre_transResult([AR|_] = ARs) when record(AR, 'ActionReply') -> +%% {actionReplies, ARs}. + +%% cre_transReply(TransId, Res) -> +%% #'TransactionReply'{transactionId = TransId, +%% transactionResult = Res}. + +%% -- + +cre_serviceChangeProf(Name, Ver) when is_list(Name) andalso is_integer(Ver) -> + #'ServiceChangeProfile'{profileName = Name, + version = Ver}. + +cre_transaction(Trans) when is_record(Trans, 'TransactionRequest') -> + {transactionRequest, Trans}; +cre_transaction(Trans) when is_record(Trans, 'TransactionPending') -> + {transactionPending, Trans}; +cre_transaction(Trans) when is_record(Trans, 'TransactionReply') -> + {transactionReply, Trans}; +cre_transaction(Trans) when is_record(Trans, 'TransactionAck') -> + {transactionResponseAck, Trans}. + +cre_transactions(Trans) when is_list(Trans) -> + {transactions, Trans}. + +cre_message(Version, Mid, Body) -> + #'Message'{version = Version, + mId = Mid, + messageBody = Body}. + +cre_megacoMessage(Mess) -> + #'MegacoMessage'{mess = Mess}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Transform a short timer to a long one. +%% The purpose of this is to trick the stack +%% to keep re-sending the request, even after +%% having received the first pending (which +%% indicates that the other side _IS_ +%% working on the request). +-ifdef(MEGACO_TEST_CODE). + +init_request_timer({short, Ref}) -> + {long, Ref}; +init_request_timer(O) -> + O. + +-endif. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +encode_msg(M, Mod, Conf) -> + Mod:encode_message(Conf, M). + +%% encode_msg(M, Mod, Conf, Ver) -> +%% Mod:encode_message(Conf, Ver, M). + +decode_msg(M, Mod, Conf) -> + Mod:decode_message(Conf, M). + +%% decode_msg(M, Mod, Conf, Ver) -> +%% Mod:decode_message(Conf, Ver, M). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% tim() -> +%% {A,B,C} = erlang:now(), +%% A*1000000000+B*1000+(C div 1000). + + +make_node_name(Name) -> + case string:tokens(atom_to_list(node()), [$@]) of + [_,Host] -> + list_to_atom(lists:concat([atom_to_list(Name) ++ "@" ++ Host])); + _ -> + exit("Test node must be started with '-sname'") + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +await_completion(Ids) -> + case megaco_test_generator_lib:await_completion(Ids) of + {ok, Reply} -> + d("OK => Reply: ~n~p", [Reply]), + ok; + {error, Reply} -> + d("ERROR => Reply: ~n~p", [Reply]), + ?ERROR({failed, Reply}) + end. + +%% await_completion(Ids, Timeout) -> +%% case megaco_test_generator_lib:await_completion(Ids, Timeout) of +%% {ok, Reply} -> +%% d("OK => Reply: ~n~p", [Reply]), +%% ok; +%% {error, Reply} -> +%% d("ERROR => Reply: ~n~p", [Reply]), +%% ?ERROR({failed, Reply}) +%% end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +sleep(X) -> receive after X -> ok end. + +%% error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +i(F) -> + i(F, []). + +i(F, A) -> + print(info, get(verbosity), now(), get(tc), "INF", F, A). + + +d(F) -> + d(F, []). + +d(F, A) -> + print(debug, get(verbosity), now(), get(tc), "DBG", F, A). + + +printable(_, debug) -> true; +printable(info, info) -> true; +printable(_,_) -> false. + +print(Severity, Verbosity, Ts, Tc, P, F, A) -> + print(printable(Severity,Verbosity), Ts, Tc, P, F, A). + +print(true, Ts, Tc, P, F, A) -> + io:format("*** [~s] ~s ~p ~s:~w ***" + "~n " ++ F ++ "~n", + [format_timestamp(Ts), P, self(), get(sname), Tc | A]); +print(_, _, _, _, _, _) -> + ok. + +%% print(F, A) -> +%% io:format("*** [~s] ***" +%% "~n " ++ F ++ "~n", +%% [format_timestamp(now()) | A]). + +format_timestamp(Now) -> megaco:format_timestamp(Now). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% random_init() -> +%% {A,B,C} = now(), +%% random:seed(A,B,C). + +%% random() -> +%% 10 * random:uniform(50). + +%% apply_load_timer() -> +%% erlang:send_after(random(), self(), apply_load_timeout). + + + diff --git a/lib/megaco/test/megaco_profile.erl b/lib/megaco/test/megaco_profile.erl new file mode 100644 index 0000000000..01fa0b5a14 --- /dev/null +++ b/lib/megaco/test/megaco_profile.erl @@ -0,0 +1,138 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% megaco_profile: Utility module used for megaco profiling +%%---------------------------------------------------------------------- + +-module(megaco_profile). + +-export([profile/2]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Execute Fun and profile it with fprof. +profile(Slogan, Fun) when is_function(Fun) -> + Pids = [self()], + profile(Slogan, Fun, Pids). + +profile(Slogan, Fun, Pids) -> + TraceFile = lists:concat(["profile_", Slogan, "-fprof.trace"]), + DestFile = lists:concat(["profile_", Slogan, ".fprof"]), + TreeFile = lists:concat(["profile_", Slogan, ".calltree"]), + erlang:garbage_collect(), + {ok, _Pid} = fprof:start(), + TraceOpts = [start, + {cpu_time, false}, + {procs, Pids}, + {file, TraceFile} + ], + ok = fprof:trace(TraceOpts), + Res = (catch Fun()), + ok = fprof:trace(stop), + ok = fprof:profile([{file, TraceFile}]), + ok = fprof:analyse([{dest, DestFile}]), + ok = fprof:stop(), + ok = file:delete(TraceFile), + reformat_total(DestFile, TreeFile), + Res. + +reformat_total(FromFile, ToFile) -> + {ok, ConsultedFromFile} = file:consult(FromFile), + [_AnalysisOpts, [Totals] | Terms] = ConsultedFromFile, + {totals, _, TotalAcc, _} = Totals, + {ok, Fd} = file:open(ToFile, [write, raw]), + Indent = "", + log(Fd, Indent, TotalAcc, Totals), + Processes = split_processes(Terms, [], []), + Reformat = fun(P) -> reformat_process(Fd, " " ++ Indent, TotalAcc, P) end, + lists:foreach(Reformat, Processes), + file:close(Fd). + + +split_processes([H | T], ProcAcc, TotalAcc) -> + if + is_tuple(H) -> + split_processes(T, [H | ProcAcc], TotalAcc); + is_list(H), ProcAcc =:= [] -> + split_processes(T, [H], TotalAcc); + is_list(H) -> + split_processes(T, [H], [lists:reverse(ProcAcc) | TotalAcc]) + end; +split_processes([], [], TotalAcc) -> + lists:reverse(TotalAcc); +split_processes([], ProcAcc, TotalAcc) -> + lists:reverse([lists:reverse(ProcAcc) | TotalAcc]). + +reformat_process(Fd, Indent, TotalAcc, Terms) -> + case Terms of + [[{ProcLabel, _, _, _}] | All] -> ok; + [[{ProcLabel,_,_,_} | _] | All] -> ok + end, + [{_, {TopKey, TopCnt, TopAcc, TopOwn}, _} | _] = All, + Process = {ProcLabel, TopCnt, TopAcc, TopOwn}, + log(Fd, Indent, TotalAcc, Process), + reformat_calls(Fd, " " ++ Indent, TotalAcc, TopKey, All, []). + +reformat_calls(Fd, Indent, TotalAcc, Key, Terms, Stack) -> + {_CalledBy, Current, Calls} = find(Key, Terms), + log(Fd, Indent, TotalAcc, Current), + case lists:member(Key, Stack) of + true -> + ok; + false -> + case Key of + {io_lib, _, _} -> + ok; + {disk_log, _, _} -> + ok; + {lists, flatten, _} -> + ok; + {lists, keysort, _} -> + ok; + _ -> + Fun = fun({NextKey, _, _, _}) -> + reformat_calls(Fd, + " " ++ Indent, + TotalAcc, + NextKey, + Terms, + [Key | Stack]) + end, + lists:foreach(Fun, Calls) + end + end. + +find(Key, [{_, {Key, _, _, _}, _} = H | _]) -> + H; +find(Key, [{_, {_, _, _, _}, _} | T]) -> + find(Key, T). + +log(Fd, Indent, Total, {Label, Cnt, Acc, Own}) -> + Percent = case Acc of + undefined -> 100; + _ -> trunc((lists:max([Acc, Own]) * 100) / Total) + end, + Label2 = io_lib:format("~p", [Label]), + IoList = io_lib:format("~s~p% ~s \t~p \t~p \t~p\n", + [Indent, Percent, Label2, Cnt, trunc(Acc), trunc(Own)]), + file:write(Fd, IoList). + diff --git a/lib/megaco/test/megaco_sdp_test.erl b/lib/megaco/test/megaco_sdp_test.erl new file mode 100644 index 0000000000..e9bd550518 --- /dev/null +++ b/lib/megaco/test/megaco_sdp_test.erl @@ -0,0 +1,1286 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test application config +%%---------------------------------------------------------------------- + +-module(megaco_sdp_test). + +-export([all/1, + decode_encode/1, + + tickets/1, + otp8123/1, + + init_per_testcase/2, fin_per_testcase/2, + + t/0, t/1]). + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). +-include_lib("megaco/include/megaco_sdp.hrl"). + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + +%% Test server callbacks +init_per_testcase(Case, Config) -> + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top test case +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +all(suite) -> + [ + decode_encode, + tickets + ]. + +tickets(suite) -> + [ + otp8123 + ]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +decode_encode(suite) -> + []; +decode_encode(Config) when is_list(Config) -> + io:format("decode_encode -> entry with" + "~n Config: ~p" + "~n", [Config]), + + %%------------------------------------- + %% Test data + %%------------------------------------- + + %% -- (PP) (ok) -- + io:format("setup for protocol version 01 (ok)~n", []), + PP_V01_V = 0, + PP_V01 = cre_PropertyParm_v(PP_V01_V), + SDP_V01 = cre_sdp_v(PP_V01_V), + PP_V01_Exp = {ok, SDP_V01}, + SDP_V01_Exp = {ok, PP_V01}, + + + %% -- (PP) (ok) -- + io:format("setup for protocol version 02 (ok)~n", []), + PP_V02_V = 100, + PP_V02 = cre_PropertyParm_v(PP_V02_V), + SDP_V02 = cre_sdp_v(PP_V02_V), + PP_V02_Exp = {ok, SDP_V02}, + SDP_V02_Exp = {ok, PP_V02}, + + + %% -- (PP) (error) -- + io:format("setup for protocol version 03 (error)~n", []), + PP_V03_V = "sune", + PP_V03 = cre_PropertyParm_v(PP_V03_V), + SDP_V03 = cre_sdp_v(PP_V03_V), + PP_V03_Exp = {error, {invalid_protocol_version, PP_V03_V}}, + SDP_V03_Exp = PP_V03_Exp, + + + %% -- (PP) (ok) -- + io:format("setup for connection info 01 (ok)~n", []), + PP_C01_CA = "123.123.123.120", + PP_C01 = cre_PropertyParm_c(ip4, PP_C01_CA), + SDP_C01 = cre_sdp_c(ip4, PP_C01_CA), + PP_C01_Exp = {ok, SDP_C01}, + SDP_C01_Exp = {ok, PP_C01}, + + + %% -- (PP) (ok) -- + io:format("setup for connection info 02 (ok)~n", []), + PP_C02_TTL = 121, + PP_C02_Base = "123.123.123.121", + PP_C02 = cre_PropertyParm_c(ip4, PP_C02_Base, PP_C02_TTL), + SDP_C02_CA = #megaco_sdp_c_conn_addr{base = PP_C02_Base, + ttl = PP_C02_TTL}, + SDP_C02 = cre_sdp_c(ip4, SDP_C02_CA), + PP_C02_Exp = {ok, SDP_C02}, + SDP_C02_Exp = {ok, PP_C02}, + + + %% -- (PP) (ok) -- + io:format("setup for connection info 03 (ok)~n", []), + PP_C03_CA = "123.123.123.122", + PP_C03 = cre_PropertyParm_c(ip4, PP_C03_CA ++ "/"), + SDP_C03 = cre_sdp_c(ip4, PP_C03_CA), + PP_C03_Exp = {ok, SDP_C03}, + SDP_C03_Exp = {ok, cre_PropertyParm_c(ip4, PP_C03_CA)}, + + + %% -- (PP) (error) -- + io:format("setup for connection info 04 (error)~n", []), + PP_C04_Base = "123.123.123.123", + PP_C04_TTL = "sune", + PP_C04_CA = PP_C04_Base ++ "/" ++ PP_C04_TTL, + PP_C04 = cre_PropertyParm_c(ip4, PP_C04_CA), + PP_C04_Exp = {error, {invalid_connection_data_conn_addr_ttl, "sune"}}, + + + %% -- (PP) (ok) -- + io:format("setup for connection info 05 (ok)~n", []), + PP_C05_TTL = 124, + PP_C05_NOF = 224, + PP_C05_Base = "123.123.123.124", + PP_C05 = cre_PropertyParm_c(ip4, PP_C05_Base, PP_C05_TTL, + PP_C05_NOF), + SDP_C05_CA = #megaco_sdp_c_conn_addr{base = PP_C05_Base, + ttl = PP_C05_TTL, + num_of = PP_C05_NOF}, + SDP_C05 = cre_sdp_c(ip4, SDP_C05_CA), + PP_C05_Exp = {ok, SDP_C05}, + SDP_C05_Exp = {ok, PP_C05}, + + + %% -- (PP) (ok) -- + io:format("setup for connection info 06 (ok)~n", []), + PP_C06_TTL = 125, + PP_C06_Base = "123.123.123.125", + PP_C06_CA = PP_C06_Base ++ "/" ++ integer_to_list(PP_C06_TTL) ++ "/", + PP_C06 = cre_PropertyParm_c(ip4, PP_C06_CA), + SDP_C06_CA = #megaco_sdp_c_conn_addr{base = PP_C06_Base, + ttl = PP_C06_TTL}, + SDP_C06 = cre_sdp_c(ip4, SDP_C06_CA), + PP_C06_Exp = {ok, SDP_C06}, + SDP_C06_Exp = {ok, cre_PropertyParm_c(ip4, PP_C06_Base ++ "/" ++ integer_to_list(PP_C06_TTL))}, + + + %% -- (PP) (error) -- + io:format("setup for connection info 07 (ok)~n", []), + PP_C07_NOF = "sune", + PP_C07_TTL = 125, + PP_C07_Base = "123.123.123.126", + PP_C07_CA = PP_C07_Base ++ "/" ++ + integer_to_list(PP_C07_TTL) ++ "/" ++ PP_C07_NOF, + PP_C07 = cre_PropertyParm_c(ip4, PP_C07_CA), + SDP_C07_CA = #megaco_sdp_c_conn_addr{base = PP_C07_Base, + ttl = PP_C07_TTL, + num_of = PP_C07_NOF}, + SDP_C07 = cre_sdp_c(ip4, SDP_C07_CA), + PP_C07_Exp = {error, {invalid_connection_data_conn_addr_num_of, PP_C07_NOF}}, + SDP_C07_Exp = {error, {invalid_connection_data_conn_addr_num_of, PP_C07_NOF}}, + + + %% -- (PP) (ok) -- + io:format("setup for connection info 08 (ok)~n", []), + PP_C08_CA = "FF1E:03AD::7F2E:172A:1E24", + PP_C08 = cre_PropertyParm_c(ip6, PP_C08_CA), + SDP_C08 = cre_sdp_c(ip6, PP_C08_CA), + PP_C08_Exp = {ok, SDP_C08}, + SDP_C08_Exp = {ok, PP_C08}, + + + %% -- (PP) (ok) -- + io:format("setup for media announcement 01 (ok)~n", []), + PP_M01_Media = audio, + PP_M01_Port = 2000, + PP_M01_Transport = "RTP/AVP", + PP_M01_FMT_LST = ["0"], + PP_M01 = cre_PropertyParm_m(PP_M01_Media, + PP_M01_Port, + PP_M01_Transport, + PP_M01_FMT_LST), + SDP_M01 = cre_sdp_m(PP_M01_Media, PP_M01_Port, + PP_M01_Transport, PP_M01_FMT_LST), + PP_M01_Exp = {ok, SDP_M01}, + SDP_M01_Exp = {ok, PP_M01}, + + + %% -- (PP) (ok) -- + io:format("setup for media announcement 02 (ok)~n", []), + PP_M02_Media = audio, + PP_M02_Port = 2000, + PP_M02_NOP = 2, + PP_M02_Transport = "RTP/AVP", + PP_M02_FMT_LST = ["0"], + PP_M02 = cre_PropertyParm_m(PP_M02_Media, PP_M02_Port, + PP_M02_NOP, PP_M02_Transport, + PP_M02_FMT_LST), + SDP_M02 = cre_sdp_m(PP_M02_Media, PP_M02_Port, PP_M02_NOP, + PP_M02_Transport, PP_M02_FMT_LST), + PP_M02_Exp = {ok, SDP_M02}, + SDP_M02_Exp = {ok, PP_M02}, + + %% -- (PP) (ok) -- + io:format("setup for origin 01 (ok)~n", []), + PP_O01_Name = "kalle", + PP_O01_SID = 1414, + PP_O01_V = 2, + PP_O01_AT = ip4, + PP_O01_A = "126.12.64.4", + PP_O01 = cre_PropertyParm_o(PP_O01_Name, PP_O01_SID, PP_O01_V, + PP_O01_AT, PP_O01_A), + SDP_O01 = cre_sdp_o(PP_O01_Name, PP_O01_SID, PP_O01_V, + PP_O01_AT, PP_O01_A), + PP_O01_Exp = {ok, SDP_O01}, + SDP_O01_Exp = {ok, PP_O01}, + + + %% -- (PP) (ok) -- + io:format("setup for origin 02 (ok)~n", []), + PP_O02_Name = "bobbe", + PP_O02_SID = 1515, + PP_O02_V = 3, + PP_O02_NT = in, + PP_O02_AT = ip6, + PP_O02_A = "2201:056D::112E:144A:1E24", + PP_O02 = cre_PropertyParm_o(PP_O02_Name, PP_O02_SID, PP_O02_V, + PP_O02_NT, PP_O02_AT, PP_O02_A), + SDP_O02 = cre_sdp_o(PP_O02_Name, PP_O02_SID, PP_O02_V, PP_O02_NT, + PP_O02_AT, PP_O02_A), + PP_O02_Exp = {ok, SDP_O02}, + SDP_O02_Exp = {ok, PP_O02}, + + + %% -- (PP) (ok) -- + PP_A01_PL = 2, + PP_A01_EN = "G726-32", + PP_A01_CR = 8000, + PP_A01 = cre_PropertyParm_rtpmap(PP_A01_PL, PP_A01_EN, PP_A01_CR), + SDP_A01 = cre_sdp_a_rtpmap(PP_A01_PL, PP_A01_EN, PP_A01_CR), + PP_A01_Exp = {ok, SDP_A01}, + SDP_A01_Exp = {ok, PP_A01}, + + + %% -- (PP) (ok) -- + PP_A02_PL = 2, + PP_A02_EN = "xxx", + PP_A02_CR = 42, + PP_A02_EP = ["1","2","3"], + PP_A02 = cre_PropertyParm_rtpmap(PP_A02_PL, PP_A02_EN, + PP_A02_CR, PP_A02_EP), + SDP_A02 = cre_sdp_a_rtpmap(PP_A02_PL, PP_A02_EN, PP_A02_CR, PP_A02_EP), + PP_A02_Exp = {ok, SDP_A02}, + SDP_A02_Exp = {ok, PP_A02}, + + + %% -- (PP) (ok) -- + PP_A03_PT = 12, + PP_A03 = cre_PropertyParm_ptime(PP_A03_PT), + SDP_A03 = cre_sdp_a_ptime(PP_A03_PT), + PP_A03_Exp = {ok, SDP_A03}, + SDP_A03_Exp = {ok, PP_A03}, + + + %% -- (PP) (error) -- + PP_A04_PT = "sune", + PP_A04 = cre_PropertyParm_ptime(PP_A04_PT), + SDP_A04 = cre_sdp_a_ptime(PP_A04_PT), + PP_A04_Exp = {error, {invalid_ptime_packet_time, PP_A04_PT}}, + SDP_A04_Exp = {error, {invalid_ptime_packet_time, PP_A04_PT}}, + + + %% -- (PP) (ok) -- + PP_A05_QA = 10, + PP_A05 = cre_PropertyParm_quality(PP_A05_QA), + SDP_A05 = cre_sdp_a_quality(PP_A05_QA), + PP_A05_Exp = {ok, SDP_A05}, + SDP_A05_Exp = {ok, PP_A05}, + + + %% -- (PP) (error) -- + PP_A06_QA = "sune", + PP_A06 = cre_PropertyParm_quality(PP_A06_QA), + SDP_A06 = cre_sdp_a_quality(PP_A06_QA), + PP_A06_Exp = {error, {invalid_quality_quality, PP_A06_QA}}, + SDP_A06_Exp = {error, {invalid_quality_quality, PP_A06_QA}}, + + + %% -- (PP) (ok) -- + PP_A07_A = "recvonly", + PP_A07 = cre_PropertyParm_a(PP_A07_A), + SDP_A07 = cre_sdp_a(PP_A07_A), + PP_A07_Exp = {ok, SDP_A07}, + SDP_A07_Exp = {ok, PP_A07}, + + + %% -- (PP) (ok) -- + PP_A08_V = portrait, + PP_A08 = cre_PropertyParm_orient(PP_A08_V), + SDP_A08 = cre_sdp_a_orient(PP_A08_V), + PP_A08_Exp = {ok, SDP_A08}, + SDP_A08_Exp = {ok, PP_A08}, + + + %% -- (PP) (ok) -- + PP_A09_V = landscape, + PP_A09 = cre_PropertyParm_orient(PP_A09_V), + SDP_A09 = cre_sdp_a_orient(PP_A09_V), + PP_A09_Exp = {ok, SDP_A09}, + SDP_A09_Exp = {ok, PP_A09}, + + + %% -- (PP) (ok) -- + PP_A10_V = seascape, + PP_A10 = cre_PropertyParm_orient(PP_A10_V), + SDP_A10 = cre_sdp_a_orient(PP_A10_V), + PP_A10_Exp = {ok, SDP_A10}, + SDP_A10_Exp = {ok, PP_A10}, + + + %% -- (PP) (error) -- + PP_A11_V = gurka, + SDP_A11_V = atom_to_list(PP_A11_V), + PP_A11 = cre_PropertyParm_orient(PP_A11_V), + SDP_A11 = cre_sdp_a_orient(PP_A11_V), + PP_A11_Exp = {error, {invalid_orient_orientation, SDP_A11_V}}, + SDP_A11_Exp = {error, {invalid_orient_orientation, PP_A11_V}}, + + + %% -- (PP) (ok) -- + PP_A12_V = "gurka", + PP_A12 = cre_PropertyParm_cat(PP_A12_V), + SDP_A12 = cre_sdp_a_cat(PP_A12_V), + PP_A12_Exp = {ok, SDP_A12}, + SDP_A12_Exp = {ok, PP_A12}, + + + %% -- (PP) (ok) -- + PP_A13_V = "gurka", + PP_A13 = cre_PropertyParm_keywds(PP_A13_V), + SDP_A13 = cre_sdp_a_keywds(PP_A13_V), + PP_A13_Exp = {ok, SDP_A13}, + SDP_A13_Exp = {ok, PP_A13}, + + + %% -- (PP) (ok) -- + PP_A14_V = "gurka 1.0", + PP_A14 = cre_PropertyParm_tool(PP_A14_V), + SDP_A14 = cre_sdp_a_tool(PP_A14_V), + PP_A14_Exp = {ok, SDP_A14}, + SDP_A14_Exp = {ok, PP_A14}, + + + %% -- (PP) (ok) -- + PP_A15_V = 15, + PP_A15 = cre_PropertyParm_maxptime(PP_A15_V), + SDP_A15 = cre_sdp_a_maxptime(PP_A15_V), + PP_A15_Exp = {ok, SDP_A15}, + SDP_A15_Exp = {ok, PP_A15}, + + + %% -- (PP) (error) -- + PP_A16_V = "gurka", + PP_A16 = cre_PropertyParm_maxptime(PP_A16_V), + SDP_A16 = cre_sdp_a_maxptime(PP_A16_V), + PP_A16_Exp = {error, {invalid_maxptime_maximum_packet_time, PP_A16_V}}, + SDP_A16_Exp = {error, {invalid_maxptime_maximum_packet_time, PP_A16_V}}, + + + %% -- (PP) (ok) -- + PP_A17_V = "H332", + PP_A17 = cre_PropertyParm_type(PP_A17_V ), + SDP_A17 = cre_sdp_a_type(PP_A17_V), + PP_A17_Exp = {ok, SDP_A17}, + SDP_A17_Exp = {ok, PP_A17}, + + + %% -- (PP) (ok) -- + PP_A18_V = "ISO-8859-1", + PP_A18 = cre_PropertyParm_charset(PP_A18_V), + SDP_A18 = cre_sdp_a_charset(PP_A18_V), + PP_A18_Exp = {ok, SDP_A18}, + SDP_A18_Exp = {ok, PP_A18}, + + + %% -- (PP) (ok) -- + PP_A19_PT = "gurka", + PP_A19 = cre_PropertyParm_sdplang(PP_A19_PT), + SDP_A19 = cre_sdp_a_sdplang(PP_A19_PT), + PP_A19_Exp = {ok, SDP_A19}, + SDP_A19_Exp = {ok, PP_A19}, + + + %% -- (PP) (ok) -- + PP_A20_PT = "gurka", + PP_A20 = cre_PropertyParm_lang(PP_A20_PT), + SDP_A20 = cre_sdp_a_lang(PP_A20_PT), + PP_A20_Exp = {ok, SDP_A20}, + SDP_A20_Exp = {ok, PP_A20}, + + + %% -- (PP) (ok) -- + PP_A21_PT = "21.0", + PP_A21 = cre_PropertyParm_framerate(PP_A21_PT), + SDP_A21 = cre_sdp_a_framerate(PP_A21_PT), + PP_A21_Exp = {ok, SDP_A21}, + SDP_A21_Exp = {ok, PP_A21}, + + +%% %% -- (PP) (ok) -- +%% PP_A22_PT = "ISO-8859-1", +%% PP_A22 = cre_PropertyParm_(PP_A22_T), +%% SDP_A22 = cre_sdp_a_(PP_A22_PT), +%% PP_A22_Exp = {ok, SDP_A22}, +%% SDP_A22_Exp = {ok, PP_A22}, + + + %% -- (PP) (ok) -- + PP_A23_FORMAT = "125", + PP_A23_PARAM = "profile-level-id=222; max-br=1212; max-mbps=20200", + PP_A23 = cre_PropertyParm_a_fmtp(PP_A23_FORMAT, PP_A23_PARAM), + SDP_A23 = cre_sdp_a_fmtp(PP_A23_FORMAT, PP_A23_PARAM), + PP_A23_Exp = {ok, SDP_A23}, + SDP_A23_Exp = {ok, PP_A23}, + + + %% -- (PP) (ok) -- + PP_B01_MOD = "2", + PP_B01_BW = 523, + PP_B01 = cre_PropertyParm_b(PP_B01_MOD, PP_B01_BW), + SDP_B01 = cre_sdp_b(PP_B01_MOD, PP_B01_BW), + PP_B01_Exp = {ok, SDP_B01}, + SDP_B01_Exp = {ok, PP_B01}, + + + %% -- (PP) (error) -- + PP_B02_B = "sune", + PP_B02 = cre_PropertyParm("b", PP_B02_B), + PP_B02_Exp = {error, {invalid_PropertyParm, + {bandwidth_info, PP_B02_B, [PP_B02_B]}}}, + + + %% -- (PP) (ok) -- + PP_B03_MOD = "X", + PP_B03_BW = 525, + PP_B03 = cre_PropertyParm_b(PP_B03_MOD, PP_B03_BW), + SDP_B03 = cre_sdp_b(PP_B03_MOD, PP_B03_BW), + PP_B03_Exp = {ok, SDP_B03}, + SDP_B03_Exp = {ok, PP_B03}, + + + %% -- (PP) (error) -- + PP_B04_BWT = "X", + PP_B04_BW = "sune", + PP_B04 = cre_PropertyParm_b(PP_B04_BWT, PP_B04_BW), + SDP_B04 = cre_sdp_b(PP_B04_BWT, PP_B04_BW), + PP_B04_Exp = {error, {invalid_bandwidth_bandwidth, PP_B04_BW}}, + SDP_B04_Exp = {error, {invalid_bandwidth_bandwidth, PP_B04_BW}}, + + + %% -- (PP) (ok) -- + PP_T01_START = 1200, + PP_T01_STOP = 1300, + PP_T01 = cre_PropertyParm_t(PP_T01_START, PP_T01_STOP), + SDP_T01 = cre_sdp_t(PP_T01_START, PP_T01_STOP), + PP_T01_Exp = {ok, SDP_T01}, + SDP_T01_Exp = {ok, PP_T01}, + + + %% -- (PP) (ok) -- + PP_R01_RPT = "10", + PP_R01_DUR = "100", + PP_R01_LOO = ["2", "4", "6"], + PP_R01 = cre_PropertyParm_r(PP_R01_RPT, PP_R01_DUR, PP_R01_LOO), + SDP_R01 = cre_sdp_r(PP_R01_RPT, PP_R01_DUR, PP_R01_LOO), + PP_R01_Exp = {ok, SDP_R01}, + SDP_R01_Exp = {ok, PP_R01}, + + + %% -- (PP) (ok) -- + PP_Z01_LOA_V1 = #megaco_sdp_z_adjustement{time = "12121212", + offset = "-1h"}, + PP_Z01_LOA_V2 = #megaco_sdp_z_adjustement{time = "34343434", + offset = "0"}, + PP_Z01_LOA = [PP_Z01_LOA_V1, PP_Z01_LOA_V2], + PP_Z01 = cre_PropertyParm_z(PP_Z01_LOA), + SDP_Z01 = cre_sdp_z(PP_Z01_LOA), + PP_Z01_Exp = {ok, SDP_Z01}, + SDP_Z01_Exp = {ok, PP_Z01}, + + + %% -- (PP) (error) -- + PP_Z02 = cre_PropertyParm("z", []), + SDP_Z02 = cre_sdp_z([]), + PP_Z02_Exp = {error, {invalid_tzones_list_of_adjustments, []}}, + SDP_Z02_Exp = {error, {invalid_tzones_list_of_adjustments, []}}, + + + %% -- (PP) (ok) -- + PP_K01_M = prompt, + PP_K01_EK = undefined, + PP_K01 = cre_PropertyParm_k(PP_K01_M, PP_K01_EK), + SDP_K01 = cre_sdp_k(PP_K01_M), + PP_K01_Exp = {ok, SDP_K01}, + SDP_K01_Exp = {ok, PP_K01}, + + + %% -- (PP) (ok) -- + PP_K02_M = clear, + PP_K02_EK = "whatever", + PP_K02 = cre_PropertyParm_k(PP_K02_M, PP_K02_EK), + SDP_K02 = cre_sdp_k(PP_K02_M, PP_K02_EK), + PP_K02_Exp = {ok, SDP_K02}, + SDP_K02_Exp = {ok, PP_K02}, + + + %% -- (PP) (ok) -- + PP_K03_M = "method", + PP_K03_EK = "key", + PP_K03 = cre_PropertyParm_k(PP_K03_M, PP_K03_EK), + SDP_K03 = cre_sdp_k(PP_K03_M, PP_K03_EK), + PP_K03_Exp = {ok, SDP_K03}, + SDP_K03_Exp = {ok, PP_K03}, + + + %% -- (PP) (ok) -- + PP_S01_SN = "new session", + PP_S01 = cre_PropertyParm_s(PP_S01_SN), + SDP_S01 = cre_sdp_s(PP_S01_SN), + PP_S01_Exp = {ok, SDP_S01}, + SDP_S01_Exp = {ok, PP_S01}, + + + %% -- (PP) (ok) -- + PP_I01_SD = "Session and Media Information", + PP_I01 = cre_PropertyParm_i(PP_I01_SD), + SDP_I01 = cre_sdp_i(PP_I01_SD), + PP_I01_Exp = {ok, SDP_I01}, + SDP_I01_Exp = {ok, PP_I01}, + + + %% -- (PP) (ok) -- + PP_U01_URI = "http://www.erlang.org/", + PP_U01 = cre_PropertyParm_u(PP_U01_URI), + SDP_U01 = cre_sdp_u(PP_U01_URI), + PP_U01_Exp = {ok, SDP_U01}, + SDP_U01_Exp = {ok, PP_U01}, + + + %% -- (PP) (ok) -- + PP_E01_EMAIL = "[email protected]", + PP_E01 = cre_PropertyParm_e(PP_E01_EMAIL), + SDP_E01 = cre_sdp_e(PP_E01_EMAIL), + PP_E01_Exp = {ok, SDP_E01}, + SDP_E01_Exp = {ok, PP_E01}, + + + %% -- (PP) (ok) -- + PP_P01_PHONE = "+1 713 555 1234", + PP_P01 = cre_PropertyParm_p(PP_P01_PHONE), + SDP_P01 = cre_sdp_p(PP_P01_PHONE), + PP_P01_Exp = {ok, SDP_P01}, + SDP_P01_Exp = {ok, PP_P01}, + + + %% -- (PP) (error) -- + PP_N01 = cre_PropertyParm("not_recognized", "whatever"), + PP_N01_Exp = {error, undefined_PropertyParm}, + + + %% -- (PG) (ok) -- + PG01 = [{PP_V01, ok}, + {PP_C01, ok}, + {PP_M01, ok}], + + + %% -- (PG) (ok) -- + PG02 = [{PP_V02, ok}, + {PP_C05, ok}, + {PP_A02, ok}], + + + %% -- (PG) (error) -- + PG03 = [{PP_V03, error}, + {PP_C08, ok}, + {PP_M02, ok}], + + + %% -- (PG) (error) -- + PG04 = [{PP_V02, ok}, + {PP_C04, error}, + {PP_C07, error}], + + + %% -- (PGs) (ok) -- + PGS01 = [PG01, PG02], + + + %% -- (PGs) (error) -- + PGS02 = [PG01, PG04], + + + Instructions = + [ + pp_dec_instruction("version 01 - dec [ok]", PP_V01, PP_V01_Exp), + pp_enc_instruction("version 01 - enc [ok]", SDP_V01, SDP_V01_Exp), + pp_dec_instruction("version 02 - dec [ok]", PP_V02, PP_V02_Exp), + pp_enc_instruction("version 02 - enc [ok]", SDP_V02, SDP_V02_Exp), + pp_dec_instruction("version 03 - dec [error]", PP_V03, PP_V03_Exp), + pp_enc_instruction("version 03 - enc [error]", SDP_V03, SDP_V03_Exp), + pp_dec_instruction("connection info 01 - dec [ok]", PP_C01, PP_C01_Exp), + pp_enc_instruction("connection info 01 - enc [ok]", SDP_C01, SDP_C01_Exp), + pp_dec_instruction("connection info 02 - dec [ok]", PP_C02, PP_C02_Exp), + pp_enc_instruction("connection info 02 - enc [ok]", SDP_C02, SDP_C02_Exp), + pp_dec_instruction("connection info 03 - dec [ok]", PP_C03, PP_C03_Exp), + pp_enc_instruction("connection info 03 - enc [ok]", SDP_C03, SDP_C03_Exp), + pp_dec_instruction("connection info 04 - dec [error]", PP_C04, PP_C04_Exp), + + pp_dec_instruction("connection info 05 - dec [ok]", PP_C05, PP_C05_Exp), + pp_enc_instruction("connection info 05 - enc [ok]", SDP_C05, SDP_C05_Exp), + pp_dec_instruction("connection info 06 - dec [ok]", PP_C06, PP_C06_Exp), + pp_enc_instruction("connection info 06 - enc [ok]", SDP_C06, SDP_C06_Exp), + pp_dec_instruction("connection info 07 - dec [error]", PP_C07, PP_C07_Exp), + pp_enc_instruction("connection info 07 - enc [error]", SDP_C07, SDP_C07_Exp), + pp_dec_instruction("connection info 08 - dec [ok]", PP_C08, PP_C08_Exp), + pp_enc_instruction("connection info 08 - enc [ok]", SDP_C08, SDP_C08_Exp), + pp_dec_instruction("media announcement 01 - dec [ok]", PP_M01, PP_M01_Exp), + pp_enc_instruction("media announcement 01 - enc [ok]", SDP_M01, SDP_M01_Exp), + pp_dec_instruction("media announcement 02 - dec [ok]", PP_M02, PP_M02_Exp), + pp_enc_instruction("media announcement 02 - enc [ok]", SDP_M02, SDP_M02_Exp), + pp_dec_instruction("origin 01 - dec [ok]", PP_O01, PP_O01_Exp), + pp_enc_instruction("origin 01 - enc [ok]", SDP_O01, SDP_O01_Exp), + pp_dec_instruction("origin 02 - dec [ok]", PP_O02, PP_O02_Exp), + pp_enc_instruction("origin 02 - enc [ok]", SDP_O02, SDP_O02_Exp), + pp_dec_instruction("attributes 01 - dec [ok]", PP_A01, PP_A01_Exp), + pp_enc_instruction("attributes 01 - enc [ok]", SDP_A01, SDP_A01_Exp), + pp_dec_instruction("attributes 02 - dec [ok]", PP_A02, PP_A02_Exp), + pp_enc_instruction("attributes 02 - enc [ok]", SDP_A02, SDP_A02_Exp), + pp_dec_instruction("attributes 03 - dec [ok]", PP_A03, PP_A03_Exp), + pp_enc_instruction("attributes 03 - enc [ok]", SDP_A03, SDP_A03_Exp), + pp_dec_instruction("attributes 04 - dec [error]", PP_A04, PP_A04_Exp), + pp_enc_instruction("attributes 04 - enc [error]", SDP_A04, SDP_A04_Exp), + pp_dec_instruction("attributes 05 - dec [ok]", PP_A05, PP_A05_Exp), + pp_enc_instruction("attributes 05 - enc [ok]", SDP_A05, SDP_A05_Exp), + pp_dec_instruction("attributes 06 - dec [error]", PP_A06, PP_A06_Exp), + pp_enc_instruction("attributes 06 - dec [error]", SDP_A06, SDP_A06_Exp), + pp_dec_instruction("attributes 07 - dec [ok]", PP_A07, PP_A07_Exp), + pp_enc_instruction("attributes 07 - enc [ok]", SDP_A07, SDP_A07_Exp), + pp_dec_instruction("attributes 08 - dec [ok]", PP_A08, PP_A08_Exp), + pp_enc_instruction("attributes 08 - enc [ok]", SDP_A08, SDP_A08_Exp), + + pp_dec_instruction("attributes 09 - dec [ok]", PP_A09, PP_A09_Exp), + pp_enc_instruction("attributes 09 - enc [ok]", SDP_A09, SDP_A09_Exp), + pp_dec_instruction("attributes 10 - dec [ok]", PP_A10, PP_A10_Exp), + pp_enc_instruction("attributes 10 - enc [ok]", SDP_A10, SDP_A10_Exp), + pp_dec_instruction("attributes 11 - dec [error]", PP_A11, PP_A11_Exp), + pp_enc_instruction("attributes 11 - enc [error]", SDP_A11, SDP_A11_Exp), + + pp_dec_instruction("attributes 12 - dec [ok]", PP_A12, PP_A12_Exp), + pp_enc_instruction("attributes 12 - enc [ok]", SDP_A12, SDP_A12_Exp), + pp_dec_instruction("attributes 13 - dec [ok]", PP_A13, PP_A13_Exp), + pp_enc_instruction("attributes 13 - enc [ok]", SDP_A13, SDP_A13_Exp), + pp_dec_instruction("attributes 14 - dec [ok]", PP_A14, PP_A14_Exp), + pp_enc_instruction("attributes 14 - enc [ok]", SDP_A14, SDP_A14_Exp), + pp_dec_instruction("attributes 15 - dec [ok]", PP_A15, PP_A15_Exp), + pp_enc_instruction("attributes 15 - enc [ok]", SDP_A15, SDP_A15_Exp), + pp_dec_instruction("attributes 16 - dec [error]", PP_A16, PP_A16_Exp), + pp_enc_instruction("attributes 16 - enc [error]", SDP_A16, SDP_A16_Exp), + pp_dec_instruction("attributes 17 - dec [ok]", PP_A17, PP_A17_Exp), + pp_enc_instruction("attributes 17 - enc [ok]", SDP_A17, SDP_A17_Exp), + pp_dec_instruction("attributes 18 - dec [ok]", PP_A18, PP_A18_Exp), + pp_enc_instruction("attributes 18 - enc [ok]", SDP_A18, SDP_A18_Exp), + pp_dec_instruction("attributes 19 - dec [ok]", PP_A19, PP_A19_Exp), + pp_enc_instruction("attributes 19 - enc [ok]", SDP_A19, SDP_A19_Exp), + pp_dec_instruction("attributes 20 - dec [ok]", PP_A20, PP_A20_Exp), + pp_enc_instruction("attributes 20 - enc [ok]", SDP_A20, SDP_A20_Exp), + pp_dec_instruction("attributes 21 - dec [ok]", PP_A21, PP_A21_Exp), + pp_enc_instruction("attributes 21 - enc [ok]", SDP_A21, SDP_A21_Exp), + pp_dec_instruction("attributes 23 - dec [ok]", PP_A23, PP_A23_Exp), + pp_enc_instruction("attributes 24 - enc [ok]", SDP_A23, SDP_A23_Exp), + + pp_dec_instruction("bandwidth 01 - dec [ok]", PP_B01, PP_B01_Exp), + pp_enc_instruction("bandwidth 01 - enc [ok]", SDP_B01, SDP_B01_Exp), + pp_dec_instruction("bandwidth 02 - dec [ok]", PP_B02, PP_B02_Exp), + + pp_dec_instruction("bandwidth 03 - dec [ok]", PP_B03, PP_B03_Exp), + pp_enc_instruction("bandwidth 03 - enc [ok]", SDP_B03, SDP_B03_Exp), + pp_dec_instruction("bandwidth 04 - dec [error]", PP_B04, PP_B04_Exp), + pp_enc_instruction("bandwidth 04 - enc [error]", SDP_B04, SDP_B04_Exp), + pp_dec_instruction("times 01 - dec [ok]", PP_T01, PP_T01_Exp), + pp_enc_instruction("times 01 - enc [ok]", SDP_T01, SDP_T01_Exp), + pp_dec_instruction("repeat times 01 - dec [ok]", PP_R01, PP_R01_Exp), + pp_enc_instruction("repeat times 01 - enc [ok]", SDP_R01, SDP_R01_Exp), + pp_dec_instruction("time zones 01 - dec [ok]", PP_Z01, PP_Z01_Exp), + pp_enc_instruction("time zones 01 - enc [ok]", SDP_Z01, SDP_Z01_Exp), + pp_dec_instruction("time zones 02 - dec [error]", PP_Z02, PP_Z02_Exp), + pp_enc_instruction("time zones 02 - enc [error]", SDP_Z02, SDP_Z02_Exp), + pp_dec_instruction("encryption keys 01 - dec [ok]", PP_K01, PP_K01_Exp), + pp_enc_instruction("encryption keys 01 - enc [ok]", SDP_K01, SDP_K01_Exp), + pp_dec_instruction("encryption keys 01 - dec [ok]", PP_K02, PP_K02_Exp), + pp_enc_instruction("encryption keys 01 - enc [ok]", SDP_K02, SDP_K02_Exp), + pp_dec_instruction("encryption keys 01 - dec [ok]", PP_K03, PP_K03_Exp), + pp_enc_instruction("encryption keys 01 - enc [ok]", SDP_K03, SDP_K03_Exp), + pp_dec_instruction("session name 01 - dec [ok]", PP_S01, PP_S01_Exp), + pp_enc_instruction("session name 01 - enc [ok]", SDP_S01, SDP_S01_Exp), + pp_dec_instruction("session and media information 01 - dec [ok]", PP_I01, PP_I01_Exp), + pp_enc_instruction("session and media information 01 - enc [ok]", SDP_I01, SDP_I01_Exp), + pp_dec_instruction("uri 01 - dec [ok]", PP_U01, PP_U01_Exp), + pp_enc_instruction("uri 01 - enc [ok]", SDP_U01, SDP_U01_Exp), + pp_dec_instruction("email 01 - dec [ok]", PP_E01, PP_E01_Exp), + pp_enc_instruction("email 01 - enc [ok]", SDP_E01, SDP_E01_Exp), + pp_dec_instruction("phone 01 - dec [ok]", PP_P01, PP_P01_Exp), + pp_enc_instruction("phone 01 - enc [ok]", SDP_P01, SDP_P01_Exp), + pp_dec_instruction("undefined 01 - dec [error]", PP_N01, PP_N01_Exp), + + pg_dec_instruction("property group 01 - ok", PG01), + pg_dec_instruction("property group 02 - ok", PG02), + pg_dec_instruction("property group 03 - error", PG03), + pg_dec_instruction("property group 04 - error", PG04), + + pgs_dec_instruction("property groups 01 - ok", PGS01), + pgs_dec_instruction("property groups 02 - error", PGS02) + + ], + exec(Instructions). + + +verify_decode_pg([], []) -> + ok; +verify_decode_pg([{PP, error}|PPs], [{PP, _Err}|SDPs]) -> + verify_decode_pg(PPs, SDPs); +verify_decode_pg([{PP, ok}|_], [{PP, _Err}|_]) -> + error; +verify_decode_pg([{_PP, _ExpStatus}|PG], [_SDP|SDP_PG]) -> + verify_decode_pg(PG, SDP_PG). + +verify_decode_pgs(PGS, SDP_PGS) -> + verify_decode_pg(lists:flatten(PGS), lists:flatten(SDP_PGS)). + + +%% =============================================================== + +otp8123(suite) -> + []; +otp8123(Config) when is_list(Config) -> + io:format("otp8123 -> entry with" + "~n Config: ~p" + "~n", [Config]), + + Instructions = + [ + pg_dec_instruction("property group 01 - dec [ok]", otp8123_pg1()), + pg_dec_instruction("property group 02 - dec [ok]", otp8123_pg2()), + pg_dec_instruction("property group 03 - dec [ok]", otp8123_pg3()), + pg_dec_instruction("property group 04 - dec [ok]", otp8123_pg4()) + ], + exec(Instructions), + ok. + +otp8123_pg1() -> + PP1 = #'PropertyParm'{name = "m", + value = ["audio 49154 RTP/AVP 8"]}, + PP2 = #'PropertyParm'{name = "a", + value = ["maxptime: 30"]}, + PP3 = #'PropertyParm'{name = "a", + value = ["ptime:2"]}, + PP4 = #'PropertyParm'{name = "a", + value = ["tpmap:8 PCMA/8000/1"]}, + PG = [PP1, PP2, PP3, PP4], + [{PP, ok} || PP <- PG]. + +otp8123_pg2() -> + PP1 = #'PropertyParm'{name = "m", + value = ["audio 49154 RTP/AVP 8"]}, + PP2 = #'PropertyParm'{name = "a", + value = ["maxptime: 30 "]}, + PP3 = #'PropertyParm'{name = "a", + value = ["ptime:2"]}, + PP4 = #'PropertyParm'{name = "a", + value = ["tpmap:8 PCMA/8000/1"]}, + PG = [PP1, PP2, PP3, PP4], + [{PP, ok} || PP <- PG]. + +otp8123_pg3() -> + PP1 = #'PropertyParm'{name = "m", + value = ["audio 49154 RTP/AVP 8"]}, + PP2 = #'PropertyParm'{name = "a", + value = ["maxptime:30"]}, + PP3 = #'PropertyParm'{name = "a", + value = ["ptime: 2"]}, + PP4 = #'PropertyParm'{name = "a", + value = ["tpmap:8 PCMA/8000/1"]}, + PG = [PP1, PP2, PP3, PP4], + [{PP, ok} || PP <- PG]. + +otp8123_pg4() -> + PP1 = #'PropertyParm'{name = "m", + value = ["audio 49154 RTP/AVP 8"]}, + PP2 = #'PropertyParm'{name = "a", + value = ["maxptime:30"]}, + PP3 = #'PropertyParm'{name = "a", + value = ["ptime: 2 "]}, + PP4 = #'PropertyParm'{name = "a", + value = ["tpmap:8 PCMA/8000/1"]}, + PG = [PP1, PP2, PP3, PP4], + [{PP, ok} || PP <- PG]. + + + +%% =============================================================== +%% +%% Instruction engine +%% + +instr_verify_pp(Expected) -> + fun(Res) -> + case Res of + Expected -> ok; + _ -> {error, Expected} + end + end. + +instr_verify_dec_pg(Data) -> + fun({ok, SDP}) -> + verify_decode_pg(Data, SDP); + (_Bad) -> + error + end. + +instr_verify_dec_pgs(Data) -> + fun({ok, SDP}) -> + verify_decode_pgs(Data, SDP); + (_Bad) -> + error + end. + + +pp_dec_instruction(Desc, Data, Exp) -> + dec_instruction(Desc, Data, instr_verify_pp(Exp)). + +pp_enc_instruction(Desc, Data, Exp) -> + enc_instruction(Desc, Data, instr_verify_pp(Exp)). + +pg_dec_instruction(Desc, Data0) -> + Data = [D || {D, _} <- Data0], + dec_instruction(Desc, Data, instr_verify_dec_pg(Data0)). + +pgs_dec_instruction(Desc, Data0) -> + Data = [[D || {D, _} <- PG] || PG <- Data0], + dec_instruction(Desc, Data, instr_verify_dec_pgs(Data0)). + +dec_instruction(Desc, Data, Verify) -> + instruction(Desc, fun(D) -> megaco:decode_sdp(D) end, Data, Verify). + +enc_instruction(Desc, Data, Verify) -> + instruction(Desc, fun(D) -> megaco:encode_sdp(D) end, Data, Verify). + +instruction(Desc, Cmd, Data, Verify) -> + {Desc, Cmd, Data, Verify}. + +exec(Instructions) -> + exec(Instructions, []). + +exec([], []) -> + ok; +exec([], Acc) -> + {error, lists:reverse(Acc)}; +exec([Instr|Instructions], Acc) -> + case exec_instruction(Instr) of + ok -> + exec(Instructions, Acc); + Error -> + exec(Instructions, [Error|Acc]) + end. + + +exec_instruction({Desc, Cmd, Data, Verify}) -> + io:format("~n" + "*** Test ~s ***" + "~n", [Desc]), + Res = (catch Cmd(Data)), + case (catch Verify(Res)) of + ok -> + ok; + error -> + {error, {instruction_failed, {Desc, Data, Res}}}; + {error, Expected} -> + {error, {instruction_failed, {Desc, Data, Res, Expected}}}; + Else -> + {error, {verification_error, {Desc, Data, Res, Else}}} + end. + + +%% =============================================================== +%% +%% Utility functions to generate PropertyParm records +%% + +cre_PropertyParm_p(Num) when is_list(Num) -> + cre_PropertyParm("p", Num). + +cre_sdp_p(PN) -> + #megaco_sdp_p{phone_number = PN}. + +cre_PropertyParm_e(Email) when is_list(Email) -> + cre_PropertyParm("e", Email). + +cre_sdp_e(E) -> + #megaco_sdp_e{email = E}. + +cre_PropertyParm_u(URI) when is_list(URI) -> + cre_PropertyParm("u", URI). + +cre_sdp_u(U) -> + #megaco_sdp_u{uri = U}. + +cre_PropertyParm_i(SessionDescr) when is_list(SessionDescr) -> + cre_PropertyParm("i", SessionDescr). + +cre_sdp_i(SD) -> + #megaco_sdp_i{session_descriptor = SD}. + +cre_PropertyParm_s(Name) when is_list(Name) -> + cre_PropertyParm("s", Name). + +cre_sdp_s(N) -> + #megaco_sdp_s{name = N}. + +cre_PropertyParm_k(prompt, _) -> + cre_PropertyParm("k", "prompt"); +cre_PropertyParm_k(clear, EncryptionKey) when is_list(EncryptionKey) -> + cre_PropertyParm("k", "clear:" ++ EncryptionKey); +cre_PropertyParm_k(base64, EncryptionKey) when is_list(EncryptionKey) -> + cre_PropertyParm("k", "base64:" ++ EncryptionKey); +cre_PropertyParm_k(uri, EncryptionKey) when is_list(EncryptionKey) -> + cre_PropertyParm("k", "uri:" ++ EncryptionKey); +cre_PropertyParm_k(Method, EncryptionKey) + when is_list(Method) and is_list(EncryptionKey) -> + cre_PropertyParm("k", Method ++ ":" ++ EncryptionKey). + +cre_sdp_k(M) -> + #megaco_sdp_k{method = M}. +cre_sdp_k(M, EK) -> + #megaco_sdp_k{method = M, encryption_key = EK}. + +cre_PropertyParm_z([H | _] = LOA) when is_record(H, megaco_sdp_z_adjustement) -> + F = fun(#megaco_sdp_z_adjustement{time = T, offset = O}, Str) -> + Str ++ " " ++ T ++ " " ++ O + end, + cre_PropertyParm("z", lists:foldl(F, [], LOA)). + +cre_sdp_z(LOA) -> + #megaco_sdp_z{list_of_adjustments = LOA}. + +cre_PropertyParm_r(Repeat, Duration, ListOfOffsets) + when is_list(Repeat) and is_list(Duration) and is_list(ListOfOffsets) -> + F = fun(Elem, Str) -> Str ++ " " ++ Elem end, + Val = Repeat ++ " " ++ Duration ++ lists:foldl(F, [], ListOfOffsets), + cre_PropertyParm("r", Val). + +cre_sdp_r(Repeat, Duration, ListOfOffsets) -> + #megaco_sdp_r{repeat_interval = Repeat, + active_duration = Duration, + list_of_offsets = ListOfOffsets}. + +cre_PropertyParm_t(Start, Stop) + when is_list(Start) and is_list(Stop) -> + cre_PropertyParm("t", Start ++ " " ++ Stop); +cre_PropertyParm_t(Start, Stop) -> + cre_PropertyParm_t(i2s(Start), i2s(Stop)). + +cre_sdp_t(Start, Stop) -> + #megaco_sdp_t{start = Start, stop = Stop}. + +cre_PropertyParm_b(BwType, Bandwidth) + when is_list(BwType) and is_integer(Bandwidth) -> + cre_PropertyParm_b(BwType, i2s(Bandwidth)); +cre_PropertyParm_b(BwType, Bandwidth) + when is_list(BwType) and is_list(Bandwidth) -> + cre_PropertyParm("b", BwType ++ ":" ++ Bandwidth). + +cre_sdp_b(BWT, BW) -> + #megaco_sdp_b{bwtype = BWT, bandwidth = BW}. + + +cre_PropertyParm_cat(Cat) when is_list(Cat) -> + cre_PropertyParm_a("cat", Cat). + +cre_sdp_a_cat(C) -> + #megaco_sdp_a_cat{category = C}. + + +cre_PropertyParm_keywds(KeyWds) when is_list(KeyWds) -> + cre_PropertyParm_a("keywds", KeyWds). + +cre_sdp_a_keywds(KW) -> + #megaco_sdp_a_keywds{keywords = KW}. + + +cre_PropertyParm_tool(NameAndVersion) when is_list(NameAndVersion) -> + cre_PropertyParm_a("tool", NameAndVersion). + +cre_sdp_a_tool(NAV) -> + #megaco_sdp_a_tool{name_and_version = NAV}. + + +cre_PropertyParm_ptime(PacketTime) when is_integer(PacketTime) -> + cre_PropertyParm_ptime(i2s(PacketTime)); +cre_PropertyParm_ptime(PacketTime) when is_list(PacketTime) -> + cre_PropertyParm_a("ptime", PacketTime). + +cre_sdp_a_ptime(PT) -> + #megaco_sdp_a_ptime{packet_time = PT}. + + +cre_PropertyParm_maxptime(MaxPacketTime) when is_integer(MaxPacketTime) -> + cre_PropertyParm_maxptime(i2s(MaxPacketTime)); +cre_PropertyParm_maxptime(MaxPacketTime) when is_list(MaxPacketTime) -> + cre_PropertyParm_a("maxptime", MaxPacketTime). + +cre_sdp_a_maxptime(PT) -> + #megaco_sdp_a_maxptime{maximum_packet_time = PT}. + + +cre_PropertyParm_rtpmap(Payload, EncName, ClockRate) -> + cre_PropertyParm_rtpmap(Payload, EncName, ClockRate, []). + +cre_PropertyParm_rtpmap(Payload, EncName, ClockRate, EncPar) + when is_integer(Payload) and + is_list(EncName) and + is_integer(ClockRate) and + is_list(EncPar) -> + F = fun(Elem, Str) -> Str ++ "/" ++ Elem end, + Val = + integer_to_list(Payload) ++ " " ++ + EncName ++ "/" ++ integer_to_list(ClockRate) ++ + lists:foldl(F, [], EncPar), + cre_PropertyParm_a("rtpmap", Val). + +cre_sdp_a_rtpmap(Payload, EncName, ClockRate) -> + #megaco_sdp_a_rtpmap{payload_type = Payload, + encoding_name = EncName, + clock_rate = ClockRate}. +cre_sdp_a_rtpmap(Payload, EncName, ClockRate, EncParms) -> + #megaco_sdp_a_rtpmap{payload_type = Payload, + encoding_name = EncName, + clock_rate = ClockRate, + encoding_parms = EncParms}. + +cre_PropertyParm_orient(Orientation) when is_atom(Orientation) -> + cre_PropertyParm_orient(atom_to_list(Orientation)); +cre_PropertyParm_orient(Orientation) when is_list(Orientation) -> + cre_PropertyParm_a("orient", Orientation). + +cre_sdp_a_orient(O) -> + #megaco_sdp_a_orient{orientation = O}. + +cre_PropertyParm_type(CT) when is_list(CT) -> + cre_PropertyParm_a("type", CT). + +cre_sdp_a_type(CT) -> + #megaco_sdp_a_type{conf_type = CT}. + +cre_PropertyParm_charset(CS) when is_list(CS) -> + cre_PropertyParm_a("charset", CS). + +cre_sdp_a_charset(CS) -> + #megaco_sdp_a_charset{char_set = CS}. + +cre_PropertyParm_sdplang(L) when is_list(L) -> + cre_PropertyParm_a("sdplang", L). + +cre_sdp_a_sdplang(L) -> + #megaco_sdp_a_sdplang{tag = L}. + +cre_PropertyParm_lang(L) when is_list(L) -> + cre_PropertyParm_a("lang", L). + +cre_sdp_a_lang(L) -> + #megaco_sdp_a_lang{tag = L}. + +cre_PropertyParm_framerate(FR) when is_list(FR) -> + cre_PropertyParm_a("framerate", FR). + +cre_sdp_a_framerate(FR) -> + #megaco_sdp_a_framerate{frame_rate = FR}. + +cre_PropertyParm_quality(Quality) when is_integer(Quality) -> + cre_PropertyParm_quality(i2s(Quality)); +cre_PropertyParm_quality(Quality) when is_list(Quality) -> + cre_PropertyParm_a("quality", Quality). + +cre_sdp_a_quality(Qa) -> + #megaco_sdp_a_quality{quality = Qa}. + +cre_PropertyParm_a(Attr, AttrValue) + when is_list(Attr) and is_list(AttrValue) -> + cre_PropertyParm("a", Attr ++ ":" ++ AttrValue). + +cre_PropertyParm_a(Attr) when is_list(Attr) -> + cre_PropertyParm("a", Attr). + +cre_PropertyParm_a_fmtp(Format, Param) + when is_list(Format) and is_list(Param) -> + cre_PropertyParm_a("fmtp", Format ++ " " ++ Param). + +cre_sdp_a_fmtp(Fmt, Parm) -> + #megaco_sdp_a_fmtp{format = Fmt, param = Parm}. + +cre_sdp_a(Attr) -> + #megaco_sdp_a{attribute = Attr}. + +%% cre_sdp_a(Attr, Val) -> +%% #megaco_sdp_a{attribute = Attr, +%% value = Val}. + +cre_PropertyParm_o(User, SID, Version, AddrType, Addr) -> + cre_PropertyParm_o(User, SID, Version, in, AddrType, Addr). + +cre_PropertyParm_o(User, SID, Version, NetType, AddrType, Addr) + when is_list(User) and + is_integer(SID) and + is_integer(Version) and + is_list(NetType) or (NetType == in) and + is_list(AddrType) or ((AddrType == ip4) or (AddrType == ip6)) and + is_list(Addr) -> + NT = case NetType of + in -> "IN"; + _ -> NetType + end, + AT = case AddrType of + ip4 -> "IP4"; + ip6 -> "IP6"; + _ -> AddrType + end, + Val = + User ++ " " ++ + i2s(SID) ++ " " ++ + i2s(Version) ++ " " ++ + NT ++ " " ++ + AT ++ " " ++ + Addr, + cre_PropertyParm("o", Val). + +cre_sdp_o(Name, SID, V, AddrType, Addr) -> + cre_sdp_o(Name, SID, V, in, AddrType, Addr). +cre_sdp_o(Name, SID, V, NetType, AddrType, Addr) -> + #megaco_sdp_o{user_name = Name, + session_id = SID, + version = V, + network_type = NetType, + address_type = AddrType, + address = Addr}. + +cre_PropertyParm_m(Media, Port, Transport, FmtList) + when is_atom(Media) -> + cre_PropertyParm_m(atom_to_list(Media), + Port, Transport, FmtList); +cre_PropertyParm_m(Media, Port0, Transport, FmtList) + when is_list(Media) and is_list(Transport) and is_list(FmtList) -> + Port = i2s(Port0), + Val = + Media ++ " " ++ Port ++ " " ++ Transport ++ " " ++ val(FmtList), + cre_PropertyParm("m", Val). + +cre_PropertyParm_m(Media, Port, NumPorts, Transport, FmtList) + when is_atom(Media) -> + cre_PropertyParm_m(atom_to_list(Media), + Port, NumPorts, Transport, FmtList); +cre_PropertyParm_m(Media, Port0, NumPorts0, Transport, FmtList) + when is_list(Media) and is_list(Transport) and is_list(FmtList) -> + Port = i2s(Port0), + NumPorts = i2s(NumPorts0), + Val = + Media ++ " " ++ Port ++ "/" ++ NumPorts ++ " " ++ Transport ++ + " " ++ val(FmtList), + cre_PropertyParm("m", Val). + +cre_sdp_m(Media, Port, Transport, FmtList) -> + #megaco_sdp_m{media = Media, + port = Port, + transport = Transport, + fmt_list = FmtList}. + +cre_sdp_m(Media, Port, NumPorts, Transport, FmtList) -> + #megaco_sdp_m{media = Media, + port = Port, + num_ports = NumPorts, + transport = Transport, + fmt_list = FmtList}. + + +cre_PropertyParm_c(ip4, ConnAddr) -> + cre_PropertyParm_c("IP4", ConnAddr); +cre_PropertyParm_c(ip6, ConnAddr) -> + cre_PropertyParm_c("IP6", ConnAddr); +cre_PropertyParm_c(AddrType, ConnAddr) + when is_list(AddrType) and is_list(ConnAddr) -> + Val = "IN " ++ AddrType ++ " " ++ ConnAddr, + cre_PropertyParm("c", Val). + +cre_PropertyParm_c(ip4, Base, TTL) -> + cre_PropertyParm_c("IP4", Base, i2s(TTL)); +cre_PropertyParm_c(AddrType, Base, TTL) + when is_list(AddrType) and + is_list(Base) and + is_list(TTL) -> + Val = "IN " ++ AddrType ++ " " ++ Base ++ "/" ++ TTL, + cre_PropertyParm("c", Val). + +cre_PropertyParm_c(ip4, Base, TTL, NumOf) -> + cre_PropertyParm_c("IP4", Base, i2s(TTL), i2s(NumOf)); +cre_PropertyParm_c(AddrType, Base, TTL, NumOf) + when is_list(AddrType) and + is_list(Base) and + is_list(TTL) and + is_list(NumOf) -> + Val = + "IN " ++ AddrType ++ " " ++ Base ++ "/" ++ TTL ++ "/" ++ NumOf, + cre_PropertyParm("c", Val). + + +cre_sdp_c(AddrType, ConnAddr) -> + cre_sdp_c(in, AddrType, ConnAddr). + +cre_sdp_c(NetType, AddrType, ConnAddr) -> + #megaco_sdp_c{network_type = NetType, + address_type = AddrType, + connection_addr = ConnAddr}. + + +cre_PropertyParm_v(Version) when is_integer(Version) -> + cre_PropertyParm_v(integer_to_list(Version)); +cre_PropertyParm_v(Version) when is_list(Version) -> + cre_PropertyParm("v", Version). + +cre_sdp_v(Version) -> + #megaco_sdp_v{version = Version}. + + +cre_PropertyParm(Name, Val) when is_list(Name) and is_list(Val) -> + #'PropertyParm'{name = Name, value = [Val]}. + + +val(Vals) -> + val(Vals, " "). +val([Head|Tail], Sep) -> + lists:foldl(fun(E, S) -> S ++ Sep ++ E end, Head, Tail). + +i2s(I) when is_integer(I) -> + integer_to_list(I); +i2s(S) when is_list(S) -> + S. + + +%% error(Reason) -> +%% throw({error, Reason}). diff --git a/lib/megaco/test/megaco_segment_test.erl b/lib/megaco/test/megaco_segment_test.erl new file mode 100644 index 0000000000..ef07ee54b1 --- /dev/null +++ b/lib/megaco/test/megaco_segment_test.erl @@ -0,0 +1,7819 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Test the segment package introduced in v3 of the megaco std. +%%---------------------------------------------------------------------- +-module(megaco_segment_test). + +-export([t/0, t/1]). +-export([init_per_testcase/2, fin_per_testcase/2]). +-export([all/1, + + send/1, + send_segmented_msg_plain1/1, + send_segmented_msg_plain2/1, + send_segmented_msg_plain3/1, + send_segmented_msg_plain4/1, + send_segmented_msg_ooo1/1, + send_segmented_msg_missing_seg_reply1/1, + send_segmented_msg_missing_seg_reply2/1, + + recv/1, + recv_segmented_msg_plain/1, + recv_segmented_msg_ooo_seg/1, + recv_segmented_msg_missing_seg1/1, + recv_segmented_msg_missing_seg2/1, + + tickets/1 + + ]). + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v3.hrl"). + +-define(TEST_VERBOSITY, debug). + +-define(VERSION, 3). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + + +%% Test server callbacks +init_per_testcase(Case, Config) -> + process_flag(trap_exit, true), + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + process_flag(trap_exit, false), + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all(suite) -> + [ + send, + recv + + %% Tickets last + %% tickets + ]. + +send(suite) -> + [ + send_segmented_msg_plain1, + send_segmented_msg_plain2, + send_segmented_msg_plain3, + send_segmented_msg_plain4, + send_segmented_msg_ooo1, + send_segmented_msg_missing_seg_reply1, + send_segmented_msg_missing_seg_reply2 + ]. + +recv(suite) -> + [ + recv_segmented_msg_plain, + recv_segmented_msg_ooo_seg, + recv_segmented_msg_missing_seg1, + recv_segmented_msg_missing_seg2 + ]. + +tickets(suite) -> + [ + ]. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% %%% +%%% Segmented reply send test cases %%% +%%% %%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +send_segmented_msg_plain1(suite) -> + []; +send_segmented_msg_plain1(doc) -> + "First plain test that it is possible to send segmented messages. " + "Send window = infinity. "; +send_segmented_msg_plain1(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, ssmp1), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = ssmp1_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = ssmp1_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + + +%% +%% MGC generator stuff +%% + +ssmp1_mgc_event_sequence(text, tcp) -> + DecodeFun = ssmp1_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ssmp1_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mgc"}, + ScrVerifyFun = ssmp1_mgc_verify_service_change_req_msg_fun(), + ServiceChangeRep = ssmp1_mgc_service_change_reply_msg(Mid, 1), + TermId1 = + #megaco_term_id{id = ["00000000","00000000","00000001"]}, + CtxId1 = 1, + TermId2 = + #megaco_term_id{id = ["00000000","00000000","00000002"]}, + CtxId2 = 2, + TransId = 2, + NotifyReq = ssmp1_mgc_notify_request_msg(Mid, TransId, + TermId1, CtxId1, + TermId2, CtxId2), + NrVerifyFun1 = + ssmp1_mgc_verify_notify_reply_segment_msg_fun(1, false, TransId, + TermId1, CtxId1), + NrVerifyFun2 = + ssmp1_mgc_verify_notify_reply_segment_msg_fun(2, true, TransId, + TermId2, CtxId2), + SegmentRep1 = ssmp1_mgc_segment_reply_msg(Mid, TransId, 1, false), + SegmentRep2 = ssmp1_mgc_segment_reply_msg(Mid, TransId, 2, true), + TransAck = ssmp1_mgc_trans_ack_msg(Mid, TransId), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-request", {ScrVerifyFun, 5000}}, + {send, "service-change-reply", ServiceChangeRep}, + {expect_nothing, timer:seconds(1)}, + {send, "notify request", NotifyReq}, + {expect_receive, "notify reply: segment 1", {NrVerifyFun1, 2000}}, + {expect_receive, "notify reply: segment 2", {NrVerifyFun2, 1000}}, + {send, "segment reply 1", SegmentRep1}, + {sleep, 100}, + {send, "segment reply 2", SegmentRep2}, + {sleep, 100}, % {expect_nothing, 500}, + {send, "transaction-ack", TransAck}, + {expect_closed, timer:seconds(5)}, + disconnect + ], + EvSeq. + +ssmp1_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:encode_message(Conf, M) + end. + +ssmp1_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:decode_message(Conf, M) + end. + +ssmp1_mgc_verify_service_change_req_msg_fun() -> + fun(Msg) -> + (catch ssmp1_mgc_verify_service_change_req(Msg)) + end. + +ssmp1_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) -> + io:format("ssmp1_mgc_verify_service_change_req -> entry with" + "~n M: ~p" + "~n", [M]), + Body = + case Mess of + #'Message'{version = 1, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = _TransId, + actions = [ActionReq]} -> + ActionReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + CR = + case AR of + #'ActionRequest'{contextId = _Cid, + commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_action, AR}}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + throw({error, {invalid_terminationID, Tid}}) + end, + case Parms of + %% Version 1 'ServiceChangeParm' + {'ServiceChangeParm', + restart, % serviceChangeMethod + asn1_NOVALUE, % serviceChangeAddress + ?VERSION, % serviceChangeVersion, + {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile + [[$9,$0,$1|_]], % serviceChangeReason + asn1_NOVALUE, % serviceChangeDelay + asn1_NOVALUE, % serviceChangeMgcId + asn1_NOVALUE, % timeStamp + asn1_NOVALUE % nonStandardData + } -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeParms, Parms}} + end. + +ssmp1_mgc_verify_notify_reply_segment_msg_fun(SN, Last, + TransId, TermId, Cid) -> + fun(Msg) -> + (catch ssmp1_mgc_verify_notify_reply_segment(Msg, + SN, Last, + TransId, TermId, Cid)) + end. + +ssmp1_mgc_verify_notify_reply_segment(#'MegacoMessage'{mess = Mess} = M, + SN, Last, TransId, TermId, Cid) -> + io:format("ssmp1_mgc_verify_notify_reply_segment -> entry with" + "~n M: ~p" + "~n SN: ~p" + "~n Last: ~p" + "~n TransId: ~p" + "~n TermId: ~p" + "~n Cid: ~p" + "~n", [M, SN, Last, TransId, TermId, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = TransId, + transactionResult = TransRes, + segmentNumber = SN, + segmentationComplete = asn1_NOVALUE} when (Last == false) -> + TransRes; + #'TransactionReply'{transactionId = TransId, + transactionResult = TransRes, + segmentNumber = SN, + segmentationComplete = 'NULL'} when (Last == true) -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActionReply]} -> + ActionReply; + {actionReplies, ActionReplies} -> + throw({error, {invalid_actionReplies, ActionReplies}}); + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = Cid, + commandReply = [CommandReply]} -> + CommandReply; + #'ActionReply'{contextId = Cid, + commandReply = CommandReplies} -> + throw({error, {invalid_commandReplies, CommandReplies}}); + _ -> + throw({error, {invalid_actionReply, AR}}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + case NR of + #'NotifyReply'{terminationID = [TermId], + errorDescriptor = asn1_NOVALUE} -> + {ok, M}; + _ -> + {error, {invalid_NotifyReply, NR}} + end; +ssmp1_mgc_verify_notify_reply_segment(Crap, + _SN, _Last, _TransId, _TermId, _Cid) -> + {error, {invalid_MegacoMessage, Crap}}. + + +ssmp1_mgc_service_change_reply_msg(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + TRes = cre_transResult([AR]), + TR = {'TransactionReply', 1, asn1_NOVALUE, TRes}, + Trans = cre_transaction(TR), + Mess = cre_message(1, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmp1_mgc_notify_request_msg(Mid, TransId, TermId1, Cid1, TermId2, Cid2) -> + AR1 = ssmp1_mgc_notify_request_ar(1, TermId1, Cid1), + AR2 = ssmp1_mgc_notify_request_ar(2, TermId2, Cid2), + TR = cre_transReq(TransId, [AR1, AR2]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmp1_mgc_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation(integer_to_list(19990720+Rid), + integer_to_list(22000000+Rid)), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +ssmp1_mgc_segment_reply_msg(Mid, TransId, SN, Last) -> + SR = ssmp1_mgc_segment_reply(TransId, SN, Last), + Trans = cre_transaction(SR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmp1_mgc_segment_reply(TransId, SN, true) -> + cre_segReply(TransId, SN, 'NULL'); +ssmp1_mgc_segment_reply(TransId, SN, false) -> + cre_segReply(TransId, SN, asn1_NOVALUE). + +ssmp1_mgc_trans_ack_msg(Mid, TransId) -> + TA = cre_transAck(TransId), + Trans = cre_transaction([TA]), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +ssmp1_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ssmp1_mg_verify_handle_connect_fun(), + ServiceChangeReq = ssmp1_mg_service_change_request_ar(Mid, 1), + ServiceChangeReplyVerify = ssmp1_mg_verify_service_change_reply_fun(), + Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]}, + Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]}, + NotifyReqVerify = ssmp1_mg_verify_notify_request_fun(Tid1, Tid2), + AckVerify = ssmp1_mg_verify_ack_fun(), + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + %% {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {megaco_update_conn_info, protocol_version, ?VERSION}, + {megaco_update_conn_info, segment_send, infinity}, + {megaco_update_conn_info, max_pdu_size, 128}, + {sleep, 1000}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, AckVerify, 5000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +ssmp1_mg_verify_handle_connect_fun() -> + fun(Ev) -> ssmp1_mg_verify_handle_connect(Ev) end. + +ssmp1_mg_verify_handle_connect({handle_connect, CH, 1}) -> + io:format("ssmp1_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +ssmp1_mg_verify_handle_connect(Else) -> + io:format("ssmp1_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +ssmp1_mg_verify_service_change_reply_fun() -> + fun(Rep) -> ssmp1_mg_verify_scr(Rep) end. + +ssmp1_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) -> + (catch ssmp1_mg_do_verify_scr(AR)); +ssmp1_mg_verify_scr(Crap) -> + io:format("ssmp1_mg_verify_scr -> error: " + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + +ssmp1_mg_do_verify_scr(AR) -> + io:format("ssmp1_mg_do_verify_scr -> ok: " + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +ssmp1_mg_verify_notify_request_fun(Tid1, Tid2) -> + fun(Req) -> + ssmp1_mg_verify_notify_request(Req, Tid1, Tid2) + end. + +ssmp1_mg_verify_notify_request( + {handle_trans_request, _CH, ?VERSION, [AR1, AR2]}, Tid1, Tid2) -> + (catch ssmp1_mg_do_verify_notify_request(Tid1, Tid2, AR1, AR2)); +ssmp1_mg_verify_notify_request( + {handle_trans_request, _CH, ?VERSION, ARs}, _Tid1, _Tid2) -> + {error, {invalid_action_requests, ARs}, ok}; +ssmp1_mg_verify_notify_request( + {handle_trans_request, CH, V, ARs}, _Tid1, _Tid2) -> + {error, {invalid_trans_request, {CH, V, ARs}}, ok}; +ssmp1_mg_verify_notify_request(Crap, _Tid1, _Tid2) -> + io:format("ssmp1_mg_verify_notify_request -> unknown request" + "~n Tid1: ~p" + "~n Tid2: ~p" + "~n Crap: ~p" + "~n", [_Tid1, _Tid2, Crap]), + {error, {unexpected_event, Crap}, ok}. + +ssmp1_mg_do_verify_notify_request(Tid1, Tid2, AR1, AR2) -> + io:format("ssmp1_mg_do_verify_notify_request -> ok" + "~n Tid1: ~p" + "~n Tid2: ~p" + "~n AR1: ~p" + "~n AR2: ~p" + "~n", [Tid1, Tid2, AR1, AR2]), + ActionReply1 = ssmp1_mg_do_verify_notify_request(Tid1, AR1), + ActionReply2 = ssmp1_mg_do_verify_notify_request(Tid2, AR2), + Reply = {{handle_ack, ssmp1}, [ActionReply1, ActionReply2]}, + {ok, [AR1, AR2], Reply}. + +ssmp1_mg_do_verify_notify_request(Tid, AR) -> + io:format("ssmp1_mg_do_verify_notify_request -> ok" + "~n Tid: ~p" + "~n AR: ~p" + "~n", [Tid, AR]), + {Cid, CR} = + case AR of + #'ActionRequest'{contextId = CtxId, + commandRequests = [CmdReq]} -> + {CtxId, CmdReq}; + _ -> + Reason1 = {invalid_actionRequest, AR}, + throw({error, Reason1, ok}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}, ok}) + end, + OED = + case Cmd of + {notifyReq, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = ObsEvDesc, + errorDescriptor = asn1_NOVALUE}} -> + ObsEvDesc; + _ -> + throw({error, {invalid_command, Cmd}, ok}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEv]} -> + ObsEv; + #'ObservedEventsDescriptor'{observedEventLst = ObsEvLst} -> + throw({error, {invalid_observedEventLst, ObsEvLst}, ok}); + _ -> + throw({error, {invalid_ObservedEventsDescriptor, OED}, ok}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + ssmp1_mg_notify_reply_ar(Cid, Tid); + _ -> + throw({error, {invalid_ObservedEvent, OE}, ok}) + end. + + +ssmp1_mg_verify_ack_fun() -> + fun(Event) -> ssmp1_mg_verify_ack(Event) end. + +ssmp1_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, ssmp1}) -> + io:format("ssmp1_mg_verify_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +ssmp1_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, CrapAckData}) -> + io:format("ssmp1_mg_verify_ack -> error" + "~n CrapAckData: ~p" + "~n CH: ~p" + "~n", [CrapAckData, CH]), + {error, {unknown_ack_data, CrapAckData, CH}, ok}; +ssmp1_mg_verify_ack({handle_trans_ack, CH, ?VERSION, + BadAckStatus, BadAckData}) -> + io:format("ssmp1_mg_verify_ack -> error" + "~n BadAckStatus: ~p" + "~n BadAckData: ~p" + "~n CH: ~p" + "~n", [BadAckStatus, BadAckData, CH]), + {error, {unknown_ack_status, BadAckStatus, BadAckData, CH}, ok}; +ssmp1_mg_verify_ack(BadEvent) -> + {error, {unknown_event, BadEvent}, ok}. + + +ssmp1_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +ssmp1_mg_notify_reply_ar(Cid, Tid) -> + NR = cre_notifyReply([Tid]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +send_segmented_msg_plain2(suite) -> + []; +send_segmented_msg_plain2(doc) -> + "Second plain test that it is possible to send segmented messages. " + "Send window = infinity. "; +send_segmented_msg_plain2(Config) when is_list(Config) -> + %% <CONDITIONAL-SKIP> + Skippable = [{unix, [linux]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, ssmp2), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = ssmp2_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = ssmp2_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + + +%% +%% MGC generator stuff +%% + +ssmp2_mgc_event_sequence(text, tcp) -> + DecodeFun = ssmp2_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ssmp2_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mgc"}, + ScrVerifyFun = ssmp2_mgc_verify_service_change_req_msg_fun(), + ServiceChangeRep = ssmp2_mgc_service_change_reply_msg(Mid, 1), + TermId1 = + #megaco_term_id{id = ["00000000","00000000","00000001"]}, + CtxId1 = 1, + TermId2 = + #megaco_term_id{id = ["00000000","00000000","00000002"]}, + CtxId2 = 2, + TransId = 2, + NotifyReq = ssmp2_mgc_notify_request_msg(Mid, TransId, + TermId1, CtxId1, + TermId2, CtxId2), + NrVerifyFun1 = + ssmp2_mgc_verify_notify_reply_segment_msg_fun(1, false, TransId, + TermId1, CtxId1), + NrVerifyFun2 = + ssmp2_mgc_verify_notify_reply_segment_msg_fun(2, true, TransId, + TermId2, CtxId2), + SegmentRep1 = ssmp2_mgc_segment_reply_msg(Mid, TransId, 1, false), + SegmentRep2 = ssmp2_mgc_segment_reply_msg(Mid, TransId, 2, true), + TransAck = ssmp2_mgc_trans_ack_msg(Mid, TransId), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-request", {ScrVerifyFun, 5000}}, + {send, "service-change-reply", ServiceChangeRep}, + {expect_nothing, timer:seconds(1)}, + {send, "notify request", NotifyReq}, + {expect_receive, "notify reply: segment 1", {NrVerifyFun1, 2000}}, + {send, "segment reply 1", SegmentRep1}, + {expect_receive, "notify reply: segment 2", {NrVerifyFun2, 1000}}, + {send, "segment reply 2", SegmentRep2}, + {sleep, 100}, % {expect_nothing, 500}, + {send, "transaction-ack", TransAck}, + {expect_closed, timer:seconds(5)}, + disconnect + ], + EvSeq. + +ssmp2_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:encode_message(Conf, M) + end. + +ssmp2_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:decode_message(Conf, M) + end. + +ssmp2_mgc_verify_service_change_req_msg_fun() -> + fun(Msg) -> + (catch ssmp2_mgc_verify_service_change_req(Msg)) + end. + +ssmp2_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) -> + io:format("ssmp2_mgc_verify_service_change_req -> entry with" + "~n M: ~p" + "~n", [M]), + Body = + case Mess of + #'Message'{version = 1, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = _TransId, + actions = [ActionReq]} -> + ActionReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + CR = + case AR of + #'ActionRequest'{contextId = _Cid, + commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_action, AR}}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + throw({error, {invalid_terminationID, Tid}}) + end, + case Parms of + %% Version 1 'ServiceChangeParm' + {'ServiceChangeParm', + restart, % serviceChangeMethod + asn1_NOVALUE, % serviceChangeAddress + ?VERSION, % serviceChangeVersion, + {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile + [[$9,$0,$1|_]], % serviceChangeReason + asn1_NOVALUE, % serviceChangeDelay + asn1_NOVALUE, % serviceChangeMgcId + asn1_NOVALUE, % timeStamp + asn1_NOVALUE % nonStandardData + } -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeParms, Parms}} + end. + +ssmp2_mgc_verify_notify_reply_segment_msg_fun(SN, Last, + TransId, TermId, Cid) -> + fun(Msg) -> + (catch ssmp2_mgc_verify_notify_reply_segment(Msg, + SN, Last, + TransId, TermId, Cid)) + end. + +ssmp2_mgc_verify_notify_reply_segment(#'MegacoMessage'{mess = Mess} = M, + SN, Last, TransId, TermId, Cid) -> + io:format("ssmp2_mgc_verify_notify_reply_segment -> entry with" + "~n M: ~p" + "~n SN: ~p" + "~n Last: ~p" + "~n TransId: ~p" + "~n TermId: ~p" + "~n Cid: ~p" + "~n", [M, SN, Last, TransId, TermId, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = TransId, + transactionResult = TransRes, + segmentNumber = SN, + segmentationComplete = asn1_NOVALUE} when (Last == false) -> + TransRes; + #'TransactionReply'{transactionId = TransId, + transactionResult = TransRes, + segmentNumber = SN, + segmentationComplete = 'NULL'} when (Last == true) -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActionReply]} -> + ActionReply; + {actionReplies, ActionReplies} -> + throw({error, {invalid_actionReplies, ActionReplies}}); + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = Cid, + commandReply = [CommandReply]} -> + CommandReply; + #'ActionReply'{contextId = Cid, + commandReply = CommandReplies} -> + throw({error, {invalid_commandReplies, CommandReplies}}); + _ -> + throw({error, {invalid_actionReply, AR}}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + case NR of + #'NotifyReply'{terminationID = [TermId], + errorDescriptor = asn1_NOVALUE} -> + {ok, M}; + _ -> + {error, {invalid_NotifyReply, NR}} + end; +ssmp2_mgc_verify_notify_reply_segment(Crap, + _SN, _Last, _TransId, _TermId, _Cid) -> + {error, {invalid_MegacoMessage, Crap}}. + + +ssmp2_mgc_service_change_reply_msg(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + TRes = cre_transResult([AR]), + TR = {'TransactionReply', 1, asn1_NOVALUE, TRes}, + Trans = cre_transaction(TR), + Mess = cre_message(1, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmp2_mgc_notify_request_msg(Mid, TransId, TermId1, Cid1, TermId2, Cid2) -> + AR1 = ssmp2_mgc_notify_request_ar(1, TermId1, Cid1), + AR2 = ssmp2_mgc_notify_request_ar(2, TermId2, Cid2), + TR = cre_transReq(TransId, [AR1, AR2]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmp2_mgc_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation(integer_to_list(19990720+Rid), + integer_to_list(22000000+Rid)), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +ssmp2_mgc_segment_reply_msg(Mid, TransId, SN, Last) -> + SR = ssmp2_mgc_segment_reply(TransId, SN, Last), + Trans = cre_transaction(SR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmp2_mgc_segment_reply(TransId, SN, true) -> + cre_segReply(TransId, SN, 'NULL'); +ssmp2_mgc_segment_reply(TransId, SN, false) -> + cre_segReply(TransId, SN, asn1_NOVALUE). + +ssmp2_mgc_trans_ack_msg(Mid, TransId) -> + TA = cre_transAck(TransId), + Trans = cre_transaction([TA]), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +ssmp2_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ssmp2_mg_verify_handle_connect_fun(), + ServiceChangeReq = ssmp2_mg_service_change_request_ar(Mid, 1), + ServiceChangeReplyVerify = ssmp2_mg_verify_service_change_reply_fun(), + Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]}, + Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]}, + NotifyReqVerify = ssmp2_mg_verify_notify_request_fun(Tid1, Tid2), + AckVerify = ssmp2_mg_verify_ack_fun(), + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + %% {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {megaco_update_conn_info, protocol_version, ?VERSION}, + {megaco_update_conn_info, segment_send, infinity}, + {megaco_update_conn_info, max_pdu_size, 128}, + {sleep, 1000}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, AckVerify, 5000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +ssmp2_mg_verify_handle_connect_fun() -> + fun(Ev) -> ssmp2_mg_verify_handle_connect(Ev) end. + +ssmp2_mg_verify_handle_connect({handle_connect, CH, 1}) -> + io:format("ssmp2_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +ssmp2_mg_verify_handle_connect(Else) -> + io:format("ssmp2_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +ssmp2_mg_verify_service_change_reply_fun() -> + fun(Rep) -> ssmp2_mg_verify_scr(Rep) end. + +ssmp2_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) -> + (catch ssmp2_mg_do_verify_scr(AR)); +ssmp2_mg_verify_scr(Crap) -> + io:format("ssmp2_mg_verify_scr -> error: " + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + +ssmp2_mg_do_verify_scr(AR) -> + io:format("ssmp2_mg_do_verify_scr -> ok: " + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +ssmp2_mg_verify_notify_request_fun(Tid1, Tid2) -> + fun(Req) -> ssmp2_mg_verify_notify_request(Req, Tid1, Tid2) end. + +ssmp2_mg_verify_notify_request( + {handle_trans_request, _CH, ?VERSION, [AR1, AR2]}, Tid1, Tid2) -> + (catch ssmp2_mg_do_verify_notify_request(Tid1, Tid2, AR1, AR2)); +ssmp2_mg_verify_notify_request( + {handle_trans_request, _CH, ?VERSION, ARs}, _Tid1, _Tid2) -> + {error, {invalid_action_requests, ARs}, ok}; +ssmp2_mg_verify_notify_request( + {handle_trans_request, CH, V, ARs}, _Tid1, _Tid2) -> + {error, {invalid_trans_request, {CH, V, ARs}}, ok}; +ssmp2_mg_verify_notify_request(Crap, _Tid1, _Tid2) -> + io:format("ssmp2_mg_verify_notify_request -> unknown request" + "~n Tid1: ~p" + "~n Tid2: ~p" + "~n Crap: ~p" + "~n", [_Tid1, _Tid2, Crap]), + {error, {unexpected_event, Crap}, ok}. + +ssmp2_mg_do_verify_notify_request(Tid1, Tid2, AR1, AR2) -> + io:format("ssmp2_mg_do_verify_notify_request -> ok" + "~n Tid1: ~p" + "~n Tid2: ~p" + "~n AR1: ~p" + "~n AR2: ~p" + "~n", [Tid1, Tid2, AR1, AR2]), + ActionReply1 = ssmp2_mg_do_verify_notify_request(Tid1, AR1), + ActionReply2 = ssmp2_mg_do_verify_notify_request(Tid2, AR2), + Reply = {{handle_ack, ssmp2}, [ActionReply1, ActionReply2]}, + {ok, [AR1, AR2], Reply}. + +ssmp2_mg_do_verify_notify_request(Tid, AR) -> + io:format("ssmp2_mg_do_verify_notify_request -> ok" + "~n Tid: ~p" + "~n AR: ~p" + "~n", [Tid, AR]), + {Cid, CR} = + case AR of + #'ActionRequest'{contextId = CtxId, + commandRequests = [CmdReq]} -> + {CtxId, CmdReq}; + _ -> + Reason1 = {invalid_actionRequest, AR}, + throw({error, Reason1, ok}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}, ok}) + end, + OED = + case Cmd of + {notifyReq, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = ObsEvDesc, + errorDescriptor = asn1_NOVALUE}} -> + ObsEvDesc; + _ -> + throw({error, {invalid_command, Cmd}, ok}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEv]} -> + ObsEv; + #'ObservedEventsDescriptor'{observedEventLst = ObsEvLst} -> + throw({error, {invalid_observedEventLst, ObsEvLst}, ok}); + _ -> + throw({error, {invalid_ObservedEventsDescriptor, OED}, ok}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + ssmp2_mg_notify_reply_ar(Cid, Tid); + _ -> + throw({error, {invalid_ObservedEvent, OE}, ok}) + end. + + +ssmp2_mg_verify_ack_fun() -> + fun(Event) -> ssmp2_mg_verify_ack(Event) end. + +ssmp2_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, ssmp2}) -> + io:format("ssmp2_mg_verify_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +ssmp2_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, CrapAckData}) -> + {error, {unknown_ack_data, CrapAckData, CH}, ok}; +ssmp2_mg_verify_ack({handle_trans_ack, CH, ?VERSION, + BadAckStatus, BadAckData}) -> + {error, {unknown_ack_status, BadAckStatus, BadAckData, CH}, ok}; +ssmp2_mg_verify_ack(BadEvent) -> + {error, {unknown_event, BadEvent}, ok}. + + +ssmp2_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +ssmp2_mg_notify_reply_ar(Cid, Tid) -> + NR = cre_notifyReply([Tid]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +send_segmented_msg_plain3(suite) -> + []; +send_segmented_msg_plain3(doc) -> + "Third plain test that it is possible to send segmented messages. " + "Send window = 1. "; +send_segmented_msg_plain3(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, ssmp3), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = ssmp3_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = ssmp3_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + + +%% +%% MGC generator stuff +%% + +ssmp3_mgc_event_sequence(text, tcp) -> + DecodeFun = ssmp3_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ssmp3_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mgc"}, + ScrVerifyFun = ssmp3_mgc_verify_service_change_req_msg_fun(), + ServiceChangeRep = ssmp3_mgc_service_change_reply_msg(Mid, 1), + TermId1 = + #megaco_term_id{id = ["00000000","00000000","00000001"]}, + CtxId1 = 1, + TermId2 = + #megaco_term_id{id = ["00000000","00000000","00000002"]}, + CtxId2 = 2, + TermId3 = + #megaco_term_id{id = ["00000000","00000000","00000003"]}, + CtxId3 = 3, + TermId4 = + #megaco_term_id{id = ["00000000","00000000","00000004"]}, + CtxId4 = 4, + TermId5 = + #megaco_term_id{id = ["00000000","00000000","00000005"]}, + CtxId5 = 5, + TermId6 = + #megaco_term_id{id = ["00000000","00000000","00000006"]}, + CtxId6 = 6, + TermId7 = + #megaco_term_id{id = ["00000000","00000000","00000007"]}, + CtxId7 = 7, + TermId8 = + #megaco_term_id{id = ["00000000","00000000","00000008"]}, + CtxId8 = 8, + TransId = 2, + TermIDs = [TermId1, TermId2, TermId3, TermId4, + TermId5, TermId6, TermId7, TermId8], + CIDs = [CtxId1, CtxId2, CtxId3, CtxId4, + CtxId5, CtxId6, CtxId7, CtxId8], + NotifyReq = ssmp3_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs), + NrVerifyFun1 = + ssmp3_mgc_verify_notify_reply_segment_msg_fun(1, false, TransId, + TermId1, CtxId1), + NrVerifyFun2 = + ssmp3_mgc_verify_notify_reply_segment_msg_fun(2, false, TransId, + TermId2, CtxId2), + NrVerifyFun3 = + ssmp3_mgc_verify_notify_reply_segment_msg_fun(3, false, TransId, + TermId3, CtxId3), + NrVerifyFun4 = + ssmp3_mgc_verify_notify_reply_segment_msg_fun(4, false, TransId, + TermId4, CtxId4), + NrVerifyFun5 = + ssmp3_mgc_verify_notify_reply_segment_msg_fun(5, false, TransId, + TermId5, CtxId5), + NrVerifyFun6 = + ssmp3_mgc_verify_notify_reply_segment_msg_fun(6, false, TransId, + TermId6, CtxId6), + NrVerifyFun7 = + ssmp3_mgc_verify_notify_reply_segment_msg_fun(7, false, TransId, + TermId7, CtxId7), + NrVerifyFun8 = + ssmp3_mgc_verify_notify_reply_segment_msg_fun(8, true, TransId, + TermId8, CtxId8), + SegmentRep1 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 1, false), + SegmentRep2 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 2, false), + SegmentRep3 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 3, false), + SegmentRep4 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 4, false), + SegmentRep5 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 5, false), + SegmentRep6 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 6, false), + SegmentRep7 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 7, false), + SegmentRep8 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 8, true), + TransAck = ssmp3_mgc_trans_ack_msg(Mid, TransId), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-request", {ScrVerifyFun, 5000}}, + {send, "service-change-reply", ServiceChangeRep}, + {expect_nothing, 1000}, + {send, "notify request", NotifyReq}, + {expect_receive, "notify reply: segment 1", {NrVerifyFun1, 1000}}, + {expect_nothing, 200}, + {send, "segment reply 1", SegmentRep1}, + + {expect_receive, "notify reply: segment 2", {NrVerifyFun2, 1000}}, + {expect_nothing, 200}, + {send, "segment reply 2", SegmentRep2}, + + {expect_receive, "notify reply: segment 3", {NrVerifyFun3, 1000}}, + {expect_nothing, 200}, + {send, "segment reply 3", SegmentRep3}, + + {expect_receive, "notify reply: segment 4", {NrVerifyFun4, 1000}}, + {expect_nothing, 200}, + {send, "segment reply 4", SegmentRep4}, + + {expect_receive, "notify reply: segment 5", {NrVerifyFun5, 1000}}, + {expect_nothing, 200}, + {send, "segment reply 5", SegmentRep5}, + + {expect_receive, "notify reply: segment 6", {NrVerifyFun6, 1000}}, + {expect_nothing, 200}, + {send, "segment reply 6", SegmentRep6}, + + {expect_receive, "notify reply: segment 7", {NrVerifyFun7, 1000}}, + {expect_nothing, 200}, + {send, "segment reply 7", SegmentRep7}, + + {expect_receive, "notify reply: segment 8", {NrVerifyFun8, 1000}}, + {expect_nothing, 200}, + {send, "segment reply 8", SegmentRep8}, + + {expect_nothing, 200}, + {send, "transaction-ack", TransAck}, + {expect_closed, 5000}, + disconnect + ], + EvSeq. + +ssmp3_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:encode_message(Conf, M) + end. + +ssmp3_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:decode_message(Conf, M) + end. + +ssmp3_mgc_verify_service_change_req_msg_fun() -> + fun(Msg) -> + (catch ssmp3_mgc_verify_service_change_req(Msg)) + end. + +ssmp3_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) -> + io:format("ssmp3_mgc_verify_service_change_req -> entry with" + "~n M: ~p" + "~n", [M]), + Body = + case Mess of + #'Message'{version = 1, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = _TransId, + actions = [ActionReq]} -> + ActionReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + CR = + case AR of + #'ActionRequest'{contextId = _Cid, + commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_action, AR}}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + throw({error, {invalid_terminationID, Tid}}) + end, + case Parms of + %% Version 1 'ServiceChangeParm' + {'ServiceChangeParm', + restart, % serviceChangeMethod + asn1_NOVALUE, % serviceChangeAddress + ?VERSION, % serviceChangeVersion, + {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile + [[$9,$0,$1|_]], % serviceChangeReason + asn1_NOVALUE, % serviceChangeDelay + asn1_NOVALUE, % serviceChangeMgcId + asn1_NOVALUE, % timeStamp + asn1_NOVALUE % nonStandardData + } -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeParms, Parms}} + end. + +ssmp3_mgc_verify_notify_reply_segment_msg_fun(SN, Last, + TransId, TermId, Cid) -> + fun(Msg) -> + (catch ssmp3_mgc_verify_notify_reply_segment(Msg, + SN, Last, + TransId, TermId, Cid)) + end. + +ssmp3_mgc_verify_notify_reply_segment(#'MegacoMessage'{mess = Mess} = M, + SN, Last, TransId, TermId, Cid) -> + io:format("ssmp3_mgc_verify_notify_reply_segment -> entry with" + "~n M: ~p" + "~n SN: ~p" + "~n Last: ~p" + "~n TransId: ~p" + "~n TermId: ~p" + "~n Cid: ~p" + "~n", [M, SN, Last, TransId, TermId, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = TransId, + transactionResult = TransRes, + segmentNumber = SN, + segmentationComplete = asn1_NOVALUE} when (Last == false) -> + TransRes; + #'TransactionReply'{transactionId = TransId, + transactionResult = TransRes, + segmentNumber = SN, + segmentationComplete = 'NULL'} when (Last == true) -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActionReply]} -> + ActionReply; + {actionReplies, ActionReplies} -> + throw({error, {invalid_actionReplies, ActionReplies}}); + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = Cid, + commandReply = [CommandReply]} -> + CommandReply; + #'ActionReply'{contextId = Cid, + commandReply = CommandReplies} -> + throw({error, {invalid_commandReplies, CommandReplies}}); + _ -> + throw({error, {invalid_actionReply, AR}}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + case NR of + #'NotifyReply'{terminationID = [TermId], + errorDescriptor = asn1_NOVALUE} -> + {ok, M}; + _ -> + {error, {invalid_NotifyReply, NR}} + end; +ssmp3_mgc_verify_notify_reply_segment(Crap, + _SN, _Last, _TransId, _TermId, _Cid) -> + {error, {invalid_MegacoMessage, Crap}}. + + +ssmp3_mgc_service_change_reply_msg(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + TRes = cre_transResult([AR]), + TR = {'TransactionReply', 1, asn1_NOVALUE, TRes}, + Trans = cre_transaction(TR), + Mess = cre_message(1, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmp3_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs) -> + ARs = ssmp3_mgc_notify_request_ars(TermIDs, CIDs), + TR = cre_transReq(TransId, ARs), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmp3_mgc_notify_request_ars(TermIDs, CIDs) -> + ssmp3_mgc_notify_request_ars(TermIDs, CIDs, []). + +ssmp3_mgc_notify_request_ars([], [], Acc) -> + lists:reverse(Acc); +ssmp3_mgc_notify_request_ars([TermID|TermIDs], [CID|CIDs], Acc) -> + AR = ssmp3_mgc_notify_request_ar(100+CID, TermID, CID), + ssmp3_mgc_notify_request_ars(TermIDs, CIDs, [AR|Acc]). + +ssmp3_mgc_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation(integer_to_list(19990720+Rid), + integer_to_list(22000000+Rid)), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +ssmp3_mgc_segment_reply_msg(Mid, TransId, SN, Last) -> + SR = ssmp3_mgc_segment_reply(TransId, SN, Last), + Trans = cre_transaction(SR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmp3_mgc_segment_reply(TransId, SN, true) -> + cre_segReply(TransId, SN, 'NULL'); +ssmp3_mgc_segment_reply(TransId, SN, false) -> + cre_segReply(TransId, SN, asn1_NOVALUE). + +ssmp3_mgc_trans_ack_msg(Mid, TransId) -> + TA = cre_transAck(TransId), + Trans = cre_transaction([TA]), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +ssmp3_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ssmp3_mg_verify_handle_connect_fun(), + ServiceChangeReq = ssmp3_mg_service_change_request_ar(Mid, 1), + ServiceChangeReplyVerify = ssmp3_mg_verify_service_change_reply_fun(), + Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]}, + Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]}, + Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]}, + Tid4 = #megaco_term_id{id = ["00000000","00000000","00000004"]}, + Tid5 = #megaco_term_id{id = ["00000000","00000000","00000005"]}, + Tid6 = #megaco_term_id{id = ["00000000","00000000","00000006"]}, + Tid7 = #megaco_term_id{id = ["00000000","00000000","00000007"]}, + Tid8 = #megaco_term_id{id = ["00000000","00000000","00000008"]}, + Tids = [Tid1, Tid2, Tid3, Tid4, Tid5, Tid6, Tid7, Tid8], + NotifyReqVerify = ssmp3_mg_verify_notify_request_fun(Tids), + AckVerify = ssmp3_mg_verify_ack_fun(), + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + %% {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {megaco_update_conn_info, protocol_version, ?VERSION}, + {megaco_update_conn_info, segment_send, 1}, + {megaco_update_conn_info, max_pdu_size, 128}, + {sleep, 500}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, AckVerify, 5000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +ssmp3_mg_verify_handle_connect_fun() -> + fun(Ev) -> ssmp3_mg_verify_handle_connect(Ev) end. + +ssmp3_mg_verify_handle_connect({handle_connect, CH, 1}) -> + io:format("ssmp3_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +ssmp3_mg_verify_handle_connect(Else) -> + io:format("ssmp3_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +ssmp3_mg_verify_service_change_reply_fun() -> + fun(Rep) -> ssmp3_mg_verify_scr(Rep) end. + +ssmp3_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) -> + (catch ssmp3_mg_do_verify_scr(AR)); +ssmp3_mg_verify_scr(Crap) -> + io:format("ssmp3_mg_verify_scr -> error: " + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + +ssmp3_mg_do_verify_scr(AR) -> + io:format("ssmp3_mg_do_verify_scr -> ok: " + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +ssmp3_mg_verify_notify_request_fun(Tids) -> + fun(Req) -> ssmp3_mg_verify_notify_request(Req, Tids) end. + +ssmp3_mg_verify_notify_request( + {handle_trans_request, _CH, ?VERSION, ARs}, Tids) + when length(ARs) == length(Tids) -> + (catch ssmp3_mg_do_verify_notify_request(Tids, ARs)); +ssmp3_mg_verify_notify_request( + {handle_trans_request, _CH, ?VERSION, ARs}, _Tids) -> + {error, {invalid_action_requests, ARs}, ok}; +ssmp3_mg_verify_notify_request( + {handle_trans_request, CH, V, ARs}, _Tids) -> + {error, {invalid_trans_request, {CH, V, ARs}}, ok}; +ssmp3_mg_verify_notify_request(Crap, _Tids) -> + io:format("ssmp3_mg_verify_notify_request -> unknown request" + "~n Crap: ~p" + "~n Tids: ~p" + "~n", [Crap, _Tids]), + {error, {unexpected_event, Crap}, ok}. + +ssmp3_mg_do_verify_notify_request(Tids, ARs) -> + io:format("ssmp3_mg_do_verify_notify_request -> ok" + "~n Tids: ~p" + "~n ARs: ~p" + "~n", [Tids, ARs]), + ActionReplies = ssmp3_mg_do_verify_notify_request_ars(Tids, ARs), + io:format("ssmp3_mg_do_verify_notify_request -> ok" + "~n ActionReplies: ~p" + "~n", [ActionReplies]), + Reply = {{handle_ack, ssmp3}, ActionReplies}, + {ok, ARs, Reply}. + +ssmp3_mg_do_verify_notify_request_ars(Tids, ARs) -> + ssmp3_mg_do_verify_notify_request_ars(Tids, ARs, []). + +ssmp3_mg_do_verify_notify_request_ars([], [], Acc) -> + lists:reverse(Acc); +ssmp3_mg_do_verify_notify_request_ars([Tid|Tids], [AR|ARs], Acc) -> + ActionReply = ssmp3_mg_do_verify_notify_request_ar(Tid, AR), + ssmp3_mg_do_verify_notify_request_ars(Tids, ARs, [ActionReply|Acc]). + +ssmp3_mg_do_verify_notify_request_ar(Tid, AR) -> + io:format("ssmp3_mg_do_verify_notify_request_ar -> ok" + "~n Tid: ~p" + "~n AR: ~p" + "~n", [Tid, AR]), + {Cid, CR} = + case AR of + #'ActionRequest'{contextId = CtxId, + commandRequests = [CmdReq]} -> + {CtxId, CmdReq}; + _ -> + Reason1 = {invalid_actionRequest, AR}, + throw({error, Reason1, ok}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}, ok}) + end, + OED = + case Cmd of + {notifyReq, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = ObsEvDesc, + errorDescriptor = asn1_NOVALUE}} -> + ObsEvDesc; + _ -> + throw({error, {invalid_command, Cmd}, ok}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEv]} -> + ObsEv; + #'ObservedEventsDescriptor'{observedEventLst = ObsEvLst} -> + throw({error, {invalid_observedEventLst, ObsEvLst}, ok}); + _ -> + throw({error, {invalid_ObservedEventsDescriptor, OED}, ok}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + ssmp3_mg_notify_reply_ar(Cid, Tid); + _ -> + throw({error, {invalid_ObservedEvent, OE}, ok}) + end. + + +ssmp3_mg_verify_ack_fun() -> + fun(Event) -> ssmp3_mg_verify_ack(Event) end. + +ssmp3_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, ssmp3}) -> + io:format("ssmp3_mg_verify_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +ssmp3_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, CrapAckData}) -> + {error, {unknown_ack_data, CrapAckData, CH}, ok}; +ssmp3_mg_verify_ack({handle_trans_ack, CH, ?VERSION, + BadAckStatus, BadAckData}) -> + {error, {unknown_ack_status, BadAckStatus, BadAckData, CH}, ok}; +ssmp3_mg_verify_ack(BadEvent) -> + {error, {unknown_event, BadEvent}, ok}. + + +ssmp3_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +ssmp3_mg_notify_reply_ar(Cid, Tid) -> + NR = cre_notifyReply([Tid]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +send_segmented_msg_plain4(suite) -> + []; +send_segmented_msg_plain4(doc) -> + "Forth plain test that it is possible to send segmented messages. " + "Send window = 3. "; +send_segmented_msg_plain4(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, ssmp4), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = ssmp4_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = ssmp4_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + + +%% +%% MGC generator stuff +%% + +ssmp4_mgc_event_sequence(text, tcp) -> + DecodeFun = ssmp4_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ssmp4_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mgc"}, + ScrVerifyFun = ssmp4_mgc_verify_service_change_req_msg_fun(), + ServiceChangeRep = ssmp4_mgc_service_change_reply_msg(Mid, 1), + TermId1 = + #megaco_term_id{id = ["00000000","00000000","00000001"]}, + CtxId1 = 1, + TermId2 = + #megaco_term_id{id = ["00000000","00000000","00000002"]}, + CtxId2 = 2, + TermId3 = + #megaco_term_id{id = ["00000000","00000000","00000003"]}, + CtxId3 = 3, + TermId4 = + #megaco_term_id{id = ["00000000","00000000","00000004"]}, + CtxId4 = 4, + TermId5 = + #megaco_term_id{id = ["00000000","00000000","00000005"]}, + CtxId5 = 5, + TermId6 = + #megaco_term_id{id = ["00000000","00000000","00000006"]}, + CtxId6 = 6, + TermId7 = + #megaco_term_id{id = ["00000000","00000000","00000007"]}, + CtxId7 = 7, + TermId8 = + #megaco_term_id{id = ["00000000","00000000","00000008"]}, + CtxId8 = 8, + TransId = 2, + TermIDs = [TermId1, TermId2, TermId3, TermId4, + TermId5, TermId6, TermId7, TermId8], + CIDs = [CtxId1, CtxId2, CtxId3, CtxId4, + CtxId5, CtxId6, CtxId7, CtxId8], + NotifyReq = ssmp4_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs), + NrVerifyFun1 = + ssmp4_mgc_verify_notify_reply_segment_msg_fun(1, false, TransId, + TermId1, CtxId1), + NrVerifyFun2 = + ssmp4_mgc_verify_notify_reply_segment_msg_fun(2, false, TransId, + TermId2, CtxId2), + NrVerifyFun3 = + ssmp4_mgc_verify_notify_reply_segment_msg_fun(3, false, TransId, + TermId3, CtxId3), + NrVerifyFun4 = + ssmp4_mgc_verify_notify_reply_segment_msg_fun(4, false, TransId, + TermId4, CtxId4), + NrVerifyFun5 = + ssmp4_mgc_verify_notify_reply_segment_msg_fun(5, false, TransId, + TermId5, CtxId5), + NrVerifyFun6 = + ssmp4_mgc_verify_notify_reply_segment_msg_fun(6, false, TransId, + TermId6, CtxId6), + NrVerifyFun7 = + ssmp4_mgc_verify_notify_reply_segment_msg_fun(7, false, TransId, + TermId7, CtxId7), + NrVerifyFun8 = + ssmp4_mgc_verify_notify_reply_segment_msg_fun(8, true, TransId, + TermId8, CtxId8), + SegmentRep1 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 1, false), + SegmentRep2 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 2, false), + SegmentRep3 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 3, false), + SegmentRep4 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 4, false), + SegmentRep5 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 5, false), + SegmentRep6 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 6, false), + SegmentRep7 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 7, false), + SegmentRep8 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 8, true), + TransAck = ssmp4_mgc_trans_ack_msg(Mid, TransId), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-request", {ScrVerifyFun, 5000}}, + {send, "service-change-reply", ServiceChangeRep}, + {expect_nothing, 1000}, + {send, "notify request", NotifyReq}, + {expect_receive, "notify reply: segment 1", {NrVerifyFun1, 1000}}, + {expect_receive, "notify reply: segment 2", {NrVerifyFun2, 1000}}, + {expect_receive, "notify reply: segment 3", {NrVerifyFun3, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 1", SegmentRep1}, + {expect_receive, "notify reply: segment 4", {NrVerifyFun4, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 2", SegmentRep2}, + {expect_receive, "notify reply: segment 5", {NrVerifyFun5, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 3", SegmentRep3}, + {expect_receive, "notify reply: segment 6", {NrVerifyFun6, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 4", SegmentRep4}, + {expect_receive, "notify reply: segment 7", {NrVerifyFun7, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 5", SegmentRep5}, + {expect_receive, "notify reply: segment 8", {NrVerifyFun8, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 6", SegmentRep6}, + {expect_nothing, 1000}, + {send, "segment reply 7", SegmentRep7}, + {expect_nothing, 1000}, + {send, "segment reply 8", SegmentRep8}, + {expect_nothing, 1000}, + {send, "transaction-ack", TransAck}, + {expect_closed, 5000}, + disconnect + ], + EvSeq. + +ssmp4_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:encode_message(Conf, M) + end. + +ssmp4_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:decode_message(Conf, M) + end. + +ssmp4_mgc_verify_service_change_req_msg_fun() -> + fun(Msg) -> + (catch ssmp4_mgc_verify_service_change_req(Msg)) + end. + +ssmp4_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) -> + io:format("ssmp4_mgc_verify_service_change_req -> entry with" + "~n M: ~p" + "~n", [M]), + Body = + case Mess of + #'Message'{version = 1, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = _TransId, + actions = [ActionReq]} -> + ActionReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + CR = + case AR of + #'ActionRequest'{contextId = _Cid, + commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_action, AR}}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + throw({error, {invalid_terminationID, Tid}}) + end, + case Parms of + %% Version 1 'ServiceChangeParm' + {'ServiceChangeParm', + restart, % serviceChangeMethod + asn1_NOVALUE, % serviceChangeAddress + ?VERSION, % serviceChangeVersion, + {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile + [[$9,$0,$1|_]], % serviceChangeReason + asn1_NOVALUE, % serviceChangeDelay + asn1_NOVALUE, % serviceChangeMgcId + asn1_NOVALUE, % timeStamp + asn1_NOVALUE % nonStandardData + } -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeParms, Parms}} + end. + +ssmp4_mgc_verify_notify_reply_segment_msg_fun(SN, Last, + TransId, TermId, Cid) -> + fun(Msg) -> + (catch ssmp4_mgc_verify_notify_reply_segment(Msg, + SN, Last, + TransId, TermId, Cid)) + end. + +ssmp4_mgc_verify_notify_reply_segment(#'MegacoMessage'{mess = Mess} = M, + SN, Last, TransId, TermId, Cid) -> + io:format("ssmp4_mgc_verify_notify_reply_segment -> entry with" + "~n M: ~p" + "~n SN: ~p" + "~n Last: ~p" + "~n TransId: ~p" + "~n TermId: ~p" + "~n Cid: ~p" + "~n", [M, SN, Last, TransId, TermId, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = TransId, + transactionResult = TransRes, + segmentNumber = SN, + segmentationComplete = asn1_NOVALUE} when (Last == false) -> + TransRes; + #'TransactionReply'{transactionId = TransId, + transactionResult = TransRes, + segmentNumber = SN, + segmentationComplete = 'NULL'} when (Last == true) -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActionReply]} -> + ActionReply; + {actionReplies, ActionReplies} -> + throw({error, {invalid_actionReplies, ActionReplies}}); + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = Cid, + commandReply = [CommandReply]} -> + CommandReply; + #'ActionReply'{contextId = Cid, + commandReply = CommandReplies} -> + throw({error, {invalid_commandReplies, CommandReplies}}); + _ -> + throw({error, {invalid_actionReply, AR}}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + case NR of + #'NotifyReply'{terminationID = [TermId], + errorDescriptor = asn1_NOVALUE} -> + {ok, M}; + _ -> + {error, {invalid_NotifyReply, NR}} + end; +ssmp4_mgc_verify_notify_reply_segment(Crap, + _SN, _Last, _TransId, _TermId, _Cid) -> + {error, {invalid_MegacoMessage, Crap}}. + + +ssmp4_mgc_service_change_reply_msg(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + TRes = cre_transResult([AR]), + TR = {'TransactionReply', 1, asn1_NOVALUE, TRes}, + Trans = cre_transaction(TR), + Mess = cre_message(1, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmp4_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs) -> + ARs = ssmp4_mgc_notify_request_ars(TermIDs, CIDs), + TR = cre_transReq(TransId, ARs), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmp4_mgc_notify_request_ars(TermIDs, CIDs) -> + ssmp4_mgc_notify_request_ars(TermIDs, CIDs, []). + +ssmp4_mgc_notify_request_ars([], [], Acc) -> + lists:reverse(Acc); +ssmp4_mgc_notify_request_ars([TermID|TermIDs], [CID|CIDs], Acc) -> + AR = ssmp4_mgc_notify_request_ar(100+CID, TermID, CID), + ssmp4_mgc_notify_request_ars(TermIDs, CIDs, [AR|Acc]). + +ssmp4_mgc_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation(integer_to_list(19990720+Rid), + integer_to_list(22000000+Rid)), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +ssmp4_mgc_segment_reply_msg(Mid, TransId, SN, Last) -> + SR = ssmp4_mgc_segment_reply(TransId, SN, Last), + Trans = cre_transaction(SR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmp4_mgc_segment_reply(TransId, SN, true) -> + cre_segReply(TransId, SN, 'NULL'); +ssmp4_mgc_segment_reply(TransId, SN, false) -> + cre_segReply(TransId, SN, asn1_NOVALUE). + +ssmp4_mgc_trans_ack_msg(Mid, TransId) -> + TA = cre_transAck(TransId), + Trans = cre_transaction([TA]), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +ssmp4_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ssmp4_mg_verify_handle_connect_fun(), + ServiceChangeReq = ssmp4_mg_service_change_request_ar(Mid, 1), + ServiceChangeReplyVerify = ssmp4_mg_verify_service_change_reply_fun(), + Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]}, + Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]}, + Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]}, + Tid4 = #megaco_term_id{id = ["00000000","00000000","00000004"]}, + Tid5 = #megaco_term_id{id = ["00000000","00000000","00000005"]}, + Tid6 = #megaco_term_id{id = ["00000000","00000000","00000006"]}, + Tid7 = #megaco_term_id{id = ["00000000","00000000","00000007"]}, + Tid8 = #megaco_term_id{id = ["00000000","00000000","00000008"]}, + Tids = [Tid1, Tid2, Tid3, Tid4, Tid5, Tid6, Tid7, Tid8], + NotifyReqVerify = ssmp4_mg_verify_notify_request_fun(Tids), + AckVerify = ssmp4_mg_verify_ack_fun(), + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + %% {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {megaco_update_conn_info, protocol_version, ?VERSION}, + {megaco_update_conn_info, segment_send, 3}, + {megaco_update_conn_info, max_pdu_size, 128}, + {sleep, 1000}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, AckVerify, 15000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +ssmp4_mg_verify_handle_connect_fun() -> + fun(Ev) -> ssmp4_mg_verify_handle_connect(Ev) end. + +ssmp4_mg_verify_handle_connect({handle_connect, CH, 1}) -> + io:format("ssmp4_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +ssmp4_mg_verify_handle_connect(Else) -> + io:format("ssmp4_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +ssmp4_mg_verify_service_change_reply_fun() -> + fun(Rep) -> ssmp4_mg_verify_scr(Rep) end. + +ssmp4_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) -> + (catch ssmp4_mg_do_verify_scr(AR)); +ssmp4_mg_verify_scr(Crap) -> + io:format("ssmp4_mg_verify_scr -> error: " + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + +ssmp4_mg_do_verify_scr(AR) -> + io:format("ssmp4_mg_do_verify_scr -> ok: " + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +ssmp4_mg_verify_notify_request_fun(Tids) -> + fun(Req) -> ssmp4_mg_verify_notify_request(Req, Tids) end. + +ssmp4_mg_verify_notify_request( + {handle_trans_request, _CH, ?VERSION, ARs}, Tids) + when length(ARs) == length(Tids) -> + (catch ssmp4_mg_do_verify_notify_request(Tids, ARs)); +ssmp4_mg_verify_notify_request( + {handle_trans_request, _CH, ?VERSION, ARs}, _Tids) -> + {error, {invalid_action_requests, ARs}, ok}; +ssmp4_mg_verify_notify_request( + {handle_trans_request, CH, V, ARs}, _Tids) -> + {error, {invalid_trans_request, {CH, V, ARs}}, ok}; +ssmp4_mg_verify_notify_request(Crap, _Tids) -> + io:format("ssmp4_mg_verify_notify_request -> unknown request" + "~n Crap: ~p" + "~n Tids: ~p" + "~n", [Crap, _Tids]), + {error, {unexpected_event, Crap}, ok}. + +ssmp4_mg_do_verify_notify_request(Tids, ARs) -> + io:format("ssmp4_mg_do_verify_notify_request -> ok" + "~n Tids: ~p" + "~n ARs: ~p" + "~n", [Tids, ARs]), + ActionReplies = ssmp4_mg_do_verify_notify_request_ars(Tids, ARs), + io:format("ssmp4_mg_do_verify_notify_request -> ok" + "~n ActionReplies: ~p" + "~n", [ActionReplies]), + Reply = {{handle_ack, ssmp4}, ActionReplies}, + {ok, ARs, Reply}. + +ssmp4_mg_do_verify_notify_request_ars(Tids, ARs) -> + ssmp4_mg_do_verify_notify_request_ars(Tids, ARs, []). + +ssmp4_mg_do_verify_notify_request_ars([], [], Acc) -> + lists:reverse(Acc); +ssmp4_mg_do_verify_notify_request_ars([Tid|Tids], [AR|ARs], Acc) -> + ActionReply = ssmp4_mg_do_verify_notify_request_ar(Tid, AR), + ssmp4_mg_do_verify_notify_request_ars(Tids, ARs, [ActionReply|Acc]). + +ssmp4_mg_do_verify_notify_request_ar(Tid, AR) -> + io:format("ssmp4_mg_do_verify_notify_request_ar -> ok" + "~n Tid: ~p" + "~n AR: ~p" + "~n", [Tid, AR]), + {Cid, CR} = + case AR of + #'ActionRequest'{contextId = CtxId, + commandRequests = [CmdReq]} -> + {CtxId, CmdReq}; + _ -> + Reason1 = {invalid_actionRequest, AR}, + throw({error, Reason1, ok}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}, ok}) + end, + OED = + case Cmd of + {notifyReq, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = ObsEvDesc, + errorDescriptor = asn1_NOVALUE}} -> + ObsEvDesc; + _ -> + throw({error, {invalid_command, Cmd}, ok}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEv]} -> + ObsEv; + #'ObservedEventsDescriptor'{observedEventLst = ObsEvLst} -> + throw({error, {invalid_observedEventLst, ObsEvLst}, ok}); + _ -> + throw({error, {invalid_ObservedEventsDescriptor, OED}, ok}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + ssmp4_mg_notify_reply_ar(Cid, Tid); + _ -> + throw({error, {invalid_ObservedEvent, OE}, ok}) + end. + + +ssmp4_mg_verify_ack_fun() -> + fun(Event) -> ssmp4_mg_verify_ack(Event) end. + +ssmp4_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, ssmp4}) -> + io:format("ssmp4_mg_verify_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +ssmp4_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, CrapAckData}) -> + {error, {unknown_ack_data, CrapAckData, CH}, ok}; +ssmp4_mg_verify_ack({handle_trans_ack, CH, ?VERSION, + BadAckStatus, BadAckData}) -> + {error, {unknown_ack_status, BadAckStatus, BadAckData, CH}, ok}; +ssmp4_mg_verify_ack(BadEvent) -> + {error, {unknown_event, BadEvent}, ok}. + + +ssmp4_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +ssmp4_mg_notify_reply_ar(Cid, Tid) -> + NR = cre_notifyReply([Tid]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +send_segmented_msg_ooo1(suite) -> + []; +send_segmented_msg_ooo1(doc) -> + "First segment out of order test. " + "Tests that it is possible to send segmented messages, when the " + "segment reply is sent out-of-order. " + "Send window = 3. "; +send_segmented_msg_ooo1(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, ssmo1), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = ssmo1_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = ssmo1_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + + +%% +%% MGC generator stuff +%% + +ssmo1_mgc_event_sequence(text, tcp) -> + DecodeFun = ssmo1_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ssmo1_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mgc"}, + ScrVerifyFun = ssmo1_mgc_verify_service_change_req_msg_fun(), + ServiceChangeRep = ssmo1_mgc_service_change_reply_msg(Mid, 1), + TermId1 = + #megaco_term_id{id = ["00000000","00000000","00000001"]}, + CtxId1 = 1, + TermId2 = + #megaco_term_id{id = ["00000000","00000000","00000002"]}, + CtxId2 = 2, + TermId3 = + #megaco_term_id{id = ["00000000","00000000","00000003"]}, + CtxId3 = 3, + TermId4 = + #megaco_term_id{id = ["00000000","00000000","00000004"]}, + CtxId4 = 4, + TermId5 = + #megaco_term_id{id = ["00000000","00000000","00000005"]}, + CtxId5 = 5, + TermId6 = + #megaco_term_id{id = ["00000000","00000000","00000006"]}, + CtxId6 = 6, + TermId7 = + #megaco_term_id{id = ["00000000","00000000","00000007"]}, + CtxId7 = 7, + TermId8 = + #megaco_term_id{id = ["00000000","00000000","00000008"]}, + CtxId8 = 8, + TransId = 2, + TermIDs = [TermId1, TermId2, TermId3, TermId4, + TermId5, TermId6, TermId7, TermId8], + CIDs = [CtxId1, CtxId2, CtxId3, CtxId4, + CtxId5, CtxId6, CtxId7, CtxId8], + NotifyReq = ssmo1_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs), + NrVerifyFun1 = + ssmo1_mgc_verify_notify_reply_segment_msg_fun(1, false, TransId, + TermId1, CtxId1), + NrVerifyFun2 = + ssmo1_mgc_verify_notify_reply_segment_msg_fun(2, false, TransId, + TermId2, CtxId2), + NrVerifyFun3 = + ssmo1_mgc_verify_notify_reply_segment_msg_fun(3, false, TransId, + TermId3, CtxId3), + NrVerifyFun4 = + ssmo1_mgc_verify_notify_reply_segment_msg_fun(4, false, TransId, + TermId4, CtxId4), + NrVerifyFun5 = + ssmo1_mgc_verify_notify_reply_segment_msg_fun(5, false, TransId, + TermId5, CtxId5), + NrVerifyFun6 = + ssmo1_mgc_verify_notify_reply_segment_msg_fun(6, false, TransId, + TermId6, CtxId6), + NrVerifyFun7 = + ssmo1_mgc_verify_notify_reply_segment_msg_fun(7, false, TransId, + TermId7, CtxId7), + NrVerifyFun8 = + ssmo1_mgc_verify_notify_reply_segment_msg_fun(8, true, TransId, + TermId8, CtxId8), + SegmentRep1 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 1, false), + SegmentRep2 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 2, false), + SegmentRep3 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 3, false), + SegmentRep4 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 4, false), + SegmentRep5 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 5, false), + SegmentRep6 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 6, false), + SegmentRep7 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 7, false), + SegmentRep8 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 8, true), + TransAck = ssmo1_mgc_trans_ack_msg(Mid, TransId), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-request", {ScrVerifyFun, 5000}}, + {send, "service-change-reply", ServiceChangeRep}, + {expect_nothing, 1000}, + {send, "notify request", NotifyReq}, + {expect_receive, "notify reply: segment 1", {NrVerifyFun1, 1000}}, + {expect_receive, "notify reply: segment 2", {NrVerifyFun2, 1000}}, + {expect_receive, "notify reply: segment 3", {NrVerifyFun3, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 2 [1]", SegmentRep2}, + {expect_receive, "notify reply: segment 4", {NrVerifyFun4, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 1 [2]", SegmentRep1}, + {expect_receive, "notify reply: segment 5", {NrVerifyFun5, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 3 [3]", SegmentRep3}, + {expect_receive, "notify reply: segment 6", {NrVerifyFun6, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 5 [4]", SegmentRep5}, + {expect_receive, "notify reply: segment 7", {NrVerifyFun7, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 4 [5]", SegmentRep4}, + {expect_receive, "notify reply: segment 8", {NrVerifyFun8, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 6", SegmentRep6}, + {expect_nothing, 1000}, + {send, "segment reply 7", SegmentRep7}, + {expect_nothing, 1000}, + {send, "segment reply 8", SegmentRep8}, + {expect_nothing, 1000}, + {send, "transaction-ack", TransAck}, + {expect_closed, 5000}, + disconnect + ], + EvSeq. + +ssmo1_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:encode_message(Conf, M) + end. + +ssmo1_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:decode_message(Conf, M) + end. + +ssmo1_mgc_verify_service_change_req_msg_fun() -> + fun(Msg) -> + (catch ssmo1_mgc_verify_service_change_req(Msg)) + end. + +ssmo1_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) -> + io:format("ssmo1_mgc_verify_service_change_req -> entry with" + "~n M: ~p" + "~n", [M]), + Body = + case Mess of + #'Message'{version = 1, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = _TransId, + actions = [ActionReq]} -> + ActionReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + CR = + case AR of + #'ActionRequest'{contextId = _Cid, + commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_action, AR}}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + throw({error, {invalid_terminationID, Tid}}) + end, + case Parms of + %% Version 1 'ServiceChangeParm' + {'ServiceChangeParm', + restart, % serviceChangeMethod + asn1_NOVALUE, % serviceChangeAddress + ?VERSION, % serviceChangeVersion, + {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile + [[$9,$0,$1|_]], % serviceChangeReason + asn1_NOVALUE, % serviceChangeDelay + asn1_NOVALUE, % serviceChangeMgcId + asn1_NOVALUE, % timeStamp + asn1_NOVALUE % nonStandardData + } -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeParms, Parms}} + end. + +ssmo1_mgc_verify_notify_reply_segment_msg_fun(SN, Last, + TransId, TermId, Cid) -> + fun(Msg) -> + (catch ssmo1_mgc_verify_notify_reply_segment(Msg, + SN, Last, + TransId, TermId, Cid)) + end. + +ssmo1_mgc_verify_notify_reply_segment(#'MegacoMessage'{mess = Mess} = M, + SN, Last, TransId, TermId, Cid) -> + io:format("ssmo1_mgc_verify_notify_reply_segment -> entry with" + "~n M: ~p" + "~n SN: ~p" + "~n Last: ~p" + "~n TransId: ~p" + "~n TermId: ~p" + "~n Cid: ~p" + "~n", [M, SN, Last, TransId, TermId, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = TransId, + transactionResult = TransRes, + segmentNumber = SN, + segmentationComplete = asn1_NOVALUE} when (Last == false) -> + TransRes; + #'TransactionReply'{transactionId = TransId, + transactionResult = TransRes, + segmentNumber = SN, + segmentationComplete = 'NULL'} when (Last == true) -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActionReply]} -> + ActionReply; + {actionReplies, ActionReplies} -> + throw({error, {invalid_actionReplies, ActionReplies}}); + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = Cid, + commandReply = [CommandReply]} -> + CommandReply; + #'ActionReply'{contextId = Cid, + commandReply = CommandReplies} -> + throw({error, {invalid_commandReplies, CommandReplies}}); + _ -> + throw({error, {invalid_actionReply, AR}}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + case NR of + #'NotifyReply'{terminationID = [TermId], + errorDescriptor = asn1_NOVALUE} -> + {ok, M}; + _ -> + {error, {invalid_NotifyReply, NR}} + end; +ssmo1_mgc_verify_notify_reply_segment(Crap, + _SN, _Last, _TransId, _TermId, _Cid) -> + {error, {invalid_MegacoMessage, Crap}}. + + +ssmo1_mgc_service_change_reply_msg(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + TRes = cre_transResult([AR]), + TR = {'TransactionReply', 1, asn1_NOVALUE, TRes}, + Trans = cre_transaction(TR), + Mess = cre_message(1, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmo1_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs) -> + ARs = ssmo1_mgc_notify_request_ars(TermIDs, CIDs), + TR = cre_transReq(TransId, ARs), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmo1_mgc_notify_request_ars(TermIDs, CIDs) -> + ssmo1_mgc_notify_request_ars(TermIDs, CIDs, []). + +ssmo1_mgc_notify_request_ars([], [], Acc) -> + lists:reverse(Acc); +ssmo1_mgc_notify_request_ars([TermID|TermIDs], [CID|CIDs], Acc) -> + AR = ssmo1_mgc_notify_request_ar(100+CID, TermID, CID), + ssmo1_mgc_notify_request_ars(TermIDs, CIDs, [AR|Acc]). + +ssmo1_mgc_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation(integer_to_list(19990720+Rid), + integer_to_list(22000000+Rid)), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +ssmo1_mgc_segment_reply_msg(Mid, TransId, SN, Last) -> + SR = ssmo1_mgc_segment_reply(TransId, SN, Last), + Trans = cre_transaction(SR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmo1_mgc_segment_reply(TransId, SN, true) -> + cre_segReply(TransId, SN, 'NULL'); +ssmo1_mgc_segment_reply(TransId, SN, false) -> + cre_segReply(TransId, SN, asn1_NOVALUE). + +ssmo1_mgc_trans_ack_msg(Mid, TransId) -> + TA = cre_transAck(TransId), + Trans = cre_transaction([TA]), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +ssmo1_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ssmo1_mg_verify_handle_connect_fun(), + ServiceChangeReq = ssmo1_mg_service_change_request_ar(Mid, 1), + ServiceChangeReplyVerify = ssmo1_mg_verify_service_change_reply_fun(), + Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]}, + Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]}, + Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]}, + Tid4 = #megaco_term_id{id = ["00000000","00000000","00000004"]}, + Tid5 = #megaco_term_id{id = ["00000000","00000000","00000005"]}, + Tid6 = #megaco_term_id{id = ["00000000","00000000","00000006"]}, + Tid7 = #megaco_term_id{id = ["00000000","00000000","00000007"]}, + Tid8 = #megaco_term_id{id = ["00000000","00000000","00000008"]}, + Tids = [Tid1, Tid2, Tid3, Tid4, Tid5, Tid6, Tid7, Tid8], + NotifyReqVerify = ssmo1_mg_verify_notify_request_fun(Tids), + AckVerify = ssmo1_mg_verify_ack_fun(), + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + %% {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {megaco_update_conn_info, protocol_version, ?VERSION}, + {megaco_update_conn_info, segment_send, 3}, + {megaco_update_conn_info, max_pdu_size, 128}, + {sleep, 1000}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, AckVerify, 15000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +ssmo1_mg_verify_handle_connect_fun() -> + fun(Ev) -> ssmo1_mg_verify_handle_connect(Ev) end. + +ssmo1_mg_verify_handle_connect({handle_connect, CH, 1}) -> + io:format("ssmo1_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +ssmo1_mg_verify_handle_connect(Else) -> + io:format("ssmo1_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +ssmo1_mg_verify_service_change_reply_fun() -> + fun(Rep) -> ssmo1_mg_verify_scr(Rep) end. + +ssmo1_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) -> + (catch ssmo1_mg_do_verify_scr(AR)); +ssmo1_mg_verify_scr(Crap) -> + io:format("ssmo1_mg_verify_scr -> error: " + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + +ssmo1_mg_do_verify_scr(AR) -> + io:format("ssmo1_mg_do_verify_scr -> ok: " + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +ssmo1_mg_verify_notify_request_fun(Tids) -> + fun(Req) -> ssmo1_mg_verify_notify_request(Req, Tids) end. + +ssmo1_mg_verify_notify_request( + {handle_trans_request, _CH, ?VERSION, ARs}, Tids) + when length(ARs) == length(Tids) -> + (catch ssmo1_mg_do_verify_notify_request(Tids, ARs)); +ssmo1_mg_verify_notify_request( + {handle_trans_request, _CH, ?VERSION, ARs}, _Tids) -> + {error, {invalid_action_requests, ARs}, ok}; +ssmo1_mg_verify_notify_request( + {handle_trans_request, CH, V, ARs}, _Tids) -> + {error, {invalid_trans_request, {CH, V, ARs}}, ok}; +ssmo1_mg_verify_notify_request(Crap, _Tids) -> + io:format("ssmo1_mg_verify_notify_request -> unknown request" + "~n Crap: ~p" + "~n Tids: ~p" + "~n", [Crap, _Tids]), + {error, {unexpected_event, Crap}, ok}. + +ssmo1_mg_do_verify_notify_request(Tids, ARs) -> + io:format("ssmo1_mg_do_verify_notify_request -> ok" + "~n Tids: ~p" + "~n ARs: ~p" + "~n", [Tids, ARs]), + ActionReplies = ssmo1_mg_do_verify_notify_request_ars(Tids, ARs), + io:format("ssmo1_mg_do_verify_notify_request -> ok" + "~n ActionReplies: ~p" + "~n", [ActionReplies]), + Reply = {{handle_ack, ssmp4}, ActionReplies}, + {ok, ARs, Reply}. + +ssmo1_mg_do_verify_notify_request_ars(Tids, ARs) -> + ssmo1_mg_do_verify_notify_request_ars(Tids, ARs, []). + +ssmo1_mg_do_verify_notify_request_ars([], [], Acc) -> + lists:reverse(Acc); +ssmo1_mg_do_verify_notify_request_ars([Tid|Tids], [AR|ARs], Acc) -> + ActionReply = ssmo1_mg_do_verify_notify_request_ar(Tid, AR), + ssmo1_mg_do_verify_notify_request_ars(Tids, ARs, [ActionReply|Acc]). + +ssmo1_mg_do_verify_notify_request_ar(Tid, AR) -> + io:format("ssmo1_mg_do_verify_notify_request_ar -> ok" + "~n Tid: ~p" + "~n AR: ~p" + "~n", [Tid, AR]), + {Cid, CR} = + case AR of + #'ActionRequest'{contextId = CtxId, + commandRequests = [CmdReq]} -> + {CtxId, CmdReq}; + _ -> + Reason1 = {invalid_actionRequest, AR}, + throw({error, Reason1, ok}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}, ok}) + end, + OED = + case Cmd of + {notifyReq, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = ObsEvDesc, + errorDescriptor = asn1_NOVALUE}} -> + ObsEvDesc; + _ -> + throw({error, {invalid_command, Cmd}, ok}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEv]} -> + ObsEv; + #'ObservedEventsDescriptor'{observedEventLst = ObsEvLst} -> + throw({error, {invalid_observedEventLst, ObsEvLst}, ok}); + _ -> + throw({error, {invalid_ObservedEventsDescriptor, OED}, ok}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + ssmo1_mg_notify_reply_ar(Cid, Tid); + _ -> + throw({error, {invalid_ObservedEvent, OE}, ok}) + end. + + +ssmo1_mg_verify_ack_fun() -> + fun(Event) -> ssmo1_mg_verify_ack(Event) end. + +ssmo1_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, ssmp4}) -> + io:format("ssmo1_mg_verify_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +ssmo1_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, CrapAckData}) -> + {error, {unknown_ack_data, CrapAckData, CH}, ok}; +ssmo1_mg_verify_ack({handle_trans_ack, CH, ?VERSION, + BadAckStatus, BadAckData}) -> + {error, {unknown_ack_status, BadAckStatus, BadAckData, CH}, ok}; +ssmo1_mg_verify_ack(BadEvent) -> + {error, {unknown_event, BadEvent}, ok}. + + +ssmo1_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +ssmo1_mg_notify_reply_ar(Cid, Tid) -> + NR = cre_notifyReply([Tid]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +send_segmented_msg_missing_seg_reply1(suite) -> + []; +send_segmented_msg_missing_seg_reply1(doc) -> + "First missing segment test. " + "Tests that the callbacks and error messages are delivered " + "when a segment reply goes missing. Ack expected. " + "Send window = 3. "; +send_segmented_msg_missing_seg_reply1(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, ssmmsr1), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = ssmmsr1_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = ssmmsr1_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + %% Await MGC ready for segments + d("await MGC trigger event"), + MgcPid = + receive + {ready_for_segments, mgc, Pid1} -> + d("received MGC trigger event"), + Pid1 + after 5000 -> + d("timeout waiting for MGC trigger event: ~p", + [megaco_test_lib:flush()]), + ?ERROR(timeout_MGC_trigger_event) + end, + + %% Await MG ready for segments + d("await MG trigger event"), + MgPid = + receive + {ready_for_segments, mg, Pid2} -> + d("received MG trigger event"), + Pid2 + after 5000 -> + d("timeout waiting for MG trigger event: ~p", + [megaco_test_lib:flush()]), + ?ERROR(timeout_MG_trigger_event) + end, + + %% Instruct the MG to continue + d("send continue to MG"), + MgPid ! {continue_with_segments, self()}, + + sleep(500), + + %% Instruct the MGC to continue + d("send continue to MGC"), + MgcPid ! {continue_with_segments, self()}, + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + + +%% +%% MGC generator stuff +%% + +ssmmsr1_mgc_event_sequence(text, tcp) -> + DecodeFun = ssmmsr1_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ssmmsr1_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mgc"}, + ScrVerifyFun = ssmmsr1_mgc_verify_service_change_req_msg_fun(), + ServiceChangeRep = ssmmsr1_mgc_service_change_reply_msg(Mid, 1), + TermId1 = + #megaco_term_id{id = ["00000000","00000000","00000001"]}, + CtxId1 = 1, + TermId2 = + #megaco_term_id{id = ["00000000","00000000","00000002"]}, + CtxId2 = 2, + TermId3 = + #megaco_term_id{id = ["00000000","00000000","00000003"]}, + CtxId3 = 3, + TermId4 = + #megaco_term_id{id = ["00000000","00000000","00000004"]}, + CtxId4 = 4, + TermId5 = + #megaco_term_id{id = ["00000000","00000000","00000005"]}, + CtxId5 = 5, + TermId6 = + #megaco_term_id{id = ["00000000","00000000","00000006"]}, + CtxId6 = 6, + TermId7 = + #megaco_term_id{id = ["00000000","00000000","00000007"]}, + CtxId7 = 7, + TermId8 = + #megaco_term_id{id = ["00000000","00000000","00000008"]}, + CtxId8 = 8, + TransId = 2, + TermIDs = [TermId1, TermId2, TermId3, TermId4, + TermId5, TermId6, TermId7, TermId8], + CIDs = [CtxId1, CtxId2, CtxId3, CtxId4, + CtxId5, CtxId6, CtxId7, CtxId8], + NotifyReq = ssmmsr1_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs), + NrVerifyFun1 = + ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(1, false, TransId, + TermId1, CtxId1), + NrVerifyFun2 = + ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(2, false, TransId, + TermId2, CtxId2), + NrVerifyFun3 = + ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(3, false, TransId, + TermId3, CtxId3), + NrVerifyFun4 = + ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(4, false, TransId, + TermId4, CtxId4), + NrVerifyFun5 = + ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(5, false, TransId, + TermId5, CtxId5), + NrVerifyFun6 = + ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(6, false, TransId, + TermId6, CtxId6), + NrVerifyFun7 = + ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(7, false, TransId, + TermId7, CtxId7), + NrVerifyFun8 = + ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(8, true, TransId, + TermId8, CtxId8), + SegmentRep1 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 1, false), + SegmentRep2 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 2, false), + %% SegmentRep3 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 3, false), + SegmentRep4 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 4, false), + SegmentRep5 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 5, false), + SegmentRep6 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 6, false), + SegmentRep7 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 7, false), + SegmentRep8 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 8, true), + TransAck = ssmmsr1_mgc_trans_ack_msg(Mid, TransId), + ReadyForSegments = ssmmsr1_mgc_ready_for_segments_fun(), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-request", {ScrVerifyFun, 5000}}, + {send, "service-change-reply", ServiceChangeRep}, + %% {expect_nothing, 1000}, + {trigger, "segment send sync trigger", ReadyForSegments}, + {send, "notify request", NotifyReq}, + {expect_receive, "notify reply: segment 1", {NrVerifyFun1, 1000}}, + {expect_receive, "notify reply: segment 2", {NrVerifyFun2, 1000}}, + {expect_receive, "notify reply: segment 3", {NrVerifyFun3, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 1 [1]", SegmentRep1}, + {expect_receive, "notify reply: segment 4", {NrVerifyFun4, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 2 [2]", SegmentRep2}, + {expect_receive, "notify reply: segment 5", {NrVerifyFun5, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 4 [3]", SegmentRep4}, + {expect_receive, "notify reply: segment 6", {NrVerifyFun6, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 5 [4]", SegmentRep5}, + {expect_receive, "notify reply: segment 7", {NrVerifyFun7, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 6 [5]", SegmentRep6}, + {expect_receive, "notify reply: segment 8", {NrVerifyFun8, 1000}}, + {expect_nothing, 1000}, + {send, "segment reply 7 [6]", SegmentRep7}, + {expect_nothing, 1000}, + {send, "segment reply 8 [7]", SegmentRep8}, + {expect_nothing, 1000}, + {send, "transaction-ack", TransAck}, + {expect_closed, 5000}, + disconnect + ], + EvSeq. + +ssmmsr1_mgc_ready_for_segments_fun() -> + TC = self(), + fun() -> + io:format("ssmmsr1_mgc_ready_for_segments_fun -> entry~n", []), + TC ! {ready_for_segments, mgc, self()}, + receive + {continue_with_segments, TC} -> + io:format("ssmmsr1_mgc_ready_for_segments_fun -> " + "received continue~n", []), + ok + end + end. + +ssmmsr1_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:encode_message(Conf, M) + end. + +ssmmsr1_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:decode_message(Conf, M) + end. + +ssmmsr1_mgc_verify_service_change_req_msg_fun() -> + fun(Msg) -> + (catch ssmmsr1_mgc_verify_service_change_req(Msg)) + end. + +ssmmsr1_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) -> + io:format("ssmmsr1_mgc_verify_service_change_req -> entry with" + "~n M: ~p" + "~n", [M]), + Body = + case Mess of + #'Message'{version = 1, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = _TransId, + actions = [ActionReq]} -> + ActionReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + CR = + case AR of + #'ActionRequest'{contextId = _Cid, + commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_action, AR}}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + throw({error, {invalid_terminationID, Tid}}) + end, + case Parms of + %% Version 1 'ServiceChangeParm' + {'ServiceChangeParm', + restart, % serviceChangeMethod + asn1_NOVALUE, % serviceChangeAddress + ?VERSION, % serviceChangeVersion, + {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile + [[$9,$0,$1|_]], % serviceChangeReason + asn1_NOVALUE, % serviceChangeDelay + asn1_NOVALUE, % serviceChangeMgcId + asn1_NOVALUE, % timeStamp + asn1_NOVALUE % nonStandardData + } -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeParms, Parms}} + end. + +ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(SN, Last, + TransId, TermId, Cid) -> + fun(Msg) -> + (catch ssmmsr1_mgc_verify_notify_reply_segment(Msg, + SN, Last, + TransId, TermId, Cid)) + end. + +ssmmsr1_mgc_verify_notify_reply_segment(#'MegacoMessage'{mess = Mess} = M, + SN, Last, TransId, TermId, Cid) -> + io:format("ssmmsr1_mgc_verify_notify_reply_segment -> entry with" + "~n M: ~p" + "~n SN: ~p" + "~n Last: ~p" + "~n TransId: ~p" + "~n TermId: ~p" + "~n Cid: ~p" + "~n", [M, SN, Last, TransId, TermId, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = TransId, + transactionResult = TransRes, + segmentNumber = SN, + segmentationComplete = asn1_NOVALUE} when (Last == false) -> + TransRes; + #'TransactionReply'{transactionId = TransId, + transactionResult = TransRes, + segmentNumber = SN, + segmentationComplete = 'NULL'} when (Last == true) -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActionReply]} -> + ActionReply; + {actionReplies, ActionReplies} -> + throw({error, {invalid_actionReplies, ActionReplies}}); + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = Cid, + commandReply = [CommandReply]} -> + CommandReply; + #'ActionReply'{contextId = Cid, + commandReply = CommandReplies} -> + throw({error, {invalid_commandReplies, CommandReplies}}); + _ -> + throw({error, {invalid_actionReply, AR}}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + case NR of + #'NotifyReply'{terminationID = [TermId], + errorDescriptor = asn1_NOVALUE} -> + {ok, M}; + _ -> + {error, {invalid_NotifyReply, NR}} + end; +ssmmsr1_mgc_verify_notify_reply_segment(Crap, + _SN, _Last, _TransId, _TermId, _Cid) -> + {error, {invalid_MegacoMessage, Crap}}. + + +ssmmsr1_mgc_service_change_reply_msg(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + TRes = cre_transResult([AR]), + TR = {'TransactionReply', 1, asn1_NOVALUE, TRes}, + Trans = cre_transaction(TR), + Mess = cre_message(1, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmmsr1_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs) -> + ARs = ssmmsr1_mgc_notify_request_ars(TermIDs, CIDs), + TR = cre_transReq(TransId, ARs), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmmsr1_mgc_notify_request_ars(TermIDs, CIDs) -> + ssmmsr1_mgc_notify_request_ars(TermIDs, CIDs, []). + +ssmmsr1_mgc_notify_request_ars([], [], Acc) -> + lists:reverse(Acc); +ssmmsr1_mgc_notify_request_ars([TermID|TermIDs], [CID|CIDs], Acc) -> + AR = ssmmsr1_mgc_notify_request_ar(100+CID, TermID, CID), + ssmmsr1_mgc_notify_request_ars(TermIDs, CIDs, [AR|Acc]). + +ssmmsr1_mgc_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation(integer_to_list(19990720+Rid), + integer_to_list(22000000+Rid)), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +ssmmsr1_mgc_segment_reply_msg(Mid, TransId, SN, Last) -> + SR = ssmmsr1_mgc_segment_reply(TransId, SN, Last), + Trans = cre_transaction(SR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmmsr1_mgc_segment_reply(TransId, SN, true) -> + cre_segReply(TransId, SN, 'NULL'); +ssmmsr1_mgc_segment_reply(TransId, SN, false) -> + cre_segReply(TransId, SN, asn1_NOVALUE). + +ssmmsr1_mgc_trans_ack_msg(Mid, TransId) -> + TA = cre_transAck(TransId), + Trans = cre_transaction([TA]), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +ssmmsr1_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ssmmsr1_mg_verify_handle_connect_fun(), + ServiceChangeReq = ssmmsr1_mg_service_change_request_ar(Mid, 1), + ServiceChangeReplyVerify = ssmmsr1_mg_verify_service_change_reply_fun(), + Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]}, + Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]}, + Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]}, + Tid4 = #megaco_term_id{id = ["00000000","00000000","00000004"]}, + Tid5 = #megaco_term_id{id = ["00000000","00000000","00000005"]}, + Tid6 = #megaco_term_id{id = ["00000000","00000000","00000006"]}, + Tid7 = #megaco_term_id{id = ["00000000","00000000","00000007"]}, + Tid8 = #megaco_term_id{id = ["00000000","00000000","00000008"]}, + Tids = [Tid1, Tid2, Tid3, Tid4, Tid5, Tid6, Tid7, Tid8], + NotifyReqVerify = ssmmsr1_mg_verify_notify_request_fun(Tids), + AckVerify = ssmmsr1_mg_verify_ack_fun(), + ReadyForSegments = ssmmsr1_mg_ready_for_segments_fun(), + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + %% {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {megaco_update_conn_info, protocol_version, ?VERSION}, + {megaco_update_conn_info, reply_timer, 20000}, + {megaco_update_conn_info, segment_send, 3}, + {megaco_update_conn_info, max_pdu_size, 128}, + %% {sleep, 1000}, + {trigger, ReadyForSegments}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, AckVerify, 15000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +ssmmsr1_mg_ready_for_segments_fun() -> + TC = self(), + fun() -> + io:format("ssmmsr1_mg_ready_for_segments_fun -> entry~n", []), + TC ! {ready_for_segments, mg, self()}, + receive + {continue_with_segments, TC} -> + io:format("ssmmsr1_mg_ready_for_segments_fun -> " + "received continue~n", []), + ok + end + end. + +ssmmsr1_mg_verify_handle_connect_fun() -> + fun(Ev) -> ssmmsr1_mg_verify_handle_connect(Ev) end. + +ssmmsr1_mg_verify_handle_connect({handle_connect, CH, 1}) -> + io:format("ssmmsr1_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +ssmmsr1_mg_verify_handle_connect(Else) -> + io:format("ssmmsr1_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +ssmmsr1_mg_verify_service_change_reply_fun() -> + fun(Rep) -> ssmmsr1_mg_verify_scr(Rep) end. + +ssmmsr1_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) -> + (catch ssmmsr1_mg_do_verify_scr(AR)); +ssmmsr1_mg_verify_scr(Crap) -> + io:format("ssmmsr1_mg_verify_scr -> error: " + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + +ssmmsr1_mg_do_verify_scr(AR) -> + io:format("ssmmsr1_mg_do_verify_scr -> ok: " + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +ssmmsr1_mg_verify_notify_request_fun(Tids) -> + fun(Req) -> ssmmsr1_mg_verify_notify_request(Req, Tids) end. + +ssmmsr1_mg_verify_notify_request( + {handle_trans_request, _CH, ?VERSION, ARs}, Tids) + when length(ARs) == length(Tids) -> + (catch ssmmsr1_mg_do_verify_notify_request(Tids, ARs)); +ssmmsr1_mg_verify_notify_request( + {handle_trans_request, _CH, ?VERSION, ARs}, _Tids) -> + {error, {invalid_action_requests, ARs}, ok}; +ssmmsr1_mg_verify_notify_request( + {handle_trans_request, CH, V, ARs}, _Tids) -> + {error, {invalid_trans_request, {CH, V, ARs}}, ok}; +ssmmsr1_mg_verify_notify_request(Crap, _Tids) -> + io:format("ssmmsr1_mg_verify_notify_request -> unknown request" + "~n Crap: ~p" + "~n Tids: ~p" + "~n", [Crap, _Tids]), + {error, {unexpected_event, Crap}, ok}. + +ssmmsr1_mg_do_verify_notify_request(Tids, ARs) -> + io:format("ssmmsr1_mg_do_verify_notify_request -> ok" + "~n Tids: ~p" + "~n ARs: ~p" + "~n", [Tids, ARs]), + ActionReplies = ssmmsr1_mg_do_verify_notify_request_ars(Tids, ARs), + io:format("ssmmsr1_mg_do_verify_notify_request -> ok" + "~n ActionReplies: ~p" + "~n", [ActionReplies]), + Reply = {{handle_ack, ssmmsr1}, ActionReplies}, + {ok, ARs, Reply}. + +ssmmsr1_mg_do_verify_notify_request_ars(Tids, ARs) -> + ssmmsr1_mg_do_verify_notify_request_ars(Tids, ARs, []). + +ssmmsr1_mg_do_verify_notify_request_ars([], [], Acc) -> + lists:reverse(Acc); +ssmmsr1_mg_do_verify_notify_request_ars([Tid|Tids], [AR|ARs], Acc) -> + ActionReply = ssmmsr1_mg_do_verify_notify_request_ar(Tid, AR), + ssmmsr1_mg_do_verify_notify_request_ars(Tids, ARs, [ActionReply|Acc]). + +ssmmsr1_mg_do_verify_notify_request_ar(Tid, AR) -> + io:format("ssmmsr1_mg_do_verify_notify_request_ar -> ok" + "~n Tid: ~p" + "~n AR: ~p" + "~n", [Tid, AR]), + {Cid, CR} = + case AR of + #'ActionRequest'{contextId = CtxId, + commandRequests = [CmdReq]} -> + {CtxId, CmdReq}; + _ -> + Reason1 = {invalid_actionRequest, AR}, + throw({error, Reason1, ok}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}, ok}) + end, + OED = + case Cmd of + {notifyReq, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = ObsEvDesc, + errorDescriptor = asn1_NOVALUE}} -> + ObsEvDesc; + _ -> + throw({error, {invalid_command, Cmd}, ok}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEv]} -> + ObsEv; + #'ObservedEventsDescriptor'{observedEventLst = ObsEvLst} -> + throw({error, {invalid_observedEventLst, ObsEvLst}, ok}); + _ -> + throw({error, {invalid_ObservedEventsDescriptor, OED}, ok}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + ssmmsr1_mg_notify_reply_ar(Cid, Tid); + _ -> + throw({error, {invalid_ObservedEvent, OE}, ok}) + end. + + +ssmmsr1_mg_verify_ack_fun() -> + fun(Event) -> ssmmsr1_mg_verify_ack(Event) end. + +ssmmsr1_mg_verify_ack({handle_trans_ack, CH, ?VERSION, AckStatus, ssmmsr1}) -> + io:format("ssmmsr1_mg_verify_ack -> " + "~n AckStatus: ~p" + "~n CH: ~p" + "~n", [AckStatus, CH]), + case AckStatus of + {error, Reason} -> + case Reason of + {segment_failure, SegInfo} when is_list(SegInfo) -> + case lists:keysearch(segments_not_acked, 1, SegInfo) of + {value, {segments_not_acked, [3]}} -> + {ok, CH, ok}; + {value, {segments_not_acked, SNs}} -> + X = {unexpected_not_acked_segments, SNs}, + {error, X, ok}; + false -> + X = {unexpected_seg_info, SegInfo}, + {error, X, ok} + end; + _ -> + X = {unexpected_reason, Reason}, + {error, X, ok} + end; + _ -> + X = {unexpected_ack_status, AckStatus}, + {error, X, ok} + end; +ssmmsr1_mg_verify_ack({handle_trans_ack, CH, ?VERSION, + BadAckStatus, BadAckData}) -> + {error, {unknown_ack_status, BadAckStatus, BadAckData, CH}, ok}; +ssmmsr1_mg_verify_ack(BadEvent) -> + {error, {unknown_event, BadEvent}, ok}. + + +ssmmsr1_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +ssmmsr1_mg_notify_reply_ar(Cid, Tid) -> + NR = cre_notifyReply([Tid]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +send_segmented_msg_missing_seg_reply2(suite) -> + []; +send_segmented_msg_missing_seg_reply2(doc) -> + "First missing segment test. " + "Tests that the callbacks and error messages are delivered " + "when a segment reply goes missing. Ack expected. " + "Send window = 1. "; +send_segmented_msg_missing_seg_reply2(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, ssmmsr2), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = ssmmsr2_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = ssmmsr2_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + %% Await MGC ready for segments + d("await MGC trigger event"), + MgcPid = + receive + {ready_for_segments, mgc, Pid1} -> + d("received MGC trigger event"), + Pid1 + after 5000 -> + d("timeout waiting for MGC trigger event: ~p", + [megaco_test_lib:flush()]), + ?ERROR(timeout_MGC_trigger_event) + end, + + %% Await MG ready for segments + d("await MG trigger event"), + MgPid = + receive + {ready_for_segments, mg, Pid2} -> + d("received MG trigger event"), + Pid2 + after 5000 -> + d("timeout waiting for MG trigger event: ~p", + [megaco_test_lib:flush()]), + ?ERROR(timeout_MG_trigger_event) + end, + + %% Instruct the MG to continue + d("send continue to MG"), + MgPid ! {continue_with_segments, self()}, + + sleep(500), + + %% Instruct the MGC to continue + d("send continue to MGC"), + MgcPid ! {continue_with_segments, self()}, + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + + +%% +%% MGC generator stuff +%% + +ssmmsr2_mgc_event_sequence(text, tcp) -> + DecodeFun = ssmmsr2_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = ssmmsr2_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mgc"}, + ScrVerifyFun = ssmmsr2_mgc_verify_service_change_req_msg_fun(), + ServiceChangeRep = ssmmsr2_mgc_service_change_reply_msg(Mid, 1), + TermId1 = + #megaco_term_id{id = ["00000000","00000000","00000001"]}, + CtxId1 = 1, + TermId2 = + #megaco_term_id{id = ["00000000","00000000","00000002"]}, + CtxId2 = 2, + TermId3 = + #megaco_term_id{id = ["00000000","00000000","00000003"]}, + CtxId3 = 3, + TermId4 = + #megaco_term_id{id = ["00000000","00000000","00000004"]}, + CtxId4 = 4, + TermId5 = + #megaco_term_id{id = ["00000000","00000000","00000005"]}, + CtxId5 = 5, + TermId6 = + #megaco_term_id{id = ["00000000","00000000","00000006"]}, + CtxId6 = 6, + TermId7 = + #megaco_term_id{id = ["00000000","00000000","00000007"]}, + CtxId7 = 7, + TermId8 = + #megaco_term_id{id = ["00000000","00000000","00000008"]}, + CtxId8 = 8, + TransId = 2, + TermIDs = [TermId1, TermId2, TermId3, TermId4, + TermId5, TermId6, TermId7, TermId8], + CIDs = [CtxId1, CtxId2, CtxId3, CtxId4, + CtxId5, CtxId6, CtxId7, CtxId8], + NotifyReq = ssmmsr2_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs), + NrVerifyFun1 = + ssmmsr2_mgc_verify_notify_reply_segment_msg_fun(1, false, TransId, + TermId1, CtxId1), + NrVerifyFun2 = + ssmmsr2_mgc_verify_notify_reply_segment_msg_fun(2, false, TransId, + TermId2, CtxId2), + SegmentRep1 = ssmmsr2_mgc_segment_reply_msg(Mid, TransId, 1, false), + ReadyForSegments = ssmmsr2_mgc_ready_for_segments_fun(), + EvSeq = [{debug, true}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-request", {ScrVerifyFun, 5000}}, + {send, "service-change-reply", ServiceChangeRep}, + %% {expect_nothing, 1000}, + {trigger, "segment send sync trigger", ReadyForSegments}, + {send, "notify request", NotifyReq}, + {expect_receive, "notify reply: segment 1", {NrVerifyFun1, 1000}}, + {send, "segment reply 1", SegmentRep1}, + {expect_receive, "notify reply: segment 2", {NrVerifyFun2, 1000}}, + {expect_closed, 20000}, + disconnect + ], + EvSeq. + +ssmmsr2_mgc_ready_for_segments_fun() -> + TC = self(), + fun() -> + io:format("ssmmsr2_mgc_ready_for_segments_fun -> entry~n", []), + TC ! {ready_for_segments, mgc, self()}, + receive + {continue_with_segments, TC} -> + io:format("ssmmsr2_mgc_ready_for_segments_fun -> " + "received continue~n", []), + ok + end + end. + +ssmmsr2_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:encode_message(Conf, M) + end. + +ssmmsr2_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:decode_message(Conf, M) + end. + +ssmmsr2_mgc_verify_service_change_req_msg_fun() -> + fun(Msg) -> + (catch ssmmsr2_mgc_verify_service_change_req(Msg)) + end. + +ssmmsr2_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) -> + io:format("ssmmsr2_mgc_verify_service_change_req -> entry with" + "~n M: ~p" + "~n", [M]), + Body = + case Mess of + #'Message'{version = 1, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = _TransId, + actions = [ActionReq]} -> + ActionReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + CR = + case AR of + #'ActionRequest'{contextId = _Cid, + commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_action, AR}}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + throw({error, {invalid_terminationID, Tid}}) + end, + case Parms of + %% Version 1 'ServiceChangeParm' + {'ServiceChangeParm', + restart, % serviceChangeMethod + asn1_NOVALUE, % serviceChangeAddress + ?VERSION, % serviceChangeVersion, + {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile + [[$9,$0,$1|_]], % serviceChangeReason + asn1_NOVALUE, % serviceChangeDelay + asn1_NOVALUE, % serviceChangeMgcId + asn1_NOVALUE, % timeStamp + asn1_NOVALUE % nonStandardData + } -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeParms, Parms}} + end. + +ssmmsr2_mgc_verify_notify_reply_segment_msg_fun(SN, Last, + TransId, TermId, Cid) -> + fun(Msg) -> + (catch ssmmsr2_mgc_verify_notify_reply_segment(Msg, + SN, Last, + TransId, TermId, Cid)) + end. + +ssmmsr2_mgc_verify_notify_reply_segment(#'MegacoMessage'{mess = Mess} = M, + SN, Last, TransId, TermId, Cid) -> + io:format("ssmmsr2_mgc_verify_notify_reply_segment -> entry with" + "~n M: ~p" + "~n SN: ~p" + "~n Last: ~p" + "~n TransId: ~p" + "~n TermId: ~p" + "~n Cid: ~p" + "~n", [M, SN, Last, TransId, TermId, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionReply, TransReply} -> + TransReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + TRes = + case TR of + #'TransactionReply'{transactionId = TransId, + transactionResult = TransRes, + segmentNumber = SN, + segmentationComplete = asn1_NOVALUE} when (Last == false) -> + TransRes; + #'TransactionReply'{transactionId = TransId, + transactionResult = TransRes, + segmentNumber = SN, + segmentationComplete = 'NULL'} when (Last == true) -> + TransRes; + _ -> + throw({error, {invalid_transactionReply, TR}}) + end, + AR = + case TRes of + {actionReplies, [ActionReply]} -> + ActionReply; + {actionReplies, ActionReplies} -> + throw({error, {invalid_actionReplies, ActionReplies}}); + _ -> + throw({error, {invalid_transactionResult, TRes}}) + end, + CR = + case AR of + #'ActionReply'{contextId = Cid, + commandReply = [CommandReply]} -> + CommandReply; + #'ActionReply'{contextId = Cid, + commandReply = CommandReplies} -> + throw({error, {invalid_commandReplies, CommandReplies}}); + _ -> + throw({error, {invalid_actionReply, AR}}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + throw({error, {invalid_commandReply, CR}}) + end, + case NR of + #'NotifyReply'{terminationID = [TermId], + errorDescriptor = asn1_NOVALUE} -> + {ok, M}; + _ -> + {error, {invalid_NotifyReply, NR}} + end; +ssmmsr2_mgc_verify_notify_reply_segment(Crap, + _SN, _Last, _TransId, _TermId, _Cid) -> + {error, {invalid_MegacoMessage, Crap}}. + + +ssmmsr2_mgc_service_change_reply_msg(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + TRes = cre_transResult([AR]), + TR = {'TransactionReply', 1, asn1_NOVALUE, TRes}, + Trans = cre_transaction(TR), + Mess = cre_message(1, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmmsr2_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs) -> + ARs = ssmmsr2_mgc_notify_request_ars(TermIDs, CIDs), + TR = cre_transReq(TransId, ARs), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmmsr2_mgc_notify_request_ars(TermIDs, CIDs) -> + ssmmsr2_mgc_notify_request_ars(TermIDs, CIDs, []). + +ssmmsr2_mgc_notify_request_ars([], [], Acc) -> + lists:reverse(Acc); +ssmmsr2_mgc_notify_request_ars([TermID|TermIDs], [CID|CIDs], Acc) -> + AR = ssmmsr2_mgc_notify_request_ar(100+CID, TermID, CID), + ssmmsr2_mgc_notify_request_ars(TermIDs, CIDs, [AR|Acc]). + +ssmmsr2_mgc_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation(integer_to_list(19990720+Rid), + integer_to_list(22000000+Rid)), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +ssmmsr2_mgc_segment_reply_msg(Mid, TransId, SN, Last) -> + SR = ssmmsr2_mgc_segment_reply(TransId, SN, Last), + Trans = cre_transaction(SR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +ssmmsr2_mgc_segment_reply(TransId, SN, true) -> + cre_segReply(TransId, SN, 'NULL'); +ssmmsr2_mgc_segment_reply(TransId, SN, false) -> + cre_segReply(TransId, SN, asn1_NOVALUE). + +%% ssmmsr2_mgc_trans_ack_msg(Mid, TransId) -> +%% TA = cre_transAck(TransId), +%% Trans = cre_transaction([TA]), +%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), +%% cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +ssmmsr2_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ssmmsr2_mg_verify_handle_connect_fun(), + ServiceChangeReq = ssmmsr2_mg_service_change_request_ar(Mid, 1), + ServiceChangeReplyVerify = ssmmsr2_mg_verify_service_change_reply_fun(), + Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]}, + Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]}, + Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]}, + Tid4 = #megaco_term_id{id = ["00000000","00000000","00000004"]}, + Tid5 = #megaco_term_id{id = ["00000000","00000000","00000005"]}, + Tid6 = #megaco_term_id{id = ["00000000","00000000","00000006"]}, + Tid7 = #megaco_term_id{id = ["00000000","00000000","00000007"]}, + Tid8 = #megaco_term_id{id = ["00000000","00000000","00000008"]}, + Tids = [Tid1, Tid2, Tid3, Tid4, Tid5, Tid6, Tid7, Tid8], + NotifyReqVerify = ssmmsr2_mg_verify_notify_request_fun(Tids), + AckVerify = ssmmsr2_mg_verify_ack_fun(), + ReadyForSegments = ssmmsr2_mg_ready_for_segments_fun(), + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + %% {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {megaco_update_conn_info, protocol_version, ?VERSION}, + {megaco_update_conn_info, reply_timer, 12000}, + {megaco_update_conn_info, segment_send, 1}, + {megaco_update_conn_info, max_pdu_size, 128}, + %% {sleep, 1000}, + {trigger, ReadyForSegments}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, AckVerify, 15000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +ssmmsr2_mg_ready_for_segments_fun() -> + TC = self(), + fun() -> + io:format("ssmmsr2_mg_ready_for_segments_fun -> entry~n", []), + TC ! {ready_for_segments, mg, self()}, + receive + {continue_with_segments, TC} -> + io:format("ssmmsr2_mg_ready_for_segments_fun -> " + "received continue~n", []), + ok + end + end. + +ssmmsr2_mg_verify_handle_connect_fun() -> + fun(Ev) -> ssmmsr2_mg_verify_handle_connect(Ev) end. + +ssmmsr2_mg_verify_handle_connect({handle_connect, CH, 1}) -> + io:format("ssmmsr2_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +ssmmsr2_mg_verify_handle_connect(Else) -> + io:format("ssmmsr2_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +ssmmsr2_mg_verify_service_change_reply_fun() -> + fun(Rep) -> ssmmsr2_mg_verify_scr(Rep) end. + +ssmmsr2_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) -> + (catch ssmmsr2_mg_do_verify_scr(AR)); +ssmmsr2_mg_verify_scr(Crap) -> + io:format("ssmmsr2_mg_verify_scr -> error: " + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + +ssmmsr2_mg_do_verify_scr(AR) -> + io:format("ssmmsr2_mg_do_verify_scr -> ok: " + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +ssmmsr2_mg_verify_notify_request_fun(Tids) -> + fun(Req) -> ssmmsr2_mg_verify_notify_request(Req, Tids) end. + +ssmmsr2_mg_verify_notify_request( + {handle_trans_request, _CH, ?VERSION, ARs}, Tids) + when length(ARs) == length(Tids) -> + (catch ssmmsr2_mg_do_verify_notify_request(Tids, ARs)); +ssmmsr2_mg_verify_notify_request( + {handle_trans_request, _CH, ?VERSION, ARs}, _Tids) -> + {error, {invalid_action_requests, ARs}, ok}; +ssmmsr2_mg_verify_notify_request( + {handle_trans_request, CH, V, ARs}, _Tids) -> + {error, {invalid_trans_request, {CH, V, ARs}}, ok}; +ssmmsr2_mg_verify_notify_request(Crap, _Tids) -> + io:format("ssmmsr2_mg_verify_notify_request -> unknown request" + "~n Crap: ~p" + "~n Tids: ~p" + "~n", [Crap, _Tids]), + {error, {unexpected_event, Crap}, ok}. + +ssmmsr2_mg_do_verify_notify_request(Tids, ARs) -> + io:format("ssmmsr2_mg_do_verify_notify_request -> ok" + "~n Tids: ~p" + "~n ARs: ~p" + "~n", [Tids, ARs]), + ActionReplies = ssmmsr2_mg_do_verify_notify_request_ars(Tids, ARs), + io:format("ssmmsr2_mg_do_verify_notify_request -> ok" + "~n ActionReplies: ~p" + "~n", [ActionReplies]), + Reply = {{handle_ack, ssmmsr2}, ActionReplies}, + {ok, ARs, Reply}. + +ssmmsr2_mg_do_verify_notify_request_ars(Tids, ARs) -> + ssmmsr2_mg_do_verify_notify_request_ars(Tids, ARs, []). + +ssmmsr2_mg_do_verify_notify_request_ars([], [], Acc) -> + lists:reverse(Acc); +ssmmsr2_mg_do_verify_notify_request_ars([Tid|Tids], [AR|ARs], Acc) -> + ActionReply = ssmmsr2_mg_do_verify_notify_request_ar(Tid, AR), + ssmmsr2_mg_do_verify_notify_request_ars(Tids, ARs, [ActionReply|Acc]). + +ssmmsr2_mg_do_verify_notify_request_ar(Tid, AR) -> + io:format("ssmmsr2_mg_do_verify_notify_request_ar -> ok" + "~n Tid: ~p" + "~n AR: ~p" + "~n", [Tid, AR]), + {Cid, CR} = + case AR of + #'ActionRequest'{contextId = CtxId, + commandRequests = [CmdReq]} -> + {CtxId, CmdReq}; + _ -> + Reason1 = {invalid_actionRequest, AR}, + throw({error, Reason1, ok}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}, ok}) + end, + OED = + case Cmd of + {notifyReq, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = ObsEvDesc, + errorDescriptor = asn1_NOVALUE}} -> + ObsEvDesc; + _ -> + throw({error, {invalid_command, Cmd}, ok}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEv]} -> + ObsEv; + #'ObservedEventsDescriptor'{observedEventLst = ObsEvLst} -> + throw({error, {invalid_observedEventLst, ObsEvLst}, ok}); + _ -> + throw({error, {invalid_ObservedEventsDescriptor, OED}, ok}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + ssmmsr2_mg_notify_reply_ar(Cid, Tid); + _ -> + throw({error, {invalid_ObservedEvent, OE}, ok}) + end. + + +ssmmsr2_mg_verify_ack_fun() -> + fun(Event) -> (catch ssmmsr2_mg_verify_ack(Event)) end. + +ssmmsr2_mg_verify_ack({handle_trans_ack, CH, ?VERSION, AckStatus, ssmmsr2}) -> + io:format("ssmmsr2_mg_verify_ack -> " + "~n AckStatus: ~p" + "~n CH: ~p" + "~n", [AckStatus, CH]), + case AckStatus of + {error, Reason} -> + case Reason of + {segment_failure, SegInfo} when is_list(SegInfo) -> + io:format("ssmmsr2_mg_verify_ack -> verify not acked" + "~n", []), + case lists:keysearch(segments_not_acked, 1, SegInfo) of + {value, {segments_not_acked, [2]}} -> + ok; + {value, {segments_not_acked, SNs}} -> + X = {unexpected_not_acked_segments, SNs}, + throw({error, X, ok}); + false -> + X = {unexpected_seg_info, SegInfo}, + throw({error, X, ok}) + end, + io:format("ssmmsr2_mg_verify_ack -> verify not sent" + "~n", []), + case lists:keysearch(segments_not_sent, 1, SegInfo) of + {value, {segments_not_sent, NotSent}} -> + case [3,4,5,6,7,8] -- NotSent of + [] -> + {ok, CH, ok}; + _ -> + Y = {unexpected_not_sent_segments, + NotSent}, + throw({error, Y, ok}) + end; + false -> + Y = {unexpected_seg_info, SegInfo}, + throw({error, Y, ok}) + end; + _ -> + X = {unexpected_reason, Reason}, + {error, X, ok} + end; + _ -> + X = {unexpected_ack_status, AckStatus}, + {error, X, ok} + end; +ssmmsr2_mg_verify_ack({handle_trans_ack, CH, ?VERSION, + BadAckStatus, BadAckData}) -> + {error, {unknown_ack_status, BadAckStatus, BadAckData, CH}, ok}; +ssmmsr2_mg_verify_ack(BadEvent) -> + {error, {unknown_event, BadEvent}, ok}. + + +ssmmsr2_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +ssmmsr2_mg_notify_reply_ar(Cid, Tid) -> + NR = cre_notifyReply([Tid]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% %%% +%%% Segmented reply received test cases %%% +%%% %%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +recv_segmented_msg_plain(suite) -> + []; +recv_segmented_msg_plain(doc) -> + "Received segmented megaco message [plain]"; +recv_segmented_msg_plain(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, rsmp), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = rsmp_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = rsmp_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% + +rsmp_mgc_event_sequence(text, tcp) -> + DecodeFun = rsmp_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = rsmp_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mgc"}, + ScrVerifyFun = rsmp_mgc_verify_service_change_req_msg_fun(), + ServiceChangeRep = rsmp_mgc_service_change_reply_msg(Mid, 1), + TermId1 = + #megaco_term_id{id = ["00000000","00000000","00000001"]}, + TermId2 = + #megaco_term_id{id = ["00000000","00000000","00000002"]}, + TermId3 = + #megaco_term_id{id = ["00000000","00000000","00000003"]}, + TermIds = [TermId1, TermId2, TermId3], + TransId = 2, + ReqId = 1, + CtxId = 1, + NrVerifyFun = + rsmp_mgc_verify_notify_req_msg_fun(TermIds, TransId, ReqId, CtxId), + NotifyRep1 = rsmp_mgc_notify_reply_msg(1, Mid, TransId, CtxId, TermId1), + NotifyRep2 = rsmp_mgc_notify_reply_msg(2, Mid, TransId, CtxId, TermId2), + NotifyRep3 = rsmp_mgc_notify_reply_msg(3, Mid, TransId, CtxId, TermId3), + SrVerifyFun1 = rsmp_mgc_verify_segment_reply_msg_fun(1, TransId), + SrVerifyFun2 = rsmp_mgc_verify_segment_reply_msg_fun(2, TransId), + SrVerifyFun3 = rsmp_mgc_verify_segment_reply_msg_fun(3, TransId), + AckVerifyFun = rsmp_mgc_verify_trans_ack_msg_fun(TransId), + EvSeq = [{debug, false}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-request", {ScrVerifyFun, 5000}}, + {sleep, 500}, + + {send, "service-change-reply", ServiceChangeRep}, + {expect_receive, "notify-request(1)", {NrVerifyFun, 4000}}, + {sleep, 500}, + + {send, "notify reply - segment 1", NotifyRep1}, + {expect_receive, "segment reply 1", {SrVerifyFun1, 2000}}, + {sleep, 500}, + + {send, "notify reply - segment 2", NotifyRep2}, + {expect_receive, "segment reply 2", {SrVerifyFun2, 2000}}, + {sleep, 500}, + + {send, "notify reply - segment 3 (last)", NotifyRep3}, + {expect_receive, "segment reply 3 (last)", {SrVerifyFun3, 2000}}, + {expect_receive, "ack", {AckVerifyFun, 4000}}, + {sleep, 1000}, + disconnect + ], + EvSeq. + +rsmp_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:encode_message(Conf, M) + end. + +rsmp_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:decode_message(Conf, M) + end. + +rsmp_mgc_verify_service_change_req_msg_fun() -> + fun(Msg) -> + (catch rsmp_mgc_verify_service_change_req(Msg)) + end. + +rsmp_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) -> + io:format("rsmp_mgc_verify_service_change_req -> entry with" + "~n M: ~p" + "~n", [M]), + Body = + case Mess of + #'Message'{version = 1, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = _TransId, + actions = [ActionReq]} -> + ActionReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + CR = + case AR of + #'ActionRequest'{contextId = _Cid, + commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_action, AR}}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + throw({error, {invalid_terminationID, Tid}}) + end, + case Parms of + %% Version 1 'ServiceChangeParm' + {'ServiceChangeParm', + restart, % serviceChangeMethod + asn1_NOVALUE, % serviceChangeAddress + ?VERSION, % serviceChangeVersion, + {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile + [[$9,$0,$1|_]], % serviceChangeReason + asn1_NOVALUE, % serviceChangeDelay + asn1_NOVALUE, % serviceChangeMgcId + asn1_NOVALUE, % timeStamp + asn1_NOVALUE % nonStandardData + } -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeParms, Parms}} + end. + +rsmp_mgc_verify_notify_req_msg_fun(TermIds, TransId, Rid, Cid) -> + fun(Msg) -> + (catch rsmp_mgc_verify_notify_req(Msg, + TermIds, TransId, Rid, Cid)) + end. + +rsmp_mgc_verify_notify_req(#'MegacoMessage'{mess = Mess} = M, + TermIds, TransId, Rid, Cid) -> + io:format("rsmp_mgc_verify_notify_req -> entry with" + "~n M: ~p" + "~n TermIds: ~p" + "~n TransId: ~p" + "~n Rid: ~p" + "~n Cid: ~p" + "~n", [M, TermIds, TransId, Rid, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = TransId, + actions = [ActReq]} -> + ActReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + Cmds = + case AR of + #'ActionRequest'{contextId = Cid, + commandRequests = Commands} -> + Commands; + _ -> + throw({error, {invalid_actions, AR}}) + end, + ok = rsmp_mgc_verify_notify_req_cmds(TermIds, Cmds), + {ok, M}; +rsmp_mgc_verify_notify_req(Crap, _TermId, _TransId, _Rid, _Cid) -> + {error, {invalid_MegacoMessage, Crap}}. + +rsmp_mgc_verify_notify_req_cmds([], []) -> + ok; +rsmp_mgc_verify_notify_req_cmds([TermId|TermIds], [Cmd|Cmds]) -> + rsmp_mgc_verify_notify_req_cmd(TermId, Cmd), + rsmp_mgc_verify_notify_req_cmds(TermIds, Cmds); +rsmp_mgc_verify_notify_req_cmds(TermIds, Cmds) -> + throw({error, {invalid_commands, TermIds, Cmds}}). + +rsmp_mgc_verify_notify_req_cmd(TermId, #'CommandRequest'{command = Cmd}) -> + io:format("rsmp_mgc_verify_notify_req_cmd -> entry with" + "~n TermId: ~p" + "~n Cmd: ~p" + "~n", [TermId, Cmd]), + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + throw({error, {invalid_command}}) + end, + OED = + case NR of + #'NotifyRequest'{terminationID = [TermId], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + ObsEvsDesc; + _ -> + throw({error, {invalid_notifyReq, NR}}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + throw({error, {invalid_observedEventsDescriptor, OED}}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + ok; + _ -> + throw({error, {invalid_observedEventLst, OE}}) + end; +rsmp_mgc_verify_notify_req_cmd(_, BadCmdReq) -> + io:format("rsmp_mgc_verify_notify_req_cmd -> invalid" + "~n BadCmdReq: ~p" + "~n", [BadCmdReq]), + throw({error, {invalid_CommandRequest, BadCmdReq}}). + +rsmp_mgc_verify_segment_reply_msg_fun(SN, TransId) -> + fun(Msg) -> + (catch rsmp_mgc_verify_segment_reply(Msg, SN, TransId)) + end. + +rsmp_mgc_verify_segment_reply(#'MegacoMessage'{mess = Mess} = M, + SN, TransId) -> + io:format("rsmp_mgc_verify_segment_reply -> entry with" + "~n SN: ~p" + "~n TransId: ~p" + "~n M: ~p" + "~n", [SN, TransId, M]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + SR = + case Trans of + {segmentReply, SegmentReply} -> + SegmentReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + case SR of + #'SegmentReply'{transactionId = TransId, + segmentNumber = SN, + segmentationComplete = 'NULL'} when SN == 3 -> + {ok, M}; + #'SegmentReply'{transactionId = TransId, + segmentNumber = SN, + segmentationComplete = asn1_NOVALUE} -> + {ok, M}; + _ -> + throw({error, {invalid_segmentReply, SR}}) + end; +rsmp_mgc_verify_segment_reply(Crap, SN, TransId) -> + io:format("rsmp_mgc_verify_segment_reply -> invalid: " + "~n SN: ~p" + "~n TransId: ~p" + "~n Crap: ~p" + "~n", [SN, TransId, Crap]), + {error, {invalid_MegacoMessage, Crap, SN, TransId}}. + +rsmp_mgc_verify_trans_ack_msg_fun(TransId) -> + fun(Msg) -> + (catch rsmp_mgc_verify_trans_ack(Msg, TransId)) + end. + +rsmp_mgc_verify_trans_ack(#'MegacoMessage'{mess = Mess} = M, TransId) -> + io:format("rsmp_mgc_verify_trans_ack -> entry with" + "~n TransId: ~p" + "~n M: ~p" + "~n", [TransId, M]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TA = + case Trans of + {transactionResponseAck, [TransAck]} -> + TransAck; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + case TA of + #'TransactionAck'{firstAck = TransId, + lastAck = asn1_NOVALUE} -> + {ok, M}; + _ -> + throw({error, {invalid_transactionResponseAck, TA}}) + end; +rsmp_mgc_verify_trans_ack(Crap, _TransId) -> + {error, {invalid_MegacoMessage, Crap}}. + +rsmp_mgc_service_change_reply_msg(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + TRes = cre_transResult([AR]), + TR = {'TransactionReply', 1, asn1_NOVALUE, TRes}, + Trans = cre_transaction(TR), + Mess = cre_message(1, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +rsmp_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +rsmp_mgc_notify_reply_msg(SN, Mid, TransId, Cid, TermId) -> + AR = rsmp_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = + if + SN == 3 -> + cre_transReply(TransId, TRes, SN, 'NULL'); + true -> + cre_transReply(TransId, TRes, SN) + end, + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +rsmp_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = rsmp_mg_service_change_request_ar(Mid, 1), + ConnectVerify = rsmp_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = rsmp_mg_verify_service_change_reply_fun(), + Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]}, + Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]}, + Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]}, + Tids = [Tid1, Tid2, Tid3], + NotifyReq = rsmp_mg_notify_request_ar(1, Tids, 1), + NotifyReplyVerify1 = rsmp_mg_verify_notify_reply_fun(1, Tid1), + NotifyReplyVerify2 = rsmp_mg_verify_notify_reply_fun(2, Tid2), + NotifyReplyVerify3 = rsmp_mg_verify_notify_reply_fun(3, Tid3), + EvSeq = [ + {debug, true}, + %% {megaco_trace, disable}, + {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {megaco_update_user_info, protocol_version, ?VERSION}, + {megaco_update_conn_info, protocol_version, ?VERSION}, + {sleep, 1000}, + {megaco_cast, [NotifyReq], []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify1}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify2}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify3}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + + +rsmp_mg_verify_handle_connect_fun() -> + fun(Ev) -> rsmp_mg_verify_handle_connect(Ev) end. + +rsmp_mg_verify_handle_connect({handle_connect, CH, 1}) -> + io:format("rsmp_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +rsmp_mg_verify_handle_connect(Else) -> + io:format("rsmp_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +rsmp_mg_verify_service_change_reply_fun() -> + fun(Rep) -> rsmp_mg_verify_scr(Rep) end. + +rsmp_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) -> + (catch rsmp_mg_do_verify_scr(AR)); +rsmp_mg_verify_scr(Crap) -> + io:format("rsmp_mg_verify_scr -> error: " + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + +rsmp_mg_do_verify_scr(AR) -> + io:format("rsmp_mg_do_verify_scr -> ok: " + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +rsmp_mg_verify_notify_reply_fun(SN, Tid) -> + fun(Rep) -> rsmp_mg_verify_notify_reply(Rep, SN, Tid) end. + +rsmp_mg_verify_notify_reply( + {handle_trans_reply, _CH, ?VERSION, {ok, {SN, Last, [AR]}}, _}, SN, Tid) + when ((SN =:= 3) andalso (Last =:= true)) orelse + ((SN =/= 3) andalso (Last =:= false)) -> + (catch rsmp_mg_do_verify_notify_reply(Tid, AR)); +rsmp_mg_verify_notify_reply( + {handle_trans_reply, _CH, Version, {ok, {SN1, Last, ARs}}, _}, SN2, Tid) -> + io:format("rsmp_mg_verify_notify_reply -> unknown reply" + "~n Version: ~p" + "~n SN1: ~p" + "~n Last: ~p" + "~n ARs: ~p" + "~n SN2: ~p" + "~n Tid: ~p" + "~n", [Version, SN1, Last, ARs, SN2, Tid]), + Crap = {unexpected_segment_data, [SN1, Last, ARs, SN2, Tid]}, + {error, Crap, ok}; +rsmp_mg_verify_notify_reply(Crap, SN, Tid) -> + io:format("rsmp_mg_verify_notify_reply -> unknown reply" + "~n SN: ~p" + "~n Tid: ~p" + "~n Crap: ~p" + "~n", [SN, Tid, Crap]), + {error, Crap, ok}. + +rsmp_mg_do_verify_notify_reply(Tid, AR) -> + io:format("rsmp_mg_do_verify_notify_reply -> ok" + "~n Tid: ~p" + "~n AR: ~p" + "~n", [Tid, AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + case NR of + #'NotifyReply'{terminationID = [Tid], + errorDescriptor = asn1_NOVALUE} -> + {ok, AR, ok}; + _ -> + Reason3 = {invalid_NotifyReply, NR}, + {error, Reason3, ok} + end. + + +rsmp_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +rsmp_mg_notify_request_ar(Rid, Tids, Cid) -> + rsmp_mg_notify_request_ar(Rid, Tids, Cid, []). + +rsmp_mg_notify_request_ar(_Rid, [], Cid, Cmds) -> + cre_actionReq(Cid, lists:reverse(Cmds)); +rsmp_mg_notify_request_ar(Rid, [Tid|Tids], Cid, Cmds) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + rsmp_mg_notify_request_ar(Rid, Tids, Cid, [CR|Cmds]). + +%% rsmp_internalError(Text) -> +%% Code = ?megaco_internal_gateway_error, +%% cre_errorDesc(Code, Text). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +recv_segmented_msg_ooo_seg(suite) -> + []; +recv_segmented_msg_ooo_seg(doc) -> + "Received segmented megaco message [out-of-order segments]"; +recv_segmented_msg_ooo_seg(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, rsmos), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = rsmos_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = rsmos_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% + +rsmos_mgc_event_sequence(text, tcp) -> + DecodeFun = rsmos_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = rsmos_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mgc"}, + ScrVerifyFun = rsmos_mgc_verify_service_change_req_msg_fun(), + ServiceChangeRep = rsmos_mgc_service_change_reply_msg(Mid, 1), + TermId1 = + #megaco_term_id{id = ["00000000","00000000","00000001"]}, + TermId2 = + #megaco_term_id{id = ["00000000","00000000","00000002"]}, + TermId3 = + #megaco_term_id{id = ["00000000","00000000","00000003"]}, + TermIds = [TermId1, TermId2, TermId3], + TransId = 2, + ReqId = 1, + CtxId = 1, + NrVerifyFun = + rsmos_mgc_verify_notify_req_msg_fun(TermIds, TransId, ReqId, CtxId), + NotifyRep1 = rsmos_mgc_notify_reply_msg(1, Mid, TransId, CtxId, TermId1), + NotifyRep2 = rsmos_mgc_notify_reply_msg(2, Mid, TransId, CtxId, TermId2), + NotifyRep3 = rsmos_mgc_notify_reply_msg(3, Mid, TransId, CtxId, TermId3), + SrVerifyFun1 = rsmos_mgc_verify_segment_reply_msg_fun(1, TransId), + SrVerifyFun2 = rsmos_mgc_verify_segment_reply_msg_fun(2, TransId), + SrVerifyFun3 = rsmos_mgc_verify_segment_reply_msg_fun(3, TransId), + AckVerifyFun = rsmos_mgc_verify_trans_ack_msg_fun(TransId), + EvSeq = [{debug, false}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-request", {ScrVerifyFun, 5000}}, + {send, "service-change-reply", ServiceChangeRep}, + {expect_receive, "notify-request", {NrVerifyFun, 4000}}, + {send, "notify reply - segment 3", NotifyRep3}, + {expect_receive, "segment reply 3", {SrVerifyFun3, 2000}}, + {sleep, 1000}, + {send, "notify reply - segment 2", NotifyRep2}, + {expect_receive, "segment reply 2", {SrVerifyFun2, 2000}}, + {sleep, 1000}, + {send, "notify reply - segment 1 (last)", NotifyRep1}, + {expect_receive, "segment reply 1 (last)", {SrVerifyFun1, 2000}}, + {expect_receive, "ack", {AckVerifyFun, 4000}}, + {expect_nothing, 10000}, + disconnect + ], + EvSeq. + +rsmos_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:encode_message(Conf, M) + end. + +rsmos_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:decode_message(Conf, M) + end. + +rsmos_mgc_verify_service_change_req_msg_fun() -> + fun(Msg) -> + (catch rsmos_mgc_verify_service_change_req(Msg)) + end. + +rsmos_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) -> + io:format("rsmos_mgc_verify_service_change_req -> entry with" + "~n M: ~p" + "~n", [M]), + Body = + case Mess of + #'Message'{version = 1, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = _TransId, + actions = [ActionReq]} -> + ActionReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + CR = + case AR of + #'ActionRequest'{contextId = _Cid, + commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_action, AR}}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + throw({error, {invalid_terminationID, Tid}}) + end, + case Parms of + %% Version 1 'ServiceChangeParm' + {'ServiceChangeParm', + restart, % serviceChangeMethod + asn1_NOVALUE, % serviceChangeAddress + ?VERSION, % serviceChangeVersion, + {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile + [[$9,$0,$1|_]], % serviceChangeReason + asn1_NOVALUE, % serviceChangeDelay + asn1_NOVALUE, % serviceChangeMgcId + asn1_NOVALUE, % timeStamp + asn1_NOVALUE % nonStandardData + } -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeParms, Parms}} + end. + +rsmos_mgc_verify_notify_req_msg_fun(TermIds, TransId, Rid, Cid) -> + fun(Msg) -> + (catch rsmos_mgc_verify_notify_req(Msg, + TermIds, TransId, Rid, Cid)) + end. + +rsmos_mgc_verify_notify_req(#'MegacoMessage'{mess = Mess} = M, + TermIds, TransId, Rid, Cid) -> + io:format("rsmos_mgc_verify_notify_req -> entry with" + "~n M: ~p" + "~n TermIds: ~p" + "~n TransId: ~p" + "~n Rid: ~p" + "~n Cid: ~p" + "~n", [M, TermIds, TransId, Rid, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = TransId, + actions = [ActReq]} -> + ActReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + Cmds = + case AR of + #'ActionRequest'{contextId = Cid, + commandRequests = Commands} -> + Commands; + _ -> + throw({error, {invalid_actions, AR}}) + end, + ok = rsmos_mgc_verify_notify_req_cmds(TermIds, Cmds), + {ok, M}; +rsmos_mgc_verify_notify_req(Crap, _TermId, _TransId, _Rid, _Cid) -> + {error, {invalid_MegacoMessage, Crap}}. + +rsmos_mgc_verify_notify_req_cmds([], []) -> + ok; +rsmos_mgc_verify_notify_req_cmds([TermId|TermIds], [Cmd|Cmds]) -> + rsmos_mgc_verify_notify_req_cmd(TermId, Cmd), + rsmos_mgc_verify_notify_req_cmds(TermIds, Cmds); +rsmos_mgc_verify_notify_req_cmds(TermIds, Cmds) -> + throw({error, {invalid_commands, TermIds, Cmds}}). + +rsmos_mgc_verify_notify_req_cmd(TermId, #'CommandRequest'{command = Cmd}) -> + io:format("rsmos_mgc_verify_notify_req_cmd -> entry with" + "~n TermId: ~p" + "~n Cmd: ~p" + "~n", [TermId, Cmd]), + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + throw({error, {invalid_command}}) + end, + OED = + case NR of + #'NotifyRequest'{terminationID = [TermId], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + ObsEvsDesc; + _ -> + throw({error, {invalid_notifyReq, NR}}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + throw({error, {invalid_observedEventsDescriptor, OED}}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + ok; + _ -> + throw({error, {invalid_observedEventLst, OE}}) + end; +rsmos_mgc_verify_notify_req_cmd(_, BadCmdReq) -> + io:format("rsmos_mgc_verify_notify_req_cmd -> invalid" + "~n BadCmdReq: ~p" + "~n", [BadCmdReq]), + throw({error, {invalid_CommandRequest, BadCmdReq}}). + +rsmos_mgc_verify_segment_reply_msg_fun(SN, TransId) -> + fun(Msg) -> + (catch rsmos_mgc_verify_segment_reply(Msg, SN, TransId)) + end. + +rsmos_mgc_verify_segment_reply(#'MegacoMessage'{mess = Mess} = M, + SN, TransId) -> + io:format("rsmos_mgc_verify_segment_reply -> entry with" + "~n SN: ~p" + "~n TransId: ~p" + "~n M: ~p" + "~n", [SN, TransId, M]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + SR = + case Trans of + {segmentReply, SegmentReply} -> + SegmentReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + case SR of + #'SegmentReply'{transactionId = TransId, + segmentNumber = SN, + segmentationComplete = 'NULL'} when SN == 3 -> + {ok, M}; + #'SegmentReply'{transactionId = TransId, + segmentNumber = SN, + segmentationComplete = asn1_NOVALUE} -> + {ok, M}; + _ -> + throw({error, {invalid_segmentReply, SR}}) + end; +rsmos_mgc_verify_segment_reply(Crap, SN, TransId) -> + io:format("rsmos_mgc_verify_segment_reply -> invalid: " + "~n SN: ~p" + "~n TransId: ~p" + "~n Crap: ~p" + "~n", [SN, TransId, Crap]), + {error, {invalid_MegacoMessage, Crap, SN, TransId}}. + +rsmos_mgc_verify_trans_ack_msg_fun(TransId) -> + fun(Msg) -> + (catch rsmos_mgc_verify_trans_ack(Msg, TransId)) + end. + +rsmos_mgc_verify_trans_ack(#'MegacoMessage'{mess = Mess} = M, TransId) -> + io:format("rsmos_mgc_verify_trans_ack -> entry with" + "~n TransId: ~p" + "~n M: ~p" + "~n", [TransId, M]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TA = + case Trans of + {transactionResponseAck, [TransAck]} -> + TransAck; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + case TA of + #'TransactionAck'{firstAck = TransId, + lastAck = asn1_NOVALUE} -> + {ok, M}; + _ -> + throw({error, {invalid_transactionResponseAck, TA}}) + end; +rsmos_mgc_verify_trans_ack(Crap, _TransId) -> + {error, {invalid_MegacoMessage, Crap}}. + +rsmos_mgc_service_change_reply_msg(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + TRes = cre_transResult([AR]), + TR = {'TransactionReply', 1, asn1_NOVALUE, TRes}, + Trans = cre_transaction(TR), + Mess = cre_message(1, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +rsmos_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +rsmos_mgc_notify_reply_msg(SN, Mid, TransId, Cid, TermId) -> + AR = rsmos_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = + if + SN == 3 -> + cre_transReply(TransId, TRes, SN, 'NULL'); + true -> + cre_transReply(TransId, TRes, SN) + end, + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +rsmos_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = rsmos_mg_service_change_request_ar(Mid, 1), + ConnectVerify = rsmos_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = rsmos_mg_verify_service_change_reply_fun(), + Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]}, + Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]}, + Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]}, + Tids = [Tid1, Tid2, Tid3], + NotifyReq = rsmos_mg_notify_request_ar(1, Tids, 1), + NotifyReplyVerify1 = rsmos_mg_verify_notify_reply_fun(1, Tid1), + NotifyReplyVerify2 = rsmos_mg_verify_notify_reply_fun(2, Tid2), + NotifyReplyVerify3 = rsmos_mg_verify_notify_reply_fun(3, Tid3), + DiscoVerify = rsmos_mg_verify_handle_disco_fun(), + EvSeq = [ + {debug, true}, + %% {megaco_trace, disable}, + {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {megaco_update_user_info, segment_recv_timer, 3000}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {megaco_update_conn_info, protocol_version, ?VERSION}, + {sleep, 1000}, + {megaco_cast, [NotifyReq], []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify3}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify2}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify1}, + {megaco_callback, handle_disconnect, DiscoVerify}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +rsmos_mg_verify_handle_connect_fun() -> + fun(Ev) -> rsmos_mg_verify_handle_connect(Ev) end. + +rsmos_mg_verify_handle_connect({handle_connect, CH, 1}) -> + io:format("rsmos_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +rsmos_mg_verify_handle_connect(Else) -> + io:format("rsmos_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +rsmos_mg_verify_service_change_reply_fun() -> + fun(Rep) -> rsmos_mg_verify_scr(Rep) end. + +rsmos_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) -> + (catch rsmos_mg_do_verify_scr(AR)); +rsmos_mg_verify_scr(Crap) -> + io:format("rsmos_mg_verify_scr -> error: " + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + +rsmos_mg_do_verify_scr(AR) -> + io:format("rsmos_mg_do_verify_scr -> ok: " + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +rsmos_mg_verify_notify_reply_fun(SN, Tid) -> + fun(Rep) -> rsmos_mg_verify_notify_reply(Rep, SN, Tid) end. + +rsmos_mg_verify_notify_reply( + {handle_trans_reply, _CH, ?VERSION, {ok, {SN, Last, [AR]}}, _}, SN, Tid) + when ((SN == 1) and (Last == true)) or + ((SN =/= 1) and (Last == false)) -> + (catch rsmos_mg_do_verify_notify_reply(Tid, AR)); +rsmos_mg_verify_notify_reply(Crap, SN, Tid) -> + io:format("rsmos_mg_verify_notify_reply -> unknown reply" + "~n SN: ~p" + "~n Tid: ~p" + "~n Crap: ~p" + "~n", [SN, Tid, Crap]), + {error, Crap, ok}. + +rsmos_mg_do_verify_notify_reply(Tid, AR) -> + io:format("rsmos_mg_do_verify_notify_reply -> ok" + "~n Tid: ~p" + "~n AR: ~p" + "~n", [Tid, AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + case NR of + #'NotifyReply'{terminationID = [Tid], + errorDescriptor = asn1_NOVALUE} -> + {ok, AR, ok}; + _ -> + Reason3 = {invalid_NotifyReply, NR}, + {error, Reason3, ok} + end. + +rsmos_mg_verify_handle_disco_fun() -> + fun(Ev) -> rsmos_mg_verify_handle_disconnect(Ev) end. + +rsmos_mg_verify_handle_disconnect({handle_disconnect, _CH, ?VERSION, R}) -> + io:format("rsmos_mg_verify_handle_disconnect -> ok" + "~n R: ~p" + "~n", [R]), + case R of + {no_controlling_process,shutdown} -> + {ok, R, ok}; + _ -> + {error, {unexpected_reason, R}, ok} + end; +rsmos_mg_verify_handle_disconnect(Crap) -> + io:format("rsmos_mg_verify_handle_disconnect -> invalid: " + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + + +rsmos_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +rsmos_mg_notify_request_ar(Rid, Tids, Cid) -> + rsmos_mg_notify_request_ar(Rid, Tids, Cid, []). + +rsmos_mg_notify_request_ar(_Rid, [], Cid, Cmds) -> + cre_actionReq(Cid, lists:reverse(Cmds)); +rsmos_mg_notify_request_ar(Rid, [Tid|Tids], Cid, Cmds) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + rsmos_mg_notify_request_ar(Rid, Tids, Cid, [CR|Cmds]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +recv_segmented_msg_missing_seg1(suite) -> + []; +recv_segmented_msg_missing_seg1(doc) -> + "Received segmented megaco message with one segment missing " + "using plain integer recv segment timer"; +recv_segmented_msg_missing_seg1(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, rsmms1), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = rsmms1_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = rsmms1_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% + +rsmms1_mgc_event_sequence(text, tcp) -> + DecodeFun = rsmms1_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = rsmms1_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mgc"}, + ScrVerifyFun = rsmms1_mgc_verify_service_change_req_msg_fun(), + ServiceChangeRep = rsmms1_mgc_service_change_reply_msg(Mid, 1), + TermId1 = + #megaco_term_id{id = ["00000000","00000000","00000001"]}, + TermId2 = + #megaco_term_id{id = ["00000000","00000000","00000002"]}, + TermId3 = + #megaco_term_id{id = ["00000000","00000000","00000003"]}, + TermIds = [TermId1, TermId2, TermId3], + TransId = 2, + ReqId = 1, + CtxId = 1, + NrVerifyFun = + rsmms1_mgc_verify_notify_req_msg_fun(TermIds, TransId, ReqId, CtxId), + NotifyRep1 = + rsmms1_mgc_notify_reply_msg(1, Mid, TransId, CtxId, TermId1), + NotifyRep3 = + rsmms1_mgc_notify_reply_msg(3, Mid, TransId, CtxId, TermId3), + SrVerifyFun1 = rsmms1_mgc_verify_segment_reply_msg_fun(1, TransId), + SrVerifyFun3 = rsmms1_mgc_verify_segment_reply_msg_fun(3, TransId), + MissingSegVerifyFun = rsmms1_mgc_verify_missing_segment_fun("2"), + EvSeq = [{debug, false}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-request", {ScrVerifyFun, 5000}}, + {send, "service-change-reply", ServiceChangeRep}, + {expect_receive, "notify-request", {NrVerifyFun, 4000}}, + {sleep, 1000}, + {send, "notify reply - segment 1", NotifyRep1}, + {expect_receive, "segment reply 1", {SrVerifyFun1, 2000}}, + {sleep, 1000}, + {send, "notify reply - segment 3", NotifyRep3}, + {expect_receive, "segment reply 3", {SrVerifyFun3, 2000}}, + {expect_receive, "missing segment error", {MissingSegVerifyFun, 4000}}, + {expect_nothing, 10000}, + disconnect + ], + EvSeq. + +rsmms1_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:encode_message(Conf, M) + end. + +rsmms1_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:decode_message(Conf, M) + end. + +rsmms1_mgc_verify_service_change_req_msg_fun() -> + fun(Msg) -> + (catch rsmms1_mgc_verify_service_change_req(Msg)) + end. + +rsmms1_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) -> + io:format("rsmms1_mgc_verify_service_change_req -> entry with" + "~n M: ~p" + "~n", [M]), + Body = + case Mess of + #'Message'{version = 1, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = _TransId, + actions = [ActionReq]} -> + ActionReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + CR = + case AR of + #'ActionRequest'{contextId = _Cid, + commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_action, AR}}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + throw({error, {invalid_terminationID, Tid}}) + end, + case Parms of + %% Version 1 'ServiceChangeParm' + {'ServiceChangeParm', + restart, % serviceChangeMethod + asn1_NOVALUE, % serviceChangeAddress + ?VERSION, % serviceChangeVersion, + {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile + [[$9,$0,$1|_]], % serviceChangeReason + asn1_NOVALUE, % serviceChangeDelay + asn1_NOVALUE, % serviceChangeMgcId + asn1_NOVALUE, % timeStamp + asn1_NOVALUE % nonStandardData + } -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeParms, Parms}} + end. + +rsmms1_mgc_verify_notify_req_msg_fun(TermIds, TransId, Rid, Cid) -> + fun(Msg) -> + (catch rsmms1_mgc_verify_notify_req(Msg, + TermIds, TransId, Rid, Cid)) + end. + +rsmms1_mgc_verify_notify_req(#'MegacoMessage'{mess = Mess} = M, + TermIds, TransId, Rid, Cid) -> + io:format("rsmms1_mgc_verify_notify_req -> entry with" + "~n M: ~p" + "~n TermIds: ~p" + "~n TransId: ~p" + "~n Rid: ~p" + "~n Cid: ~p" + "~n", [M, TermIds, TransId, Rid, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = TransId, + actions = [ActReq]} -> + ActReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + Cmds = + case AR of + #'ActionRequest'{contextId = Cid, + commandRequests = Commands} -> + Commands; + _ -> + throw({error, {invalid_actions, AR}}) + end, + ok = rsmms1_mgc_verify_notify_req_cmds(TermIds, Cmds), + {ok, M}; +rsmms1_mgc_verify_notify_req(Crap, _TermId, _TransId, _Rid, _Cid) -> + {error, {invalid_MegacoMessage, Crap}}. + +rsmms1_mgc_verify_notify_req_cmds([], []) -> + ok; +rsmms1_mgc_verify_notify_req_cmds([TermId|TermIds], [Cmd|Cmds]) -> + rsmms1_mgc_verify_notify_req_cmd(TermId, Cmd), + rsmms1_mgc_verify_notify_req_cmds(TermIds, Cmds); +rsmms1_mgc_verify_notify_req_cmds(TermIds, Cmds) -> + throw({error, {invalid_commands, TermIds, Cmds}}). + +rsmms1_mgc_verify_notify_req_cmd(TermId, #'CommandRequest'{command = Cmd}) -> + io:format("rsmms1_mgc_verify_notify_req_cmd -> entry with" + "~n TermId: ~p" + "~n Cmd: ~p" + "~n", [TermId, Cmd]), + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + throw({error, {invalid_command}}) + end, + OED = + case NR of + #'NotifyRequest'{terminationID = [TermId], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + ObsEvsDesc; + _ -> + throw({error, {invalid_notifyReq, NR}}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + throw({error, {invalid_observedEventsDescriptor, OED}}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + ok; + _ -> + throw({error, {invalid_observedEventLst, OE}}) + end; +rsmms1_mgc_verify_notify_req_cmd(_, BadCmdReq) -> + io:format("rsmms1_mgc_verify_notify_req_cmd -> invalid" + "~n BadCmdReq: ~p" + "~n", [BadCmdReq]), + throw({error, {invalid_CommandRequest, BadCmdReq}}). + +rsmms1_mgc_verify_segment_reply_msg_fun(SN, TransId) -> + fun(Msg) -> + (catch rsmms1_mgc_verify_segment_reply(Msg, SN, TransId)) + end. + +rsmms1_mgc_verify_segment_reply(#'MegacoMessage'{mess = Mess} = M, + SN, TransId) -> + io:format("rsmms1_mgc_verify_segment_reply -> entry with" + "~n SN: ~p" + "~n TransId: ~p" + "~n M: ~p" + "~n", [SN, TransId, M]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + SR = + case Trans of + {segmentReply, SegmentReply} -> + SegmentReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + case SR of + #'SegmentReply'{transactionId = TransId, + segmentNumber = SN, + segmentationComplete = 'NULL'} when SN == 3 -> + {ok, M}; + #'SegmentReply'{transactionId = TransId, + segmentNumber = SN, + segmentationComplete = asn1_NOVALUE} -> + {ok, M}; + _ -> + throw({error, {invalid_segmentReply, SR}}) + end; +rsmms1_mgc_verify_segment_reply(Crap, SN, TransId) -> + io:format("rsmms1_mgc_verify_segment_reply -> invalid: " + "~n SN: ~p" + "~n TransId: ~p" + "~n Crap: ~p" + "~n", [SN, TransId, Crap]), + {error, {invalid_MegacoMessage, Crap, SN, TransId}}. + + +rsmms1_mgc_verify_missing_segment_fun(SN) -> + fun(Msg) -> (catch rsmms1_mgc_verify_missing_segment(Msg, SN)) end. + +rsmms1_mgc_verify_missing_segment(#'MegacoMessage'{mess = Mess} = M, Text) -> + io:format("rsmms1_mgc_verify_missing_segment -> entry with" + "~n Text: ~p" + "~n M: ~p" + "~n", [Text, M]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + case Body of + {messageError, + #'ErrorDescriptor'{errorCode = ?megaco_segments_not_received, + errorText = Text}} -> + {ok, M}; + _ -> + throw({error, {invalid_messageError, Body}}) + end; +rsmms1_mgc_verify_missing_segment(Crap, _SN) -> + {error, {invalid_MegacoMessage, Crap}}. + +rsmms1_mgc_service_change_reply_msg(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + TRes = cre_transResult([AR]), + TR = {'TransactionReply', 1, asn1_NOVALUE, TRes}, + Trans = cre_transaction(TR), + Mess = cre_message(1, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +rsmms1_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +rsmms1_mgc_notify_reply_msg(SN, Mid, TransId, Cid, TermId) -> + AR = rsmms1_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = + if + SN == 3 -> + cre_transReply(TransId, TRes, SN, 'NULL'); + true -> + cre_transReply(TransId, TRes, SN) + end, + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +rsmms1_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = rsmms1_mg_service_change_request_ar(Mid, 1), + ConnectVerify = rsmms1_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = rsmms1_mg_verify_service_change_reply_fun(), + Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]}, + Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]}, + Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]}, + Tids = [Tid1, Tid2, Tid3], + NotifyReq = rsmms1_mg_notify_request_ar(1, Tids, 1), + NotifyReplyVerify1 = rsmms1_mg_verify_notify_reply_fun(1, Tid1), + NotifyReplyVerify3 = rsmms1_mg_verify_notify_reply_fun(3, Tid3), + SegTimeoutVerify = rsmms1_mg_verify_segment_timeout_fun(2), + DiscoVerify = rsmms1_mg_verify_handle_disco_fun(), + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + %% {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {megaco_update_user_info, segment_recv_timer, 3000}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {megaco_update_conn_info, protocol_version, ?VERSION}, + {sleep, 1000}, + {megaco_cast, [NotifyReq], []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify1}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify3}, + {megaco_callback, handle_trans_reply, SegTimeoutVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +rsmms1_mg_verify_handle_connect_fun() -> + fun(Ev) -> rsmms1_mg_verify_handle_connect(Ev) end. + +rsmms1_mg_verify_handle_connect({handle_connect, CH, 1}) -> + io:format("rsmms1_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +rsmms1_mg_verify_handle_connect(Else) -> + io:format("rsmms1_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +rsmms1_mg_verify_service_change_reply_fun() -> + fun(Rep) -> rsmms1_mg_verify_scr(Rep) end. + +rsmms1_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) -> + (catch rsmms1_mg_do_verify_scr(AR)); +rsmms1_mg_verify_scr(Crap) -> + io:format("rsmms1_mg_verify_scr -> error: " + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + +rsmms1_mg_do_verify_scr(AR) -> + io:format("rsmms1_mg_do_verify_scr -> ok: " + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +rsmms1_mg_verify_notify_reply_fun(SN, Tid) -> + fun(Rep) -> rsmms1_mg_verify_notify_reply(Rep, SN, Tid) end. + +rsmms1_mg_verify_notify_reply( + {handle_trans_reply, _CH, ?VERSION, {ok, {SN, Last, [AR]}}, _}, SN, Tid) + when (Last == false) -> + (catch rsmms1_mg_do_verify_notify_reply(Tid, AR)); +rsmms1_mg_verify_notify_reply(Crap, SN, Tid) -> + io:format("rsmms1_mg_verify_notify_reply -> unknown reply" + "~n SN: ~p" + "~n Tid: ~p" + "~n Crap: ~p" + "~n", [SN, Tid, Crap]), + {error, Crap, ok}. + +rsmms1_mg_do_verify_notify_reply(Tid, AR) -> + io:format("rsmms1_mg_do_verify_notify_reply -> ok" + "~n Tid: ~p" + "~n AR: ~p" + "~n", [Tid, AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + case NR of + #'NotifyReply'{terminationID = [Tid], + errorDescriptor = asn1_NOVALUE} -> + {ok, AR, ok}; + _ -> + Reason3 = {invalid_NotifyReply, NR}, + {error, Reason3, ok} + end. + +rsmms1_mg_verify_segment_timeout_fun(SN) -> + fun(Rep) -> rsmms1_mg_verify_segment_timeout(Rep, SN) end. + +rsmms1_mg_verify_segment_timeout( + {handle_trans_reply, _CH, ?VERSION, {error, Reason}, _}, SN) -> + case Reason of + {segment_timeout, [SN]} -> + {ok, Reason, ok}; + _ -> + {error, {invalid_reason, Reason}, ok} + end; +rsmms1_mg_verify_segment_timeout(Crap, SN) -> + io:format("rsmms1_mg_verify_segment_timeout -> unknown reply" + "~n SN: ~p" + "~n Crap: ~p" + "~n", [SN, Crap]), + {error, Crap, ok}. + +rsmms1_mg_verify_handle_disco_fun() -> + fun(Ev) -> rsmms1_mg_verify_handle_disconnect(Ev) end. + +rsmms1_mg_verify_handle_disconnect({handle_disconnect, _CH, ?VERSION, R}) -> + io:format("rsmms1_mg_verify_handle_disconnect -> ok" + "~n R: ~p" + "~n", [R]), + case R of + {no_controlling_process,shutdown} -> + {ok, R, ok}; + _ -> + {error, {unexpected_reason, R}, ok} + end; +rsmms1_mg_verify_handle_disconnect(Crap) -> + io:format("rsmms1_mg_verify_handle_disconnect -> invalid: " + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + + +rsmms1_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +rsmms1_mg_notify_request_ar(Rid, Tids, Cid) -> + rsmms1_mg_notify_request_ar(Rid, Tids, Cid, []). + +rsmms1_mg_notify_request_ar(_Rid, [], Cid, Cmds) -> + cre_actionReq(Cid, lists:reverse(Cmds)); +rsmms1_mg_notify_request_ar(Rid, [Tid|Tids], Cid, Cmds) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + rsmms1_mg_notify_request_ar(Rid, Tids, Cid, [CR|Cmds]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +recv_segmented_msg_missing_seg2(suite) -> + []; +recv_segmented_msg_missing_seg2(doc) -> + "Received segmented megaco message with one segment missing " + "using incremental recv segment timer"; +recv_segmented_msg_missing_seg2(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, rsmms2), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = rsmms2_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = rsmms2_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_tcp_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% + +rsmms2_mgc_event_sequence(text, tcp) -> + DecodeFun = rsmms2_mgc_decode_msg_fun(megaco_pretty_text_encoder, []), + EncodeFun = rsmms2_mgc_encode_msg_fun(megaco_pretty_text_encoder, []), + Mid = {deviceName,"mgc"}, + ScrVerifyFun = rsmms2_mgc_verify_service_change_req_msg_fun(), + ServiceChangeRep = rsmms2_mgc_service_change_reply_msg(Mid, 1), + TermId1 = + #megaco_term_id{id = ["00000000","00000000","00000001"]}, + TermId2 = + #megaco_term_id{id = ["00000000","00000000","00000002"]}, + TermId3 = + #megaco_term_id{id = ["00000000","00000000","00000003"]}, + TermIds = [TermId1, TermId2, TermId3], + TransId = 2, + ReqId = 1, + CtxId = 1, + NrVerifyFun = + rsmms2_mgc_verify_notify_req_msg_fun(TermIds, TransId, ReqId, CtxId), + NotifyRep1 = + rsmms2_mgc_notify_reply_msg(1, Mid, TransId, CtxId, TermId1), + NotifyRep3 = + rsmms2_mgc_notify_reply_msg(3, Mid, TransId, CtxId, TermId3), + SrVerifyFun1 = rsmms2_mgc_verify_segment_reply_msg_fun(1, TransId), + SrVerifyFun3 = rsmms2_mgc_verify_segment_reply_msg_fun(3, TransId), + MissingSegVerifyFun = rsmms2_mgc_verify_missing_segment_fun("2"), + EvSeq = [{debug, false}, + {decode, DecodeFun}, + {encode, EncodeFun}, + {listen, 2944}, + {expect_accept, any}, + {expect_receive, "service-change-request", {ScrVerifyFun, 5000}}, + {send, "service-change-reply", ServiceChangeRep}, + {expect_receive, "notify-request", {NrVerifyFun, 4000}}, + {sleep, 1000}, + {send, "notify reply - segment 1", NotifyRep1}, + {expect_receive, "segment reply 1", {SrVerifyFun1, 2000}}, + {sleep, 1000}, + {send, "notify reply - segment 3", NotifyRep3}, + {expect_receive, "segment reply 3", {SrVerifyFun3, 2000}}, + {expect_receive, "missing segment error", {MissingSegVerifyFun, 4000}}, + {expect_nothing, 10000}, + disconnect + ], + EvSeq. + +rsmms2_mgc_encode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:encode_message(Conf, M) + end. + +rsmms2_mgc_decode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:decode_message(Conf, M) + end. + +rsmms2_mgc_verify_service_change_req_msg_fun() -> + fun(Msg) -> + (catch rsmms2_mgc_verify_service_change_req(Msg)) + end. + +rsmms2_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) -> + io:format("rsmms2_mgc_verify_service_change_req -> entry with" + "~n M: ~p" + "~n", [M]), + Body = + case Mess of + #'Message'{version = 1, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = _TransId, + actions = [ActionReq]} -> + ActionReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + CR = + case AR of + #'ActionRequest'{contextId = _Cid, + commandRequests = [CmdReq]} -> + CmdReq; + _ -> + throw({error, {invalid_action, AR}}) + end, + Cmd = + case CR of + #'CommandRequest'{command = Command} -> + Command; + _ -> + throw({error, {invalid_commandRequest, CR}}) + end, + {Tid, Parms} = + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [TermID], + serviceChangeParms = ServChParms}} -> + {TermID, ServChParms}; + _ -> + throw({error, {invalid_command, Cmd}}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + throw({error, {invalid_terminationID, Tid}}) + end, + case Parms of + %% Version 1 'ServiceChangeParm' + {'ServiceChangeParm', + restart, % serviceChangeMethod + asn1_NOVALUE, % serviceChangeAddress + ?VERSION, % serviceChangeVersion, + {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile + [[$9,$0,$1|_]], % serviceChangeReason + asn1_NOVALUE, % serviceChangeDelay + asn1_NOVALUE, % serviceChangeMgcId + asn1_NOVALUE, % timeStamp + asn1_NOVALUE % nonStandardData + } -> + {ok, M}; + _ -> + {error, {invalid_serviceChangeParms, Parms}} + end. + +rsmms2_mgc_verify_notify_req_msg_fun(TermIds, TransId, Rid, Cid) -> + fun(Msg) -> + (catch rsmms2_mgc_verify_notify_req(Msg, + TermIds, TransId, Rid, Cid)) + end. + +rsmms2_mgc_verify_notify_req(#'MegacoMessage'{mess = Mess} = M, + TermIds, TransId, Rid, Cid) -> + io:format("rsmms2_mgc_verify_notify_req -> entry with" + "~n M: ~p" + "~n TermIds: ~p" + "~n TransId: ~p" + "~n Rid: ~p" + "~n Cid: ~p" + "~n", [M, TermIds, TransId, Rid, Cid]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + TR = + case Trans of + {transactionRequest, TransRequest} -> + TransRequest; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + AR = + case TR of + #'TransactionRequest'{transactionId = TransId, + actions = [ActReq]} -> + ActReq; + _ -> + throw({error, {invalid_transactionRequest, TR}}) + end, + Cmds = + case AR of + #'ActionRequest'{contextId = Cid, + commandRequests = Commands} -> + Commands; + _ -> + throw({error, {invalid_actions, AR}}) + end, + ok = rsmms2_mgc_verify_notify_req_cmds(TermIds, Cmds), + {ok, M}; +rsmms2_mgc_verify_notify_req(Crap, _TermId, _TransId, _Rid, _Cid) -> + {error, {invalid_MegacoMessage, Crap}}. + +rsmms2_mgc_verify_notify_req_cmds([], []) -> + ok; +rsmms2_mgc_verify_notify_req_cmds([TermId|TermIds], [Cmd|Cmds]) -> + rsmms2_mgc_verify_notify_req_cmd(TermId, Cmd), + rsmms2_mgc_verify_notify_req_cmds(TermIds, Cmds); +rsmms2_mgc_verify_notify_req_cmds(TermIds, Cmds) -> + throw({error, {invalid_commands, TermIds, Cmds}}). + +rsmms2_mgc_verify_notify_req_cmd(TermId, #'CommandRequest'{command = Cmd}) -> + io:format("rsmms2_mgc_verify_notify_req_cmd -> entry with" + "~n TermId: ~p" + "~n Cmd: ~p" + "~n", [TermId, Cmd]), + NR = + case Cmd of + {notifyReq, NotifReq} -> + NotifReq; + _ -> + throw({error, {invalid_command}}) + end, + OED = + case NR of + #'NotifyRequest'{terminationID = [TermId], + observedEventsDescriptor = ObsEvsDesc, + errorDescriptor = asn1_NOVALUE} -> + ObsEvsDesc; + _ -> + throw({error, {invalid_notifyReq, NR}}) + end, + OE = + case OED of + #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} -> + ObsEvLst; + _ -> + throw({error, {invalid_observedEventsDescriptor, OED}}) + end, + case OE of + #'ObservedEvent'{eventName = "al/of"} -> + ok; + _ -> + throw({error, {invalid_observedEventLst, OE}}) + end; +rsmms2_mgc_verify_notify_req_cmd(_, BadCmdReq) -> + io:format("rsmms2_mgc_verify_notify_req_cmd -> invalid" + "~n BadCmdReq: ~p" + "~n", [BadCmdReq]), + throw({error, {invalid_CommandRequest, BadCmdReq}}). + +rsmms2_mgc_verify_segment_reply_msg_fun(SN, TransId) -> + fun(Msg) -> + (catch rsmms2_mgc_verify_segment_reply(Msg, SN, TransId)) + end. + +rsmms2_mgc_verify_segment_reply(#'MegacoMessage'{mess = Mess} = M, + SN, TransId) -> + io:format("rsmms2_mgc_verify_segment_reply -> entry with" + "~n SN: ~p" + "~n TransId: ~p" + "~n M: ~p" + "~n", [SN, TransId, M]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _MgMid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + Trans = + case Body of + {transactions, [Transactions]} -> + Transactions; + _ -> + throw({error, {invalid_messageBody, Body}}) + end, + SR = + case Trans of + {segmentReply, SegmentReply} -> + SegmentReply; + _ -> + throw({error, {invalid_transactions, Trans}}) + end, + case SR of + #'SegmentReply'{transactionId = TransId, + segmentNumber = SN, + segmentationComplete = 'NULL'} when SN == 3 -> + {ok, M}; + #'SegmentReply'{transactionId = TransId, + segmentNumber = SN, + segmentationComplete = asn1_NOVALUE} -> + {ok, M}; + _ -> + throw({error, {invalid_segmentReply, SR}}) + end; +rsmms2_mgc_verify_segment_reply(Crap, SN, TransId) -> + io:format("rsmms2_mgc_verify_segment_reply -> invalid: " + "~n SN: ~p" + "~n TransId: ~p" + "~n Crap: ~p" + "~n", [SN, TransId, Crap]), + {error, {invalid_MegacoMessage, Crap, SN, TransId}}. + + +rsmms2_mgc_verify_missing_segment_fun(SN) -> + fun(Msg) -> (catch rsmms2_mgc_verify_missing_segment(Msg, SN)) end. + +rsmms2_mgc_verify_missing_segment(#'MegacoMessage'{mess = Mess} = M, Text) -> + io:format("rsmms2_mgc_verify_missing_segment -> entry with" + "~n Text: ~p" + "~n M: ~p" + "~n", [Text, M]), + Body = + case Mess of + #'Message'{version = ?VERSION, + mId = _Mid, + messageBody = MsgBody} -> + MsgBody; + _ -> + throw({error, {invalid_Message, Mess}}) + end, + case Body of + {messageError, + #'ErrorDescriptor'{errorCode = ?megaco_segments_not_received, + errorText = Text}} -> + {ok, M}; + _ -> + throw({error, {invalid_messageError, Body}}) + end; +rsmms2_mgc_verify_missing_segment(Crap, _SN) -> + {error, {invalid_MegacoMessage, Crap}}. + +rsmms2_mgc_service_change_reply_msg(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + AR = cre_actionReply(Cid, [CR]), + TRes = cre_transResult([AR]), + TR = {'TransactionReply', 1, asn1_NOVALUE, TRes}, + Trans = cre_transaction(TR), + Mess = cre_message(1, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +rsmms2_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +rsmms2_mgc_notify_reply_msg(SN, Mid, TransId, Cid, TermId) -> + AR = rsmms2_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = + if + SN == 3 -> + cre_transReply(TransId, TRes, SN, 'NULL'); + true -> + cre_transReply(TransId, TRes, SN) + end, + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +rsmms2_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + SegRecvTmr = #megaco_incr_timer{wait_for = 1000, + factor = 1, + incr = 0, + max_retries = 2 + }, + ServiceChangeReq = rsmms2_mg_service_change_request_ar(Mid, 1), + ConnectVerify = rsmms2_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = rsmms2_mg_verify_service_change_reply_fun(), + Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]}, + Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]}, + Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]}, + Tids = [Tid1, Tid2, Tid3], + NotifyReq = rsmms2_mg_notify_request_ar(1, Tids, 1), + NotifyReplyVerify1 = rsmms2_mg_verify_notify_reply_fun(1, Tid1), + NotifyReplyVerify3 = rsmms2_mg_verify_notify_reply_fun(3, Tid3), + SegTimeoutVerify = rsmms2_mg_verify_segment_timeout_fun(2), + DiscoVerify = rsmms2_mg_verify_handle_disco_fun(), + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + %% {megaco_trace, max}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {megaco_update_user_info, segment_recv_timer, SegRecvTmr}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, [ServiceChangeReq], []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {megaco_update_conn_info, protocol_version, ?VERSION}, + {sleep, 1000}, + {megaco_cast, [NotifyReq], []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify1}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify3}, + {megaco_callback, handle_trans_reply, SegTimeoutVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +rsmms2_mg_verify_handle_connect_fun() -> + fun(Ev) -> rsmms2_mg_verify_handle_connect(Ev) end. + +rsmms2_mg_verify_handle_connect({handle_connect, CH, 1}) -> + io:format("rsmms2_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +rsmms2_mg_verify_handle_connect(Else) -> + io:format("rsmms2_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +rsmms2_mg_verify_service_change_reply_fun() -> + fun(Rep) -> rsmms2_mg_verify_scr(Rep) end. + +rsmms2_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) -> + (catch rsmms2_mg_do_verify_scr(AR)); +rsmms2_mg_verify_scr(Crap) -> + io:format("rsmms2_mg_verify_scr -> error: " + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + +rsmms2_mg_do_verify_scr(AR) -> + io:format("rsmms2_mg_do_verify_scr -> ok: " + "~n AR: ~p~n", [AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + SCR = + case CR of + {serviceChangeReply, ServChRep} -> + ServChRep; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + {Tid, SCRes} = + case SCR of + #'ServiceChangeReply'{terminationID = [TermID], + serviceChangeResult = Res} -> + {TermID, Res}; + _ -> + Reason3 = {invalid_service_change_reply, SCR}, + throw({error, Reason3, ok}) + end, + case Tid of + #megaco_term_id{contains_wildcards = false, id = ["root"]} -> + ok; + _ -> + Reason4 = {invalid_termination_id, Tid}, + throw({error, Reason4, ok}) + end, + SCRParm = + case SCRes of + {serviceChangeResParms, ServChResParms} -> + ServChResParms; + _ -> + Reason5 = {invalid_serviceChangeResult, SCRes}, + throw({error, Reason5, ok}) + end, + case SCRParm of + #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} -> + {ok, AR, ok}; + _ -> + Reason6 = {invalid_service_change_result, SCRParm}, + {error, Reason6, ok} + end. + +rsmms2_mg_verify_notify_reply_fun(SN, Tid) -> + fun(Rep) -> rsmms2_mg_verify_notify_reply(Rep, SN, Tid) end. + +rsmms2_mg_verify_notify_reply( + {handle_trans_reply, _CH, ?VERSION, {ok, {SN, Last, [AR]}}, _}, SN, Tid) + when (Last == false) -> + (catch rsmms2_mg_do_verify_notify_reply(Tid, AR)); +rsmms2_mg_verify_notify_reply(Crap, SN, Tid) -> + io:format("rsmms2_mg_verify_notify_reply -> unknown reply" + "~n SN: ~p" + "~n Tid: ~p" + "~n Crap: ~p" + "~n", [SN, Tid, Crap]), + {error, Crap, ok}. + +rsmms2_mg_do_verify_notify_reply(Tid, AR) -> + io:format("rsmms2_mg_do_verify_notify_reply -> ok" + "~n Tid: ~p" + "~n AR: ~p" + "~n", [Tid, AR]), + CR = + case AR of + #'ActionReply'{commandReply = [CmdRep]} -> + CmdRep; + _ -> + Reason1 = {invalid_action_reply, AR}, + throw({error, Reason1, ok}) + end, + NR = + case CR of + {notifyReply, NotifyReply} -> + NotifyReply; + _ -> + Reason2 = {invalid_command_reply, CR}, + throw({error, Reason2, ok}) + end, + case NR of + #'NotifyReply'{terminationID = [Tid], + errorDescriptor = asn1_NOVALUE} -> + {ok, AR, ok}; + _ -> + Reason3 = {invalid_NotifyReply, NR}, + {error, Reason3, ok} + end. + +rsmms2_mg_verify_segment_timeout_fun(SN) -> + fun(Rep) -> rsmms2_mg_verify_segment_timeout(Rep, SN) end. + +rsmms2_mg_verify_segment_timeout( + {handle_trans_reply, _CH, ?VERSION, {error, Reason}, _}, SN) -> + case Reason of + {segment_timeout, [SN]} -> + {ok, Reason, ok}; + _ -> + {error, {invalid_reason, Reason}, ok} + end; +rsmms2_mg_verify_segment_timeout(Crap, SN) -> + io:format("rsmms2_mg_verify_segment_timeout -> unknown reply" + "~n SN: ~p" + "~n Crap: ~p" + "~n", [SN, Crap]), + {error, Crap, ok}. + +rsmms2_mg_verify_handle_disco_fun() -> + fun(Ev) -> rsmms2_mg_verify_handle_disconnect(Ev) end. + +rsmms2_mg_verify_handle_disconnect({handle_disconnect, _CH, ?VERSION, R}) -> + io:format("rsmms2_mg_verify_handle_disconnect -> ok" + "~n R: ~p" + "~n", [R]), + case R of + {no_controlling_process,shutdown} -> + {ok, R, ok}; + _ -> + {error, {unexpected_reason, R}, ok} + end; +rsmms2_mg_verify_handle_disconnect(Crap) -> + io:format("rsmms2_mg_verify_handle_disconnect -> invalid: " + "~n Crap: ~p" + "~n", [Crap]), + {error, Crap, ok}. + + +rsmms2_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +rsmms2_mg_notify_request_ar(Rid, Tids, Cid) -> + rsmms2_mg_notify_request_ar(Rid, Tids, Cid, []). + +rsmms2_mg_notify_request_ar(_Rid, [], Cid, Cmds) -> + cre_actionReq(Cid, lists:reverse(Cmds)); +rsmms2_mg_notify_request_ar(Rid, [Tid|Tids], Cid, Cmds) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + rsmms2_mg_notify_request_ar(Rid, Tids, Cid, [CR|Cmds]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Common message creation functions +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% cre_errorDesc(Code, Text) when is_list(Text) -> +%% #'ErrorDescriptor'{errorCode = Code, errorText = Text}; +%% cre_errorDesc(Code, Text0) -> +%% Text = lists:flatten(io_lib:format("~w",[Text0])), +%% #'ErrorDescriptor'{errorCode = Code, errorText = Text}. + +cre_segReply(TransId, SN, SC) -> + megaco_test_msg_v3_lib:cre_SegmentReply(TransId, SN, SC). + +cre_serviceChangeParm(M,R,P) -> + %% Version 1 'ServiceChangeParm' + {'ServiceChangeParm', + M, % serviceChangeMethod, + asn1_NOVALUE, % serviceChangeAddress + ?VERSION, % serviceChangeVersion + P, % serviceChangeProfile + R, % serviceChangeReason + asn1_NOVALUE, % serviceChangeDelay + asn1_NOVALUE, % serviceChangeMgcId + asn1_NOVALUE, % timeStamp + asn1_NOVALUE % nonStandardData + }. + +cre_serviceChangeReq(Tid, Parms) -> + #'ServiceChangeRequest'{terminationID = Tid, + serviceChangeParms = Parms}. + +cre_timeNotation(D,T) -> + #'TimeNotation'{date = D, time = T}. + +cre_obsEvent(Name, Not) -> + #'ObservedEvent'{eventName = Name, + timeNotation = Not}. +%% cre_obsEvent(Name, Not, Par) -> +%% #'ObservedEvent'{eventName = Name, +%% timeNotation = Not, +%% eventParList = Par}. + +cre_obsEvsDesc(Id, EvList) -> + #'ObservedEventsDescriptor'{requestId = Id, + observedEventLst = EvList}. + +cre_notifyReq(Tid, EvsDesc) -> + #'NotifyRequest'{terminationID = Tid, + observedEventsDescriptor = EvsDesc}. + +cre_command(R) when is_record(R, 'NotifyRequest') -> + {notifyReq, R}; +cre_command(R) when is_record(R, 'ServiceChangeRequest') -> + {serviceChangeReq, R}. + +cre_cmdReq(Cmd) -> + #'CommandRequest'{command = Cmd}. + +cre_actionReq(CtxId, CmdReqs) when is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxId, + commandRequests = CmdReqs}. + +cre_transReq(TransId, ARs) when is_list(ARs) -> + #'TransactionRequest'{transactionId = TransId, + actions = ARs}. + +%% -- + +cre_serviceChangeResParm(Mid) -> + cre_serviceChangeResParm(Mid, ?VERSION). + +cre_serviceChangeResParm(Mid, V) -> + #'ServiceChangeResParm'{serviceChangeMgcId = Mid, + serviceChangeVersion = V}. + +cre_serviceChangeResult(SCRP) when is_record(SCRP, 'ServiceChangeResParm') -> + {serviceChangeResParms, SCRP}; +cre_serviceChangeResult(ED) when is_record(ED, 'ErrorDescriptor') -> + {errorDescriptor, ED}. + +cre_serviceChangeReply(Tid, Res) -> + #'ServiceChangeReply'{terminationID = Tid, + serviceChangeResult = Res}. + +cre_cmdReply(R) when is_record(R, 'NotifyReply') -> + {notifyReply, R}; +cre_cmdReply(R) when is_record(R, 'ServiceChangeReply') -> + {serviceChangeReply, R}. + +cre_notifyReply(Tid) -> + #'NotifyReply'{terminationID = Tid}. + +cre_actionReply(CtxId, CmdRep) -> + #'ActionReply'{contextId = CtxId, + commandReply = CmdRep}. + +cre_transResult(ED) when is_record(ED, 'ErrorDescriptor') -> + {transactionError, ED}; +cre_transResult([AR|_] = ARs) when is_record(AR, 'ActionReply') -> + {actionReplies, ARs}. + +%% cre_transReply(TransId, Res) -> +%% #'TransactionReply'{transactionId = TransId, +%% transactionResult = Res}. + +cre_transReply(TransId, Res, SN) -> + #'TransactionReply'{transactionId = TransId, + transactionResult = Res, + segmentNumber = SN}. + +cre_transReply(TransId, Res, SN, SC) -> + #'TransactionReply'{transactionId = TransId, + transactionResult = Res, + segmentNumber = SN, + segmentationComplete = SC}. + +cre_transAck(TransId) -> + megaco_test_msg_v3_lib:cre_TransactionAck(TransId). + + +%% -- + +cre_serviceChangeProf(Name, Ver) when is_list(Name) andalso is_integer(Ver) -> + #'ServiceChangeProfile'{profileName = Name, + version = Ver}. + +cre_transaction(Trans) when is_record(Trans, 'TransactionRequest') -> + {transactionRequest, Trans}; +cre_transaction(Trans) when is_record(Trans, 'TransactionPending') -> + {transactionPending, Trans}; +cre_transaction(Trans) + when is_record(Trans, 'TransactionReply') or + (is_tuple(Trans) and (element(1, Trans) == 'TransactionReply')) -> + {transactionReply, Trans}; +cre_transaction(Trans) when is_list(Trans) -> + {transactionResponseAck, Trans}; +cre_transaction(SR) when is_record(SR, 'SegmentReply') -> + {segmentReply, SR}. + +cre_transactions(Trans) when is_list(Trans) -> + {transactions, Trans}. + +cre_message(Version, Mid, Body) -> + #'Message'{version = Version, + mId = Mid, + messageBody = Body}. + +cre_megacoMessage(Mess) -> + #'MegacoMessage'{mess = Mess}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Transform a short timer to a long one. +%% The purpose of this is to trick the stack +%% to keep re-sending the request, even after +%% having received the first pending (which +%% indicates that the other side _IS_ +%% working on the request). +-ifdef(MEGACO_TEST_CODE). + +init_request_timer({short, Ref}) -> + {long, Ref}; +init_request_timer(O) -> + O. + +-endif. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +await_completion(Ids) -> + case megaco_test_generator_lib:await_completion(Ids) of + {ok, Reply} -> + d("OK => Reply: ~n~p", [Reply]), + ok; + {error, {OK, ERROR}} -> + d("ERROR => " + "~n OK: ~p" + "~n ERROR: ~p", [OK, ERROR]), + ?ERROR({failed, ERROR}); + {error, Reply} -> + d("ERROR => " + "~n Reply: ~p", [Reply]), + ?ERROR({failed, Reply}) + end. + +%% await_completion(Ids, Timeout) -> +%% case megaco_test_generator_lib:await_completion(Ids, Timeout) of +%% {ok, Reply} -> +%% d("OK => Reply: ~n~p", [Reply]), +%% ok; +%% {error, {OK, ERROR}} -> +%% d("ERROR => " +%% "~n OK: ~p" +%% "~n ERROR: ~p", [OK, ERROR]), +%% ?ERROR({failed, ERROR}); +%% {error, Reply} -> +%% d("ERROR => Reply: ~n~p", [Reply]), +%% ?ERROR({failed, Reply}) +%% end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% tim() -> +%% {A,B,C} = erlang:now(), +%% A*1000000000+B*1000+(C div 1000). + + +make_node_name(Name) -> + case string:tokens(atom_to_list(node()), [$@]) of + [_,Host] -> + list_to_atom(lists:concat([atom_to_list(Name) ++ "@" ++ Host])); + _ -> + exit("Test node must be started with '-sname'") + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +sleep(X) -> receive after X -> ok end. + +%% error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +i(F) -> + i(F, []). + +i(F, A) -> + print(info, get(verbosity), now(), get(tc), "INF", F, A). + + +d(F) -> + d(F, []). + +d(F, A) -> + print(debug, get(verbosity), now(), get(tc), "DBG", F, A). + + +printable(_, debug) -> true; +printable(info, info) -> true; +printable(_,_) -> false. + +print(Severity, Verbosity, Ts, Tc, P, F, A) -> + print(printable(Severity,Verbosity), Ts, Tc, P, F, A). + +print(true, Ts, Tc, P, F, A) -> + io:format("*** [~s] ~s ~p ~s:~w ***" + "~n " ++ F ++ "~n", + [format_timestamp(Ts), P, self(), get(sname), Tc | A]); +print(_, _, _, _, _, _) -> + ok. + +format_timestamp(Now) -> megaco:format_timestamp(Now). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% random_init() -> +%% {A,B,C} = now(), +%% random:seed(A,B,C). + +%% random() -> +%% 10 * random:uniform(50). + +%% apply_load_timer() -> +%% erlang:send_after(random(), self(), apply_load_timeout). + + + diff --git a/lib/megaco/test/megaco_tc_controller.erl b/lib/megaco/test/megaco_tc_controller.erl new file mode 100644 index 0000000000..dedf45e321 --- /dev/null +++ b/lib/megaco/test/megaco_tc_controller.erl @@ -0,0 +1,171 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: +%%---------------------------------------------------------------------- +-module(megaco_tc_controller). + +-export([start_link/0, stop/0, + insert/2, lookup/1, delete/1]). +-export([init/2]). + +-include("megaco_test_lib.hrl"). + +-define(SERVER, ?MODULE). +-define(TABLE, ?MODULE). + +start_link() -> + p("start_link -> entry"), + Pid = spawn_link(?MODULE, init, [self(),get(dbg)]), + receive + {tc_started, Pid, Reply} -> + p("start_link -> ~n ~p", [Reply]), + Reply + end. + +stop() -> + request(stop, undefined). + +insert(Key, Val) -> + request(insert, {Key, Val}). + +lookup(Key) -> + case request(lookup, Key) of + {value, _} = Value -> + Value; + _ -> + false + end. + +delete(Key) -> + request(delete, Key). + +request(Tag, Data) -> + p("request -> entry with" + "~n Tag: ~p" + "~n Data: ~p", [Tag, Data]), + case global:whereis_name(?SERVER) of + Pid when is_pid(Pid) -> + Pid ! {Tag, self(), Data}, + receive + {Tag, Pid, Reply} -> + p("request -> response: " + "~n Reply: ~p", [Reply]), + Reply + end; + _ -> + {error, not_started} + end. + +init(Parent, true) -> + put(dbg,true), + init(Parent); +init(Parent, _) -> + init(Parent). + +init(Parent) -> + p("init -> entry with" + "~n Parent: ~p", [Parent]), + ets:new(?TABLE, [named_table, protected, set]), + case global:register_name(?SERVER, self()) of + yes -> + p("init -> registration ok"), + Parent ! {tc_started, self(), ok}, + loop(Parent); + no -> + p("init -> registration failed"), + Parent ! {tc_started, self(), {error, already_registered}}, + exit(normal) + end. + +loop(Parent) -> + p("loop -> entry"), + receive + {insert, Parent, {Key, Val}} -> + p("loop -> received insert request when" + "~n Key: ~p" + "~n Val: ~p", [Key, Val]), + ets:insert(?TABLE, {Key, Val}), + Parent ! {insert, self(), ok}; + {delete, Parent, Key} -> + p("loop -> received delete request when" + "~n Key: ~p", [Key]), + ets:delete(?TABLE, Key), + Parent ! {delete, self(), ok}; + {lookup, From, Key} when is_pid(From) -> + p("loop -> received lookup request when" + "~n Key: ~p", [Key]), + case ets:lookup(?TABLE, Key) of + [{Key, Val}] -> + p("loop -> lookup: ~p", [Val]), + From ! {lookup, self(), {value, Val}}; + _ -> + p("loop -> lookup unsuccessful"), + From ! {lookup, self(), false} + end; + {stop, Parent, _} -> + p("loop -> received stop request"), + ets:delete(?TABLE), + global:unregister_name(?SERVER), + Parent ! {stop, self(), ok}, + exit(normal); + + {'EXIT', Parent, Reason} when is_pid(Parent) -> + p("loop -> received exit signal from parent" + "~n Reason: ~p", [Reason]), + exit(Reason); + + {UnknownRequest, Parent, UnknownData} when is_pid(Parent) -> + p("loop -> received unknown request when" + "~n UnknownRequest: ~p" + "~n UnknownData: ~p", [UnknownRequest, UnknownData]), + Error = {error, {unknown_request, {UnknownRequest, UnknownData}}}, + Parent ! {UnknownRequest, self(), Error}; + + {Request, From, Data} when is_pid(From) -> + p("loop -> received request from unknown when" + "~n Request: ~p" + "~n From: ~p" + "~n Data: ~p", [Request, From, Data]), + Error = {error, {unknown_request, {Request, Data}}}, + Parent ! {Request, self(), Error}; + + Crap -> + p("loop -> received crap: " + "~n Crap: ~p" + "~nwhen" + "~n Parent: ~p", [Crap, Parent]), + ok + end, + loop(Parent). + + +p(F) -> + p(F, []). + +p(F, A) -> + p(get(dbg), F, A). + +p(true, F, A) -> + io:format("~w:~p:" ++ F ++ "~n", [?MODULE, self()|A]); +p(_, _, _) -> + ok. + diff --git a/lib/megaco/test/megaco_tcp_test.erl b/lib/megaco/test/megaco_tcp_test.erl new file mode 100644 index 0000000000..31c88489fe --- /dev/null +++ b/lib/megaco/test/megaco_tcp_test.erl @@ -0,0 +1,1253 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: +%%---------------------------------------------------------------------- +-module(megaco_tcp_test). + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include_lib("megaco/src/tcp/megaco_tcp.hrl"). +-include("megaco_test_lib.hrl"). + +%% -compile(export_all). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([ + all/1, + + start/1, + start_normal/1, + start_invalid_opt/1, + start_and_stop/1, + + sending/1, + sendreceive/1, + block_unblock/1, + + errors/1, + socket_failure/1, + accept_process/1, + accept_supervisor/1, + connection_supervisor/1, + tcp_server/1, + + init_per_testcase/2, fin_per_testcase/2, + + t/0, t/1 + ]). + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- + +-export([ + receive_message/4, + process_received_message/4 + ]). + + +%%---------------------------------------------------------------------- +%% Macros +%%---------------------------------------------------------------------- + +%%---------------------------------------------------------------------- +%% Records +%%---------------------------------------------------------------------- + +-record(command, {id, desc, cmd}). +-record(server, {parent, transport_ref, control_pid, handle}). +-record(client, {parent, transport_ref, control_pid, handle}). + + +%%====================================================================== +%% External functions +%%====================================================================== +%%---------------------------------------------------------------------- +%% Function: t/0 +%% Description: Run all test cases +%%---------------------------------------------------------------------- +t() -> megaco_test_lib:t(?MODULE). + + +%%---------------------------------------------------------------------- +%% Function: t/1 +%% Description: Run the specified test cases +%%---------------------------------------------------------------------- +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + + +%%====================================================================== +%% Test server callbacks +%%====================================================================== +%%---------------------------------------------------------------------- +%% Function: init_per_testcase/2 +%% Description: +%%---------------------------------------------------------------------- +init_per_testcase(Case, Config) -> + megaco_test_lib:init_per_testcase(Case, Config). + + +%%---------------------------------------------------------------------- +%% Function: fin_per_testcase/2 +%% Description: +%%---------------------------------------------------------------------- +fin_per_testcase(Case, Config) -> + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%====================================================================== +%% Test case definitions +%%====================================================================== +all(suite) -> + [ + start, + sending, + errors + ]. + +start(suite) -> + [ + start_normal, + start_invalid_opt, + start_and_stop + ]. + +sending(suite) -> + [ + sendreceive, + block_unblock + ]. + +errors(suite) -> + [ + socket_failure, + accept_process, + accept_supervisor, + connection_supervisor, + tcp_server + ]. + + +%% ------------------ start ------------------------ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_normal(suite) -> + []; +start_normal(Config) when is_list(Config) -> + put(sname, "start_normal"), + p("BEGIN TEST-CASE"), + Options = [{port, 20000}, {receive_handle, apa}], + {ok, Pid} = start_case(Options, ok), + megaco_tcp:stop_transport(Pid), + p("done"), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_invalid_opt(suite) -> + []; +start_invalid_opt(Config) when is_list(Config) -> + put(sname, "start_invalid_opt"), + p("BEGIN TEST-CASE"), + Options = [{port, 20000}, {receivehandle, apa}], + ok = start_case(Options, error), + p("done"), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_and_stop(suite) -> + []; +start_and_stop(doc) -> + ["This test case sets up a connection and then cloises it. " + "No data is sent. "]; +start_and_stop(Config) when is_list(Config) -> + put(sname, "start_and_stop"), + p("BEGIN TEST-CASE"), + + process_flag(trap_exit, true), + + p("create nodes"), + ServerNode = make_node_name(server), + ClientNode = make_node_name(client), + Nodes = [ServerNode, ClientNode], + ok = megaco_test_lib:start_nodes(Nodes, ?FILE, ?LINE), + + %% Create command sequences + p("create command sequences"), + ServerPort = 2944, + ServerCmds = start_and_stop_server_commands(ServerPort), + {ok, ServerHost} = inet:gethostname(), + ClientCmds = start_and_stop_client_commands(ServerPort, ServerHost), + + %% Start the test procs used in the test-case, one for each node + p("start command handlers"), + Server = server_start_command_handler(ServerNode, ServerCmds), + p("server command handler started: ~p", [Server]), + Client = client_start_command_handler(ClientNode, ClientCmds), + p("client command handler started: ~p", [Client]), + + ok = + receive + {listening, Server} -> + p("received listening message from server [~p] => " + "send continue to client [~p]~n", [Server, Client]), + Client ! {continue, self()}, + ok + after 5000 -> + {error, server_timeout} + end, + + await_command_handler_completion([Server, Client], timer:seconds(20)), + p("done"), + ok. + + +start_and_stop_server_commands(Port) -> + Opts = [{port, Port}], + Self = self(), + [ + #command{id = 1, + desc = "Command sequence init", + cmd = fun(State) -> + {ok, State#server{parent = Self}} + end}, + + #command{id = 2, + desc = "Start transport", + cmd = fun(State) -> + server_start_transport(State) + end}, + + #command{id = 3, + desc = "Listen", + cmd = fun(State) -> + server_listen(State, Opts) + end}, + + #command{id = 4, + desc = "Notify listening", + cmd = fun(State) -> + server_notify_listening(State) + end}, + + #command{id = 5, + desc = "Await nothing", + cmd = fun(State) -> + server_await_nothing(State, 6000) + end}, + + #command{id = 6, + desc = "Stop", + cmd = fun(State) -> + server_stop_transport(State) + end} + + ]. + + +start_and_stop_client_commands(ServerPort, ServerHost) -> + Opts = [{port, ServerPort}, {host, ServerHost}], + Self = self(), + [ + #command{id = 1, + desc = "Command sequence init", + cmd = fun(State) -> + {ok, State#client{parent = Self}} + end}, + + #command{id = 2, + desc = "Start transport", + cmd = fun(State) -> + client_start_transport(State) + end}, + + #command{id = 3, + desc = "Await continue", + cmd = fun(State) -> + client_await_continue_signal(State, 5000) + end}, + + #command{id = 4, + desc = "Connect", + cmd = fun(State) -> + client_connect(State, Opts) + end}, + + #command{id = 5, + desc = "Await nothing", + cmd = fun(State) -> + client_await_nothing(State, 5000) + end}, + + #command{id = 6, + desc = "Disconnect", + cmd = fun(State) -> + client_disconnect(State) + end}, + + #command{id = 7, + desc = "Stop transport", + cmd = fun(State) -> + client_stop_transport(State) + end} + ]. + + +%% ------------------ sending ------------------------ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +sendreceive(suite) -> + []; +sendreceive(Config) when is_list(Config) -> + put(sname, "sendreceive"), + p("BEGIN TEST-CASE"), + + process_flag(trap_exit, true), + + p("create nodes"), + ServerNode = make_node_name(server), + ClientNode = make_node_name(client), + Nodes = [ServerNode, ClientNode], + ok = megaco_test_lib:start_nodes(Nodes, ?FILE, ?LINE), + + %% Create command sequences + p("create command sequences"), + ServerPort = 2944, + ServerCmds = sendreceive_server_commands(ServerPort), + {ok, ServerHost} = inet:gethostname(), + ClientCmds = sendreceive_client_commands(ServerPort, ServerHost), + + %% Start the test procs used in the test-case, one for each node + p("start command handlers"), + Server = server_start_command_handler(ServerNode, ServerCmds), + p("server command handler started: ~p", [Server]), + Client = client_start_command_handler(ClientNode, ClientCmds), + p("client command handler started: ~p", [Client]), + + ok = + receive + {listening, Server} -> + p("received listening message from server [~p] => " + "send continue to client [~p]~n", [Server, Client]), + Client ! {continue, self()}, + ok + after 5000 -> + {error, server_timeout} + end, + + await_command_handler_completion([Server, Client], timer:seconds(20)), + p("done"), + ok. + + +sendreceive_server_commands(Port) -> + Opts = [{port, Port}], + Self = self(), + [ + #command{id = 1, + desc = "Command sequence init", + cmd = fun(State) -> + {ok, State#server{parent = Self}} + end}, + + #command{id = 2, + desc = "Start transport", + cmd = fun(State) -> + server_start_transport(State) + end}, + + #command{id = 3, + desc = "Listen", + cmd = fun(State) -> + server_listen(State, Opts) + end}, + + #command{id = 4, + desc = "Notify listening", + cmd = fun(State) -> + server_notify_listening(State) + end}, + + #command{id = 5, + desc = "Await initial message (ping)", + cmd = fun(State) -> + server_await_initial_message(State, "ping", 5000) + end}, + + #command{id = 6, + desc = "Send reply (pong) to initial message", + cmd = fun(State) -> + server_send_message(State, "pong") + end}, + + #command{id = 7, + desc = "Await nothing before sending a message (hejsan)", + cmd = fun(State) -> + server_await_nothing(State, 1000) + end}, + + #command{id = 8, + desc = "Send message (hejsan)", + cmd = fun(State) -> + server_send_message(State, "hejsan") + end}, + + #command{id = 9, + desc = "Await reply (hoppsan) to message", + cmd = fun(State) -> + server_await_message(State, "hoppsan", 1000) + end}, + + #command{id = 10, + desc = "Await nothing before disconnecting", + cmd = fun(State) -> + server_await_nothing(State, 1000) + end}, + + #command{id = 11, + desc = "Disconnect", + cmd = fun(State) -> + server_disconnect(State) + end}, + + #command{id = 12, + desc = "Await nothing before stopping transport", + cmd = fun(State) -> + server_await_nothing(State, 1000) + end}, + + #command{id = 13, + desc = "Stop", + cmd = fun(State) -> + server_stop_transport(State) + end} + + ]. + +sendreceive_client_commands(ServerPort, ServerHost) -> + Opts = [{port, ServerPort}, {host, ServerHost}], + Self = self(), + [ + #command{id = 1, + desc = "Command sequence init", + cmd = fun(State) -> + {ok, State#client{parent = Self}} + end}, + + #command{id = 2, + desc = "Start transport", + cmd = fun(State) -> + client_start_transport(State) + end}, + + #command{id = 3, + desc = "Await continue", + cmd = fun(State) -> + client_await_continue_signal(State, 5000) + end}, + + #command{id = 4, + desc = "Connect", + cmd = fun(State) -> + client_connect(State, Opts) + end}, + + #command{id = 5, + desc = "Send initial message (ping)", + cmd = fun(State) -> + client_send_message(State, "ping") + end}, + + #command{id = 6, + desc = "Await reply (pong) to initial message", + cmd = fun(State) -> + client_await_message(State, "pong", 1000) + end}, + + #command{id = 7, + desc = "Await message (hejsan)", + cmd = fun(State) -> + client_await_message(State, "hejsan", 5000) + end}, + + #command{id = 8, + desc = "Send reply (hoppsan) to message", + cmd = fun(State) -> + client_send_message(State, "hoppsan") + end}, + + #command{id = 9, + desc = "Await nothing before disconnecting", + cmd = fun(State) -> + client_await_nothing(State, 1000) + end}, + + #command{id = 10, + desc = "Disconnect", + cmd = fun(State) -> + client_disconnect(State) + end}, + + #command{id = 11, + desc = "Await nothing before stopping transport", + cmd = fun(State) -> + client_await_nothing(State, 1000) + end}, + + #command{id = 12, + desc = "Stop transport", + cmd = fun(State) -> + client_stop_transport(State) + end} + ]. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +block_unblock(suite) -> + []; +block_unblock(Config) when is_list(Config) -> + put(sname, "block_unblock"), + p("BEGIN TEST-CASE"), + + process_flag(trap_exit, true), + + p("create nodes"), + ServerNode = make_node_name(server), + ClientNode = make_node_name(client), + Nodes = [ServerNode, ClientNode], + ok = megaco_test_lib:start_nodes(Nodes, ?FILE, ?LINE), + + %% Create command sequences + p("create command sequences"), + ServerPort = 2944, + ServerCmds = block_unblock_server_commands(ServerPort), + {ok, ServerHost} = inet:gethostname(), + ClientCmds = block_unblock_client_commands(ServerPort, ServerHost), + + %% Start the test procs used in the test-case, one for each node + p("start command handlers"), + Server = server_start_command_handler(ServerNode, ServerCmds), + p("server command handler started: ~p", [Server]), + Client = client_start_command_handler(ClientNode, ClientCmds), + p("client command handler started: ~p", [Client]), + + ok = + receive + {listening, Server} -> + p("received listening message from server [~p] => " + "send continue to client [~p]~n", [Server, Client]), + Client ! {continue, self()}, + ok + after 5000 -> + {error, server_timeout} + end, + + ok = + receive + {blocked, Client} -> + p("received blocked message from client [~p] => " + "send continue to server [~p]~n", [Client, Server]), + Server ! {continue, self()}, + ok + after 5000 -> + {error, timeout} + end, + + await_command_handler_completion([Server, Client], timer:seconds(30)), + p("done"), + ok. + + +block_unblock_server_commands(Port) -> + Opts = [{port, Port}], + Self = self(), + [ + #command{id = 1, + desc = "Command sequence init", + cmd = fun(State) -> + {ok, State#server{parent = Self}} + end}, + + #command{id = 2, + desc = "Start transport", + cmd = fun(State) -> + server_start_transport(State) + end}, + + #command{id = 3, + desc = "Listen", + cmd = fun(State) -> + server_listen(State, Opts) + end}, + + #command{id = 4, + desc = "Notify listening", + cmd = fun(State) -> + server_notify_listening(State) + end}, + + #command{id = 5, + desc = "Await initial message (ping)", + cmd = fun(State) -> + server_await_initial_message(State, "ping", 5000) + end}, + + #command{id = 6, + desc = "Send reply (pong) to initial message", + cmd = fun(State) -> + server_send_message(State, "pong") + end}, + + #command{id = 7, + desc = "Await continue", + cmd = fun(State) -> + server_await_continue_signal(State, 5000) + end}, + + #command{id = 9, + desc = "Await nothing before sending a message (hejsan)", + cmd = fun(State) -> + server_await_nothing(State, 1000) + end}, + + #command{id = 10, + desc = "Send message (hejsan)", + cmd = fun(State) -> + server_send_message(State, "hejsan") + end}, + + #command{id = 11, + desc = "Await reply (hoppsan) to message", + cmd = fun(State) -> + server_await_message(State, "hoppsan", 10000) + end}, + + #command{id = 12, + desc = "Await nothing before disconnecting", + cmd = fun(State) -> + server_await_nothing(State, 1000) + end}, + + #command{id = 13, + desc = "Disconnect", + cmd = fun(State) -> + server_disconnect(State) + end}, + + #command{id = 14, + desc = "Await nothing before stopping transport", + cmd = fun(State) -> + server_await_nothing(State, 1000) + end}, + + #command{id = 15, + desc = "Stop", + cmd = fun(State) -> + server_stop_transport(State) + end} + + ]. + +block_unblock_client_commands(ServerPort, ServerHost) -> + Opts = [{port, ServerPort}, {host, ServerHost}], + Self = self(), + [ + #command{id = 1, + desc = "Command sequence init", + cmd = fun(State) -> + {ok, State#client{parent = Self}} + end}, + + #command{id = 2, + desc = "Start transport", + cmd = fun(State) -> + client_start_transport(State) + end}, + + #command{id = 3, + desc = "Await continue", + cmd = fun(State) -> + client_await_continue_signal(State, 5000) + end}, + + #command{id = 4, + desc = "Connect", + cmd = fun(State) -> + client_connect(State, Opts) + end}, + + #command{id = 5, + desc = "Send initial message (ping)", + cmd = fun(State) -> + client_send_message(State, "ping") + end}, + + #command{id = 6, + desc = "Await reply (pong) to initial message", + cmd = fun(State) -> + client_await_message(State, "pong", 1000) + end}, + + #command{id = 7, + desc = "Await nothing before blocking", + cmd = fun(State) -> + client_await_nothing(State, 1000) + end}, + + #command{id = 8, + desc = "Block", + cmd = fun(State) -> + client_block(State) + end}, + + #command{id = 9, + desc = "Notify blocked", + cmd = fun(State) -> + client_notify_blocked(State) + end}, + + #command{id = 10, + desc = "Await nothing before unblocking", + cmd = fun(State) -> + client_await_nothing(State, 5000) + end}, + + #command{id = 11, + desc = "Unblock", + cmd = fun(State) -> + client_unblock(State) + end}, + + #command{id = 12, + desc = "Await message (hejsan)", + cmd = fun(State) -> + client_await_message(State, "hejsan", 100) + end}, + + #command{id = 13, + desc = "Send reply (hoppsan) to message", + cmd = fun(State) -> + client_send_message(State, "hoppsan") + end}, + + #command{id = 14, + desc = "Await nothing before disconnecting", + cmd = fun(State) -> + client_await_nothing(State, 1000) + end}, + + #command{id = 15, + desc = "Disconnect", + cmd = fun(State) -> + client_disconnect(State) + end}, + + #command{id = 16, + desc = "Await nothing before stopping transport", + cmd = fun(State) -> + client_await_nothing(State, 1000) + end}, + + #command{id = 17, + desc = "Stop transport", + cmd = fun(State) -> + client_stop_transport(State) + end} + ]. + + + +%% ------------------ errors ------------------------ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +socket_failure(suite) -> + []; +socket_failure(Config) when is_list(Config) -> + put(sname, "socket_failure"), + p("BEGIN TEST-CASE"), + + %% process_flag(trap_exit, true), + + socket_faulure(). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +accept_process(suite) -> + []; +accept_process(Config) when is_list(Config) -> + put(sname, "accept_process"), + p("BEGIN TEST-CASE"), + + %% process_flag(trap_exit, true), + + failing_accept_process(). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +accept_supervisor(suite) -> + []; +accept_supervisor(Config) when is_list(Config) -> + put(sname, "accept_supervisor"), + p("BEGIN TEST-CASE"), + + %% process_flag(trap_exit, true), + + failing_accept_supervisor(). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +connection_supervisor(suite) -> + []; +connection_supervisor(Config) when is_list(Config) -> + put(sname, "connection_supervisor"), + p("BEGIN TEST-CASE"), + + %% process_flag(trap_exit, true), + + failing_connection_supervisor(). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +tcp_server(suite) -> + []; +tcp_server(Config) when is_list(Config) -> + put(sname, "tcp_server"), + p("BEGIN TEST-CASE"), + + %% process_flag(trap_exit, true), + + failing_tcp_server(). + + +%%====================================================================== +%% Test functions +%%====================================================================== + +start_case(Options, Expect) -> + p("start transport"), + case (catch megaco_tcp:start_transport()) of + {ok, Pid} -> + p("create listen socket"), + case (catch megaco_tcp:listen(Pid, Options)) of + ok when Expect =:= ok -> + p("extected listen result [ok]"), + {ok, Pid}; + ok -> + p("unextected listen result [ok] - stop transport"), + megaco_tcp:stop_transport(Pid), + ?ERROR(unexpected_start_sucesss); + {error, _Reason} when Expect =:= error -> + p("extected listen result [error] - stop transport"), + megaco_tcp:stop_transport(Pid), + ok; + {error, Reason} -> + p("unextected listen result [error] - stop transport"), + megaco_tcp:stop_transport(Pid), + ?ERROR({unexpected_start_failure, Reason}); + Error -> + p("unextected listen result"), + ?ERROR({unexpected_result, Error}) + end; + {error, Reason} -> + p("unextected start_transport result"), + ?ERROR({failed_starting_transport, Reason}) + end. + +socket_faulure() -> + ?SKIP(not_yet_implemented). + +failing_accept_process() -> + ?SKIP(not_yet_implemented). + +failing_accept_supervisor() -> + ?SKIP(not_yet_implemented). + +failing_connection_supervisor() -> + ?SKIP(not_yet_implemented). + +failing_tcp_server() -> + ?SKIP(not_yet_implemented). + + +%%---------------------------------------------------------------------- +%% Message Callback functions +%%---------------------------------------------------------------------- + +receive_message(ReceiveHandle, ControlPid, SendHandle, BinMsg) + when is_pid(ReceiveHandle) andalso is_binary(BinMsg) -> + Msg = binary_to_list(BinMsg), + ReceiveHandle ! {receive_message, {ControlPid, SendHandle, Msg}}, + ok. + +process_received_message(ReceiveHandle, ControlPid, SendHandle, BinMsg) + when is_pid(ReceiveHandle) andalso is_binary(BinMsg) -> + Msg = binary_to_list(BinMsg), + ReceiveHandle ! {process_received_message, {ControlPid, SendHandle, Msg}}, + ok. + + +%%====================================================================== +%% Internal functions +%%====================================================================== + +%% ------- Server command handler and utility functions ---------- + +server_start_command_handler(Node, Commands) -> + start_command_handler(Node, Commands, #server{}, "server"). + +server_start_transport(State) when is_record(State, server) -> + case (catch megaco_tcp:start_transport()) of + {ok, Ref} -> + {ok, State#server{transport_ref = Ref}}; + Error -> + Error + end. + +server_listen(#server{transport_ref = Ref} = State, Options) + when is_record(State, server) andalso is_list(Options) -> + Opts = [{receive_handle, self()}, {module, ?MODULE} | Options], + case (catch megaco_tcp:listen(Ref, Opts)) of + ok -> + {ok, State}; + Error -> + Error + end. + +server_notify_listening(#server{parent = Parent} = State) + when is_record(State, server) -> + Parent ! {listening, self()}, + {ok, State}. + +server_await_continue_signal(#server{parent = Parent} = State, Timeout) -> + receive + {continue, Parent} -> + {ok, State} + after Timeout -> + {error, timeout} + end. + +server_await_initial_message(State, InitialMessage, Timeout) + when is_record(State, server) -> + receive + {receive_message, {ControlPid, Handle, InitialMessage}} -> + NewState = State#server{control_pid = ControlPid, + handle = Handle}, + {ok, NewState}; + + Any -> + p("received unexpected event: ~p", [Any]), + {error, {unexpected_event, Any}} + + after Timeout -> + {error, timeout} + end. + +server_send_message(#server{handle = Handle} = State, Message) -> + megaco_tcp:send_message(Handle, Message), + {ok, State}. + +server_await_nothing(State, Timeout) + when is_record(State, server) -> + receive + Any -> + p("received unexpected event: ~p", [Any]), + {error, {unexpected_event, Any}} + + after Timeout -> + {ok, State} + end. + + +server_await_message(State, ExpectMessage, Timeout) + when is_record(State, server) -> + receive + {receive_message, {_, _, ExpectMessage}} -> + {ok, State}; + + Any -> + p("received unexpected event: ~p", [Any]), + {error, {unexpected_event, Any}} + + after Timeout -> + {error, timeout} + end. + +server_disconnect(#server{handle = Handle} = State) + when (Handle =/= undefined) -> + megaco_tcp:close(Handle), + {ok, State#server{handle = undefined}}. + +%% server_block(#server{handle = Handle} = State) +%% when (Handle =/= undefined) -> +%% megaco_tcp:block(Handle), +%% {ok, State}. + +%% server_unblock(#server{handle = Handle} = State) +%% when (Handle =/= undefined) -> +%% megaco_tcp:unblock(Handle), +%% {ok, State}. + +server_stop_transport(#server{transport_ref = Ref} = State) + when (Ref =/= undefined) -> + megaco_tcp:stop_transport(Ref), + {ok, State}. + + +%% ------- Client command handler and utility functions ---------- + +client_start_command_handler(Node, Commands) -> + start_command_handler(Node, Commands, #client{}, "client"). + +client_start_transport(State) when is_record(State, client) -> + case (catch megaco_tcp:start_transport()) of + {ok, Ref} -> + {ok, State#client{transport_ref = Ref}}; + Error -> + Error + end. + +client_connect(#client{transport_ref = Ref} = State, Options) + when is_record(State, client) andalso is_list(Options) -> + Opts = [{receive_handle, self()}, {module, ?MODULE} | Options], + case (catch megaco_tcp:connect(Ref, Opts)) of + {ok, Handle, ControlPid} -> + {ok, State#client{control_pid = ControlPid, + handle = Handle}}; + Error -> + Error + end. + +client_await_continue_signal(#client{parent = Parent} = State, Timeout) -> + receive + {continue, Parent} -> + {ok, State} + after Timeout -> + {error, timeout} + end. + +client_notify_blocked(#client{parent = Parent} = State) -> + Parent ! {blocked, self()}, + {ok, State}. + +client_await_nothing(State, Timeout) + when is_record(State, client) -> + receive + Any -> + p("received unexpected event: ~p", [Any]), + {error, {unexpected_event, Any}} + after Timeout -> + {ok, State} + end. + +client_send_message(#client{handle = Handle} = State, Message) -> + megaco_tcp:send_message(Handle, Message), + {ok, State}. + +client_await_message(State, ExpectMessage, Timeout) + when is_record(State, client) -> + receive + {receive_message, {_, _, ExpectMessage}} -> + {ok, State}; + + Any -> + p("received unexpected event: ~p", [Any]), + {error, {unexpected_event, Any}} + + after Timeout -> + {error, timeout} + end. + +client_block(#client{handle = Handle} = State) + when (Handle =/= undefined) -> + megaco_tcp:block(Handle), + {ok, State}. + +client_unblock(#client{handle = Handle} = State) + when (Handle =/= undefined) -> + megaco_tcp:unblock(Handle), + {ok, State}. + +client_disconnect(#client{handle = Handle} = State) + when (Handle =/= undefined) -> + megaco_tcp:close(Handle), + {ok, State#client{handle = undefined, control_pid = undefined}}. + +client_stop_transport(#client{transport_ref = Ref} = State) + when (Ref =/= undefined) -> + megaco_tcp:stop_transport(Ref), + {ok, State}. + + +%% -------- Command handler --------- + +start_command_handler(Node, Commands, State, ShortName) -> + Fun = fun() -> + put(sname, ShortName), + process_flag(trap_exit, true), + Result = (catch command_handler(Commands, State)), + p("command handler terminated with: " + "~n Result: ~p", [Result]), + exit(Result) + end, + erlang:spawn_link(Node, Fun). + +command_handler([], State) -> + p("command_handler -> entry when done with" + "~n State: ~p", [State]), + {ok, State}; +command_handler([#command{id = Id, + desc = Desc, + cmd = Cmd}|Commands], State) -> + p("command_handler -> entry with" + "~n Id: ~p" + "~n Desc: ~p", [Id, Desc]), + case (catch Cmd(State)) of + {ok, NewState} -> + p("command_handler -> cmd ~w ok", [Id]), + command_handler(Commands, NewState); + {error, Reason} -> + p("command_handler -> cmd ~w error: " + "~n Reason: ~p", [Id, Reason]), + {error, {cmd_error, Reason}}; + {'EXIT', Reason} -> + p("command_handler -> cmv ~w exit: " + "~n Reason: ~p", [Id, Reason]), + {error, {cmd_exit, Reason}}; + Error -> + p("command_handler -> cmd ~w failure: " + "~n Error: ~p", [Id, Error]), + {error, {cmd_failure, Error}} + end. + + +await_command_handler_completion(Pids, Timeout) -> + await_command_handler_completion(Pids, [], [], Timeout). + +await_command_handler_completion([], [], _Good, _Timeout) -> + p("await_command_handler_completion -> entry when done"), + ok; +await_command_handler_completion([], Bad, Good, _Timeout) -> + p("await_command_handler_completion -> entry when done with bad result: " + "~n Bad: ~p" + "~n Good: ~p", [Bad, Good]), + ok; +await_command_handler_completion(Pids, Bad, Good, Timeout) -> + p("await_command_handler_completion -> entry when waiting for" + "~n Pids: ~p" + "~n Bad: ~p" + "~n Good: ~p" + "~n Timeout: ~p", [Pids, Bad, Good, Timeout]), + Begin = ms(), + receive + {'EXIT', Pid, {ok, FinalState}} -> + p("await_command_handler_completion -> " + "received ok EXIT signal from ~p", [Pid]), + case lists:delete(Pid, Pids) of + Pids -> + await_command_handler_completion(Pids, Bad, Good, + Timeout - (ms() - Begin)); + Pids2 -> + p("await_command_handler_completion -> ~p done", [Pid]), + await_command_handler_completion(Pids2, + Bad, + [{Pid, FinalState}|Good], + Timeout - (ms() - Begin)) + end; + + {'EXIT', Pid, {error, Reason}} -> + p("await_command_handler_completion -> " + "received error EXIT signal from ~p", [Pid]), + case lists:delete(Pid, Pids) of + Pids -> + await_command_handler_completion(Pids, Bad, Good, + Timeout - (ms() - Begin)); + Pids2 -> + p("await_command_handler_completion -> ~p done", [Pid]), + await_command_handler_completion(Pids2, + [{Pid, Reason}|Bad], + Good, + Timeout - (ms() - Begin)) + end + + after Timeout -> + p("await_command_handler_completion -> timeout"), + exit({timeout, Pids}) + end. + + + +%% ------- Misc functions -------- + +make_node_name(Name) -> + case string:tokens(atom_to_list(node()), [$@]) of + [_,Host] -> + list_to_atom(lists:concat([atom_to_list(Name) ++ "@" ++ Host])); + _ -> + exit("Test node must be started with '-sname'") + end. + + +p(F) -> + p(F, []). + +p(F, A) -> + p(get(sname), F, A). + +p(S, F, A) when is_list(S) -> + io:format("*** [~s] ~p ~s ***" + "~n " ++ F ++ "~n", + [format_timestamp(now()), self(), S | A]); +p(_S, F, A) -> + io:format("*** [~s] ~p ~s *** " + "~n " ++ F ++ "~n", + [format_timestamp(now()), self(), "undefined" | A]). + + +ms() -> + {A,B,C} = erlang:now(), + A*1000000000+B*1000+(C div 1000). + + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). diff --git a/lib/megaco/test/megaco_test_deliver.erl b/lib/megaco/test/megaco_test_deliver.erl new file mode 100644 index 0000000000..2d0f0c1cbe --- /dev/null +++ b/lib/megaco/test/megaco_test_deliver.erl @@ -0,0 +1,188 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: This module takes the role of the main megaco module for +%% the transport module. It is used when delivering +%% received messages. The purpose is to be able to do +%% various forms of filtering before passing the message +%% the the megaco stack (by calling the megaco module). +%% It can be controlled with the following flags: +%% allow_recv_message - Shall the received message be +%% delivered. +%% extra_transport_info - Provide extra info from the transport +%% module. +%%---------------------------------------------------------------------- +-module(megaco_test_deliver). + + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include_lib("megaco/src/udp/megaco_udp.hrl"). +-include("megaco_test_lib.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([ + process_received_message/4, process_received_message/5, + receive_message/4, receive_message/5 + ]). + + + +%%====================================================================== +%% External functions +%%====================================================================== + +process_received_message(ReceiveHandle, ControlPid, SendHandle, BinMsg) -> + i("process_received_message -> entry with" + "~n ReceiveHandle: ~p" + "~n ControlPid: ~p" + "~n SendHandle: ~p", + [ReceiveHandle, ControlPid, SendHandle]), + case allow_recv_message() of + true -> + i("process_received_message -> allowed recv msg"), + case extra_transport_info() of + {value, Extra} -> + i("process_received_message -> extra_transport_info: " + "~n Extra: ~p", [Extra]), + megaco:process_received_message(ReceiveHandle, ControlPid, + SendHandle, BinMsg, + Extra); + _ -> + i("process_received_message -> no extra_transport_info"), + megaco:process_received_message(ReceiveHandle, ControlPid, + SendHandle, BinMsg) + end; + false -> + i("process_received_message -> recv msg not allowed"), + ok; + {false, Reason} -> + i("process_received_message -> recv msg not allowed" + "~n Reason: ~p", [Reason]), + exit(Reason) + end. + + +process_received_message(ReceiveHandle, ControlPid, SendHandle, BinMsg, Extra) -> + i("process_received_message -> entry with" + "~n ReceiveHandle: ~p" + "~n ControlPid: ~p" + "~n SendHandle: ~p" + "~n Extra: ~p", + [ReceiveHandle, ControlPid, SendHandle, Extra]), + case allow_recv_message() of + true -> + i("process_received_message -> allowed recv msg"), + megaco:process_received_message(ReceiveHandle, ControlPid, + SendHandle, BinMsg, + Extra); + false -> + i("process_received_message -> recv msg not allowed"), + ok; + {false, Reason} -> + i("process_received_message -> recv msg not allowed" + "~n Reason: ~p", [Reason]), + exit(Reason) + end. + +receive_message(ReceiveHandle, ControlPid, SendHandle, BinMsg) -> + i("receive_message -> entry with" + "~n ReceiveHandle: ~p" + "~n ControlPid: ~p" + "~n SendHandle: ~p", + [ReceiveHandle, ControlPid, SendHandle]), + case allow_recv_message() of + true -> + i("receive_message -> allowed recv msg"), + case extra_transport_info() of + {value, Extra} -> + i("receive_message -> extra_transport_info: " + "~n Extra: ~p", [Extra]), + megaco:receive_message(ReceiveHandle, ControlPid, + SendHandle, BinMsg, Extra); + _ -> + i("receive_message -> no extra_transport_info"), + megaco:receive_message(ReceiveHandle, ControlPid, + SendHandle, BinMsg) + end; + false -> + i("receive_message -> recv msg not allowed"), + ok; + {false, Reason} -> + i("receive_message -> recv msg not allowed" + "~n Reason: ~p", [Reason]), + exit(Reason) + end. + +receive_message(ReceiveHandle, ControlPid, SendHandle, BinMsg, Extra) -> + i("receive_message -> entry with" + "~n ReceiveHandle: ~p" + "~n ControlPid: ~p" + "~n SendHandle: ~p" + "~n Extra: ~p", + [ReceiveHandle, ControlPid, SendHandle, Extra]), + case allow_recv_message() of + true -> + i("receive_message -> allowed recv msg"), + megaco:receive_message(ReceiveHandle, ControlPid, + SendHandle, BinMsg, + Extra); + false -> + i("receive_message -> recv msg not allowed"), + ok; + {false, Reason} -> + i("receive_message -> recv msg not allowed" + "~n Reason: ~p", [Reason]), + exit(Reason) + end. + + +%%====================================================================== +%% Internal functions +%%====================================================================== + +allow_recv_message() -> + case megaco_tc_controller:lookup(allow_recv_message) of + {error, _} -> + true; + {value, Else} -> + Else; + false -> + true + end. + +extra_transport_info() -> + case megaco_tc_controller:lookup(extra_transport_info) of + {error, _} -> + false; + Else -> + Else + end. + +i(F) -> + i(F, []). + +i(F, A) -> + io:format("~p ~w:" ++ F ++ "~n", [self(), ?MODULE | A]). diff --git a/lib/megaco/test/megaco_test_generator.erl b/lib/megaco/test/megaco_test_generator.erl new file mode 100644 index 0000000000..8bbc60e6cd --- /dev/null +++ b/lib/megaco/test/megaco_test_generator.erl @@ -0,0 +1,549 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Sequence generator for the megaco test suite +%%---------------------------------------------------------------------- + +-module(megaco_test_generator). + +-behaviour(gen_server). + +-export([ + start_link/3, + start_link/4, + exec/2, exec/3, + stop/1 + ]). + +%% Misc utility function for modules implementing this behaviour +-export([ + sleep/1, + sz/1, + debug/1, debug/2, + error/2, + print/3, print/4 + ]). + +-export([behaviour_info/1]). + +%% Internal exports +-export([start/4]). +-export([handler_init/5]). + +%% Internal gen_server exports +-export([ + init/1, + handle_call/3, + handle_cast/2, + handle_info/2, + terminate/2, + code_change/3 + ]). + + +-include_lib("megaco/include/megaco.hrl"). + + +%%---------------------------------------------------------------------- + +-define(TIMEOUT, timer:minutes(5)). + + +%%---------------------------------------------------------------------- + +-record(state, + { + parent, + callback_module, + callback_state, + handler = {undefined, undefined}, + timer, + name, + id + }). + + +%%%========================================================================= +%%% API +%%%========================================================================= + +behaviour_info(callbacks) -> + [ + {init, 1}, + {handle_parse, 2}, + {handle_exec, 2}, + {terminate, 2} + ]; +behaviour_info(_Other) -> + undefined. + + +%%---------------------------------------------------------------------- + +start_link(Mod, Args, Name) + when is_atom(Mod) andalso is_list(Name) -> + start(Mod, Args, Name, self()). + +start_link(Mod, Args, Name, Node) + when is_atom(Mod) andalso is_list(Name) andalso (Node =/= node()) -> + case rpc:call(Node, ?MODULE, start, [Mod, Args, Name, self()]) of + {ok, Pid} -> + link(Pid), + {ok, Pid}; + Error -> + Error + end; +start_link(Mod, Args, Name, Node) + when is_atom(Mod) andalso is_list(Name) andalso (Node =:= node()) -> + case start(Mod, Args, Name, self()) of + {ok, Pid} -> + link(Pid), + {ok, Pid}; + Error -> + Error + end. + +start(Mod, Args, Name, Pid) when is_pid(Pid) -> + gen_server:start({local, Mod}, ?MODULE, [Mod, Args, Name, Pid], []). + + +exec(Server, Instructions) -> + exec(Server, Instructions, infinity). + +exec(Server, Instructions, Timeout) + when ((Timeout == infinity) orelse + (is_integer(Timeout) andalso (Timeout > 0))) -> + call(Server, {exec, Instructions, Timeout}). + + +stop(Server) -> + call(Server, stop). + + +%%---------------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% Func: init/1 +%% Returns: {ok, State} | +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} +%%-------------------------------------------------------------------- + +init([Mod, Args, Name, Parent]) -> + put(name, Name ++ "-CTRL"), + process_flag(trap_exit, true), + put(debug, true), + d("init -> entry with" + "~n Mod: ~p" + "~n Args: ~p" + "~n Name: ~p" + "~n Parent: ~p", [Mod, Args, Name, Parent]), + case (catch Mod:init(Args)) of + {ok, CallbackState} -> + d("init -> ~p initiated:" + "~n CallbackState: ~p", [Mod, CallbackState]), + State = #state{callback_module = Mod, + callback_state = CallbackState, + parent = Parent, + name = Name}, + d("init -> initiated"), + {ok, State}; + {error, Reason} -> + {stop, Reason} + end. + + +%%-------------------------------------------------------------------- +%% Func: handle_call/3 +%% Returns: {reply, Reply, State} | +%% {reply, Reply, State, Timeout} | +%% {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, Reply, State} | (terminate/2 is called) +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_call({exec, Instructions, Timeout}, _From, + #state{callback_module = Mod, + callback_state = CallbackState, + name = Name} = State) -> + d("handle_call(exec) -> entry with" + "~n Timeout: ~p", [Timeout]), + case (catch handle_parse(Mod, CallbackState, Instructions)) of + {ok, NewCallbackState, NewInstructions} -> + d("handle_call(exec) -> parsed" + "~n NewCallbackState: ~p", [NewCallbackState]), + case handler_start(Name, Mod, NewCallbackState, NewInstructions) of + {ok, Pid} -> + d("handle_call(exec) -> handler started" + "~n Pid: ~p", [Pid]), + Timer = maybe_start_timer(Timeout), + Id = {node(), make_ref()}, + Reply = {ok, Id}, + {reply, Reply, + State#state{callback_state = NewCallbackState, + handler = {running, Pid}, + timer = Timer, + id = Id}}; + {error, Reason} -> + e("failed starting handler process" + "~n Reason: ~p", [Reason]), + Reply = {error, {failed_starting_handler, Reason}}, + {stop, Reason, Reply, State} + end; + {error, Reason} -> + e("failed parsing instructions" + "~n Reason: ~p", [Reason]), + Reply = {error, {invalid_instruction, Reason}}, + {stop, Reason, Reply, State} + end; + +handle_call(stop, _From, State) -> + Reply = ok, + {stop, normal, Reply, State}; + +handle_call(Request, From, State) -> + e("unexpected request" + "~n Request: ~p" + "~n From: ~p", [Request, From]), + Reason = {error, {unknown_request, Request, From}}, + Reply = {error, unknown_request}, + {stop, Reason, Reply, State}. + + +%%-------------------------------------------------------------------- +%% Func: handle_cast/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_cast(Msg, State) -> + e("unexpected message" + "~n Msg: ~p", [Msg]), + Reason = {error, {unknown_message, Msg}}, + {stop, Reason, State}. + + +%%-------------------------------------------------------------------- +%% Func: handle_info/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_info({handler_result, Pid, Result}, + #state{parent = Parent, + handler = {running, Pid}, + timer = Timer, + id = Id} = State) -> + d("handle_info(handler_result) -> entry with" + "~n Result: ~p", [Result]), + maybe_stop_timer(Timer), + handler_stop(Pid), + deliver_exec_result(Parent, Id, Result), + NewState = State#state{handler = {stopping, Pid}, + timer = undefined, + id = undefined}, + {noreply, NewState}; + +handle_info(handler_timeout, #state{handler = {running, Pid}} = State) -> + d("handle_info(handler_timeout) -> entry with"), + handler_stop(Pid), + {noreply, State#state{handler = {stopping, Pid}}}; + +handle_info({'EXIT', Pid, {stopped, Result}}, + #state{parent = Parent, + handler = {stopping, Pid}, + id = Id} = State) -> + d("handle_info(handler stopped EXIT) -> entry with" + "~n Result: ~p", [Result]), + deliver_exec_result(Parent, Id, {error, {handler_timeout, Result}}), + {noreply, State#state{handler = {stopped, undefined}, + timer = undefined, + id = undefined}}; + +handle_info({'EXIT', Pid, normal}, + #state{handler = {_, Pid}, + timer = Timer} = State) -> + d("handle_info(handler normal EXIT) -> entry"), + maybe_stop_timer(Timer), + {noreply, State#state{handler = {stopped, undefined}, timer = undefined}}; + +handle_info({'EXIT', Pid, Reason}, + #state{parent = Parent, + handler = {_, Pid}, + timer = Timer, + id = Id} = State) -> + d("handle_info(handler EXIT) -> entry with" + "~n Reason: ~p", [Reason]), + maybe_stop_timer(Timer), + deliver_exec_result(Parent, Id, {error, {handler_crashed, Reason}}), + {noreply, State#state{handler = {crashed, undefined}, + timer = undefined, + id = undefined}}; + +handle_info(Info, State) -> + e("unexpected info" + "~n Info: ~p" + "~n State: ~p", [Info, State]), + Reason = {error, {unknown_info, Info}}, + {stop, Reason, State}. + + +%%-------------------------------------------------------------------- +%% Func: terminate/2 +%% Purpose: Shutdown the server +%% Returns: any (ignored by gen_server) +%%-------------------------------------------------------------------- +terminate(normal, #state{handler = {_HandlerState, Pid}} = _State) -> + d("terminate(normal) -> entry"), + handler_stop(Pid), + ok; + +terminate(Reason, #state{handler = {_HandlerState, Pid}, + callback_module = Mod, + callback_state = CallbackState} = _State) -> + d("terminate -> entry with" + "~n Reason: ~p", [Reason]), + handler_kill(Pid), + (catch Mod:terminate(Reason, CallbackState)), + ok. + + +%%---------------------------------------------------------------------- +%% Func: code_change/3 +%% Purpose: Convert process state when code is changed +%% Returns: {ok, NewState} +%%---------------------------------------------------------------------- + +code_change(_Vsn, S, _Extra) -> + {ok, S}. + + +%%%------------------------------------------------------------------- +%%% Internal functions +%%%------------------------------------------------------------------- + +deliver_exec_result(Parent, Id, {ok, Result}) -> + Parent ! {exec_complete, Id, ok, Result}; +deliver_exec_result(Parent, Id, {error, Reason}) -> + Parent ! {exec_complete, Id, error, Reason}. + + +handle_parse(Mod, State, Instructions) -> + handle_parse(Mod, State, Instructions, []). + +handle_parse(_Mod, State, [], Acc) -> + {ok, State, lists:reverse(Acc)}; + +handle_parse(Mod, State, [Instruction|Instructions], Acc) -> + case (catch Mod:handle_parse(Instruction, State)) of + {ok, NewInstruction, NewState} -> + handle_parse(Mod, NewState, Instructions, [NewInstruction|Acc]); + {error, Reason} -> + {error, {invalid_instruction, Instruction, Reason}}; + {'EXIT', Reason} -> + {error, {exit, Instruction, Reason}} + end. + + +%%%------------------------------------------------------------------- + +handler_kill(Pid) when is_pid(Pid) -> + erlang:exit(Pid, kill); +handler_kill(_) -> + ok. + +handler_stop(Pid) when is_pid(Pid) -> + Pid ! {stop, self()}; +handler_stop(_) -> + ok. + +handler_start(Name, Mod, State, Instructions) -> + Args = [Name, self(), Mod, State, Instructions], + proc_lib:start_link(?MODULE, handler_init, Args). + + +handler_init(Name, Parent, Mod, State, Instructions) -> + put(name, Name ++ "-HANDLER"), + proc_lib:init_ack(Parent, {ok, self()}), + d("handler_init -> initiated"), + handler_main(Parent, Mod, State, Instructions). + +handler_main(Parent, Mod, State, []) -> + d("handler_main -> done when" + "~n State: ~p", [State]), + Result = (catch Mod:terminate(normal, State)), + Parent ! {handler_result, self(), {ok, Result}}, + receive + {stop, Parent} -> + exit(normal); + {'EXIT', Parent, Reason} -> + exit({parent_died, Reason}) + end; + +handler_main(Parent, Mod, State, [Instruction|Instructions]) -> + d("handler_main -> entry with" + "~n Instruction: ~p", [Instruction]), + receive + {stop, Parent} -> + d("handler_main -> premature stop requested"), + Result = (catch Mod:terminate(stopped, State)), + exit({stopped, Result}); + {'EXIT', Parent, Reason} -> + d("handler_main -> parent exited" + "~n Reason: ~p", [Reason]), + Result = (catch Mod:terminate({parent_died, Reason}, State)), + exit({parent_died, Reason, Result}) + after 0 -> + case (catch handler_callback_exec(Mod, State, Instruction)) of + {ok, NewState} -> + handler_main(Parent, Mod, NewState, Instructions); + {error, Reason} -> + d("handler_main -> exec failed" + "~n Reason: ~p", [Reason]), + case (catch Mod:terminate(normal, State)) of + {ok, Result} -> + Parent ! {handler_result, self(), {error, Result}}; + Error -> + Result = {bad_terminate, Error}, + Parent ! {handler_result, self(), {error, Result}} + end, + receive + {stop, Parent} -> + exit(normal); + {'EXIT', Parent, Reason} -> + exit({parent_died, Reason}) + end; + {'EXIT', Reason} -> + d("handler_main -> exec EXIT" + "~n Reason: ~p", [Reason]), + exit({callback_exec_exit, Reason}) + + end + end. + +handler_callback_exec(Mod, State, Instruction) -> + Mod:handle_exec(Instruction, State). + + +%%%------------------------------------------------------------------- + +maybe_start_timer(Timeout) when is_integer(Timeout) -> + erlang:send_after(Timeout, self(), handler_timeout); +maybe_start_timer(_) -> + undefined. + + +maybe_stop_timer(undefined) -> + ok; +maybe_stop_timer(Timer) -> + (catch erlang:cancel_timer(Timer)). + + +%%% ---------------------------------------------------------------- + +call(Server, Request) -> + call(Server, Request, infinity). + +call(Server, Request, Timeout) -> + case (catch gen_server:call(Server, Request, Timeout)) of + {'EXIT', _} -> + {error, not_started}; + Res -> + Res + end. + +%% cast(Server, Msg) -> +%% case (catch gen_server:cast(Server, Msg)) of +%% {'EXIT', _} -> +%% {error, not_started}; +%% Res -> +%% Res +%% end. + + +%%% ---------------------------------------------------------------- + +sleep(X) when is_integer(X) andalso (X =< 0) -> ok; +sleep(X) -> receive after X -> ok end. + +sz(Bin) when is_binary(Bin) -> + size(Bin); +sz(L) when is_list(L) -> + length(L); +sz(_) -> + -1. + + +%%% ---------------------------------------------------------------- + +d(F) -> debug(F). +d(F, A) -> debug(F, A). + +e(F, A) -> error(F, A). + +%% p(P, F, A) -> print(P, F, A). +%% p(P, N, F, A) -> print(P, N, F, A). + + +%% ------------------------- + +debug(F) -> + debug(F, []). + +debug(F, A) -> + debug(get(debug), F, A). + +debug(true, F, A) -> + print(" DBG", F, A); +debug(_, _F, _A) -> + ok. + + +error(F, A) -> + print(" ERROR", F, A). + + +print(P, F, A) -> + print(P, get(name), F, A). + +print([], undefined, F, A) -> + io:format("*** [~s] ~p *** " ++ + "~n " ++ F ++ "~n", + [format_timestamp(now()),self()|A]); +print(P, undefined, F, A) -> + io:format("*** [~s] ~p ~s *** " ++ + "~n " ++ F ++ "~n", + [format_timestamp(now()),self(),P|A]); +print(P, N, F, A) -> + io:format("*** [~s] ~p ~s~s *** " ++ + "~n " ++ F ++ "~n", + [format_timestamp(now()),self(),N,P|A]). + + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY, MM, DD} = Date, + {Hour, Min, Sec} = Time, + FormatDate = + io_lib:format("~.4w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY, MM, DD, Hour, Min, Sec, round(N3/1000)]), + lists:flatten(FormatDate). diff --git a/lib/megaco/test/megaco_test_generator_lib.erl b/lib/megaco/test/megaco_test_generator_lib.erl new file mode 100644 index 0000000000..cf0dcaf722 --- /dev/null +++ b/lib/megaco/test/megaco_test_generator_lib.erl @@ -0,0 +1,83 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Utility module for the generator users +%%---------------------------------------------------------------------- + +-module(megaco_test_generator_lib). + +-export([ + await_completion/1, await_completion/2 + ]). + + + +%%%========================================================================= +%%% API +%%%========================================================================= + +await_completion(Tags) -> + await_completion(Tags, infinity). + +await_completion(Tags, Timeout) -> + TmrRef = start_timer(Timeout), + await_completion(TmrRef, Tags, [], []). + +await_completion(TmrRef, [], OK, []) -> + stop_timer(TmrRef), + {ok, OK}; +await_completion(TmrRef, [], OK, ERROR) -> + stop_timer(TmrRef), + {error, {OK, ERROR}}; +await_completion(TmrRef, Tags, OK, ERROR) -> + receive + exec_complete_timeout -> + {error, {timeout, Tags, OK, ERROR}}; + + {exec_complete, Tag, ok, Result} -> + case lists:delete(Tag, Tags) of + Tags -> + %% Unknown => ignore + await_completion(TmrRef, Tags, OK, ERROR); + Tags2 -> + await_completion(TmrRef, Tags2, [{Tag, Result}|OK], ERROR) + end; + + {exec_complete, Tag, error, Reason} -> + case lists:delete(Tag, Tags) of + Tags -> + %% Unknown => ignore + await_completion(TmrRef, Tags, OK, ERROR); + Tags2 -> + await_completion(TmrRef, Tags2, OK, [{Tag, Reason}|ERROR]) + end + end. + +start_timer(infinity) -> + undefined; +start_timer(Timeout) when is_integer(Timeout) andalso (Timeout > 0) -> + Msg = exec_complete_timeout, + erlang:send_after(Timeout, self(), Msg). + +stop_timer(undefined) -> + ok; +stop_timer(TmrRef) -> + erlang:cancel_timer(TmrRef). diff --git a/lib/megaco/test/megaco_test_generic_transport.erl b/lib/megaco/test/megaco_test_generic_transport.erl new file mode 100644 index 0000000000..10afa45baa --- /dev/null +++ b/lib/megaco/test/megaco_test_generic_transport.erl @@ -0,0 +1,354 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Generic megaco transport simulator module +%%---------------------------------------------------------------------- + +-module(megaco_test_generic_transport). + +-behaviour(gen_server). +-behaviour(megaco_transport). + +-export([ + start_transport/0, + listen/2, + connect/2, + start/1, + stop/0, + incomming_message/2 + ]). + +%% gen_server callbacks +-export([ + init/1, + handle_call/3, + handle_cast/2, + handle_info/2, + terminate/2, + code_change/3 + ]). + +%% megaco_transport callbacks +-export([ + send_message/2, + send_message/3, + resend_message/2 + ]). + +-record(state, {parent, + controller, + receive_handle}). + +-include_lib("megaco/include/megaco.hrl"). +%% -include("megaco_test_lib.hrl"). +-define(SERVER, ?MODULE). + + +%%------------------------------------------------------------------- +%% API +%%------------------------------------------------------------------- + +start(RH) -> + {ok, Pid} = start_transport(), + {ok, SendHandle, _} = connect(Pid, [{receive_handle, RH}]), + {ok, SendHandle}. + +start_transport() -> + %% GS_ARGS = [{debug,[trace]}], + GS_ARGS = [], + {ok, Pid} = gen_server:start_link({local, ?SERVER}, ?MODULE, [self()], GS_ARGS), + unlink(Pid), + {ok, Pid}. + +connect(Sup, Opts) -> + call({connect, Sup, Opts}). + +listen(Sup, Opts) -> + call({listen, Sup, Opts}). + +stop() -> + call(stop). + + +%%---------------------------------------------------------------------- +%% Megaco transport callback +%%---------------------------------------------------------------------- + +send_message(SendHandle, Bin) -> + call({transport, {send_message, SendHandle, Bin}}). + +send_message(SendHandle, Bin, Resend) -> + call({transport, {send_message, SendHandle, Bin, Resend}}). + +resend_message(SendHandle, Bin) -> + call({transport, {resend_message, SendHandle, Bin}}). + +incomming_message(Pid, Msg) -> + cast(Pid, {incomming_message, Msg}). + + +%%%------------------------------------------------------------------- +%%% Callback functions from gen_server +%%%------------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% Func: init/1 +%% Returns: {ok, State} | +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} +%%-------------------------------------------------------------------- +init([Parent]) -> + {ok, #state{parent = Parent}}. + + +%%-------------------------------------------------------------------- +%% Func: handle_call/3 +%% Returns: {reply, Reply, State} | +%% {reply, Reply, State, Timeout} | +%% {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, Reply, State} | (terminate/2 is called) +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_call({connect, _Sup, Opts}, _From, State) -> + d("handle_call(connect) -> entry with" + "~n Opts: ~p", [Opts]), + {value, {_, ReceiveHandle}} = lists:keysearch(receive_handle, 1, Opts), + {value, {_, Controller}} = lists:keysearch(port, 1, Opts), + SendHandle = self(), + ControlPid = self(), + Reply = {ok, SendHandle, ControlPid}, + {reply, Reply, State#state{controller = Controller, + receive_handle = ReceiveHandle}}; + +handle_call({listen, _Sup, Opts}, _From, State) -> + d("handle_call(listen) -> entry with" + "~n Opts: ~p", [Opts]), + {value, {_, ReceiveHandle}} = lists:keysearch(receive_handle, 1, Opts), + {value, {_, Controller}} = lists:keysearch(port, 1, Opts), + SendHandle = self(), + ControlPid = self(), + Reply = {ok, SendHandle, ControlPid}, + Controller ! {listen, ReceiveHandle, SendHandle, ControlPid}, + {reply, Reply, State#state{controller = Controller, + receive_handle = ReceiveHandle}}; + +handle_call(stop, _From, State) -> + d("handle_call(stop) -> entry"), + Reply = ok, + Reason = normal, + {stop, Reason, Reply, State}; + +handle_call({transport, Event}, _From, + #state{controller = Pid, receive_handle = RH} = State) -> + d("handle_call(transport) -> entry with" + "~n Event: ~p", [Event]), + Reply = handle_transport(Pid, RH, Event), + {reply, Reply, State}; + +handle_call(Req, From, State) -> + d("handle_call -> entry with" + "~n Req: ~p", [Req]), + Reply = {error, {unknown_request, Req}}, + Reason = {received_unexpected_request, Req, From}, + {stop, Reason, Reply, State}. + + +%%-------------------------------------------------------------------- +%% Func: handle_cast/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_cast({incomming_message, Msg}, + #state{receive_handle = RH} = State) -> + d("handle_cast(incomming_message) -> entry with" + "~n Msg: ~p", [Msg]), + handle_incomming_message(Msg, RH), + {noreply, State}; + +handle_cast(Msg, State) -> + d("handle_cast -> entry with" + "~n Msg: ~p", [Msg]), + Reason = {received_unexpected_message, Msg}, + {stop, Reason, State}. + + +%%-------------------------------------------------------------------- +%% Func: handle_info/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_info(Info, State) -> + d("handle_info -> entry with" + "~n Info: ~p", [Info]), + Reason = {received_unexpected_info, Info}, + {stop, Reason, State}. + + +%%-------------------------------------------------------------------- +%% Func: terminate/2 +%% Purpose: Shutdown the server +%% Returns: any (ignored by gen_server) +%%-------------------------------------------------------------------- +terminate(_Reason, _State) -> + ok. + + +%%---------------------------------------------------------------------- +%% Func: code_change/3 +%% Purpose: Convert process state when code is changed +%% Returns: {ok, NewState} +%%---------------------------------------------------------------------- + +code_change(_Vsn, State, _Extra) -> + {ok, State}. + + +%%%------------------------------------------------------------------- +%%% Internal functions +%%%------------------------------------------------------------------- + +handle_transport(Pid, + #megaco_receive_handle{encoding_mod = EM, + encoding_config = EC}, + {Event, SendHandle, Bin, Resend}) -> + Info = + case (catch EM:decode_message(EC, Bin)) of + {ok, MegMsg} -> + {message, MegMsg, Resend}; + Error -> + d("handle_transport -> decode failed" + "~n Error: ~p", [Error]), + {bad_message, Error, Bin} + end, + handle_transport(Pid, Event, SendHandle, Info); +handle_transport(Pid, + #megaco_receive_handle{encoding_mod = EM, + encoding_config = EC}, + {Event, SendHandle, Bin}) -> + Info = + case (catch EM:decode_message(EC, Bin)) of + {ok, MegMsg} -> + {message, MegMsg}; + Error -> + d("handle_transport -> decode failed" + "~n Error: ~p", [Error]), + {bad_message, Error, Bin} + end, + handle_transport(Pid, Event, SendHandle, Info). + +handle_transport(Pid, Event, SendHandle, Info) -> + Pid ! {transport_event, {Event, SendHandle, Info}, self()}, + receive + {transport_reply, Reply, Pid} -> + d("handle_transport -> received reply" + "~n Reply: ~p", [Reply]), + Reply + after 10000 -> + receive + Any -> + d("handle_transport -> received crap after timeout" + "~n Any: ~p", [Any]), + exit({timeout, Any}) + after 0 -> + d("handle_transport -> timeout"), + exit(timeout) + end + end. + + +%% This function is used to simulate incomming messages +handle_incomming_message(Msg, + #megaco_receive_handle{encoding_mod = EM, + encoding_config = EC} = RH) -> + Self = self(), + case EM:encode_message(EC, Msg) of + {ok, Bin} -> + ProcessMessage = + fun() -> + megaco:process_received_message(RH, Self, Self, Bin) + end, + spawn(ProcessMessage), + ok; + Error -> + d("handle_incomming_message -> encode failed" + "~n Error: ~p", [Error]), + exit(Error) + end. + + +%%------------------------------------------------------------------- + +call(Req) -> + call(Req, infinity). + +call(Req, Timeout) -> + case (catch gen_server:call(?SERVER, Req, Timeout)) of + {'EXIT', _} -> + {error, not_started}; + Res -> + Res + end. + +%% cast(Msg) -> +%% cast(whereis(?SERVER), Msg). + +cast(Pid, Msg) -> + d("cast -> entry with" + "~n Pid: ~p" + "~n Msg: ~p", [Pid, Msg]), + case (catch gen_server:cast(Pid, Msg)) of + {'EXIT', Reason} -> + d("cast -> failed casting" + "~n Reason: ~p", [Reason]), + {error, not_started}; + Res -> + Res + end. + + +%%------------------------------------------------------------------- + +d(F) -> + d(F, []). + +d(F, A) -> + print(now(), F, A). + + +print(Ts, F, A) -> + io:format("*** [~s] GENERIC TRANSPORT [~p] ***" + "~n " ++ F ++ "~n", + [format_timestamp(Ts), self() | A]). + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). + + diff --git a/lib/megaco/test/megaco_test_lib.erl b/lib/megaco/test/megaco_test_lib.erl new file mode 100644 index 0000000000..03c04831e8 --- /dev/null +++ b/lib/megaco/test/megaco_test_lib.erl @@ -0,0 +1,841 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Lightweight test server +%%---------------------------------------------------------------------- + +-module(megaco_test_lib). + +-compile(export_all). + +-include("megaco_test_lib.hrl"). + + +%% ---------------------------------------------------------------- +%% Time related function +%% + +sleep(infinity) -> + receive + after infinity -> + ok + end; +sleep(MSecs) -> + receive + after trunc(MSecs) -> + ok + end, + ok. + + +hours(N) -> trunc(N * 1000 * 60 * 60). +minutes(N) -> trunc(N * 1000 * 60). +seconds(N) -> trunc(N * 1000). + + +%% ---------------------------------------------------------------- +%% Conditional skip of testcases +%% + +non_pc_tc_maybe_skip(Config, Condition, File, Line) + when is_list(Config) andalso is_function(Condition) -> + %% Check if we shall skip the skip + case os:getenv("TS_OS_BASED_SKIP") of + "false" -> + ok; + _ -> + case lists:keysearch(ts, 1, Config) of + {value, {ts, megaco}} -> + %% Always run the testcase if we are using our own + %% test-server... + ok; + _ -> + case (catch Condition()) of + true -> + skip(non_pc_testcase, File, Line); + _ -> + ok + end + end + end. + + +os_based_skip(any) -> + true; +os_based_skip(Skippable) when is_list(Skippable) -> + {OsFam, OsName} = + case os:type() of + {_Fam, _Name} = FamAndName -> + FamAndName; + Fam -> + {Fam, undefined} + end, + case lists:member(OsFam, Skippable) of + true -> + true; + false -> + case lists:keysearch(OsFam, 1, Skippable) of + {value, {OsFam, OsName}} -> + true; + {value, {OsFam, OsNames}} when is_list(OsNames) -> + lists:member(OsName, OsNames); + _ -> + false + end + end; +os_based_skip(_) -> + false. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Evaluates a test case or test suite +%% Returns a list of failing test cases: +%% +%% {Mod, Fun, ExpectedRes, ActualRes} +%%---------------------------------------------------------------------- + +tickets(Case) -> + Res = lists:flatten(tickets(Case, default_config())), + %% io:format("Res: ~p~n", [Res]), + display_result(Res), + Res. + +tickets(Cases, Config) when is_list(Cases) -> + [tickets(Case, Config) || Case <- Cases]; +tickets(Mod, Config) when is_atom(Mod) -> + Res = tickets(Mod, tickets, Config), + Res; +tickets(Bad, _Config) -> + [{badarg, Bad, ok}]. + +tickets(Mod, Func, Config) -> + case (catch Mod:Func(suite)) of + [] -> + io:format("Eval: ~p:", [{Mod, Func}]), + Res = eval(Mod, Func, Config), + {R, _, _} = Res, + io:format(" ~p~n", [R]), + Res; + + Cases when is_list(Cases) -> + io:format("Expand: ~p:~p ... ~n" + " ~p~n", [Mod, Func, Cases]), + Map = fun({M,_}) when is_atom(M) -> + tickets(M, tickets, Config); + (F) when is_atom(F) -> + tickets(Mod, F, Config); + (Case) -> Case + end, + lists:map(Map, Cases); + + {req, _, {conf, Init, Cases, Finish}} -> + case (catch Mod:Init(Config)) of + Conf when is_list(Conf) -> + io:format("Expand: ~p:~p ...~n", [Mod, Func]), + Map = fun({M,_}) when is_atom(M) -> + tickets(M, tickets, Config); + (F) when is_atom(F) -> + tickets(Mod, F, Config); + (Case) -> Case + end, + Res = lists:map(Map, Cases), + (catch Mod:Finish(Conf)), + Res; + + {'EXIT', {skipped, Reason}} -> + io:format(" => skipping: ~p~n", [Reason]), + [{skipped, {Mod, Func}, Reason}]; + + Error -> + io:format(" => init failed: ~p~n", [Error]), + [{failed, {Mod, Func}, Error}] + end; + + {'EXIT', {undef, _}} -> + io:format("Undefined: ~p~n", [{Mod, Func}]), + [{nyi, {Mod, Func}, ok}]; + + Error -> + io:format("Ignoring: ~p:~p: ~p~n", [Mod, Func, Error]), + [{failed, {Mod, Func}, Error}] + end. + + +display_alloc_info() -> + io:format("Allocator memory information:~n", []), + AllocInfo = alloc_info(), + display_alloc_info(AllocInfo). + +display_alloc_info([]) -> + ok; +display_alloc_info([{Alloc, Mem}|AllocInfo]) -> + io:format(" ~15w: ~10w~n", [Alloc, Mem]), + display_alloc_info(AllocInfo). + +alloc_info() -> + case erlang:system_info(allocator) of + {_Allocator, _Version, Features, _Settings} -> + alloc_info(Features); + _ -> + [] + end. + +alloc_info(Allocators) -> + Allocs = [temp_alloc, sl_alloc, std_alloc, ll_alloc, eheap_alloc, + ets_alloc, binary_alloc, driver_alloc], + alloc_info(Allocators, Allocs, []). + +alloc_info([], _, Acc) -> + lists:reverse(Acc); +alloc_info([Allocator | Allocators], Allocs, Acc) -> + case lists:member(Allocator, Allocs) of + true -> + Instances0 = erlang:system_info({allocator, Allocator}), + Instances = + if + is_list(Instances0) -> + [Instance || Instance <- Instances0, + element(1, Instance) =:= instance]; + true -> + [] + end, + AllocatorMem = alloc_mem_info(Instances), + alloc_info(Allocators, Allocs, [{Allocator, AllocatorMem} | Acc]); + + false -> + alloc_info(Allocators, Allocs, Acc) + end. + +alloc_mem_info(Instances) -> + alloc_mem_info(Instances, []). + +alloc_mem_info([], Acc) -> + lists:sum([Mem || {instance, _, Mem} <- Acc]); +alloc_mem_info([{instance, N, Info}|Instances], Acc) -> + InstanceMemInfo = alloc_instance_mem_info(Info), + alloc_mem_info(Instances, [{instance, N, InstanceMemInfo} | Acc]). + +alloc_instance_mem_info(InstanceInfo) -> + MBCS = alloc_instance_mem_info(mbcs, InstanceInfo), + SBCS = alloc_instance_mem_info(sbcs, InstanceInfo), + MBCS + SBCS. + +alloc_instance_mem_info(Key, InstanceInfo) -> + case lists:keysearch(Key, 1, InstanceInfo) of + {value, {Key, Info}} -> + case lists:keysearch(blocks_size, 1, Info) of + {value, {blocks_size, Mem, _, _}} -> + Mem; + _ -> + 0 + end; + _ -> + 0 + end. + + +t(Case) -> + process_flag(trap_exit, true), + MEM = fun() -> case (catch erlang:memory()) of + {'EXIT', _} -> + []; + Res -> + Res + end + end, + Alloc1 = alloc_info(), + Mem1 = MEM(), + Res = lists:flatten(t(Case, default_config())), + Alloc2 = alloc_info(), + Mem2 = MEM(), + %% io:format("Res: ~p~n", [Res]), + display_result(Res, Alloc1, Mem1, Alloc2, Mem2), + Res. + +t({Mod, Fun}, Config) when is_atom(Mod) andalso is_atom(Fun) -> + case catch apply(Mod, Fun, [suite]) of + [] -> + io:format("Eval: ~p:", [{Mod, Fun}]), + Res = eval(Mod, Fun, Config), + {R, _, _, _} = Res, + io:format(" ~p~n", [R]), + Res; + + Cases when is_list(Cases) -> + io:format("Expand: ~p ...~n", [{Mod, Fun}]), + Map = fun(Case) when is_atom(Case) -> {Mod, Case}; + (Case) -> Case + end, + t(lists:map(Map, Cases), Config); + + {req, _, {conf, Init, Cases, Finish}} -> + case (catch apply(Mod, Init, [Config])) of + Conf when is_list(Conf) -> + io:format("Expand: ~p ...~n", [{Mod, Fun}]), + Map = fun(Case) when is_atom(Case) -> {Mod, Case}; + (Case) -> Case + end, + Res = t(lists:map(Map, Cases), Conf), + (catch apply(Mod, Finish, [Conf])), + Res; + + {'EXIT', {skipped, Reason}} -> + io:format(" => skipping: ~p~n", [Reason]), + [{skipped, {Mod, Fun}, Reason, 0}]; + + Error -> + io:format(" => failed: ~p~n", [Error]), + [{failed, {Mod, Fun}, Error, 0}] + end; + + {'EXIT', {undef, _}} -> + io:format("Undefined: ~p~n", [{Mod, Fun}]), + [{nyi, {Mod, Fun}, ok, 0}]; + + Error -> + io:format("Ignoring: ~p: ~p~n", [{Mod, Fun}, Error]), + [{failed, {Mod, Fun}, Error, 0}] + end; +t(Mod, Config) when is_atom(Mod) -> + Res = t({Mod, all}, Config), + Res; +t(Cases, Config) when is_list(Cases) -> + [t(Case, Config) || Case <- Cases]; +t(Bad, _Config) -> + [{badarg, Bad, ok, 0}]. + +eval(Mod, Fun, Config) -> + TestCase = {?MODULE, Mod, Fun}, + Label = lists:concat(["TEST CASE: ", Fun]), + megaco:report_event(40, ?MODULE, Mod, Label ++ " started", + [TestCase, Config]), + global:register_name(megaco_test_case_sup, self()), + Flag = process_flag(trap_exit, true), + put(megaco_test_server, true), + Config2 = Mod:init_per_testcase(Fun, Config), + Pid = spawn_link(?MODULE, do_eval, [self(), Mod, Fun, Config2]), + R = wait_for_evaluator(Pid, Mod, Fun, Config2, []), + Mod:fin_per_testcase(Fun, Config2), + erase(megaco_test_server), + global:unregister_name(megaco_test_case_sup), + process_flag(trap_exit, Flag), + R. + +-record('REASON', {mod, line, desc}). + +wait_for_evaluator(Pid, Mod, Fun, Config, Errors) -> + wait_for_evaluator(Pid, Mod, Fun, Config, Errors, 0). +wait_for_evaluator(Pid, Mod, Fun, Config, Errors, AccTime) -> + TestCase = {?MODULE, Mod, Fun}, + Label = lists:concat(["TEST CASE: ", Fun]), + receive + {done, Pid, ok, Time} when Errors =:= [] -> + megaco:report_event(40, Mod, ?MODULE, Label ++ " ok", + [TestCase, Config]), + {ok, {Mod, Fun}, Errors, Time}; + {done, Pid, ok, Time} -> + megaco:report_event(40, Mod, ?MODULE, Label ++ " failed", + [TestCase, Config]), + {failed, {Mod, Fun}, Errors, Time}; + {done, Pid, {ok, _}, Time} when Errors =:= [] -> + megaco:report_event(40, Mod, ?MODULE, Label ++ " ok", + [TestCase, Config]), + {ok, {Mod, Fun}, Errors, Time}; + {done, Pid, {ok, _}, Time} -> + megaco:report_event(40, Mod, ?MODULE, Label ++ " failed", + [TestCase, Config]), + {failed, {Mod, Fun}, Errors, Time}; + {done, Pid, Fail, Time} -> + megaco:report_event(20, Mod, ?MODULE, Label ++ " failed", + [TestCase, Config, {return, Fail}, Errors]), + {failed, {Mod,Fun}, Fail, Time}; + {'EXIT', Pid, {skipped, Reason}, Time} -> + megaco:report_event(20, Mod, ?MODULE, Label ++ " skipped", + [TestCase, Config, {skipped, Reason}]), + {skipped, {Mod, Fun}, Errors, Time}; + {'EXIT', Pid, Reason, Time} -> + megaco:report_event(20, Mod, ?MODULE, Label ++ " crashed", + [TestCase, Config, {'EXIT', Reason}]), + {crashed, {Mod, Fun}, [{'EXIT', Reason} | Errors], Time}; + {fail, Pid, Reason, Time} -> + wait_for_evaluator(Pid, Mod, Fun, Config, + Errors ++ [Reason], AccTime + Time) + end. + +do_eval(ReplyTo, Mod, Fun, Config) -> + display_system_info("before", Mod, Fun), + case timer:tc(Mod, Fun, [Config]) of + {Time, {'EXIT', {skipped, Reason}}} -> + display_tc_time(Time), + display_system_info("after (skipped)", Mod, Fun), + ReplyTo ! {'EXIT', self(), {skipped, Reason}, Time}; + {Time, Other} -> + display_tc_time(Time), + display_system_info("after", Mod, Fun), + ReplyTo ! {done, self(), Other, Time} + end, + unlink(ReplyTo), + exit(shutdown). + + +display_tc_time(Time) -> + io:format("~n" + "~n*********************************************" + "~n" + "~nTest case completion time: ~.3f sec (~w)" + "~n", [(Time / 1000000), Time]), + ok. + +display_system_info(WhenStr) -> + display_system_info(WhenStr, undefined, undefined). + +display_system_info(WhenStr, undefined, undefined) -> + display_system_info(WhenStr, ""); +display_system_info(WhenStr, Mod, Func) -> + ModFuncStr = lists:flatten(io_lib:format(" ~w:~w", [Mod, Func])), + display_system_info(WhenStr, ModFuncStr). + +display_system_info(WhenStr, ModFuncStr) -> + Fun = fun(F) -> case (catch F()) of + {'EXIT', _} -> + undefined; + Res -> + Res + end + end, + ProcCount = Fun(fun() -> erlang:system_info(process_count) end), + ProcLimit = Fun(fun() -> erlang:system_info(process_limit) end), + ProcMemAlloc = Fun(fun() -> erlang:memory(processes) end), + ProcMemUsed = Fun(fun() -> erlang:memory(processes_used) end), + ProcMemBin = Fun(fun() -> erlang:memory(binary) end), + ProcMemTot = Fun(fun() -> erlang:memory(total) end), + %% error_logger:info_msg( + io:format("~n" + "~n*********************************************" + "~n" + "System info ~s~s => " + "~n Process count: ~w" + "~n Process limit: ~w" + "~n Process memory alloc: ~w" + "~n Process memory used: ~w" + "~n Memory for binaries: ~w" + "~n Memory total: ~w" + "~n" + "~n*********************************************" + "~n" + "~n", [WhenStr, ModFuncStr, + ProcCount, ProcLimit, ProcMemAlloc, ProcMemUsed, + ProcMemBin, ProcMemTot]), + ok. + +display_result(Res, Alloc1, Mem1, Alloc2, Mem2) -> + io:format("~nAllocator info: ~n", []), + display_alloc(Alloc1, Alloc2), + io:format("~nMemory info: ~n", []), + display_memory(Mem1, Mem2), + display_result(Res). + +display_alloc([], []) -> + io:format("-~n", []), + ok; +display_alloc(A1, A2) -> + do_display_alloc(A1, A2). + +do_display_alloc([], _) -> + ok; +do_display_alloc([{Alloc, Mem1}|AllocInfo1], AllocInfo2) -> + Mem2 = + case lists:keysearch(Alloc, 1, AllocInfo2) of + {value, {_, Val}} -> + Val; + false -> + undefined + end, + io:format("~15w: ~10w -> ~w~n", [Alloc, Mem1, Mem2]), + do_display_alloc(AllocInfo1, AllocInfo2). + +display_memory([], []) -> + io:format("-~n", []), + ok; +display_memory(Mem1, Mem2) -> + do_display_memory(Mem1, Mem2). + + +do_display_memory([], _) -> + ok; +do_display_memory([{Key, Mem1}|MemInfo1], MemInfo2) -> + Mem2 = + case lists:keysearch(Key, 1, MemInfo2) of + {value, {_, Val}} -> + Val; + false -> + undefined + end, + io:format("~15w: ~10w -> ~w~n", [Key, Mem1, Mem2]), + do_display_memory(MemInfo1, MemInfo2). + +display_result([]) -> + io:format("OK~n", []); +display_result(Res) when is_list(Res) -> + Ok = [{MF, Time} || {ok, MF, _, Time} <- Res], + Nyi = [MF || {nyi, MF, _, _Time} <- Res], + Skipped = [{MF, Reason} || {skipped, MF, Reason, _Time} <- Res], + Failed = [{MF, Reason} || {failed, MF, Reason, _Time} <- Res], + Crashed = [{MF, Reason} || {crashed, MF, Reason, _Time} <- Res], + display_summery(Ok, Nyi, Skipped, Failed, Crashed), + display_ok(Ok), + display_skipped(Skipped), + display_failed(Failed), + display_crashed(Crashed). + +display_summery(Ok, Nyi, Skipped, Failed, Crashed) -> + io:format("~nTest case summery:~n", []), + display_summery(Ok, "successfull"), + display_summery(Nyi, "not yet implemented"), + display_summery(Skipped, "skipped"), + display_summery(Failed, "failed"), + display_summery(Crashed, "crashed"), + io:format("~n", []). + +display_summery(Res, Info) -> + io:format(" ~w test cases ~s~n", [length(Res), Info]). + +display_ok([]) -> + ok; +display_ok(Ok) -> + io:format("Ok test cases:~n", []), + F = fun({{M, F}, Time}) -> + io:format(" ~w : ~w => ~.2f sec~n", [M, F, Time / 1000000]) + end, + lists:foreach(F, Ok), + io:format("~n", []). + +display_skipped([]) -> + ok; +display_skipped(Skipped) -> + io:format("Skipped test cases:~n", []), + F = fun({MF, Reason}) -> io:format(" ~p => ~p~n", [MF, Reason]) end, + lists:foreach(F, Skipped), + io:format("~n", []). + + +display_failed([]) -> + ok; +display_failed(Failed) -> + io:format("Failed test cases:~n", []), + F = fun({MF, Reason}) -> io:format(" ~p => ~p~n", [MF, Reason]) end, + lists:foreach(F, Failed), + io:format("~n", []). + +display_crashed([]) -> + ok; +display_crashed(Crashed) -> + io:format("Crashed test cases:~n", []), + F = fun({MF, Reason}) -> io:format(" ~p => ~p~n", [MF, Reason]) end, + lists:foreach(F, Crashed), + io:format("~n", []). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Verify that the actual result of a test case matches the exected one +%% Returns the actual result +%% Stores the result in the process dictionary if mismatch + +error(Actual, Mod, Line) -> + global:send(megaco_global_logger, {failed, Mod, Line}), + log("<ERROR> Bad result: ~p~n", [Actual], Mod, Line), + Label = lists:concat([Mod, "(", Line, ") unexpected result"]), + megaco:report_event(60, Mod, Mod, Label, + [{line, Mod, Line}, {error, Actual}]), + case global:whereis_name(megaco_test_case_sup) of + undefined -> + ignore; + Pid -> + Fail = #'REASON'{mod = Mod, line = Line, desc = Actual}, + Pid ! {fail, self(), Fail} + end, + Actual. + +log(Format, Args, Mod, Line) -> + case global:whereis_name(megaco_global_logger) of + undefined -> + io:format(user, "~p~p(~p): " ++ Format, + [self(), Mod, Line] ++ Args); + Pid -> + io:format(Pid, "~p~p(~p): " ++ Format, + [self(), Mod, Line] ++ Args) + end. + +skip(Actual, File, Line) -> + log("Skipping test case~n", [], File, Line), + String = lists:flatten(io_lib:format("Skipping test case ~p(~p): ~p~n", + [File, Line, Actual])), + exit({skipped, String}). + +fatal_skip(Actual, File, Line) -> + error(Actual, File, Line), + exit(shutdown). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Flush the message queue and return its messages +flush() -> + receive + Msg -> + [Msg | flush()] + after 1000 -> + [] + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Check if process is alive and kicking +still_alive(Pid) -> + case catch erlang:is_process_alive(Pid) of % New BIF in Erlang/OTP R5 + true -> + true; + false -> + false; + {'EXIT', _} -> % Pre R5 backward compatibility + case process_info(Pid, message_queue_len) of + undefined -> false; + _ -> true + end + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% The proxy process + +proxy_start(ProxyId) -> + spawn_link(?MODULE, proxy_init, [ProxyId, self()]). + +proxy_start(Node, ProxyId) -> + spawn_link(Node, ?MODULE, proxy_init, [ProxyId, self()]). + +proxy_init(ProxyId, Controller) -> + process_flag(trap_exit, true), + ?LOG("[~p] proxy started by ~p~n",[ProxyId, Controller]), + proxy_loop(ProxyId, Controller). + +proxy_loop(OwnId, Controller) -> + receive + {'EXIT', Controller, Reason} -> + p("proxy_loop -> received exit from controller" + "~n Reason: ~p" + "~n", [Reason]), + exit(Reason); + {apply, Fun} -> + p("proxy_loop -> received apply request~n", []), + Res = Fun(), + p("proxy_loop -> apply result: " + "~n ~p" + "~n", [Res]), + Controller ! {res, OwnId, Res}, + proxy_loop(OwnId, Controller); + OtherMsg -> + p("proxy_loop -> received unknown message: " + "~n OtherMsg: ~p" + "~n", [OtherMsg]), + Controller ! {msg, OwnId, OtherMsg}, + proxy_loop(OwnId, Controller) + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Test server callbacks +init_per_testcase(_Case, Config) -> + Pid = group_leader(), + Name = megaco_global_logger, + case global:whereis_name(Name) of + undefined -> + global:register_name(megaco_global_logger, Pid); + Pid -> + io:format("~w:init_per_testcase -> " + "already registered to ~p~n", [?MODULE, Pid]), + ok; + OtherPid when is_pid(OtherPid) -> + io:format("~w:init_per_testcase -> " + "already registered to other ~p (~p)~n", + [?MODULE, OtherPid, Pid]), + exit({already_registered, {megaco_global_logger, OtherPid, Pid}}) + end, + set_kill_timer(Config). + +fin_per_testcase(_Case, Config) -> + Name = megaco_global_logger, + case global:whereis_name(Name) of + undefined -> + io:format("~w:fin_per_testcase -> already un-registered~n", + [?MODULE]), + ok; + Pid when is_pid(Pid) -> + global:unregister_name(megaco_global_logger), + ok + end, + reset_kill_timer(Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Set kill timer + +set_kill_timer(Config) -> + case init:get_argument(megaco_test_timeout) of + {ok, _} -> + Config; + _ -> + Time = + case lookup_config(tc_timeout, Config) of + [] -> + timer:minutes(5); + ConfigTime when is_integer(ConfigTime) -> + ConfigTime + end, + Dog = + case get(megaco_test_server) of + true -> + spawn_link(?MODULE, watchdog, [self(), Time]); + _ -> + test_server:timetrap(Time) + end, + [{kill_timer, Dog}|Config] + + + end. + +reset_kill_timer(Config) -> + DogKiller = + case get(megaco_test_server) of + true -> + fun(P) when is_pid(P) -> P ! stop; + (_) -> ok + end; + _ -> + fun(Ref) -> test_server:timetrap_cancel(Ref) end + end, + case lists:keysearch(kill_timer, 1, Config) of + {value, {kill_timer, Dog}} -> + DogKiller(Dog), + lists:keydelete(kill_timer, 1, Config); + _ -> + Config + end. + +watchdog(Pid, Time) -> + erlang:now(), + receive + stop -> + ok + after Time -> + case (catch process_info(Pid)) of + undefined -> + ok; + Info -> + ?LOG("<ERROR> Watchdog in test case timed out " + "for ~p after ~p min" + "~n~p" + "~n", + [Pid, Time div (1000*60), Info]), + exit(Pid, kill) + end + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +prepare_test_case(Actions, N, Config, File, Line) -> + OrigNodes = lookup_config(nodes, Config), + TestNodes = lookup_config(nodenames, Config), %% For testserver + This = node(), + SomeNodes = OrigNodes ++ (TestNodes -- OrigNodes), + AllNodes = [This | (SomeNodes -- [This])], + Nodes = pick_n_nodes(N, AllNodes, File, Line), + start_nodes(Nodes, File, Line), + do_prepare_test_case(Actions, Nodes, Config, File, Line). + +do_prepare_test_case([init | Actions], Nodes, Config, File, Line) -> + process_flag(trap_exit, true), + megaco_test_lib:flush(), + do_prepare_test_case(Actions, Nodes, Config, File, Line); +do_prepare_test_case([{stop_app, App} | Actions], Nodes, Config, File, Line) -> + _Res = rpc:multicall(Nodes, application, stop, [App]), + do_prepare_test_case(Actions, Nodes, Config, File, Line); +do_prepare_test_case([], Nodes, _Config, _File, _Line) -> + Nodes. + +pick_n_nodes(all, AllNodes, _File, _Line) -> + AllNodes; +pick_n_nodes(N, AllNodes, _File, _Line) + when is_integer(N) andalso (length(AllNodes) >= N) -> + AllNodes -- lists:nthtail(N, AllNodes); +pick_n_nodes(N, AllNodes, File, Line) -> + fatal_skip({too_few_nodes, N, AllNodes}, File, Line). + +lookup_config(Key,Config) -> + case lists:keysearch(Key, 1, Config) of + {value,{Key,Val}} -> + Val; + _ -> + [] + end. + +default_config() -> + [{nodes, default_nodes()}, {ts, megaco}]. + +default_nodes() -> + mk_nodes(2, []). + +mk_nodes(0, Nodes) -> + Nodes; +mk_nodes(N, []) -> + mk_nodes(N - 1, [node()]); +mk_nodes(N, Nodes) when N > 0 -> + Head = hd(Nodes), + [Name, Host] = node_to_name_and_host(Head), + Nodes ++ [mk_node(I, Name, Host) || I <- lists:seq(1, N)]. + +mk_node(N, Name, Host) -> + list_to_atom(lists:concat([Name ++ integer_to_list(N) ++ "@" ++ Host])). + +%% Returns [Name, Host] +node_to_name_and_host(Node) -> + string:tokens(atom_to_list(Node), [$@]). + +start_nodes([Node | Nodes], File, Line) -> + case net_adm:ping(Node) of + pong -> + start_nodes(Nodes, File, Line); + pang -> + [Name, Host] = node_to_name_and_host(Node), + case slave:start_link(Host, Name) of + {ok, NewNode} when NewNode =:= Node -> + Path = code:get_path(), + {ok, Cwd} = file:get_cwd(), + true = rpc:call(Node, code, set_path, [Path]), + ok = rpc:call(Node, file, set_cwd, [Cwd]), + true = rpc:call(Node, code, set_path, [Path]), + {_, []} = rpc:multicall(global, sync, []), + start_nodes(Nodes, File, Line); + Other -> + fatal_skip({cannot_start_node, Node, Other}, File, Line) + end + end; +start_nodes([], _File, _Line) -> + ok. + +p(F,A) -> + io:format("~p" ++ F ++ "~n", [self()|A]). diff --git a/lib/megaco/test/megaco_test_lib.hrl b/lib/megaco/test/megaco_test_lib.hrl new file mode 100644 index 0000000000..b92474d7b8 --- /dev/null +++ b/lib/megaco/test/megaco_test_lib.hrl @@ -0,0 +1,87 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Define common macros for testing +%%---------------------------------------------------------------------- + +-define(APPLY(Proxy, Fun), + Proxy ! {apply, Fun}). + +-define(LOG(Format, Args), + megaco_test_lib:log(Format, Args, ?MODULE, ?LINE)). + +-define(ERROR(Reason), + megaco_test_lib:error(Reason, ?MODULE, ?LINE)). + +-define(OS_BASED_SKIP(Skippable), + megaco_test_lib:os_based_skip(Skippable)). + +-define(NON_PC_TC_MAYBE_SKIP(Config, Condition), + megaco_test_lib:non_pc_tc_maybe_skip(Config, Condition, ?MODULE, ?LINE)). + +-define(SKIP(Reason), + megaco_test_lib:skip(Reason, ?MODULE, ?LINE)). + +-define(VERIFYL(Expected, Expr), + fun(A,B) when list(A), list(B) -> + A1 = lists:sort(A), + B1 = lists:sort(B), + case A1 of + B1 -> ?LOG("Ok, ~p~n", [B]); + _ -> ?ERROR(B) + end, + B; + (A,A) -> + ?LOG("Ok, ~p~n", [A]), + A; + (A,B) -> + ?ERROR(B), + B + end(Expected, (catch Expr))). + +-define(VERIFY(Expected, Expr), + fun() -> + AcTuAlReS = (catch (Expr)), + case AcTuAlReS of + Expected -> ?LOG("Ok, ~p~n", [AcTuAlReS]); + _ -> ?ERROR(AcTuAlReS) + end, + AcTuAlReS + end()). + +-define(RECEIVE(Expected), + ?VERIFY(Expected, megaco_test_lib:flush())). + +-define(MULTI_RECEIVE(Expected), + ?VERIFY(lists:sort(Expected), lists:sort(megaco_test_lib:flush()))). + +-define(ACQUIRE_NODES(N, Config), + megaco_test_lib:prepare_test_case([init, {stop_app, megaco}], + N, Config, ?FILE, ?LINE)). + + +-define(SLEEP(MSEC), megaco_test_lib:sleep(MSEC)). +-define(M(), megaco_test_lib:millis()). +-define(MDIFF(A,B), megaco_test_lib:millis_diff(A,B)). + +-define(HOURS(T), megaco_test_lib:hours(T)). +-define(MINUTES(T), megaco_test_lib:minutes(T)). +-define(SECONDS(T), megaco_test_lib:seconds(T)). diff --git a/lib/megaco/test/megaco_test_megaco_generator.erl b/lib/megaco/test/megaco_test_megaco_generator.erl new file mode 100644 index 0000000000..5ff7162223 --- /dev/null +++ b/lib/megaco/test/megaco_test_megaco_generator.erl @@ -0,0 +1,1120 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: megaco sequence generator for the megaco test suite +%%---------------------------------------------------------------------- + +-module(megaco_test_megaco_generator). + +-behaviour(megaco_test_generator). + +%% API +-export([ + start_link/1, start_link/2, + stop/1, + exec/2, exec/3 + ]). + +%% genarator behaviour callback exports +-export([ + init/1, + handle_parse/2, + handle_exec/2, + terminate/2 + ]). + +%% Megaco callback api +-export([ + handle_connect/3, handle_connect/4, + handle_disconnect/4, + handle_syntax_error/4, handle_syntax_error/5, + handle_message_error/4, handle_message_error/5, + handle_trans_request/4, handle_trans_request/5, + handle_trans_long_request/4, handle_trans_long_request/5, + handle_trans_reply/5, handle_trans_reply/6, + handle_trans_ack/5, handle_trans_ack/6, + handle_trans_request_abort/5, handle_trans_request_abort/6, + handle_unexpected_trans/4, handle_unexpected_trans/5 + ]). + + +%%---------------------------------------------------------------------- + +-include_lib("megaco/include/megaco.hrl"). + + +%%---------------------------------------------------------------------- + +-define(DELIVER_MOD, megaco_test_deliver). + + +%%---------------------------------------------------------------------- + +-record(state, + { + mid, + recv_handle, + port, + send_handle, + conn_handle, + + transport_sup, + ctrl_pid, + + result = [] % Accumulated results from verification + }). + + +%%---------------------------------------------------------------------- +%% API +%%---------------------------------------------------------------------- + +start_link(Name) -> + megaco_test_generator:start_link(?MODULE, [], Name). + +start_link(Name, Node) -> + megaco_test_generator:start_link(?MODULE, [], Name, Node). + +stop(Server) -> + megaco_test_generator:stop(Server). + +exec(Server, Instructions) when is_list(Instructions) -> + megaco_test_generator:exec(Server, Instructions). + +exec(Server, Instructions, Timeout) when is_list(Instructions) -> + megaco_test_generator:exec(Server, Instructions, Timeout). + + +%%---------------------------------------------------------------------- +%% generator callback functions +%%---------------------------------------------------------------------- + +init([]) -> + random_init(), + {ok, #state{}}. + + +%% ----- instruction parser ----- + +handle_parse({debug, Debug} = Instruction, State) + when (Debug == true) orelse (Debug == false) -> + {ok, Instruction, State}; + +handle_parse({expect_nothing, To} = Instruction, State) + when is_integer(To) andalso (To > 0) -> + {ok, Instruction, State}; + +handle_parse({megaco_trace, Level} = Instruction, State) + when (Level == disable) orelse + (Level == max) orelse + (Level == min) orelse + is_integer(Level) -> + {ok, Instruction, State}; + +handle_parse({sleep, To} = Instruction, State) + when is_integer(To) andalso (To > 0) -> + {ok, Instruction, State}; + +handle_parse(megaco_start = Instruction, State) -> + {ok, Instruction, State}; + +handle_parse(megaco_stop = Instruction, State) -> + {ok, Instruction, State}; + +handle_parse({megaco_start_user, _Mid, _RecvInfo, Conf} = Instruction, State) + when is_list(Conf) -> + {ok, Instruction, State}; + +handle_parse(megaco_stop_user = Instruction, State) -> + {ok, Instruction, State}; + +handle_parse(megaco_info = Instruction, State) -> + {ok, Instruction, State}; + +handle_parse(megaco_system_info, State) -> + Verify = fun(_) -> ok end, + Instruction = {megaco_system_info, internal_system_info_tag, Verify}, + {ok, Instruction, State}; + +handle_parse({megaco_system_info, Tag}, State) + when is_atom(Tag) -> + Verify = fun(_) -> ok end, + Instruction = {megaco_system_info, Tag, Verify}, + {ok, Instruction, State}; + +handle_parse({megaco_system_info, Tag, Verify} = Instruction, State) + when is_atom(Tag) andalso is_function(Verify) -> + {ok, Instruction, State}; + +handle_parse({megaco_user_info, Tag} = Instruction, State) + when is_atom(Tag) -> + {ok, Instruction, State}; + +handle_parse({megaco_update_user_info, Tag, _Val} = Instruction, State) + when is_atom(Tag) -> + {ok, Instruction, State}; + +handle_parse({megaco_conn_info, Tag} = Instruction, State) + when is_atom(Tag) -> + {ok, Instruction, State}; + +handle_parse({megaco_update_conn_info, Tag, _Val} = Instruction, State) + when is_atom(Tag) -> + {ok, Instruction, State}; + +handle_parse(start_transport = Instruction, State) -> + {ok, Instruction, State}; + +handle_parse(listen = _Instruction, State) -> + MeybeRetry = make_connect_retry_fun2(), + Instruction = {listen, [], MeybeRetry}, + {ok, Instruction, State}; + +handle_parse({listen, Opts} = _Instruction, State) + when is_list(Opts) -> + MeybeRetry = make_connect_retry_fun2(), + Instruction = {listen, Opts, MeybeRetry}, + {ok, Instruction, State}; + +handle_parse({listen, Opts, MeybeRetry} = Instruction, State) + when is_list(Opts) andalso is_function(MeybeRetry) -> + {ok, Instruction, State}; + +handle_parse(connect = _Instruction, State) -> + case inet:gethostname() of + {ok, LocalHost} -> + MeybeRetry = make_connect_retry_fun2(), + Instruction = {connect, LocalHost, [], MeybeRetry}, + {ok, Instruction, State}; + Error -> + Error + end; + +handle_parse({connect, Opts} = _Instruction, State) + when is_list(Opts) -> + verify_connect_opts(Opts), + case inet:gethostname() of + {ok, LocalHost} -> + MeybeRetry = make_connect_retry_fun2(), + Instruction = {connect, LocalHost, Opts, MeybeRetry}, + {ok, Instruction, State}; + Error -> + Error + end; + +handle_parse({connect, Host} = _Instruction, State) + when is_atom(Host) -> + MeybeRetry = make_connect_retry_fun2(), + Instruction = {connect, Host, [], MeybeRetry}, + {ok, Instruction, State}; + +handle_parse({connect, Host, Opts} = _Instruction, State) + when (is_atom(Host) orelse is_list(Host)) andalso is_list(Opts) -> + verify_connect_opts(Opts), + MeybeRetry = make_connect_retry_fun2(), + Instruction = {connect, Host, Opts, MeybeRetry}, + {ok, Instruction, State}; + +handle_parse({connect, Host, Opts, MeybeRetry} = Instruction, State) + when (is_atom(Host) orelse is_list(Host)) andalso + is_list(Opts) andalso + is_function(MeybeRetry) -> + verify_connect_opts(Opts), + {ok, Instruction, State}; + +handle_parse(disconnect = Instruction, State) -> + {ok, Instruction, State}; + +handle_parse(megaco_connect = Instruction, State) -> + {ok, Instruction, State}; + +handle_parse({megaco_connect, _} = Instruction, State) -> + {ok, Instruction, State}; + +handle_parse(megaco_disconnect = Instruction, State) -> + {ok, Instruction, State}; + +handle_parse({megaco_disconnect, _Reason} = Instruction, State) -> + {ok, Instruction, State}; + +handle_parse({megaco_call, ARs, Opts} = Instruction, State) + when (is_list(ARs) orelse is_binary(ARs)) andalso is_list(Opts) -> + {ok, Instruction, State}; + +handle_parse({megaco_call, _Mid, ARs, Opts} = Instruction, State) + when (is_list(ARs) orelse is_binary(ARs)) andalso is_list(Opts) -> + {ok, Instruction, State}; + +handle_parse({megaco_cast, ARs, Opts} = Instruction, State) + when (is_list(ARs) orelse is_binary(ARs)) andalso is_list(Opts) -> + {ok, Instruction, State}; + +handle_parse({megaco_cast, _Mid, ARs, Opts} = Instruction, State) + when (is_list(ARs) orelse is_binary(ARs)) andalso is_list(Opts) -> + {ok, Instruction, State}; + +handle_parse({megaco_cancel, _Reason} = Instruction, State) -> + {ok, Instruction, State}; + +handle_parse({megaco_callback, Tag, TimeoutOrVerify} = Instruction, State) + when (is_atom(Tag) andalso + ((is_integer(TimeoutOrVerify) andalso + (TimeoutOrVerify > 0)) orelse + is_function(TimeoutOrVerify))) -> + {ok, Instruction, State}; + +handle_parse({megaco_callback, Tag, Verify, Timeout} = Instruction, State) + when (is_atom(Tag) andalso + is_function(Verify) andalso + (is_integer(Timeout) andalso (Timeout > 0))) -> + {ok, Instruction, State}; + +handle_parse({megaco_callback, Tag, {VMod, VFunc, VArgs}} = _Instruction, + State) + when (is_atom(Tag) andalso + (is_atom(VMod) andalso is_atom(VFunc) andalso is_list(VArgs))) -> + Verify = fun(X) -> + io:format("[megaco_callback ~w] calling ~w:~w with" + "~n X: ~p" + "~n VArgs: ~w" + "~n", [Tag, VMod, VFunc, X, VArgs]), + (catch apply(VMod, VFunc, [X|VArgs])) + end, + Instruction = {megaco_callback, Tag, Verify}, + {ok, Instruction, State}; + +handle_parse({megaco_callback, Verifiers0} = _Instruction, State) + when is_list(Verifiers0) -> + Verifiers = [make_verifier(Verifier) || Verifier <- Verifiers0], + Instruction = {megaco_callback, Verifiers}, + {ok, Instruction, State}; + +handle_parse({trigger, Trigger} = Instruction, State) + when is_function(Trigger) -> + {ok, Instruction, State}; + +handle_parse(Instruction, _State) -> + error({invalid_instruction, Instruction}). + + +make_verifier({Tag, No, VerifyFunc} = Verify) + when is_atom(Tag) andalso is_integer(No) andalso is_function(VerifyFunc) -> + Verify; +make_verifier({Tag, No, {VMod, VFunc, VArgs}}) + when is_atom(Tag) andalso is_integer(No) andalso + (is_atom(VMod) andalso is_atom(VFunc) andalso is_list(VArgs)) -> + VerifyFunc = fun(X) -> + io:format("[megaco_callback ~w] calling ~w:~w with" + "~n X: ~p" + "~n VArgs: ~w" + "~n", [Tag, VMod, VFunc, X, VArgs]), + (catch apply(VMod, VFunc, [X|VArgs])) + end, + Verify = {Tag, No, VerifyFunc}, + Verify; +make_verifier(BadVerifier) -> + error({bad_verifier, BadVerifier}). + + +verify_connect_opts([]) -> + ok; +verify_connect_opts([{Key, _}|Opts]) when is_atom(Key) -> + verify_connect_opts(Opts); +verify_connect_opts([H|_]) -> + error({bad_opts_list, H}). + +%% make_connect_retry_fun1() -> +%% fun(Error, _) -> +%% {false, Error} +%% end. + +make_connect_retry_fun2() -> + fun(Error, noError) -> + Timeout = 250, + sleep(random(Timeout) + 100), + {true, {3, Timeout*2, Error}}; + (_Error, {0, _Timeout, OriginalError}) -> + {false, OriginalError}; + (_Error, {N, Timeout, OriginalError}) -> + sleep(random(Timeout) + 100), + {true, {N-1, Timeout*2, OriginalError}} + end. + + +%% ----- instruction exececutor ----- + +handle_exec({debug, Debug}, State) -> + p("debug: ~p", [Debug]), + put(debug, Debug), + {ok, State}; + +handle_exec({expect_nothing, To}, State) -> + p("expect_nothing: ~p", [To]), + receive + Any -> + error({expect_nothing, Any}) + after To -> + {ok, State} + end; + +handle_exec({megaco_trace, disable}, State) -> + p("megaco trace: disable"), + megaco:disable_trace(), + {ok, State}; +handle_exec({megaco_trace, Level}, State) -> + p("megaco trace: enable [~w]", [Level]), + megaco:enable_trace(Level, io), + {ok, State}; + +handle_exec(megaco_start, State) -> + p("megaco_start"), + ok = megaco:start(), + {ok, State}; + +handle_exec(megaco_stop, State) -> + p("megaco_stop"), + ok = megaco:stop(), + {ok, State}; + +handle_exec({megaco_start_user, Mid, RecvInfo, Conf}, State) -> + p("megaco_start_user: ~p", [Mid]), + + d("megaco_start_user -> start user"), + ok = megaco:start_user(Mid, Conf), + + d("megaco_start_user -> update user info: user_mod"), + ok = megaco:update_user_info(Mid, user_mod, ?MODULE), + + d("megaco_start_user -> update user info: user_args"), + ok = megaco:update_user_info(Mid, user_args, [self()]), + + Port = get_config(port, RecvInfo), + EM = get_config(encoding_module, RecvInfo), + EC = get_config(encoding_config, RecvInfo), + TM = get_config(transport_module, RecvInfo), + RH0 = megaco:user_info(Mid, receive_handle), + + RH1 = RH0#megaco_receive_handle{send_mod = TM, + encoding_mod = EM, + encoding_config = EC}, + + State1 = State#state{mid = Mid, recv_handle = RH1, port = Port}, + {ok, State1}; + +handle_exec(megaco_stop_user, #state{mid = Mid} = State) + when Mid /= undefined -> + megaco_cleanup(State), + ok = megaco:stop_user(Mid), + {ok, State#state{mid = undefined}}; + +handle_exec(start_transport, #state{recv_handle = RH} = State) -> + p("start_transport"), + #megaco_receive_handle{send_mod = TM} = RH, + case (catch TM:start_transport()) of + {ok, Sup} -> + d("start_transport -> Sup: ~p", [Sup]), + {ok, State#state{transport_sup = Sup}}; + {error, Reason} -> + e("failed starting transport (~w): " + "~n ~p", [TM, Reason]), + error({failed_starting_transport, TM, Reason}); + Crap -> + e("failed starting transport (~w): " + "~n ~p", [TM, Crap]), + error({failed_starting_transport, TM, Crap}) + end; + +handle_exec({listen, Opts0, MaybeRetry}, + #state{recv_handle = RH, port = Port, transport_sup = Pid} = State) + when RH#megaco_receive_handle.send_mod =:= megaco_tcp -> + p("listen(tcp)", []), + Opts = [{module, ?DELIVER_MOD}, + {port, Port}, + {receive_handle, RH}, + {tcp_options, [{nodelay, true}]} | Opts0], + case (catch handle_exec_listen_tcp(Pid, Opts, MaybeRetry)) of + ok -> + {ok, State}; + Else -> + error({tcp_listen_failed, Opts0, Else}) + end; +handle_exec({listen, Opts0, _MaybeRetry}, + #state{recv_handle = RH, port = Port, transport_sup = Pid} = State) + when RH#megaco_receive_handle.send_mod =:= megaco_udp -> + p("listen(udp) - open"), + Opts = [{module, ?DELIVER_MOD}, {port, Port}, {receive_handle, RH}|Opts0], + case (catch megaco_udp:open(Pid, Opts)) of + {ok, _SH, _CtrlPid} -> + {ok, State}; + Else -> + error({udp_open, Opts0, Else}) + end; +handle_exec({listen, Opts0, _MaybeRetry}, + #state{recv_handle = RH, port = Port, transport_sup = Pid} = State) + when RH#megaco_receive_handle.send_mod =:= megaco_test_generic_transport -> + p("listen(generic)"), + Opts = [{module, ?DELIVER_MOD}, {port, Port}, {receive_handle, RH}|Opts0], + case (catch megaco_test_generic_transport:listen(Pid, Opts)) of + {ok, _SH, _CtrlPid} -> + {ok, State}; + Else -> + error({udp_open, Opts0, Else}) + end; + +handle_exec({connect, Host, Opts0, MaybeRetry}, + #state{transport_sup = Sup, + recv_handle = RH, + port = Port} = State) + when RH#megaco_receive_handle.send_mod =:= megaco_tcp -> + p("connect[megaco_tcp] to ~p:~p", [Host, Port]), + PrelMid = preliminary_mid, + Opts = [{host, Host}, + {port, Port}, + {receive_handle, RH}, + {tcp_options, [{nodelay, true}]} | Opts0], + case (catch handle_exec_connect_tcp(Host, Opts, Sup, MaybeRetry)) of + {ok, SH, ControlPid} -> + d("tcp connected: ~p, ~p", [SH, ControlPid]), + megaco_connector_start(RH, PrelMid, SH, ControlPid), + {ok, State#state{send_handle = SH, + ctrl_pid = ControlPid}}; + Error -> + error({tcp_connect_failed, Host, Opts0, Error}) + end; + +handle_exec({connect, Host, Opts0, _MaybeRetry}, + #state{transport_sup = Sup, + recv_handle = RH, + port = Port} = State) + when RH#megaco_receive_handle.send_mod =:= megaco_udp -> + p("connect[megaco_udp] to ~p", [Host]), + PrelMid = preliminary_mid, + Opts = [{port, 0}, {receive_handle, RH}|Opts0], + d("udp open", []), + case (catch megaco_udp:open(Sup, Opts)) of + {ok, Handle, ControlPid} -> + d("udp opened: ~p, ~p", [Handle, ControlPid]), + SH = megaco_udp:create_send_handle(Handle, Host, Port), + megaco_connector_start(RH, PrelMid, SH, ControlPid), + {ok, State#state{send_handle = SH, + ctrl_pid = ControlPid}}; + Error -> + error({udp_connect_failed, Host, Opts0, Error}) + end; + +handle_exec({connect, Host, Opts0, _MaybeRetry}, + #state{transport_sup = Sup, + recv_handle = RH, + port = Port} = State) + when RH#megaco_receive_handle.send_mod =:= megaco_test_generic_transport -> + p("connect[megaco_test_generic_transport] to ~p", [Host]), + PrelMid = preliminary_mid, + Opts = [{host, Host}, {port, Port}, {receive_handle, RH}|Opts0], + case (catch megaco_test_generic_transport:connect(Sup, Opts)) of + {ok, SH, ControlPid} -> + d("generic connected: ~p, ~p", [SH, ControlPid]), + megaco_connector_start(RH, PrelMid, SH, ControlPid), + {ok, State#state{send_handle = SH, + ctrl_pid = ControlPid}}; + Error -> + error({generic_connect_failed, Host, Opts0, Error}) + end; + +handle_exec(megaco_connect, State) -> + p("megaco_connect"), + receive + {megaco_connect_result, {ok, CH}} -> + p("megaco connect succeeded: ~p", [CH]), + {ok, State#state{conn_handle = CH}}; + {megaco_connect_result, Error} -> + p("megaco connect failed: ~p", [Error]), + #state{result = Res} = State, + {ok, State#state{result = [Error|Res]}} + end; + +handle_exec({megaco_connect, Mid}, + #state{recv_handle = RH, + send_handle = SH, + ctrl_pid = ControlPid} = State) -> + p("megaco_connect: ~p", [Mid]), + megaco_connector_start(RH, Mid, SH, ControlPid), + {ok, State}; + +handle_exec({megaco_user_info, Tag}, #state{mid = Mid, result = Res} = State) + when Mid /= undefined -> + p("megaco_user_info: ~w", [Tag]), + Val = (catch megaco:user_info(Mid, Tag)), + d("megaco_user_info: ~p", [Val]), + {ok, State#state{result = [Val|Res]}}; + +handle_exec({megaco_update_user_info, Tag, Val}, #state{mid = Mid} = State) + when Mid /= undefined -> + p("megaco_update_user_info: ~w -> ~p", [Tag, Val]), + ok = megaco:update_user_info(Mid, Tag, Val), + {ok, State}; + +handle_exec({megaco_conn_info, Tag}, + #state{conn_handle = CH, result = Res} = State) + when CH /= undefined -> + p("megaco_conn_info: ~w", [Tag]), + Val = (catch megaco:conn_info(CH, Tag)), + d("megaco_conn_info: ~p", [Val]), + {ok, State#state{result = [Val|Res]}}; + +handle_exec({megaco_update_conn_info, Tag, Val}, + #state{conn_handle = CH} = State) + when CH /= undefined -> + p("megaco_update_conn_info: ~w -> ~p", [Tag, Val]), + case megaco:update_conn_info(CH, Tag, Val) of + ok -> + {ok, State}; + Error -> + error({failed_updating_conn_info, Tag, Val, Error}) + end; + +handle_exec(megaco_info, #state{result = Res} = State) -> + p("megaco_info", []), + Val = (catch megaco:info()), + d("megaco_info: ~p", [Val]), + {ok, State#state{result = [Val|Res]}}; + +handle_exec({megaco_system_info, Tag, Verify}, #state{result = Res} = State) -> + p("megaco_system_info: ~w", [Tag]), + Val = (catch megaco:system_info(Tag)), + d("megaco_system_info: ~p", [Val]), + case Verify(Val) of + ok -> + {ok, State#state{result = [Val|Res]}}; + Error -> + {error, State#state{result = [Error|Res]}} + end; + +%% This is either a MG or a MGC which is only connected to one MG +handle_exec({megaco_call, ARs, Opts}, #state{conn_handle = CH} = State) + when CH /= undefined -> + p("megaco_call"), + {_PV, UserReply} = megaco:call(CH, ARs, Opts), + d("megaco_call -> UserReply: ~n~p", [UserReply]), + {ok, State}; + +handle_exec({megaco_call, RemoteMid, ARs, Opts}, #state{mid = Mid} = State) -> + p("megaco_call: ~p", [RemoteMid]), + %% First we have to find the CH for this Mid + Conns = megaco:user_info(Mid, connections), + {value, {_, CH}} = + lists:keysearch(RemoteMid, #megaco_conn_handle.remote_mid, Conns), + {_PV, UserReply} = megaco:call(CH, ARs, Opts), + d("megaco_call -> UserReply: ~n~p", [UserReply]), + {ok, State}; + +%% This is either a MG or a MGC which is only connected to one MG +handle_exec({megaco_cast, ARs, Opts}, #state{conn_handle = CH} = State) + when CH =/= undefined -> + p("megaco_cast"), + case megaco:cast(CH, ARs, Opts) of + ok -> + {ok, State}; + Error -> + d("failed sending (cast) message: ~n~p", [Error]), + #state{result = Acc} = State, + {error, State#state{result = [Error|Acc]}} + end; + +handle_exec({megaco_cast, RemoteMid, ARs, Opts}, #state{mid = Mid} = State) -> + p("megaco_cast: ~p", [RemoteMid]), + %% First we have to find the CH for this Mid + Conns = megaco:user_info(Mid, connections), + {value, {_, CH}} = + lists:keysearch(RemoteMid, #megaco_conn_handle.remote_mid, Conns), + case megaco:cast(CH, ARs, Opts) of + ok -> + {ok, State}; + Error -> + d("failed sending (cast) message: ~n~p", [Error]), + #state{result = Acc} = State, + {error, State#state{result = [Error|Acc]}} + end; + +%% Nothing shall happen for atleast Timeout time +handle_exec({megaco_callback, nocall, Timeout}, State) -> + p("megaco_callback [~w,~w]", [nocall, Timeout]), + receive + {handle_megaco_callback, Type, Msg, Pid} -> + d("received unexpected megaco callback: ~n~p", [Msg]), + #state{result = Res} = State, + Err = {unexpected_callback, Type, Msg, Pid}, + {error, State#state{result = [Err|Res]}} + after Timeout -> + {ok, State} + end; + +handle_exec({megaco_callback, Tag, Verify}, State) when is_function(Verify) -> + p("megaco_callback [~w]", [Tag]), + receive + {handle_megaco_callback, Type, Msg, Pid} -> + d("received megaco callback: ~n~p", [Msg]), + case Verify(Msg) of + {VRes, Res, Reply} -> + d("megaco_callback [~w] ~w",[Tag, VRes]), + handle_megaco_callback_reply(Pid, Type, Reply), + validate(VRes, Tag, Res, State); + {VRes, Delay, Res, Reply} -> + d("megaco_callback [~w] ~w, ~w",[Tag,Delay,VRes]), + handle_megaco_callback_reply(Pid, Type, Delay, Reply), + validate(VRes, Tag, Res, State) + end + end; + +handle_exec({megaco_callback, Tag, {VMod, VFunc, VArgs}}, State) + when is_atom(VMod) andalso is_atom(VFunc) andalso is_list(VArgs) -> + p("megaco_callback [~w]", [Tag]), + receive + {handle_megaco_callback, Type, Msg, Pid} -> + d("received megaco callback: ~n~p" + "~n VMod: ~w" + "~n VFunc: ~w" + "~n VArgs: ~p", [Msg, VMod, VFunc, VArgs]), + case apply(VMod, VFunc, [Msg|VArgs]) of + {VRes, Res, Reply} -> + d("megaco_callback [~w] ~w",[Tag, VRes]), + handle_megaco_callback_reply(Pid, Type, Reply), + validate(VRes, Tag, Res, State); + {VRes, Delay, Res, Reply} -> + d("megaco_callback [~w] ~w, ~w",[Tag,Delay,VRes]), + handle_megaco_callback_reply(Pid, Type, Delay, Reply), + validate(VRes, Tag, Res, State) + end + end; + +handle_exec({megaco_callback, Tag, Verify, Timeout}, State) + when (is_function(Verify) andalso + (is_integer(Timeout) andalso (Timeout > 0))) -> + p("megaco_callback [~w]", [Tag]), + receive + {handle_megaco_callback, Type, Msg, Pid} -> + d("received megaco callback: ~n~p", [Msg]), + case Verify(Msg) of + {VRes, Res, Reply} -> + d("megaco_callback [~w] ~w",[Tag,VRes]), + handle_megaco_callback_reply(Pid, Type, Reply), + validate(VRes, Tag, Res, State); + {VRes, Delay, Res, Reply} -> + d("megaco_callback [~w] ~w, ~w",[Tag,Delay,VRes]), + handle_megaco_callback_reply(Pid, Type, Delay, Reply), + validate(VRes, Tag, Res, State) + end + after Timeout -> + #state{result = Res} = State, + Err = {callback_timeout, Tag, Timeout}, + {error, State#state{result = [Err|Res]}} + end; + +handle_exec({megaco_callback, Verifiers}, State) -> + p("megaco_callback"), + megaco_callback_verify(Verifiers, State); + +handle_exec({megaco_cancel, Reason}, #state{conn_handle = CH} = State) -> + p("megaco_cancel [~w]", [Reason]), + case megaco:cancel(CH, Reason) of + ok -> + {ok, State}; + Error -> + d("failed cancel: ~n~p", [Error]), + #state{result = Acc} = State, + {error, State#state{result = [Error|Acc]}} + end; + +handle_exec({trigger, Trigger}, State) when is_function(Trigger) -> + p("trigger"), + (catch Trigger()), + {ok, State}; + +handle_exec({sleep, To}, State) -> + p("sleep ~p", [To]), + megaco_test_generator:sleep(To), + {ok, State}; + +handle_exec(BadInstruction, _State) -> + error({invalid_instruction, BadInstruction}). + + +%% --- cleanup --- + +megaco_cleanup(#state{mid = Mid}) -> + Close = fun(CH) -> do_megaco_cleanup(CH) end, + Conns = + case (catch megaco:user_info(Mid, connections)) of + Connections when is_list(Connections) -> + Connections; + _ -> + [] + end, + lists:foreach(Close, Conns). + +do_megaco_cleanup(CH) -> + case (catch do_megaco_cleanup2(CH)) of + ok -> + ok; + {'EXIT', {no_such_connection, _}} -> + ok; + {'EXIT', Reason} -> + exit(Reason) + end. + +do_megaco_cleanup2(CH) -> + d("do_megaco_cleanup2 -> entry with" + "~n CH: ~p", [CH]), + Reason = {stopped_by_user,self()}, + Pid = megaco:conn_info(CH, control_pid), + SendMod = megaco:conn_info(CH, send_mod), + SendHandle = megaco:conn_info(CH, send_handle), + d("do_megaco_cleanup2 -> disconnect"), + megaco:disconnect(CH, Reason), + d("do_megaco_cleanup2 -> disconnected, now cancel"), + megaco:cancel(CH, Reason), + d("do_megaco_cleanup2 -> canceled, now close"), + case SendMod of + megaco_tcp -> (catch megaco_tcp:close(SendHandle)); + megaco_udp -> (catch megaco_udp:close(SendHandle)); + SendMod -> exit(Pid, Reason) + end, + ok. + + +%% --- connector --- + +megaco_connector_start(RH, PrelMid, SH, ControlPid) -> + Self = self(), + Fun = fun() -> megaco_connect(RH, PrelMid, SH, ControlPid, Self) end, + erlang:spawn_opt(Fun, [link]). + +megaco_connect(RH, PrelMid, SH, ControlPid, Parent) -> + Result = megaco:connect(RH, PrelMid, SH, ControlPid), + Parent ! {megaco_connect_result, Result}, + exit(normal). + + +%% --- megaco callback verify --- + +%% This is used when a number of callback's is expected, but where +%% the specific order is unknown. +megaco_callback_verify([], State) -> + d("megaco_callback_verify -> done"), + {ok, State}; +megaco_callback_verify(Verifiers0, State0) -> + d("megaco_callback_verify -> entry when" + "~n length(Verifiers0): ~w", [length(Verifiers0)]), + receive + {handle_megaco_callback, Type, Msg, Pid} -> + d("megaco_callback_verify -> received megaco callback: ~w" + "~n Msg: ~p", [Type, Msg]), + case megaco_callback_verify(Verifiers0, Type, Msg, Pid, State0) of + {ok, Verifiers, State} -> + megaco_callback_verify(Verifiers, State); + Error -> + Error + end + end. + +megaco_callback_verify(Verifiers0, Type, Msg, Pid, State0) -> + d("megaco_callback_verify -> entry"), + Tag = element(1, Msg), + d("megaco_callback_verify -> Tag: ~w", [Tag]), + case lists:keysearch(Tag, 1, Verifiers0) of + {value, {Tag, N, Verify}} when (N > 0) andalso is_function(Verify) -> + d("megaco_callback_verify -> N: ~w",[N]), + case Verify(Msg) of + {VRes, Res, Reply} -> + d("megaco_callback_verify -> VRes: ~w",[VRes]), + handle_megaco_callback_reply(Pid, Type, Reply), + case validate(VRes, Tag, Res, State0) of + {error, _} = EState -> + e("megaco_callback_verify -> (1) error", []), + throw(EState); + {ok, State} when N > 1 -> + d("megaco_callback_verify -> (1) validated"), + Rec = {Tag, N-1, Verify}, + Verifiers = + lists:keyreplace(Tag, 1, Verifiers0, Rec), + {ok, Verifiers, State}; + {ok, State} -> + d("megaco_callback_verify -> (2) validated"), + Verifiers = lists:keydelete(Tag, 1, Verifiers0), + {ok, Verifiers, State} + end; + {VRes, Delay, Res, Reply} -> + d("megaco_callback_verify -> Delay: ~w, VRes: ~w", + [Delay,VRes]), + handle_megaco_callback_reply(Pid, Type, Delay, Reply), + case validate(VRes, Tag, Res, State0) of + {error, _} = EState -> + e("megaco_callback_verify -> (2) error", []), + throw(EState); + {ok, State} when N > 1 -> + d("megaco_callback_verify -> (3) validated"), + Rec = {Tag, N-1, Verify}, + Verifiers = + lists:keyreplace(Tag, 1, Verifiers0, Rec), + {ok, Verifiers, State}; + {ok, State} -> + d("megaco_callback_verify -> (4) validated"), + Verifiers = lists:keydelete(Tag, 1, Verifiers0), + {ok, Verifiers, State} + end + end; + false -> + e("megaco_callback_verify -> no such tag ~w~n~p", + [Tag, Verifiers0]), + #state{result = Res} = State0, + State = State0#state{result = [{Type, error, Msg}|Res]}, + error(State) + end. + + +%% --- validate verify result --- + +validate(ok, handle_connect = Tag, CH, #state{result = Acc} = S) -> + {ok, S#state{conn_handle = CH, result = [{Tag, ok, CH}|Acc]}}; +validate(ok, Tag, Res, #state{result = Acc} = S) -> + {ok, S#state{result = [{Tag, ok, Res}|Acc]}}; +validate(error, Tag, Res, #state{result = Acc} = S) -> + {error, S#state{result = [{Tag, error, Res}|Acc]}}. + + +%% ----- termination ----- + +terminate(normal, #state{result = Result} = _State) -> + d("terminate -> entry when normal with" + "~n Result: ~p", [Result]), + %% megaco_cleanup(State), + {ok, Result}; + +terminate(Reason, #state{result = Result} = State) -> + d("terminate -> entry with" + "~n Reason: ~p" + "~n Result: ~p", [Reason, Result]), + megaco_cleanup(State), + {error, {Reason, Result}}. + + +%%---------------------------------------------------------------------- + +handle_exec_listen_tcp(Sup, Opts, MaybeRetry) -> + handle_exec_listen_tcp(Sup, Opts, MaybeRetry, noError). + +handle_exec_listen_tcp(Sup, Opts, MaybeRetry, Error0) -> + case (catch megaco_tcp:listen(Sup, Opts)) of + ok -> + ok; + Error1 -> + case (catch MaybeRetry(Error1, Error0)) of + {true, Error2} -> + handle_exec_listen_tcp(Sup, Opts, MaybeRetry, Error2); + {false, Error3} -> + {error, Error3} + end + end. + + +handle_exec_connect_tcp(Host, Opts, Sup, MaybeRetry) + when is_function(MaybeRetry) -> + handle_exec_connect_tcp(Host, Opts, Sup, MaybeRetry, noError). + +handle_exec_connect_tcp(Host, Opts, Sup, MaybeRetry, Error0) -> + case (catch megaco_tcp:connect(Sup, Opts)) of + {ok, SH, ControlPid} -> + d("tcp connected: ~p, ~p", [SH, ControlPid]), + {ok, SH, ControlPid}; + Error1 -> + case (catch MaybeRetry(Error1, Error0)) of + {true, Error2} -> + handle_exec_connect_tcp(Host, Opts, Sup, + MaybeRetry, Error2); + {false, Error3} -> + {error, Error3} + end + end. + + + +%%---------------------------------------------------------------------- +%% megaco_user callback functions +%%---------------------------------------------------------------------- + +handle_connect(CH, PV, P) -> + Req = {handle_connect, CH, PV}, + handle_megaco_callback_call(P, Req). + +handle_connect(CH, PV, Extra, P) -> + Req = {handle_connect, CH, PV, Extra}, + handle_megaco_callback_call(P, Req). + +handle_disconnect(CH, PV, R, P) -> + Msg = {handle_disconnect, CH, PV, R}, + Reply = ok, + handle_megaco_callback_cast(P, Msg, Reply). + +handle_syntax_error(RH, PV, ED, P) -> + Req = {handle_syntax_error, RH, PV, ED}, + handle_megaco_callback_call(P, Req). + +handle_syntax_error(RH, PV, ED, Extra, P) -> + Req = {handle_syntax_error, RH, PV, ED, Extra}, + handle_megaco_callback_call(P, Req). + +handle_message_error(CH, PV, ED, P) -> + Msg = {handle_message_error, CH, PV, ED}, + Reply = ok, + handle_megaco_callback_cast(P, Msg, Reply). + +handle_message_error(CH, PV, ED, Extra, P) -> + Msg = {handle_message_error, CH, PV, ED, Extra}, + Reply = ok, + handle_megaco_callback_cast(P, Msg, Reply). + +handle_trans_request(CH, PV, AR, P) -> + Req = {handle_trans_request, CH, PV, AR}, + handle_megaco_callback_call(P, Req). + +handle_trans_request(CH, PV, AR, Extra, P) -> + Req = {handle_trans_request, CH, PV, AR, Extra}, + handle_megaco_callback_call(P, Req). + +handle_trans_long_request(CH, PV, RD, P) -> + Req = {handle_trans_long_request, CH, PV, RD}, + handle_megaco_callback_call(P, Req). + +handle_trans_long_request(CH, PV, RD, Extra, P) -> + Req = {handle_trans_long_request, CH, PV, RD, Extra}, + handle_megaco_callback_call(P, Req). + +handle_trans_reply(CH, PV, AR, RD, P) -> + Msg = {handle_trans_reply, CH, PV, AR, RD}, + Reply = ok, + handle_megaco_callback_cast(P, Msg, Reply). + +handle_trans_reply(CH, PV, AR, RD, Extra, P) -> + Msg = {handle_trans_reply, CH, PV, AR, RD, Extra}, + Reply = ok, + handle_megaco_callback_cast(P, Msg, Reply). + +handle_trans_ack(CH, PV, AS, AD, P) -> + Msg = {handle_trans_ack, CH, PV, AS, AD}, + Reply = ok, + handle_megaco_callback_cast(P, Msg, Reply). + +handle_trans_ack(CH, PV, AS, AD, Extra, P) -> + Msg = {handle_trans_ack, CH, PV, AS, AD, Extra}, + Reply = ok, + handle_megaco_callback_cast(P, Msg, Reply). + +handle_unexpected_trans(CH, PV, T, P) -> + Msg = {handle_unexpected_trans, CH, PV, T}, + Reply = ok, + handle_megaco_callback_cast(P, Msg, Reply). + +handle_unexpected_trans(CH, PV, T, Extra, P) -> + Msg = {handle_unexpected_trans, CH, PV, T, Extra}, + Reply = ok, + handle_megaco_callback_cast(P, Msg, Reply). + +handle_trans_request_abort(RH, PV, TransNo, Pid, P) -> + Msg = {handle_trans_request_abort, RH, PV, TransNo, Pid}, + Reply = ok, + handle_megaco_callback_cast(P, Msg, Reply). + +handle_trans_request_abort(RH, PV, TransNo, Pid, Extra, P) -> + Msg = {handle_trans_request_abort, RH, PV, TransNo, Pid, Extra}, + Reply = ok, + handle_megaco_callback_cast(P, Msg, Reply). + +handle_megaco_callback_cast(P, Msg, Reply) -> + p("handle_megaco_callback_cast -> entry with Msg: ~n~p", [Msg]), + P ! {handle_megaco_callback, cast, Msg, self()}, + Reply. + +handle_megaco_callback_call(P, Msg) -> + p("handle_megaco_callback_call -> entry with" + "~n P: ~p" + "~n Msg: ~p", [P, Msg]), + P ! {handle_megaco_callback, call, Msg, self()}, + receive + {handle_megaco_callback_reply, Reply} -> + p("handle_megaco_callback_call -> received reply: ~n~p", [Reply]), + Reply; + {handle_megaco_callback_reply, Delay, Reply} when is_integer(Delay) -> + p("handle_megaco_callback_call -> " + "received reply [~w]: " + "~n ~p", [Delay, Reply]), + sleep(Delay), + p("handle_megaco_callback_call -> deliver reply after delay [~w]", + [Delay]), + Reply; + {'EXIT', SomePid, SomeReason} -> + p("handle_megaco_callback_call -> " + "received unexpected EXIT signal: " + "~n SomePid: ~p" + "~n SomeReason: ~p", [SomePid, SomeReason]), + exit({unexpected_EXIT_signal, SomePid, SomeReason}) + end. + + +handle_megaco_callback_reply(P, call, Reply) -> + P ! {handle_megaco_callback_reply, Reply}; +handle_megaco_callback_reply(_, _, _) -> + ok. + +handle_megaco_callback_reply(P, call, Delay, Reply) -> + P ! {handle_megaco_callback_reply, Delay, Reply}; +handle_megaco_callback_reply(_, _, _, _) -> + ok. + + +%%---------------------------------------------------------------------- +%% internal utility functions +%%---------------------------------------------------------------------- + +random_init() -> + {A,B,C} = now(), + random:seed(A,B,C). + +random(N) -> + random:uniform(N). + + +get_config(Key, Opts) -> + {value, {Key, Val}} = lists:keysearch(Key, 1, Opts), + Val. + +sleep(X) -> megaco_test_generator:sleep(X). + +d(F) -> megaco_test_generator:debug(F). +d(F, A) -> megaco_test_generator:debug(F, A). + +e(F, A) -> megaco_test_generator:error(F, A). + +p(F ) -> p("", F, []). +p(F, A) -> p("", F, A). +p(P, F, A) -> megaco_test_generator:print(P, F, A). + +error(Reason) -> + throw({error, Reason}). + diff --git a/lib/megaco/test/megaco_test_mg.erl b/lib/megaco/test/megaco_test_mg.erl new file mode 100644 index 0000000000..22b65a1ac6 --- /dev/null +++ b/lib/megaco/test/megaco_test_mg.erl @@ -0,0 +1,1585 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Implements an "MG" used by the test suite +%%---------------------------------------------------------------------- +-module(megaco_test_mg). + +-export([start/5, start/6, stop/1, + get_stats/1, reset_stats/1, + user_info/1, user_info/2, + update_user_info/3, + conn_info/1, conn_info/2, + update_conn_info/3, + service_change/1, + ack_info/2, rep_info/2, + group_requests/2, + notify_request/1, + await_notify_reply/1, + notify_request_and_reply/1, + cancel_request/2, + apply_load/2, + apply_multi_load/3, + enable_test_code/4, + encode_ar_first/2, + verbosity/2]). + +-export([mg/3, notify_request_handler_main/5]). +-export([loader_main/4]). + +%% Megaco callback api +-export([ + handle_connect/4, + handle_disconnect/5, + handle_syntax_error/5, + handle_message_error/5, + handle_trans_request/5, + handle_trans_long_request/5, + handle_trans_reply/6, + handle_trans_ack/6 + ]). + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). + +-define(A4444, tid(255*256*256) ). +-define(A4445, tid(255*256*256 + 255) ). +-define(A5555, tid(255*256*256 + 255*256) ). +-define(A5556, tid(255*256*256 + 255*256 + 255) ). + +-record(mg, {mid = undefined, + state = initiated, + req_handler = undefined, + call_mode = async, + group_size = 1, + encode_ar_first = false, + ack_info = undefined, + rep_info = undefined, + load_counter = 0, + reply_counter = 0, + mload_info = undefined, + parent = undefined, + dsi_timer}). + + +%%% -------------------------------------------------------------------- + +start(Node, Mid, Encoding, Transport, Verbosity) -> + %% Conf = [{megaco_trace, io}], + %% Conf = [{megaco_trace, "megaco-mg.trace"}], + Conf = [{megaco_trace, false}], + start(Node, Mid, Encoding, Transport, Conf, Verbosity). + +start(Node, Mid, Encoding, Transport, Conf, Verbosity) -> + d("start mg[~p]: ~p" + "~n Encoding: ~p" + "~n Transport: ~p" + "~n Conf: ~p", [Node, Mid, Encoding, Transport, Conf]), + RI1 = encoding_config(Encoding), + RI2 = transport_config(Transport), + {RI3, Conf1} = transport_opts(Conf), + RI = {receive_info, RI1 ++ RI2 ++ RI3}, + Config = [{local_mid, Mid}, RI] ++ Conf1, + Self = self(), + Fun = + fun() -> + io:format("LOADER(~p,~p) started~n", [self(),node()]), + case (catch mg(Self, Verbosity, Config)) of + {'EXIT', Reason} -> + io:format("LOADER(~p,~p) terminating with exit" + "~n~p" + "~n", [self(), node(), Reason]), + exit(Reason); + Else -> + io:format("LOADER(~p,~p) terminating with" + "~n~p" + "~n", [self(), node(), Else]), + Else + end + end, + true = erlang:monitor_node(Node, true), + Pid = spawn_link(Node, Fun), + %% Pid = spawn_link(Node, ?MODULE, mg, [self(), Verbosity, Config]), + MonRef = (catch erlang:monitor(process, Pid)), + NodePing = net_adm:ping(Node), + ProcInfo = (catch proc_info(Pid)), + i("start -> " + "~n self(): ~p" + "~n node(): ~p" + "~n net_adm:ping(~p): ~p" + "~n Loader: ~p" + "~n Monitor ref: ~p" + "~n Process info: ~p", + [self(), node(), + Node, NodePing, + Pid, + MonRef, ProcInfo]), + await_started(Node, MonRef, Pid). + +proc_info(Pid) -> + rpc:call(node(Pid), erlang, process_info, [Pid]). + +encoding_config({Encoding, EC}) when is_atom(Encoding) andalso is_list(EC) -> + {Mod, Port} = select_encoding(Encoding), + [{encoding_module, Mod}, + {encoding_config, EC}, + {port, Port}]; +encoding_config(Encoding) when is_atom(Encoding) -> + {Mod, Port} = select_encoding(Encoding), + [{encoding_module, Mod}, + {encoding_config, []}, + {port, Port}]; +encoding_config(Encoding) -> + throw({error, {invalid_encoding, Encoding}}). + +select_encoding(text) -> + {megaco_pretty_text_encoder, 2944}; +select_encoding(pretty_text) -> + {megaco_pretty_text_encoder, 2944}; +select_encoding(compact_text) -> + {megaco_compact_text_encoder, 2944}; +select_encoding(binary) -> + {megaco_ber_bin_encoder, 2945}; +select_encoding(erl_dist) -> + {megaco_erl_dist_encoder, 2946}; +select_encoding(Encoding) -> + throw({error, {invalid_encoding, Encoding}}). + +transport_config(tcp) -> + [{transport_module, megaco_tcp}]; +transport_config(udp) -> + [{transport_module, megaco_udp}]; +transport_config(TransportConfig) when is_list(TransportConfig) -> + {value, {transport, Trans}} = + lists:keysearch(transport, 1, TransportConfig), + transport_config(Trans) ++ + case lists:keysearch(host, 1, TransportConfig) of + {value, Value} -> + [Value]; + false -> + [] + end. + +transport_opts(Config) -> + case lists:keysearch(transport_opts, 1, Config) of + {value, TO} -> + Config1 = lists:keydelete(transport_opts, 1, Config), + {[TO], Config1}; + false -> + {[], Config} + end. + + +await_started(Node, MonRef, Pid) -> + i("await_started -> entry with" + "~n MonRef: ~p" + "~n Pid: ~p", [MonRef, Pid]), + receive + {started, Pid} -> + d("await_started ~p - started" + "~n Process info: ~p", [Pid, (catch proc_info(Pid))]), + true = erlang:monitor_node(Node, false), + erlang:demonitor(MonRef), + {ok, Pid}; + + {nodedown, Node} -> + i("await_started ~p - received node down", [Pid]), + exit({node_down, Node}); + + {'DOWN', MonRef, process, Pid, Info} -> + i("await_started ~p - received down signal: ~p", + [Pid, Info]), + true = erlang:monitor_node(Node, false), + exit({failed_starting, Pid, Info}); + + {'EXIT', Pid, Reason} -> + i("await_started ~p - received exit signal: ~p", [Pid, Reason]), + true = erlang:monitor_node(Node, false), + exit({failed_starting, Pid, Reason}) + + %% This timeout was originally 10 secs, but on some debug compiled + %% platforms, it was simply not long enough + after 20000 -> + NodePing = net_adm:ping(Node), + ProcInfo = (catch proc_info(Pid)), + FlushQ = megaco_test_lib:flush(), + i("await_started ~p - timeout: " + "~n net_adm:ping(~p): ~p" + "~n Process info: ~p" + "~n Messages in my queue: ~p", + [Pid, Node, NodePing, ProcInfo, FlushQ]), + true = erlang:monitor_node(Node, false), + exit({error, timeout}) + end. + + +verbosity(Pid, V) -> + Pid ! {verbosity, V, self()}. + + +stop(Pid) -> + server_request(Pid, stop, stopped). + + +get_stats(Pid) -> + server_request(Pid, statistics, statistics_reply). + +reset_stats(Pid) -> + server_request(Pid, reset_stats, reset_stats_ack). + + +user_info(Pid) -> + server_request(Pid, {user_info, all}, user_info_ack). + +user_info(Pid, Tag) when is_atom(Tag) -> + server_request(Pid, {user_info, Tag}, user_info_ack). + + +update_user_info(Pid, Tag, Val) -> + server_request(Pid, {update_user_info, Tag, Val}, update_user_info_ack). + + +conn_info(Pid) -> + server_request(Pid, {conn_info, all}, conn_info_ack). + +conn_info(Pid, Tag) when is_atom(Tag) -> + server_request(Pid, {conn_info, Tag}, conn_info_ack). + + +update_conn_info(Pid, Tag, Val) -> + server_request(Pid, {update_conn_info, Tag, Val}, update_conn_info_ack). + + +enable_test_code(Pid, Module, Where, Fun) + when is_atom(Module) andalso is_atom(Where) andalso is_function(Fun) -> + Tag = {Module, Where}, + server_request(Pid, {enable_test_code, Tag, Fun}, enable_test_code_reply). + +encode_ar_first(Pid, New) when is_atom(New) -> + server_request(Pid, {encode_ar_first, New}, encode_ar_first_reply). + +service_change(Pid) -> + server_request(Pid, service_change, service_change_reply). + + +group_requests(Pid, N) -> + server_request(Pid, {group_requests, N}, group_requests_reply). + + +ack_info(Pid, InfoPid) -> + Pid ! {{ack_info, InfoPid}, self()}. + +rep_info(Pid, InfoPid) -> + Pid ! {{rep_info, InfoPid}, self()}. + + +notify_request(Pid) -> + Pid ! {notify_request, self()}. + + +await_notify_reply(Pid) -> + await_reply(Pid, notify_request_reply). + + +notify_request_and_reply(Pid) -> + notify_request(Pid), + await_notify_reply(Pid). + + +cancel_request(Pid, Reason) -> + server_request(Pid, cancel_request, Reason, cancel_request_reply). + + +apply_load(Pid, CounterStart) -> + server_request(Pid, apply_load, CounterStart, apply_load_ack). + + +apply_multi_load(Pid, NumLoaders, NumReq) -> + server_request(Pid, apply_multi_load, {NumLoaders, NumReq}, apply_multi_load_ack). + + +server_request(Pid, Req, ReplyTag) -> + Pid ! {Req, self()}, + await_reply(Pid, ReplyTag). + +server_request(Pid, Req, ReqData, ReplyTag) -> + Pid ! {Req, ReqData, self()}, + await_reply(Pid, ReplyTag). + +await_reply(Pid, ReplyTag) -> + await_reply(Pid, ReplyTag, infinity). + +await_reply(Pid, ReplyTag, Timeout) -> + receive + {ReplyTag, Reply, Pid} -> + Reply; + {'EXIT', Pid, Reason} -> + exit({failed, ReplyTag, Pid, Reason}) + after Timeout -> + exit({timeout, ReplyTag, Pid}) + end. + + +server_reply(Pid, ReplyTag, Reply) -> + Pid ! {ReplyTag, Reply, self()}. + + +%%% -------------------------------------------------------------------- + + +mg(Parent, Verbosity, Config) -> + process_flag(trap_exit, true), + put(sname, "MG"), + %% put(verbosity, Verbosity), + put(verbosity, debug), % Enable debug printouts during init + i("mg -> starting"), + %% megaco:enable_trace(max, io), + case (catch init(Config)) of + {error, _} = Error -> + exit(Error); + {'EXIT', Reason} -> + exit({init_failed, Reason}); + {ok, Mid, DSITimer} -> + notify_started(Parent), + MG = #mg{parent = Parent, mid = Mid, dsi_timer = DSITimer}, + i("mg -> started"), + put(verbosity, Verbosity), + case (catch loop(MG)) of + {'EXIT', normal} -> + exit(normal); + {'EXIT', Reason} -> + i("mg failed with reason:~n ~p", [Reason]), + exit(Reason); + Else -> + i("mg terminated: ~n ~p", [Else]), + exit({unexpected, Else}) + end + end. + +init(Config) -> + d("init -> entry with" + "~n Config: ~p", [Config]), + random_init(), + d("init -> random initiated", []), + Mid = get_conf(local_mid, Config), + d("init -> Mid: ~p", [Mid]), + RI = get_conf(receive_info, Config), + d("init -> RI: ~p", [RI]), + + d("init -> maybe start the display system info timer"), + DSITimer = + case get_conf(display_system_info, Config, undefined) of + Time when is_integer(Time) -> + d("init -> creating display system info timer"), + create_timer(Time, display_system_info); + _ -> + undefined + end, + Conf0 = lists:keydelete(display_system_info, 1, Config), + + d("init -> start megaco"), + application:start(megaco), + + + d("init -> possibly enable megaco trace"), + case lists:keysearch(megaco_trace, 1, Conf0) of + {value, {megaco_trace, true}} -> + megaco:enable_trace(max, io); + {value, {megaco_trace, io}} -> + megaco:enable_trace(max, io); + {value, {megaco_trace, File}} when is_list(File) -> + megaco:enable_trace(max, File); + _ -> + ok + end, + Conf1 = lists:keydelete(megaco_trace, 1, Conf0), + + d("init -> start megaco user"), + Conf2 = lists:keydelete(local_mid, 1, Conf1), + Conf3 = lists:keydelete(receive_info, 1, Conf2), + ok = megaco:start_user(Mid, Conf3), + d("init -> update user info (user_mod)"), + ok = megaco:update_user_info(Mid, user_mod, ?MODULE), + d("init -> update user info (user_args)"), + ok = megaco:update_user_info(Mid, user_args, [self(), Mid]), + + d("init -> get user info (receive_handle)"), + RH = megaco:user_info(Mid, receive_handle), + d("init -> parse receive info"), + {MgcPort, MgcHost, RH1, TO} = parse_receive_info(RI, RH), + d("init -> start transport (with ~p)", [TO]), + {ok, _CH} = start_transport(MgcPort, MgcHost, RH1, TO), + {ok, Mid, DSITimer}. + + +loop(#mg{parent = Parent, mid = Mid} = S) -> + d("loop -> await request", []), + receive + {display_system_info, Time} -> + display_system_info(S#mg.mid), + NewTimer = create_timer(Time, display_system_info), + loop(S#mg{dsi_timer = NewTimer}); + + {verbosity, V, Parent} -> + i("loop -> received new verbosity: ~p", [V]), + put(verbosity,V), + loop(S); + + + {stop, Parent} -> + i("loop -> stopping", []), + display_system_info(S#mg.mid, "at finish "), + cancel_timer(S#mg.dsi_timer), + Res = do_stop(Mid), + d("loop -> stop result: ~p", [Res]), + server_reply(Parent, stopped, {ok, Res}), + exit(normal); + + {{enable_test_code, Tag, Fun}, Parent} -> + i("loop -> enable_test_code: ~p, ~p", [Tag, Fun]), + Reply = (catch ets:insert(megaco_test_data, {Tag, Fun})), + d("loop -> enable_test_code -> " + "~n Reply: ~p" + "~n ets:tab2list(megaco_test_data): ~p", + [Reply,ets:tab2list(megaco_test_data)]), + server_reply(Parent, enable_test_code_reply, Reply), + loop(S); + + {{encode_ar_first, EAF}, Parent} -> + i("loop -> encode_ar_first: ~p", [EAF]), + {Reply, S1} = handle_encode_ar_first(S, EAF), + server_reply(Parent, encode_ar_first_reply, Reply), + loop(S1#mg{encode_ar_first = EAF}); + + %% Give me statistics + {statistics, Parent} -> + i("loop -> got request for statistics", []), + Stats = do_get_statistics(Mid), + server_reply(Parent, statistics_reply, {ok, Stats}), + loop(S); + + {reset_stats, Parent} -> + i("loop -> got request to reset stats counters", []), + do_reset_stats(Mid), + server_reply(Parent, reset_stats_ack, ok), + loop(S); + + {{user_info, Tag}, Parent} -> + i("loop -> got user_info request for ~w", [Tag]), + Res = do_get_user_info(Mid, Tag), + d("loop -> Res: ~p", [Res]), + server_reply(Parent, user_info_ack, Res), + loop(S); + + {{update_user_info, Tag, Val}, Parent} -> + i("loop -> got update_user_info: ~w -> ~p", [Tag, Val]), + Res = do_update_user_info(Mid, Tag, Val), + d("loop -> Res: ~p", [Res]), + server_reply(Parent, update_user_info_ack, Res), + loop(S); + + {{conn_info, Tag}, Parent} -> + i("loop -> got conn_info request for ~w", [Tag]), + Res = do_get_conn_info(Mid, Tag), + server_reply(Parent, conn_info_ack, Res), + loop(S); + + {{update_conn_info, Tag, Val}, Parent} -> + i("loop -> got update_conn_info: ~w -> ~p", [Tag, Val]), + Res = do_update_conn_info(Mid, Tag, Val), + server_reply(Parent, update_conn_info_ack, Res), + loop(S); + + + %% Do a service change + %% No server-reply here. Since the service change is + %% async, the reply (from the MGC) will come later. + {service_change, Parent} -> + i("loop -> received request to perform service change", []), + S1 = + case (catch do_service_change(S)) of + {ok, MG} -> + d("loop -> service change initiated", []), + MG; + Error -> + d("loop -> service change failed: ~p", [Error]), + server_reply(Parent, service_change_reply, Error), + S + end, + loop(S1); + + {{group_requests, N}, Parent} when N > 0 -> + i("loop -> received group_requests ~p", [N]), + Reply = {ok, S#mg.group_size}, + server_reply(Parent, group_requests_reply, Reply), + loop(S#mg{group_size = N}); + + {{ack_info, To}, Parent} -> + i("loop -> received request to inform about received ack's ", []), + loop(S#mg{ack_info = To}); + + {{rep_info, To}, Parent} -> + i("loop -> received request to inform about received rep's ", []), + loop(S#mg{rep_info = To}); + + %% Make a sync-call + {notify_request, Parent} -> + i("loop -> received request to send notify request ", []), + {Res, S1} = do_handle_notify_request(S), + d("loop -> notify request result: ~p", [Res]), + loop(S1); + + %% sync-call complete + {notify_request_complete, NotifyReply, Pid} -> + i("loop -> received notify request complete from " + "~n ~p with" + "~n NotifyReply: ~p", + [Pid, NotifyReply]), + server_reply(Parent, notify_request_reply, NotifyReply), + loop(S#mg{req_handler = undefined}); + + + %% cancel requests + {cancel_request, Reason, Parent} -> + i("loop -> received request to cancel (all) megaco requests ", []), + Res = do_cancel_requests(Mid, Reason), + server_reply(Parent, cancel_request_reply, Res), + loop(S); + + + %% Apply multi-load + {apply_multi_load, {NL, NR}, Parent} -> + i("loop -> received apply_multi_load request: ~w, ~w", [NL, NR]), + S1 = start_loaders(S, NL, NR), + loop(S1); + + + %% Apply some load + {apply_load, Times, Parent} -> + i("loop -> received apply_load request: ~w", [Times]), + S1 = + case update_load_times(S, Times) of + {ok, MG} -> + apply_load_timer(), + server_reply(Parent, apply_load_ack, ok), + MG; + Error -> + server_reply(Parent, apply_load_ack, Error), + S + end, + loop(S1); + + {apply_load_timeout, _} -> + d("loop -> received apply_load timeout", []), + S1 = do_apply_load(S), + loop(S1); + + + %% Megaco callback messages + {request, Request, Mid, From} -> + d("loop -> received megaco request: ~n ~p" + "~n Mid: ~p" + "~n From: ~p", + [Request, Mid, From]), + {Reply, S1} = handle_megaco_request(S, Request), + d("loop -> send (megaco callback) request reply: ~n~p", [Reply]), + From ! {reply, Reply, self()}, + loop(S1); + + + {'EXIT', Pid, Reason} -> + i("loop -> received exit signal from ~p: ~n~p", [Pid, Reason]), + S1 = handle_exit(S, Pid, Reason), + loop(S1); + + + Invalid -> + error_msg("received invalid request: ~n~p", [Invalid]), + loop(S) + + end. + + +handle_encode_ar_first(#mg{encode_ar_first = Old} = MG, New) + when (New =:= true) orelse (New =:= false) -> + {{ok, Old}, MG#mg{encode_ar_first = New}}; +handle_encode_ar_first(MG, New) -> + {{error, {invalid_value, New}}, MG}. + + +%% +%% Stop user +%% +do_stop(Mid) -> + d("do_stop -> stopping user ~p", [Mid]), + Disco = fun close_conn/1, + lists:map(Disco, megaco:user_info(Mid, connections)), + megaco:stop_user(Mid). + +close_conn(CH) -> + d("do_stop -> closing connection ~p", [CH]), + Reason = {stopped_by_user,self()}, + Pid = megaco:conn_info(CH, control_pid), + SendMod = megaco:conn_info(CH, send_mod), + SendHandle = megaco:conn_info(CH, send_handle), + megaco:disconnect(CH, Reason), + megaco:cancel(CH, Reason), + case SendMod of + megaco_tcp -> megaco_tcp:close(SendHandle); + megaco_udp -> megaco_udp:close(SendHandle); + SendMod -> exit(Pid, Reason) + end. + + + +%% +%% Get statistics +%% +do_get_statistics(Mid) -> + case megaco:user_info(Mid, connections) of + [CH] -> + do_get_conn_statistics(CH); + [] -> + [] + end. + +do_get_conn_statistics(CH) -> + {ok, Gen} = megaco:get_stats(), + %% Pid = megaco:conn_info(CH, control_pid), + SendMod = megaco:conn_info(CH, send_mod), + SendHandle = megaco:conn_info(CH, send_handle), + {ok, Trans} = + case SendMod of + megaco_tcp -> megaco_tcp:get_stats(SendHandle); + megaco_udp -> megaco_udp:get_stats(SendHandle) + end, + [{gen, Gen}, {trans, Trans}]. + + +%% +%% reset user stats +%% +do_reset_stats(Mid) -> + %% We only have one connection + [CH] = megaco:user_info(Mid, connections), + do_reset_stats1(CH). + +do_reset_stats1(CH) -> + megaco:reset_stats(), + case (catch megaco:conn_info(CH, send_mod)) of + {error, Reason} -> + error_msg("unexpected result when retrieving send module for " + "own connection ~p: ~p. " + "~nexiting...", [CH, Reason]), + exit({invalid_connection, CH, Reason}); + {'EXIT', Reason} -> + error_msg("exit signal when retrieving send module for " + "own connection ~p: ~p. " + "~nexiting...", [CH, Reason]), + exit({invalid_connection, CH, Reason}); + SendMod when is_atom(SendMod) -> + SendMod:reset_stats() + end. + + +%% +%% Get user info for user +%% +do_get_user_info(Mid, all = Tag) -> + case (catch megaco:user_info(Mid, Tag)) of + L when is_list(L) -> + lists:sort(L); + Else -> + Else + end; +do_get_user_info(Mid, Tag) -> + (catch megaco:user_info(Mid, Tag)). + + +%% +%% Update user info for user +%% +do_update_user_info(Mid, Tag, Val) -> + (catch megaco:update_user_info(Mid, Tag, Val)). + + +%% +%% Get conn info +%% +do_get_conn_info(CH, all = Tag) when is_record(CH, megaco_conn_handle) -> + case (catch megaco:conn_info(CH, Tag)) of + L when is_list(L) -> + lists:sort(L); + Else -> + Else + end; +do_get_conn_info(CH, Tag) when is_record(CH, megaco_conn_handle) -> + (catch megaco:conn_info(CH, Tag)); +do_get_conn_info(Mid, Tag) -> + case megaco:user_info(Mid, connections) of + [CH|_] -> + do_get_conn_info(CH, Tag); + [] -> + [] + end. + +%% +%% Update conn info for user +%% +do_update_conn_info(Mid, Tag, Val) -> + %% We only have one connection + [CH] = megaco:user_info(Mid, connections), + (catch megaco:update_conn_info(CH, Tag, Val)). + + + + +%% +%% Perform service change +%% +do_service_change(#mg{mid = Mid, + state = initiated, + encode_ar_first = EAF} = MG) -> + %% We only have one connection + d("do service change for ~p", [Mid]), + [CH] = megaco:user_info(Mid, connections), + Method = restart, + Reason = ?megaco_cold_boot, + case do_service_change(CH, Method, EAF, Reason) of + ok -> + {ok, MG#mg{state = connecting}}; + Error -> + d("service change for ~p failed: ~n~p", [Mid, Error]), + Error + end; +do_service_change(#mg{state = State} = MG) -> + {{error, {invalid_state, State}}, MG}. + +do_service_change(ConnHandle, Method, EAF, Reason) -> + d("sending service change using:" + "~n ConnHandle: ~p" + "~n Method: ~p" + "~n EAF: ~p" + "~n Reason: ~p", [ConnHandle, Method, EAF, Reason]), + SCP = cre_serviceChangeParm(Method, [Reason]), + TermId = [?megaco_root_termination_id], + SCR = cre_serviceChangeReq(TermId, SCP), + CR = cre_commandReq({serviceChangeReq, SCR}), + AR = cre_actionReq(?megaco_null_context_id,[CR]), + send_async(EAF, ConnHandle, [AR], []). + + +%% Make a sync call +do_handle_notify_request(#mg{mid = Mid, + group_size = N, + encode_ar_first = EAF, + state = connected} = MG) -> + d("do_handle_notify_request -> entry"), + [CH] = megaco:user_info(Mid, connections), + Pid = start_notify_request_handler(EAF, CH, N), + {ok, MG#mg{req_handler = Pid}}; +do_handle_notify_request(#mg{state = State} = MG) -> + d("do_handle_notify_request -> entry with" + "~n State: ~p", [State]), + {{error, {invalid_state, State}}, MG}. + + + +%% +%% Cancel requests +%% +do_cancel_requests(Mid, Reason) -> + [CH] = megaco:user_info(Mid, connections), + megaco:cancel(CH, Reason). + + +%% +%% Apply multi load +%% +start_loaders(#mg{mid = Mid, encode_ar_first = EAF} = MG, NumLoaders, Times) -> + [CH] = megaco:user_info(Mid, connections), + Env = get(), + Loaders = start_loaders1(NumLoaders, [], [Env, EAF, Times, CH]), + d("start_loaders -> Loaders: ~n~w", [Loaders]), + MG#mg{mload_info = {Loaders, 0, 0}}. + +start_loaders1(0, Acc, _) -> + Acc; +start_loaders1(N, Acc, Args) -> + Pid = spawn_link(?MODULE, loader_main, Args), + start_loaders1(N-1, [Pid|Acc], Args). + +loader_main(Env, EAF, N, CH) -> + lists:foreach(fun({Tag,Val}) -> put(Tag,Val) end, Env), + loader_main(EAF, N, CH). + +loader_main(_EAF, 0, _) -> + d("loader_main -> done"), + exit(loader_done); +loader_main(EAF, N, CH) -> + d("loader_main -> entry with: ~w", [N]), + {Act, _} = make_notify_request(), + _Res = send_sync(EAF, CH, Act, []), + loader_main(EAF, N-1, CH). + + + +handle_exit(#mg{parent = Pid}, Pid, Reason) -> + error_msg("received exit from the parent:" + "~n ~p", [Reason]), + exit({parent_terminated, Reason}); + +handle_exit(#mg{parent = Parent, req_handler = Pid} = MG, Pid, Reason) -> + error_msg("received unexpected exit from the request handler:" + "~n ~p", [Reason]), + server_reply(Parent, notify_request_reply, + {error, {request_handler_exit, Reason}}), + MG#mg{req_handler = undefined}; + +handle_exit(#mg{parent = Parent, mload_info = {Loaders0, Ok, Err}} = MG, + Pid, loader_done) -> + d("handle_exit(loader_done) -> entry when" + "~n Loaders0: ~p" + "~n Ok: ~p" + "~n Err: ~p", [Loaders0, Ok, Err]), + Loaders = lists:delete(Pid, Loaders0), + LoadInfo = + case Loaders of + [] -> + d("handle_exit -> multi load done", []), + server_reply(Parent, apply_multi_load_ack, {ok, Ok+1, Err}), + undefined; + _ -> + {Loaders, Ok+1, Err} + end, + MG#mg{mload_info = LoadInfo}; + + +handle_exit(#mg{parent = Parent, mload_info = {Loaders, Ok, Err}} = MG, + Pid, Reason) + when length(Loaders) > 0 -> + d("handle_exit -> entry when" + "~n Reason: ~p" + "~n Loaders: ~p" + "~n Ok: ~p" + "~n Err: ~p", [Reason, Loaders, Ok, Err]), + case lists:delete(Pid, Loaders) of + [] -> + %% since we cannot be empty prior the delete, + %% the last one exited... + server_reply(Parent, apply_multi_load, {ok, Ok, Err+1}), + MG#mg{mload_info = undefined}; + Loaders -> + %% Could not be this MG, so go on to the next + error_msg("received unexpected exit signal from ~p:~n~p", + [Pid, Reason]); + Loaders1 -> + %% Not empty, but we removed one + MG#mg{mload_info = {Loaders1,Ok,Err+1}} + end; +handle_exit(_MG, Pid, Reason) -> + error_msg("received unexpected exit signal from ~p:~n~p", + [Pid, Reason]). + + +parse_receive_info(RI, RH) -> + d("parse_receive_info -> get encoding module"), + EM = get_encoding_module(RI), + d("parse_receive_info -> get encoding config"), + EC = get_encoding_config(RI, EM), + d("parse_receive_info -> get transport module"), + TM = get_transport_module(RI), + d("parse_receive_info -> get transport port"), + TP = get_transport_port(RI), + d("parse_receive_info -> get transport host"), + TH = get_transport_host(RI), + d("parse_receive_info -> get transport opts"), + TO = get_transport_opts(RI), + RH1 = RH#megaco_receive_handle{send_mod = TM, + encoding_mod = EM, + encoding_config = EC}, + {TP, TH, RH1, TO}. + + +start_transport(MgcPort, MgcHost, + #megaco_receive_handle{send_mod = megaco_tcp} = RH, TO) -> + start_tcp(MgcPort, MgcHost, RH, TO); +start_transport(MgcPort, MgcHost, + #megaco_receive_handle{send_mod = megaco_udp} = RH, TO) -> + start_udp(MgcPort, MgcHost, RH, TO); +start_transport(_, _, #megaco_receive_handle{send_mod = Mod}, _TO) -> + throw({error, {bad_send_mod, Mod}}). + + +start_tcp(MgcPort, MgcHost, RH, TO) -> + d("start tcp transport: " + "~n MGC Port: ~p" + "~n MGC Host: ~p" + "~n Receive handle: ~p" + "~n Transport options: ~p", [MgcPort, MgcHost, RH, TO]), + case megaco_tcp:start_transport() of + {ok, Sup} -> + d("tcp transport started: ~p", [Sup]), + start_tcp_connect(TO, RH, MgcPort, MgcHost, Sup); + {error, Reason} -> + throw({error, {megaco_tcp_start_transport, Reason}}) + end. + +start_tcp_connect(TO, RH, Port, Host, Sup) -> + d("try tcp connecting to: ~p:~p", [Host, Port]), + Opts = [{host, Host}, + {port, Port}, + {receive_handle, RH}, + {tcp_options, [{nodelay, true}]}] ++ TO, + try_start_tcp_connect(RH, Sup, Opts, 250, noError). + +try_start_tcp_connect(RH, Sup, Opts, Timeout, Error0) when (Timeout < 5000) -> + Sleep = random(Timeout) + 100, + d("try tcp connect (~p,~p)", [Timeout, Sleep]), + case megaco_tcp:connect(Sup, Opts) of + {ok, SendHandle, ControlPid} -> + d("tcp connected: ~p, ~p", [SendHandle, ControlPid]), + megaco_tcp_connect(RH, SendHandle, ControlPid); + Error1 when Error0 =:= noError -> % Keep the first error + d("failed connecting [1]: ~p", [Error1]), + sleep(Sleep), + try_start_tcp_connect(RH, Sup, Opts, Timeout*2, Error1); + Error2 -> + d("failed connecting [2]: ~p", [Error2]), + sleep(Sleep), + try_start_tcp_connect(RH, Sup, Opts, Timeout*2, Error0) + end; +try_start_tcp_connect(_RH, Sup, _Opts, _Timeout, Error) -> + megaco_tcp:stop_transport(Sup), + throw({error, {megaco_tcp_connect, Error}}). + +megaco_tcp_connect(RH, SendHandle, ControlPid) -> + PrelMgcMid = preliminary_mid, + d("megaco connect", []), + {ok, CH} = megaco:connect(RH, PrelMgcMid, SendHandle, ControlPid), + d("megaco connected: ~p", [CH]), + {ok, CH}. + +start_udp(MgcPort, MgcHost, RH, TO) -> + d("start udp transport (~p)", [MgcPort]), + case megaco_udp:start_transport() of + {ok, Sup} -> + d("udp transport started: ~p", [Sup]), + Opts = [{port, 0}, {receive_handle, RH}] ++ TO, + d("udp open", []), + case megaco_udp:open(Sup, Opts) of + {ok, Handle, ControlPid} -> + d("udp opened: ~p, ~p", [Handle, ControlPid]), + megaco_udp_connect(MgcPort, MgcHost, + RH, Handle, ControlPid); + {error, Reason} -> + throw({error, {megaco_udp_open, Reason}}) + end; + {error, Reason} -> + throw({error, {megaco_udp_start_transport, Reason}}) + end. + +megaco_udp_connect(MgcPort, MgcHost, RH, Handle, ControlPid) -> + MgcMid = preliminary_mid, + SendHandle = megaco_udp:create_send_handle(Handle, MgcHost, MgcPort), + d("megaco connect", []), + {ok, CH} = megaco:connect(RH, MgcMid, SendHandle, ControlPid), + d("megaco connected: ~p", [CH]), + {ok, CH}. + + +update_load_times(#mg{load_counter = 0} = MG, Times) -> + d("update_load_times(0) -> entry with" + "~n Times: ~p", [Times]), + {ok, MG#mg{load_counter = Times}}; +update_load_times(#mg{load_counter = N}, Times) -> + d("update_load_times(~p) -> entry with" + "~n Times: ~p", [N, Times]), + {error, {already_counting, N}}. + + +do_apply_load(#mg{mid = Mid} = MG) -> + d("do_apply_load -> entry"), + case megaco:user_info(Mid, connections) of + [CH] -> + do_apply_load(MG, CH); + [] -> + i("failed to apply load: no connections for ~p", [Mid]), + MG + end. + +do_apply_load(#mg{parent = Parent, + encode_ar_first = EAF, + call_mode = Mode, + group_size = Sz, + load_counter = N0} = MG, CH) -> + d("do_apply_load -> entry with" + "~n Mode: ~p" + "~n Sz: ~p" + "~n N0: ~p", [Mode, Sz, N0]), + {NofSent, Actions, ReplyData} = make_notify_request(N0, Sz), + d("do_apply_load -> notifications constructed:" + "~n NofSent: ~p" + "~n Actions: ~p" + "~n ReplyData: ~p", [NofSent, Actions, ReplyData]), + N = N0 - NofSent, + case Mode of + sync -> + Result = send_sync(EAF, CH, Actions, []), + d("do_apply_load -> call result when N = ~p: ~n~p", [N,Result]), + case N of + 0 -> + d("do_apply_load -> load complete"), + Parent ! {load_complete, self()}, + MG#mg{call_mode = async, load_counter = 0}; + _ -> + d("do_apply_load -> make another round"), + apply_load_timer(), + MG#mg{call_mode = async, load_counter = N} + end; + async -> + Result = send_async(EAF, CH, Actions, [{reply_data, ReplyData}]), + d("do_apply_load -> cast result:~n ~p", [Result]), + MG#mg{call_mode = sync, + load_counter = N, + reply_counter = NofSent} % Outstanding replies + end. + + +start_notify_request_handler(EAF, CH, N) -> + d("start_notify_request_handler -> entry with" + "~n EAF: ~p" + "~n CH: ~p" + "~n N: ~p", [EAF, CH, N]), + Env = get(), + spawn_link(?MODULE, notify_request_handler_main, [self(), Env, EAF, CH, N]). + +notify_request_handler_main(Parent, Env, EAF, CH, N) -> + F = fun({Tag, Val}) -> put(Tag, Val) end, + lists:foreach(F, Env), + d("notify_request_handler_main -> entry with" + "~n Parent: ~p" + "~n EAF: ~p" + "~n CH: ~p" + "~n N: ~p", [Parent, EAF, CH, N]), + Res = do_notify_request(EAF, CH, N), + d("notify_request_handler_main -> notify complete:" + "~n Res: ~p", [Res]), + Parent ! {notify_request_complete, {ok, Res}, self()}, + unlink(Parent), + exit(normal). + +do_notify_request(_EAF, _CH, N) when N =< 0 -> + d("do_notify_request(~p) -> ignoring", [N]), + ignore; +do_notify_request(EAF, CH, 1) -> + d("do_notify_request(1) -> entry with"), + {Action, _} = make_notify_request(), + send_sync(EAF, CH, Action, []); +do_notify_request(EAF, CH, N) -> + d("do_notify_request(~p) -> entry with", [N]), + {N, Actions, _} = make_notify_request(N,N), + send_sync(EAF, CH, Actions, []). + +make_notify_request(N, Sz) when (N >= Sz) andalso (Sz > 0) -> + {Req, ReplyData} = make_notify_request(N, Sz, [], []), + {Sz, Req, ReplyData}; +make_notify_request(N, _Sz) when N > 0 -> + {Req, ReplyData} = make_notify_request(N, N, [], []), + {N, Req, ReplyData}. + + + +make_notify_request(_Offset, 0, Actions, ReplyDatas) -> + {lists:reverse(Actions), lists:reverse(ReplyDatas)}; +make_notify_request(Offset, N, Actions, ReplyDatas) when N > 0 -> + TimeStamp = cre_timeNotation(), + Event = cre_observedEvent("al/of", TimeStamp), + Desc = cre_observedEventsDesc(2000 + N, [Event]), + TidNum = 2#10000000 + Offset - N, + NotifyReq = cre_notifyReq([#megaco_term_id{id = tid(TidNum)}],Desc), + CmdReq = cre_commandReq({notifyReq, NotifyReq}), + ActReq = cre_actionReq(?megaco_null_context_id, [CmdReq]), + make_notify_request(Offset, N-1, [[ActReq]|Actions], [Desc|ReplyDatas]). + +make_notify_request() -> + TimeStamp = cre_timeNotation("19990729", "22000000"), + Event = cre_observedEvent("al/of", TimeStamp), + Desc1 = cre_observedEventsDesc(2221, [Event]), + Desc2 = cre_observedEventsDesc(2222, [Event]), + Desc3 = cre_observedEventsDesc(2223, [Event]), + Desc4 = cre_observedEventsDesc(2224, [Event]), + NotifyReq1 = cre_notifyReq([#megaco_term_id{id = ?A4444}], Desc1), + NotifyReq2 = cre_notifyReq([#megaco_term_id{id = ?A4445}], Desc2), + CmdReq1 = cre_commandReq({notifyReq, NotifyReq1}), + CmdReq2 = cre_commandReq({notifyReq, NotifyReq2}), + ActReq = cre_actionReq(?megaco_null_context_id, [CmdReq1,CmdReq2]), + {[ActReq], [Desc3,Desc4]}. + + +cre_actionReq(Cid, Cmds) -> + #'ActionRequest'{contextId = Cid, + commandRequests = Cmds}. + +cre_commandReq(Cmd) -> + #'CommandRequest'{command = Cmd}. + +cre_serviceChangeReq(TermId, Parms) -> + #'ServiceChangeRequest'{terminationID = TermId, + serviceChangeParms = Parms}. + +cre_serviceChangeParm(Method, Reason) -> + #'ServiceChangeParm'{serviceChangeMethod = Method, + serviceChangeReason = Reason}. + +cre_notifyReq(Tid, EvsDesc) -> + #'NotifyRequest'{terminationID = Tid, observedEventsDescriptor = EvsDesc}. + +% cre_notifyRep(Tid) -> +% #'NotifyReply'{terminationID = [Tid]}. + +% cre_notifyRep(Tid,Err) -> +% #'NotifyReply'{terminationID = [Tid], errorDescriptor = Err}. + +cre_observedEventsDesc(Id, EvList) -> + #'ObservedEventsDescriptor'{requestId = Id, observedEventLst = EvList}. + +cre_observedEvent(Name, Not) -> + #'ObservedEvent'{eventName = Name, timeNotation = Not}. + +cre_timeNotation() -> + {{Year,Month,Day},{Hour,Min,Sec}} = calendar:universal_time(), + D = lists:flatten(io_lib:format("~4..0w~2..0w~2..0w", [Year,Month,Day])), + T = lists:flatten(io_lib:format("~2..0w~2..0w~4..0w", [Hour,Min,Sec])), + cre_timeNotation(D, T). + +cre_timeNotation(D,T) -> + #'TimeNotation'{date = D, time = T}. + +cre_error_descr(Code,Text) -> + #'ErrorDescriptor'{errorCode = Code, errorText = Text}. + +% cre_error_descr(Code,FormatString,Args) -> +% Text = lists:flatten(io_lib:format(FormatString,Args)), +% cre_error_descr(Code,Text). + + +%% ----------------------- +%% Handle megaco callbacks +%% + +handle_megaco_request(#mg{state = connecting} = MG, + {handle_connect, _CH, _PV}) -> + d("handle_megaco_request(handle_connect,connecting) -> entry"), + {ok, MG}; +handle_megaco_request(#mg{state = S} = MG, + {handle_connect, _CH, _PV}) -> + d("handle_megaco_request(handle_connect) -> entry"), + Desc = + lists:flatten(io_lib:format("not ready for connect in state ~p", [S])), + ED = cre_error_descr(?megaco_internal_gateway_error, Desc), + {{discard_ack, ED}, MG}; + +handle_megaco_request(#mg{req_handler = Pid} = MG, + {handle_disconnect, _CH, _PV, R}) + when is_pid(Pid) -> + d("handle_megaco_request(handle_disconnect) -> entry with" + "~n Pid: ~p", [Pid]), + Error = {error, {disconnected, R}}, + self() ! {notify_request_complete, Error, Pid}, + unlink(Pid), + exit(Pid, kill), + {ok, MG#mg{req_handler = undefined, state = initiated}}; +handle_megaco_request(MG, {handle_disconnect, _CH, _PV, _R}) -> + d("handle_megaco_request(handle_disconnect) -> entry"), + {ok, MG#mg{state = initiated}}; + +handle_megaco_request(MG, + {handle_syntax_error, _RH, _PV, _ED}) -> + {reply, MG}; + +handle_megaco_request(#mg{req_handler = Pid} = MG, + {handle_message_error, CH, PV, ED}) + when is_pid(Pid) -> + d("handle_megaco_request(handle_message_error) -> entry with" + "~n Pid: ~p" + "~n CH: ~p" + "~n PV: ~p" + "~n ED: ~p", [Pid, CH, PV, ED]), + self() ! {notify_request_complete, ED, Pid}, + unlink(Pid), + exit(Pid, kill), + {no_reply, MG#mg{req_handler = undefined}}; +handle_megaco_request(MG, {handle_message_error, CH, PV, ED}) -> + d("handle_megaco_request(handle_message_error) -> entry with" + "~n CH: ~p" + "~n PV: ~p" + "~n ED: ~p", [CH, PV, ED]), + {no_reply, MG}; + +handle_megaco_request(MG, {handle_trans_request, _CH, _PV, _AR}) -> + ED = cre_error_descr(?megaco_not_implemented, + "Transaction requests not handled"), + {{discard_ack, ED}, MG}; + +handle_megaco_request(MG, + {handle_trans_long_request, _CH, _PV, _RD}) -> + ED = cre_error_descr(?megaco_not_implemented, + "Long transaction requests not handled"), + {{discard_ack, ED}, MG}; + +handle_megaco_request(#mg{rep_info = P} = MG, + {handle_trans_reply, CH, PV, AR, RD}) when is_pid(P) -> + P ! {rep_received, self(), AR}, + do_handle_trans_reply(MG, CH, PV, AR, RD); +handle_megaco_request(MG, {handle_trans_reply, CH, PV, AR, RD}) -> + do_handle_trans_reply(MG, CH, PV, AR, RD); + +handle_megaco_request(#mg{ack_info = P} = MG, + {handle_trans_ack, _CH, _PV, AS, _AD}) when is_pid(P) -> + d("handle_megaco_request(handle_trans_ack,~p) -> entry",[P]), + P ! {ack_received, self(), AS}, + {ok, MG}; +handle_megaco_request(MG, {handle_trans_ack, _CH, _PV, _AS, _AD}) -> + d("handle_megaco_request(handle_trans_ack) -> entry"), + {ok, MG}. + +do_handle_trans_reply(#mg{parent = Parent, state = connecting} = MG, + CH, _PV, {ok, Rep}, _RD) -> + d("do_handle_trans_reply(connecting) -> entry with" + "~n CH: ~p" + "~n Rep: ~p", [CH, Rep]), + server_reply(Parent, service_change_reply, ok), + {ok, MG#mg{state = connected}}; +do_handle_trans_reply(#mg{parent = Parent, load_counter = 0} = MG, + CH, _PV, {ok, Rep}, _RD) -> + d("do_handle_trans_reply(load_counter = 0) -> entry with" + "~n CH: ~p" + "~n Rep: ~p", [CH, Rep, Parent]), + handle_trans_reply_verify_act(Rep), + server_reply(Parent, load_complete, ok), + {ok, MG#mg{reply_counter = 0}}; +do_handle_trans_reply(#mg{reply_counter = 0} = MG, + CH, _PV, {ok, Rep}, _RD) -> + d("do_handle_trans_reply(reply_counter = 0) -> entry with" + "~n CH: ~p" + "~n Rep: ~p", [CH, Rep]), + handle_trans_reply_verify_act(Rep), + apply_load_timer(), + {ok, MG}; +do_handle_trans_reply(#mg{reply_counter = N} = MG, + CH, _PV, {ok, Rep}, _RD) -> + d("do_handle_trans_reply(reply_counter = ~p) -> entry with" + "~n CH: ~p" + "~n Rep: ~p", [N, CH, Rep]), + handle_trans_reply_verify_act(Rep), + apply_load_timer(), + {ok, MG#mg{reply_counter = N-1}}; +do_handle_trans_reply(MG, _CH, _PV, {error, ED}, _RD) -> + i("unexpected error transaction: ~p", [ED]), + {ok, MG}. + + +handle_trans_reply_verify_act([]) -> + ok; +handle_trans_reply_verify_act([#'ActionReply'{commandReply = Rep}|Reps]) -> + handle_trans_reply_verify_cmd(Rep), + handle_trans_reply_verify_act(Reps); +handle_trans_reply_verify_act([Rep|Reps]) -> + i("received 'propably' unexpected reply: ~n~p", [Rep]), + handle_trans_reply_verify_act(Reps). + +handle_trans_reply_verify_cmd([]) -> + ok; +handle_trans_reply_verify_cmd([Cmd|Cmds]) -> + case Cmd of + {notifyReply, #'NotifyReply'{terminationID = [Tid]}} -> + d("received expected notification reply from ~n ~p", [Tid]); + Else -> + i("received unexpected notification reply ~n~p", [Else]) + end, + handle_trans_reply_verify_cmd(Cmds). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +notify_started(Parent) -> + Parent ! {started, self()}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% The megaco user callback interface + +handle_connect(CH, PV, Pid, Mid) -> + case CH#megaco_conn_handle.remote_mid of + preliminary_mid -> + %% Avoids deadlock + ok; + _ -> + Reply = request(Pid, {handle_connect, CH, PV}, Mid), + Reply + end. + +handle_disconnect(_CH, _PV, + {user_disconnect, {stopped_by_user, Pid}}, + Pid, _Mid) -> + ok; +handle_disconnect(CH, PV, R, Pid, Mid) -> + request(Pid, {handle_disconnect, CH, PV, R}, Mid). + +handle_syntax_error(ReceiveHandle, ProtocolVersion, ErrorDescriptor, Pid, Mid) -> + Req = {handle_syntax_error, ReceiveHandle, ProtocolVersion, + ErrorDescriptor}, + request(Pid, Req, Mid). + +handle_message_error(ConnHandle, ProtocolVersion, ErrorDescriptor, Pid, Mid) -> + Req = {handle_message_error, ConnHandle, ProtocolVersion, ErrorDescriptor}, + request(Pid, Req, Mid). + +handle_trans_request(CH, PV, AR, Pid, Mid) -> + Reply = request(Pid, {handle_trans_request, CH, PV, AR}, Mid), + Reply. + +handle_trans_long_request(ConnHandle, ProtocolVersion, ReqData, Pid, Mid) -> + Req = {handle_trans_long_request, ConnHandle, ProtocolVersion, ReqData}, + request(Pid, Req, Mid). + +handle_trans_reply(ConnHandle, ProtocolVersion, ActualReply, ReplyData, Pid, Mid) -> + Req = {handle_trans_reply, ConnHandle, ProtocolVersion, + ActualReply, ReplyData}, + request(Pid, Req, Mid). + +handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData, Pid, Mid) -> + Req = {handle_trans_ack, ConnHandle, ProtocolVersion, AckStatus, AckData}, + request(Pid, Req, Mid). + + +request(Pid, Request, Mid) -> + Pid ! {request, Request, Mid, self()}, + receive + {reply, {delay, To, ED}, Pid} -> + sleep(To), + {discard_ack, ED}; + {reply, Reply, Pid} -> + Reply + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +send_async(true, CH, Actions, Opts) -> + d("send_async(true) -> encode actions first"), + case megaco:encode_actions(CH, Actions, Opts) of + {ok, BinOrBins} -> + d("send_async(true) -> send message"), + megaco:cast(CH, BinOrBins, Opts); + Error -> + d("send_async(true) -> encode failed: ~n~p", [Error]), + Error + end; +send_async(_, CH, Actions, Opts) -> + d("send_async(true) -> send message"), + megaco:cast(CH, Actions, Opts). + +send_sync(true, CH, Actions, Opts) -> + d("send_sync(true) -> encode actions first"), + case megaco:encode_actions(CH, Actions, Opts) of + {ok, BinOrBins} -> + d("send_sync(true) -> send message"), + megaco:call(CH, BinOrBins, Opts); + Error -> + d("send_sync(true) -> encode failed: ~n~p", [Error]), + Error + end; +send_sync(_, CH, Actions, Opts) -> + d("send_sync(false) -> send message"), + megaco:call(CH, Actions, Opts). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +sleep(X) -> + receive after X -> ok end. + + +error_msg(F,A) -> error_logger:error_msg("MG: " ++ F ++ "~n",A). + + +get_encoding_module(RI) -> + case (catch get_conf(encoding_module, RI)) of + {error, _} -> + undefined; + Val -> + Val + end. + +get_encoding_config(RI, EM) -> + case text_codec(EM) of + true -> + case megaco:system_info(text_config) of + [Conf] when is_list(Conf) -> + Conf; + _ -> + [] + end; + + false -> + get_conf(encoding_config, RI) + end. + +text_codec(megaco_compact_text_encoder) -> + true; +text_codec(megaco_pretty_text_encoder) -> + true; +text_codec(_) -> + false. + + +get_transport_module(RI) -> + get_conf(transport_module, RI). + +get_transport_port(RI) -> + get_conf(port, RI). + +get_transport_host(RI) -> + {ok, LocalHost} = inet:gethostname(), + get_conf(host, RI, LocalHost). + +get_transport_opts(RI) -> + get_conf(transport_opts, RI, []). + + +get_conf(Key, Config) -> + case lists:keysearch(Key, 1, Config) of + {value, {Key, Val}} -> + Val; + _ -> + exit({error, {not_found, Key, Config}}) + end. + +get_conf(Key, Config, Default) -> + case lists:keysearch(Key, 1, Config) of + {value, {Key, Val}} -> + Val; + _ -> + Default + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +tid(N) when N >= 0 -> + {Rem1, Val1} = num2str(N), + {Rem2, Val2} = num2str(Rem1), + {0, Val3} = num2str(Rem2), + [Val3, Val2, Val1]. + +num2str(N) when N >= 0 -> + num2str(N, []). + +num2str(Rem, Val) when length(Val) == 8 -> + {Rem, Val}; +num2str(N, Val) -> + D = N div 2, + case N rem 2 of + 1 -> + num2str(D, [$1|Val]); + 0 -> + num2str(D, [$0|Val]) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +i(F) -> + i(F, []). + +i(F, A) -> + print(info, get(verbosity), "", F, A). + + +d(F) -> + d(F, []). + +d(F, A) -> + print(debug, get(verbosity), "DBG", F, A). + + +printable(_, debug) -> true; +printable(info, info) -> true; +printable(_,_) -> false. + +print(Severity, Verbosity, P, F, A) -> + print(printable(Severity,Verbosity), P, F, A). + +print(true, P, F, A) -> + io:format("*** [~s] ~s ~p ~s ***" + "~n " ++ F ++ "~n~n", + [format_timestamp(now()), P, self(), get(sname) | A]); +print(_, _, _, _) -> + ok. + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +random_init() -> + {A,B,C} = now(), + random:seed(A,B,C). + +random() -> + random(50). +random(N) -> + random:uniform(N). + + +display_system_info(Mid) -> + display_system_info(Mid, ""). + +display_system_info(Mid, Pre) -> + TimeStr = format_timestamp(now()), + MibStr = lists:flatten(io_lib:format("~p ", [Mid])), + megaco_test_lib:display_system_info(MibStr ++ Pre ++ TimeStr). + + +create_timer(Time, Event) -> + erlang:send_after(Time, self(), {Event, Time}). + +cancel_timer(undefined) -> + ok; +cancel_timer(Ref) -> + erlang:cancel_timer(Ref). + + +apply_load_timer() -> + create_timer(random(), apply_load_timeout). + + diff --git a/lib/megaco/test/megaco_test_mgc.erl b/lib/megaco/test/megaco_test_mgc.erl new file mode 100644 index 0000000000..05c482f1af --- /dev/null +++ b/lib/megaco/test/megaco_test_mgc.erl @@ -0,0 +1,1221 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Implements an "MGC" used by the test suite +%%---------------------------------------------------------------------- +-module(megaco_test_mgc). + +-export([start/4, start/5, stop/1, + get_stats/2, reset_stats/1, + user_info/1, user_info/2, conn_info/1, conn_info/2, + update_user_info/3, update_conn_info/3, + request_ignore/1, + request_discard/1, request_discard/2, + request_pending/1, request_pending/2, request_pending_ignore/1, + request_handle/1, request_handle/2, + request_handle_pending/1, request_handle_pending/2, + request_handle_sloppy/1, request_handle_sloppy/2, + ack_info/2, abort_info/2, req_info/2, + disconnect/2, + verbosity/2]). +-export([mgc/3]). + +%% Megaco callback api +-export([ + handle_connect/3, + handle_disconnect/4, + handle_syntax_error/4, + handle_message_error/4, + handle_trans_request/4, + handle_trans_long_request/4, + handle_trans_reply/5, + handle_trans_ack/5, + handle_unexpected_trans/4, + handle_trans_request_abort/5 + ]). + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). + +-define(A4444, ["11111111", "00000000", "00000000"]). +-define(A4445, ["11111111", "00000000", "11111111"]). +-define(A5555, ["11111111", "11111111", "00000000"]). +-define(A5556, ["11111111", "11111111", "11111111"]). + +-define(valid_actions, + [ignore, pending, pending_ignore, discard_ack, handle_ack, handle_pending_ack, handle_sloppy_ack]). + +-record(mgc, {parent = undefined, + tcp_sup = undefined, + udp_sup = undefined, + req_action = discard_ack, + req_timeout = 0, + mid = undefined, + ack_info = undefined, + abort_info = undefined, + req_info = undefined, + mg = [], + dsi_timer}). + + +%%% ------------------------------------------------------------------ + +start(Node, Mid, ET, Verbosity) -> + %% Conf = [{megaco_trace, io}], + %% Conf = [{megaco_trace, "megaco-mgc.trace"}], + Conf = [{megaco_trace, false}], + start(Node, Mid, ET, Conf, Verbosity). + +start(Node, Mid, ET, Conf, Verbosity) -> + d("start mgc[~p]: ~p", [Node, Mid]), + RI = {receive_info, mk_recv_info(ET)}, + Config = [{local_mid, Mid}, RI] ++ Conf, + Pid = spawn_link(Node, ?MODULE, mgc, [self(), Verbosity, Config]), + await_started(Pid). + +mk_recv_info(ET) -> + mk_recv_info(ET, []). + +mk_recv_info([], Acc) -> + Acc; +mk_recv_info([{Encoding, Transport}|ET], Acc) + when is_atom(Encoding) andalso is_atom(Transport) -> + {EMod, Port} = select_encoding(Encoding), + TMod = select_transport(Transport), + RI = [{encoding_module, EMod}, + {encoding_config, []}, + {transport_module, TMod}, + {port, Port}], + mk_recv_info(ET, [RI|Acc]); +mk_recv_info([{Encoding, Transport, TO}|ET], Acc) + when is_atom(Encoding) andalso is_atom(Transport) andalso is_list(TO) -> + {EMod, Port} = select_encoding(Encoding), + TMod = select_transport(Transport), + RI = [{encoding_module, EMod}, + {encoding_config, []}, + {transport_module, TMod}, + {port, Port}, + {transport_opts, TO}], + mk_recv_info(ET, [RI|Acc]); +mk_recv_info([{Encoding, EC, Transport}|ET], Acc) + when is_atom(Encoding) andalso is_list(EC) andalso is_atom(Transport) -> + {EMod, Port} = select_encoding(Encoding), + TMod = select_transport(Transport), + RI = [{encoding_module, EMod}, + {encoding_config, EC}, + {transport_module, TMod}, + {port, Port}], + mk_recv_info(ET, [RI|Acc]); +mk_recv_info([ET|_], _) -> + throw({error, {invalid_encoding_transport, ET}}). + +select_encoding(text) -> + {megaco_pretty_text_encoder, 2944}; +select_encoding(pretty_text) -> + {megaco_pretty_text_encoder, 2944}; +select_encoding(compact_text) -> + {megaco_compact_text_encoder, 2944}; +select_encoding(binary) -> + {megaco_ber_bin_encoder, 2945}; +select_encoding(erl_dist) -> + {megaco_erl_dist_encoder, 2946}; +select_encoding(Encoding) -> + throw({error, {invalid_encoding, Encoding}}). + +select_transport(tcp) -> + megaco_tcp; +select_transport(udp) -> + megaco_udp; +select_transport(Transport) -> + throw({error, {invalid_transport, Transport}}). + + +await_started(Pid) -> + receive + {started, Pid} -> + d("await_started ~p: ok", [Pid]), + {ok, Pid}; + {'EXIT', Pid, + {failed_starting_tcp_listen, {could_not_start_listener, {gen_tcp_listen, eaddrinuse}}}} -> + i("await_started ~p: address already in use", [Pid]), + ?SKIP(eaddrinuse); + {'EXIT', Pid, Reason} -> + i("await_started ~p: received exit signal: ~p", [Pid, Reason]), + exit({failed_starting, Pid, Reason}) + after 10000 -> + i("await_started ~p: timeout", [Pid]), + exit({error, timeout}) + end. + + +stop(Pid) -> + server_request(Pid, stop, stopped). + +get_stats(Pid, No) -> + server_request(Pid, {statistics, No}, {statistics_reply, No}). + +reset_stats(Pid) -> + server_request(Pid, reset_stats, reset_stats_ack). + +user_info(Pid) -> + server_request(Pid, {user_info, all}, user_info_ack). + +user_info(Pid, Tag) -> + server_request(Pid, {user_info, Tag}, user_info_ack). + +conn_info(Pid) -> + server_request(Pid, {conn_info, all}, conn_info_ack). + +conn_info(Pid, Tag) -> + server_request(Pid, {conn_info, Tag}, conn_info_ack). + +update_user_info(Pid, Tag, Val) -> + server_request(Pid, {update_user_info, Tag, Val}, update_user_info_ack). + +update_conn_info(Pid, Tag, Val) -> + server_request(Pid, {update_conn_info, Tag, Val}, update_conn_info_ack). + +disconnect(Pid, Reason) -> + server_request(Pid, {disconnect, Reason}, disconnected). + +ack_info(Pid, InfoPid) -> + Pid ! {ack_info, InfoPid, self()}. + +abort_info(Pid, InfoPid) -> + Pid ! {abort_info, InfoPid, self()}. + +req_info(Pid, InfoPid) -> + Pid ! {req_info, InfoPid, self()}. + +verbosity(Pid, V) -> + Pid ! {verbosity, V, self()}. + +request_ignore(Pid) -> + request_action(Pid, {ignore, infinity}). + +request_pending_ignore(Pid) -> + request_action(Pid, {pending_ignore, infinity}). + +request_discard(Pid) -> + request_discard(Pid,0). + +request_discard(Pid, To) -> + request_action(Pid, {discard_ack, To}). + +request_pending(Pid) -> + request_pending(Pid, 5000). + +request_pending(Pid, To) -> + request_action(Pid, {pending, To}). + +request_handle(Pid) -> + request_handle(Pid, 0). + +request_handle(Pid, To) -> + request_action(Pid, {handle_ack, To}). + +request_handle_pending(Pid) -> + request_handle_pending(Pid, 0). + +request_handle_pending(Pid, To) -> + request_action(Pid, {handle_pending_ack, To}). + +request_handle_sloppy(Pid) -> + request_handle_sloppy(Pid, 0). + +request_handle_sloppy(Pid, To) -> + request_action(Pid, {handle_sloppy_ack, To}). + +request_action(Pid, Action) -> + server_request(Pid, request_action, Action, request_action_ack). + + +server_request(Pid, Req, ReplyTag) -> + Pid ! {Req, self()}, + receive + {ReplyTag, Reply, Pid} -> + Reply; + {'EXIT', Pid, Reason} -> + exit({failed, Req, Pid, Reason}) + after 10000 -> + exit({timeout, Req, Pid}) + end. + +server_request(Pid, Req, ReqData, ReplyTag) -> + Pid ! {Req, ReqData, self()}, + receive + {ReplyTag, Reply, Pid} -> + Reply; + {'EXIT', Pid, Reason} -> + exit({failed, Req, Pid, Reason}) + after 10000 -> + exit({timeout, Req, Pid}) + end. + + +server_reply(Pid, ReplyTag, Reply) -> + Pid ! {ReplyTag, Reply, self()}. + + +%%% ------------------------------------------------------------------ + + +mgc(Parent, Verbosity, Config) -> + process_flag(trap_exit, true), + put(verbosity, Verbosity), + put(sname, "MGC"), + i("mgc -> starting"), + case (catch init(Config)) of + {error, Reason} -> + exit(Reason); + {Mid, TcpSup, UdpSup, DSITimer} -> + notify_started(Parent), + S = #mgc{parent = Parent, + tcp_sup = TcpSup, + udp_sup = UdpSup, + mid = Mid, + dsi_timer = DSITimer}, + i("mgc -> started"), + display_system_info("at start "), + loop(S) + end. + +init(Config) -> + d("init -> entry"), + random_init(), + Mid = get_conf(local_mid, Config), + RI = get_conf(receive_info, Config), + + d("init -> maybe start the display system info timer"), + DSITimer = + case get_conf(display_system_info, Config, undefined) of + Time when is_integer(Time) -> + d("init -> creating display system info timer"), + create_timer(Time, display_system_info); + _ -> + undefined + end, + Conf0 = lists:keydelete(display_system_info, 1, Config), + + d("init -> start megaco"), + application:start(megaco), + + d("init -> possibly enable megaco trace"), + case lists:keysearch(megaco_trace, 1, Config) of + {value, {megaco_trace, true}} -> + megaco:enable_trace(max, io); + {value, {megaco_trace, io}} -> + megaco:enable_trace(max, io); + {value, {megaco_trace, File}} when is_list(File) -> + megaco:enable_trace(max, File); + _ -> + ok + end, + Conf1 = lists:keydelete(megaco_trace, 1, Conf0), + + d("init -> start megaco user"), + Conf2 = lists:keydelete(local_mid, 1, Conf1), + Conf3 = lists:keydelete(receive_info, 1, Conf2), + ok = megaco:start_user(Mid, Conf3), + + d("init -> update user info (user_mod)"), + ok = megaco:update_user_info(Mid, user_mod, ?MODULE), + + d("init -> update user info (user_args)"), + ok = megaco:update_user_info(Mid, user_args, [self()]), + + d("init -> get user info (receive_handle)"), + RH = megaco:user_info(Mid,receive_handle), + d("init -> parse receive info"), + Transports = parse_receive_info(RI, RH), + + d("init -> start transports"), + {Tcp, Udp} = start_transports(Transports), + {Mid, Tcp, Udp, DSITimer}. + +loop(S) -> + d("loop -> await request"), + receive + {display_system_info, Time} -> + display_system_info(S#mgc.mid), + NewTimer = create_timer(Time, display_system_info), + loop(S#mgc{dsi_timer = NewTimer}); + + {stop, Parent} when S#mgc.parent =:= Parent -> + i("loop -> stopping", []), + display_system_info(S#mgc.mid, "at finish "), + cancel_timer(S#mgc.dsi_timer), + Mid = S#mgc.mid, + (catch close_conns(Mid)), + megaco:stop_user(Mid), + application:stop(megaco), + i("loop -> stopped", []), + server_reply(Parent, stopped, ok), + exit(normal); + + {{disconnect, Reason}, Parent} when S#mgc.parent == Parent -> + i("loop -> disconnecting", []), + Mid = S#mgc.mid, + [Conn|_] = megaco:user_info(Mid, connections), + Res = megaco:disconnect(Conn, {self(), Reason}), + server_reply(Parent, disconnected, Res), + loop(S); + + {{update_user_info, Tag, Val}, Parent} when S#mgc.parent == Parent -> + i("loop -> got update_user_info: ~w -> ~p", [Tag, Val]), + Res = (catch megaco:update_user_info(S#mgc.mid, Tag, Val)), + d("loop -> Res: ~p", [Res]), + server_reply(Parent, update_user_info_ack, Res), + loop(S); + + {{user_info, Tag}, Parent} when S#mgc.parent == Parent -> + i("loop -> got user_info request for ~w", [Tag]), + Res = (catch megaco:user_info(S#mgc.mid, Tag)), + d("loop -> Res: ~p", [Res]), + server_reply(Parent, user_info_ack, Res), + loop(S); + + {{update_conn_info, Tag, Val}, Parent} when S#mgc.parent == Parent -> + i("loop -> got update_conn_info: ~w -> ~p", [Tag, Val]), + Conns = megaco:user_info(S#mgc.mid, connections), + Fun = fun(CH) -> + (catch megaco:update_conn_info(CH, Tag, Val)) + end, + Res = lists:map(Fun, Conns), + d("loop -> Res: ~p", [Res]), + server_reply(Parent, update_conn_info_ack, Res), + loop(S); + + {{conn_info, Tag}, Parent} when S#mgc.parent == Parent -> + i("loop -> got conn_info request for ~w", [Tag]), + Conns = megaco:user_info(S#mgc.mid, connections), + Fun = fun(CH) -> + {CH, (catch megaco:conn_info(CH, Tag))} + end, + Res = lists:map(Fun, Conns), + d("loop -> Res: ~p", [Res]), + server_reply(Parent, conn_info_ack, Res), + loop(S); + + + %% + {request_action, {Action, To}, Parent} when S#mgc.parent == Parent -> + i("loop -> got new request_action: ~p:~w", [Action,To]), + {Reply, S1} = + case lists:member(Action, ?valid_actions) of + true when To >= 0; To == infinity -> + {{ok, S#mgc.req_action}, + S#mgc{req_action = Action, req_timeout = To}}; + true -> + {{error, {invalid_action_timeout, To}}, S}; + false -> + {{error, {invalid_action, Action}}, S} + end, + server_reply(Parent, request_action_ack, Reply), + loop(S1); + + + %% Reset stats + {reset_stats, Parent} when S#mgc.parent == Parent -> + i("loop -> got request to reset stats counters"), + do_reset_stats(S#mgc.mid), + server_reply(Parent, reset_stats_ack, ok), + loop(S); + + + %% Give me statistics + {{statistics, 1}, Parent} when S#mgc.parent == Parent -> + i("loop -> got request for statistics 1"), + {ok, Gen} = megaco:get_stats(), + GetTrans = + fun(CH) -> + Reason = {statistics, CH}, + Pid = megaco:conn_info(CH, control_pid), + SendMod = megaco:conn_info(CH, send_mod), + SendHandle = megaco:conn_info(CH, send_handle), + {ok, Stats} = + case SendMod of + megaco_tcp -> megaco_tcp:get_stats(SendHandle); + megaco_udp -> megaco_udp:get_stats(SendHandle); + SendMod -> exit(Pid, Reason) + end, + {SendHandle, Stats} + end, + Mid = S#mgc.mid, + Trans = + lists:map(GetTrans, megaco:user_info(Mid, connections)), + Reply = {ok, [{gen, Gen}, {trans, Trans}]}, + server_reply(Parent, {statistics_reply, 1}, Reply), + loop(S); + + + {{statistics, 2}, Parent} when S#mgc.parent == Parent -> + i("loop -> got request for statistics 2"), + {ok, Gen} = megaco:get_stats(), + #mgc{tcp_sup = TcpSup, udp_sup = UdpSup} = S, + TcpStats = get_trans_stats(TcpSup, megaco_tcp), + UdpStats = get_trans_stats(UdpSup, megaco_udp), + Reply = {ok, [{gen, Gen}, {trans, [TcpStats, UdpStats]}]}, + server_reply(Parent, {statistics_reply, 2}, Reply), + loop(S); + + + %% Megaco callback messages + {request, Request, From} -> + d("loop -> received megaco request from ~p:~n~p", + [From, Request]), + {Reply, S1} = handle_megaco_request(Request, S), + d("loop -> send request reply: ~n~p", [Reply]), + reply(From, Reply), + loop(S1); + + + {ack_info, To, Parent} when S#mgc.parent == Parent -> + i("loop -> received request to inform about received ack's ", []), + loop(S#mgc{ack_info = To}); + + + {abort_info, To, Parent} when S#mgc.parent == Parent -> + i("loop -> received request to inform about received aborts ", []), + loop(S#mgc{abort_info = To}); + + + {req_info, To, Parent} when S#mgc.parent == Parent -> + i("loop -> received request to inform about received req's ", []), + loop(S#mgc{req_info = To}); + + + {verbosity, V, Parent} when S#mgc.parent == Parent -> + i("loop -> received new verbosity: ~p", [V]), + put(verbosity,V), + loop(S); + + + {'EXIT', Pid, Reason} when S#mgc.tcp_sup =:= Pid -> + error_msg("MGC received unexpected exit " + "from TCP transport supervisor (~p):~n~p", + [Pid, Reason]), + i("loop -> [tcp] exiting", []), + display_system_info(S#mgc.mid, "at bad finish (tcp) "), + cancel_timer(S#mgc.dsi_timer), + Mid = S#mgc.mid, + (catch close_conns(Mid)), + megaco:stop_user(Mid), + application:stop(megaco), + i("loop -> stopped", []), + StopReason = {error, {tcp_terminated, Pid, Reason}}, + server_reply(S#mgc.parent, stopped, StopReason), + exit(StopReason); + + + {'EXIT', Pid, Reason} when S#mgc.udp_sup =:= Pid -> + error_msg("MGC received unexpected exit " + "from UDP transport supervisor (~p):~n~p", + [Pid, Reason]), + i("loop -> [udp] exiting", []), + display_system_info(S#mgc.mid, "at bad finish (udp) "), + cancel_timer(S#mgc.dsi_timer), + Mid = S#mgc.mid, + (catch close_conns(Mid)), + megaco:stop_user(Mid), + application:stop(megaco), + i("loop -> stopped", []), + StopReason = {error, {udp_terminated, Pid, Reason}}, + server_reply(S#mgc.parent, stopped, StopReason), + exit(StopReason); + + + Invalid -> + i("loop -> received invalid request: ~p", [Invalid]), + loop(S) + end. + + +do_reset_stats(Mid) -> + megaco:reset_stats(), + do_reset_trans_stats(megaco:user_info(Mid, connections), []). + +do_reset_trans_stats([], _Reset) -> + ok; +do_reset_trans_stats([CH|CHs], Reset) -> + SendMod = megaco:conn_info(CH, send_mod), + case lists:member(SendMod, Reset) of + true -> + do_reset_trans_stats(CHs, Reset); + false -> + SendMod:reset_stats(), + do_reset_trans_stats(CHs, [SendMod|Reset]) + end. + + +close_conns(Mid) -> + Reason = {self(), ignore}, + Disco = fun(CH) -> + (catch do_close_conn(CH, Reason)) + end, + lists:map(Disco, megaco:user_info(Mid, connections)). + +do_close_conn(CH, Reason) -> + d("close connection to ~p", [CH#megaco_conn_handle.remote_mid]), + Pid = megaco:conn_info(CH, control_pid), + SendMod = megaco:conn_info(CH, send_mod), + SendHandle = megaco:conn_info(CH, send_handle), + megaco:disconnect(CH, Reason), + case SendMod of + megaco_tcp -> megaco_tcp:close(SendHandle); + megaco_udp -> megaco_udp:close(SendHandle); + SendMod -> exit(Pid, Reason) + end. + +get_trans_stats(P, SendMod) when is_pid(P) -> + case (catch SendMod:get_stats()) of + {ok, Stats} -> + {SendMod, Stats}; + Else -> + {SendMod, Else} + end; +get_trans_stats(_P, SendMod) -> + {SendMod, undefined}. + +parse_receive_info([], _RH) -> + throw({error, no_receive_info}); +parse_receive_info(RI, RH) -> + parse_receive_info(RI, RH, []). + +parse_receive_info([], _RH, Transports) -> + d("parse_receive_info -> done when" + "~n Transports: ~p", [Transports]), + Transports; +parse_receive_info([RI|RIs], RH, Transports) -> + d("parse_receive_info -> parse receive info"), + case (catch parse_receive_info1(RI, RH)) of + {error, Reason} -> + i("failed parsing receive info: ~p~n~p", [RI, Reason]), + exit({failed_parsing_recv_info, RI, Reason}); + RH1 -> + parse_receive_info(RIs, RH, [RH1|Transports]) + end. + +parse_receive_info1(RI, RH) -> + d("parse_receive_info1 -> get encoding module"), + EM = get_encoding_module(RI), + d("parse_receive_info1 -> get encoding config"), + EC = get_encoding_config(RI, EM), + d("parse_receive_info1 -> get transport module"), + TM = get_transport_module(RI), + d("parse_receive_info1 -> get transport port"), + TP = get_transport_port(RI), + d("parse_receive_info1 -> get transport opts"), + TO = get_transport_opts(RI), + RH1 = RH#megaco_receive_handle{send_mod = TM, + encoding_mod = EM, + encoding_config = EC}, + d("parse_receive_info1 -> " + "~n Transport Opts: ~p" + "~n Port: ~p" + "~n Receive handle: ~p", [TO, TP, RH1]), + {TO, TP, RH1}. + + + +%% -------------------------------------------------------- +%% On some platforms there seem to take some time before +%% a port is released by the OS (after having been used, +%% as is often the case in the test suites). +%% So, starting the transports is done in two steps. +%% First) Start the actual transport(s) +%% Second) Create the listener (tcp) or open the +%% send/receive port (udp). +%% The second step *may* need to be repeated! +%% -------------------------------------------------------- +start_transports([]) -> + throw({error, no_transport}); +start_transports(Transports) when is_list(Transports) -> + {Tcp, Udp} = start_transports1(Transports, undefined, undefined), + ok = start_transports2(Transports, Tcp, Udp), + {Tcp, Udp}. + +start_transports1([], Tcp, Udp) -> + {Tcp, Udp}; +start_transports1([{_TO, _Port, RH}|Transports], Tcp, Udp) + when ((RH#megaco_receive_handle.send_mod =:= megaco_tcp) andalso + (not is_pid(Tcp))) -> + case megaco_tcp:start_transport() of + {ok, Sup} -> + start_transports1(Transports, Sup, Udp); + Else -> + throw({error, {failed_starting_tcp_transport, Else}}) + end; +start_transports1([{_TO, _Port, RH}|Transports], Tcp, Udp) + when ((RH#megaco_receive_handle.send_mod =:= megaco_udp) andalso + (not is_pid(Udp))) -> + case megaco_udp:start_transport() of + {ok, Sup} -> + start_transports1(Transports, Tcp, Sup); + Else -> + throw({error, {failed_starting_udp_transport, Else}}) + end; +start_transports1([_|Transports], Tcp, Udp) -> + start_transports1(Transports, Tcp, Udp). + +start_transports2([], _, _) -> + ok; +start_transports2([{TO, Port, RH}|Transports], Tcp, Udp) + when RH#megaco_receive_handle.send_mod =:= megaco_tcp -> + start_tcp(TO, RH, Port, Tcp), + start_transports2(Transports, Tcp, Udp); +start_transports2([{TO, Port, RH}|Transports], Tcp, Udp) + when RH#megaco_receive_handle.send_mod =:= megaco_udp -> + start_udp(TO, RH, Port, Udp), + start_transports2(Transports, Tcp, Udp). + +start_tcp(TO, RH, Port, Sup) -> + d("start tcp transport"), + start_tcp(TO, RH, Port, Sup, 250). + +start_tcp(TO, RH, Port, Sup, Timeout) + when is_pid(Sup) andalso is_integer(Timeout) andalso (Timeout > 0) -> + d("tcp listen on ~p", [Port]), + Opts = [{port, Port}, + {receive_handle, RH}, + {tcp_options, [{nodelay, true}]}] ++ TO, + try_start_tcp(Sup, Opts, Timeout, noError). + +try_start_tcp(Sup, Opts, Timeout, Error0) when (Timeout < 5000) -> + Sleep = random(Timeout) + 100, + d("try create tcp listen socket (~p,~p)", [Timeout, Sleep]), + case megaco_tcp:listen(Sup, Opts) of + ok -> + d("listen socket created", []), + Sup; + Error1 when Error0 =:= noError -> % Keep the first error + d("failed creating listen socket [1]: ~p", [Error1]), + sleep(Sleep), + try_start_tcp(Sup, Opts, Timeout*2, Error1); + Error2 -> + d("failed creating listen socket [2]: ~p", [Error2]), + sleep(Sleep), + try_start_tcp(Sup, Opts, Timeout*2, Error0) + end; +try_start_tcp(Sup, _Opts, _Timeout, Error) -> + megaco_tcp:stop_transport(Sup), + case Error of + {error, Reason} -> + throw({error, {failed_starting_tcp_listen, Reason}}); + _ -> + throw({error, {failed_starting_tcp_listen, Error}}) + end. + + +start_udp(TO, RH, Port, Sup) -> + d("start udp transport"), + start_udp(TO, RH, Port, Sup, 250). + +start_udp(TO, RH, Port, Sup, Timeout) -> + d("udp open ~p", [Port]), + Opts = [{port, Port}, {receive_handle, RH}] ++ TO, + try_start_udp(Sup, Opts, Timeout, noError). + +try_start_udp(Sup, Opts, Timeout, Error0) when (Timeout < 5000) -> + d("try open udp socket (~p)", [Timeout]), + case megaco_udp:open(Sup, Opts) of + {ok, _SendHandle, _ControlPid} -> + d("port opened", []), + Sup; + Error1 when Error0 =:= noError -> % Keep the first error + d("failed open port [1]: ~p", [Error1]), + sleep(Timeout), + try_start_udp(Sup, Opts, Timeout*2, Error1); + Error2 -> + d("failed open port [2]: ~p", [Error2]), + sleep(Timeout), + try_start_udp(Sup, Opts, Timeout*2, Error0) + end; +try_start_udp(Sup, _Opts, _Timeout, Error) -> + megaco_udp:stop_transport(Sup), + throw({error, {failed_starting_udp_open, Error}}). + + +%% ----------------------- +%% Handle megaco callbacks +%% + +handle_megaco_request({handle_connect, CH, _PV}, #mgc{mg = MGs} = S) -> + case lists:member(CH, MGs) of + true -> + i("MG already connected: ~n ~p", [CH]), + {error, S}; + false -> + {ok, S#mgc{mg = [CH|MGs]}} + end; + +handle_megaco_request({handle_disconnect, CH, _PV, R}, S) -> + d("handle_megaco_request(handle_disconnect) -> entry with" + "~n CH: ~p" + "~n R: ~p", [CH, R]), + CancelRes = (catch megaco:cancel(CH, R)), % Cancel the outstanding messages + d("handle_megaco_request(handle_disconnect) -> megaco cancel result: ~p", [CancelRes]), + MGs = lists:delete(CH, S#mgc.mg), + d("handle_megaco_request(handle_disconnect) -> MGs: ~p", [MGs]), + {ok, S#mgc{mg = MGs}}; + +handle_megaco_request({handle_syntax_error, _RH, _PV, _ED}, S) -> + {reply, S}; + +handle_megaco_request({handle_message_error, _CH, _PV, _ED}, S) -> + {no_reply, S}; + +handle_megaco_request({handle_trans_request, CH, PV, ARs}, + #mgc{req_info = P} = S) when is_pid(P) -> + d("handle_megaco_request(handle_trans_request,~p) -> entry", [P]), + P ! {req_received, self(), ARs}, + do_handle_trans_request(CH, PV, ARs, S); +handle_megaco_request({handle_trans_request, CH, PV, ARs}, S) -> + d("handle_megaco_request(handle_trans_request) -> entry"), + do_handle_trans_request(CH, PV, ARs, S); + +handle_megaco_request({handle_trans_long_request, CH, PV, RD}, S) -> + d("handle_megaco_request(handle_long_trans_request) -> entry"), + Reply0 = handle_act_requests(CH, PV, RD, discard_ack), + Reply = + case S of + #mgc{req_action = ignore, req_timeout = To} -> + d("handle_megaco_request(handle_long_trans_request) -> " + "~n To: ~p", [To]), + {delay_reply, To, Reply0}; + _ -> + d("handle_megaco_request(handle_long_trans_request) -> " + "~n S: ~p", [S]), + Reply0 + end, + {Reply, S}; + +handle_megaco_request({handle_trans_reply, _CH, _PV, _AR, _RD}, S) -> + {ok, S}; + +handle_megaco_request({handle_trans_ack, CH, PV, AS, AD}, + #mgc{ack_info = P} = S) when is_pid(P) -> + d("handle_megaco_request(handle_trans_ack,~p) -> entry when" + "~n CH: ~p" + "~n PV: ~p" + "~n AS: ~p" + "~n AD: ~p", [P, CH, PV, AS, AD]), + P ! {ack_received, self(), AS}, + {ok, S}; + +handle_megaco_request({handle_trans_ack, CH, PV, AS, AD}, S) -> + d("handle_megaco_request(handle_trans_ack) -> entry with" + "~n CH: ~p" + "~n PV: ~p" + "~n AS: ~p" + "~n AD: ~p", [CH, PV, AS, AD]), + {ok, S}; + +handle_megaco_request({handle_unexpected_trans, CH, PV, TR}, S) -> + d("handle_megaco_request(handle_unexpected_trans) -> entry with" + "~n CH: ~p" + "~n PV: ~p" + "~n TR: ~p", [CH, PV, TR]), + {ok, S}; + +handle_megaco_request({handle_trans_request_abort, CH, PV, TI, Handler}, S) -> + d("handle_megaco_request(handle_trans_request_abort) -> entry with" + "~n CH: ~p" + "~n PV: ~p" + "~n TI: ~p" + "~n Handler: ~p", [CH, PV, TI, Handler]), + Reply = + case S#mgc.abort_info of + P when is_pid(P) -> + P ! {abort_received, self(), TI}, + ok; + _ -> + ok + end, + {Reply, S}. + + +do_handle_trans_request(CH, PV, ARs, + #mgc{req_action = Action, req_timeout = To} = S) -> + d("do_handle_megaco_request(handle_trans_request) -> entry with" + "~n Action: ~p" + "~n To: ~p", [Action, To]), + case handle_act_requests(CH, PV, ARs, Action) of + {pending_ignore, ActReqs} -> + {{pending, ActReqs}, S#mgc{req_action = ignore}}; + Reply -> + {{delay_reply, To, Reply}, S} + end. + + +handle_act_requests(_CH, _PV, _ActReqs, ignore) -> + ignore; +handle_act_requests(_CH, _PV, ActReqs, pending) -> + {pending, ActReqs}; +handle_act_requests(_CH, _PV, ActReqs, pending_ignore) -> + {pending_ignore, ActReqs}; +handle_act_requests(CH, PV, ActReqs, handle_ack) -> + Reply = (catch do_handle_act_requests(CH, PV, ActReqs, [])), + {{handle_ack, ActReqs}, Reply}; +handle_act_requests(CH, PV, ActReqs, handle_sloppy_ack) -> + Reply = (catch do_handle_act_requests(CH, PV, ActReqs, [])), + {{handle_sloppy_ack, ActReqs}, Reply}; +handle_act_requests(CH, PV, ActReqs, _) -> + Reply = (catch do_handle_act_requests(CH, PV, ActReqs, [])), + {discard_ack, Reply}. + +do_handle_act_requests(_CH, _PV, [], ActReplies) -> + lists:reverse(ActReplies); +do_handle_act_requests(CH, PV, [ActReq|ActReqs], ActReplies) -> + ActReply = handle_act_request(CH, PV, ActReq), + do_handle_act_requests(CH, PV, ActReqs, [ActReply|ActReplies]). + +handle_act_request(CH, PV, ActReq) -> + #'ActionRequest'{contextId = CtxId, commandRequests = Cmds} = ActReq, + CmdReplies = handle_cmd_requests(CH, PV, CtxId, Cmds), + #'ActionReply'{contextId = CtxId, + commandReply = CmdReplies}. + +handle_cmd_requests(CH, PV, ?megaco_null_context_id, + [#'CommandRequest'{command={serviceChangeReq,Req}}]) -> + Rep = service_change(CH, PV, Req), + [{serviceChangeReply, Rep}]; +handle_cmd_requests(CH, PV, CtxId, Cmds) -> + do_handle_cmd_requests(CH, PV, CtxId, Cmds, []). + +do_handle_cmd_requests(_CH, _PV, _CtxId, [], CmdReplies) -> + lists:reverse(CmdReplies); +do_handle_cmd_requests(CH, PV, CtxId, [Cmd|Cmds], CmdReplies) -> + CmdReply = handle_cmd_request(CH, PV, CtxId, Cmd), + do_handle_cmd_requests(CH, PV, CtxId, Cmds, [CmdReply|CmdReplies]). + +handle_cmd_request(CH, PV, CtxId, + #'CommandRequest'{command = {Tag,Req}}) -> + case Tag of + notifyReq -> + (catch handle_notify_req(CH,PV,CtxId,Req)); + + serviceChangeReq -> + ED = cre_error_descr(?megaco_not_implemented, + "Service change only allowed " + "on null context handled"), + throw(ED); + + _ -> + Code = ?megaco_not_implemented, + ED = cre_error_descr(Code,"Unknown command requst received:" + "~n Tag: ~p~n Req: ~p",[Tag,Req]), + throw(ED) + end. + +handle_notify_req(CH, PV, CtxId, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = EvDesc}) -> + handle_event(CH, PV, CtxId, Tid, EvDesc). + +handle_event(_CH, _PV, _Cid, Tid, EvDesc) -> + d("handle_event -> received" + "~n EvDesc: ~p" + "~n Tid: ~p", [EvDesc, Tid]), + {notifyReply, cre_notifyRep(Tid)}. + + +service_change(CH, _PV, SCR) -> + SCP = SCR#'ServiceChangeRequest'.serviceChangeParms, + #'ServiceChangeParm'{serviceChangeAddress = Address, + serviceChangeProfile = Profile, + serviceChangeReason = [_Reason]} = SCP, + TermId = SCR#'ServiceChangeRequest'.terminationID, + if + TermId == [?megaco_root_termination_id] -> + MyMid = CH#megaco_conn_handle.local_mid, + Res = {serviceChangeResParms, + cre_serviceChangeResParms(MyMid, Address, Profile)}, + cre_serviceChangeReply(TermId, Res); + true -> + Res = {errorDescriptor, + cre_error_descr(?megaco_not_implemented, + "Only handled for root")}, + cre_serviceChangeReply(TermId, Res) + end. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +cre_serviceChangeReply(TermId, Result) -> + #'ServiceChangeReply'{terminationID = TermId, + serviceChangeResult = Result}. + +cre_serviceChangeResParms(Mid, Addr, Prof) -> + #'ServiceChangeResParm'{serviceChangeMgcId = Mid, + serviceChangeAddress = Addr, + serviceChangeProfile = Prof}. + + +cre_notifyRep(Tid) -> + #'NotifyReply'{terminationID = [Tid]}. + +% cre_notifyRep(Tid,Err) -> +% #'NotifyReply'{terminationID = [Tid], errorDescriptor = Err}. + +cre_error_descr(Code,Text) -> + #'ErrorDescriptor'{errorCode = Code, errorText = Text}. + +cre_error_descr(Code,FormatString,Args) -> + Text = lists:flatten(io_lib:format(FormatString,Args)), + cre_error_descr(Code,Text). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +notify_started(Parent) -> + Parent ! {started, self()}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% The megaco user callback interface + +handle_connect(CH, PV, Pid) -> + case CH#megaco_conn_handle.remote_mid of + preliminary_mid -> + %% Avoids deadlock + ok; + _ -> + Reply = request(Pid, {handle_connect, CH, PV}), + Reply + end. + +handle_disconnect(_CH, _PV, + {user_disconnect, {Pid, ignore}}, + Pid) -> + ok; +handle_disconnect(CH, _PV, + {user_disconnect, {Pid, cancel}}, + Pid) -> + megaco:cancel(CH, disconnected), + ok; +handle_disconnect(CH, PV, R, Pid) -> + request(Pid, {handle_disconnect, CH, PV, R}). + +handle_syntax_error(ReceiveHandle, ProtocolVersion, ErrorDescriptor, Pid) -> + Req = {handle_syntax_error, ReceiveHandle, ProtocolVersion, + ErrorDescriptor}, + request(Pid, Req). + +handle_message_error(ConnHandle, ProtocolVersion, ErrorDescriptor, Pid) -> + Req = {handle_message_error, ConnHandle, ProtocolVersion, ErrorDescriptor}, + request(Pid, Req). + +handle_trans_request(CH, PV, AR, Pid) -> + Reply = request(Pid, {handle_trans_request, CH, PV, AR}), + Reply. + +handle_trans_long_request(ConnHandle, ProtocolVersion, ReqData, Pid) -> + Req = {handle_trans_long_request, ConnHandle, ProtocolVersion, ReqData}, + request(Pid, Req). + +handle_trans_reply(ConnHandle, ProtocolVersion, ActualReply, ReplyData, Pid) -> + Req = {handle_trans_reply, ConnHandle, ProtocolVersion, + ActualReply, ReplyData}, + request(Pid, Req). + +handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData, Pid) -> + Req = {handle_trans_ack, ConnHandle, ProtocolVersion, AckStatus, AckData}, + request(Pid, Req). + +handle_unexpected_trans(ConnHandle, ProtocolVersion, Trans, Pid) -> + Req = {handle_unexpected_trans, ConnHandle, ProtocolVersion, Trans}, + request(Pid, Req). + +handle_trans_request_abort(ConnHandle, ProtocolVersion, TransId, + Handler, Pid) -> + Req = {handle_trans_request_abort, + ConnHandle, ProtocolVersion, TransId, Handler}, + request(Pid, Req). + + +request(Pid, Request) -> + Pid ! {request, Request, self()}, + receive + {reply, {delay_reply, To, Reply}, Pid} -> + megaco:report_event(ignore, self(), Pid, + "reply: delay_reply", [To, Reply]), + sleep(To), + megaco:report_event(ignore, self(), Pid, + "reply: delay done now return", []), + Reply; + {reply, {exit, To, Reason}, Pid} -> + megaco:report_event(ignore, self(), Pid, + "reply: exit", [To, Reason]), + sleep(To), + megaco:report_event(ignore, self(), Pid, + "reply: sleep done now exit", []), + exit(Reason); + {reply, Reply, Pid} -> + megaco:report_event(ignore, self(), Pid, "reply", [Reply]), + Reply + end. + + +reply(To, Reply) -> + To ! {reply, Reply, self()}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +sleep(X) -> + d("sleep -> ~w", [X]), + receive after X -> ok end. + + +error_msg(F,A) -> error_logger:error_msg("MGC: " ++ F ++ "~n",A). + + +get_encoding_module(RI) -> + case (catch get_conf(encoding_module, RI)) of + {error, _} -> + undefined; + Val -> + Val + end. + +get_encoding_config(RI, EM) -> + case text_codec(EM) of + true -> + case megaco:system_info(text_config) of + [Conf] when is_list(Conf) -> + Conf; + _ -> + [] + end; + + false -> + get_conf(encoding_config, RI) + end. + +text_codec(megaco_compact_text_encoder) -> + true; +text_codec(megaco_pretty_text_encoder) -> + true; +text_codec(_) -> + false. + + +get_transport_module(RI) -> + get_conf(transport_module, RI). + +get_transport_port(RI) -> + get_conf(port, RI). + +get_transport_opts(RI) -> + get_conf(transport_opts, RI, []). + + +get_conf(Key, Config) -> + case lists:keysearch(Key, 1, Config) of + {value, {Key, Val}} -> + Val; + _ -> + exit({error, {not_found, Key, Config}}) + end. + +get_conf(Key, Config, Default) -> + case lists:keysearch(Key, 1, Config) of + {value, {Key, Val}} -> + Val; + _ -> + Default + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +random_init() -> + {A,B,C} = now(), + random:seed(A,B,C). + +random(N) -> + random:uniform(N). + + +display_system_info(Mid) -> + display_system_info(Mid, ""). + +display_system_info(Mid, Pre) -> + TimeStr = format_timestamp(now()), + MibStr = lists:flatten(io_lib:format("~p ", [Mid])), + megaco_test_lib:display_system_info(MibStr ++ Pre ++ TimeStr). + + +create_timer(Time, Event) -> + erlang:send_after(Time, self(), {Event, Time}). + +cancel_timer(undefined) -> + ok; +cancel_timer(Ref) -> + erlang:cancel_timer(Ref). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +i(F) -> + i(F, []). + +i(F, A) -> + print(info, get(verbosity), "", F, A). + + +d(F) -> + d(F, []). + +d(F, A) -> + print(debug, get(verbosity), "DBG: ", F, A). + + +printable(_, debug) -> true; +printable(info, info) -> true; +printable(_,_) -> false. + +print(Severity, Verbosity, P, F, A) -> + print(printable(Severity,Verbosity), P, F, A). + +print(true, P, F, A) -> + print(P, F, A); +print(_, _, _, _) -> + ok. + +print(P, F, A) -> + io:format("*** [~s] ~s ~p ~s ***" + "~n " ++ F ++ "~n~n", + [format_timestamp(now()), P, self(), get(sname) | A]). + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). + diff --git a/lib/megaco/test/megaco_test_msg_prev3a_lib.erl b/lib/megaco/test/megaco_test_msg_prev3a_lib.erl new file mode 100644 index 0000000000..5ce2ec302b --- /dev/null +++ b/lib/megaco/test/megaco_test_msg_prev3a_lib.erl @@ -0,0 +1,7503 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Utility functions for creating the megaco types +%%---------------------------------------------------------------------- + +-module(megaco_test_msg_prev3a_lib). + +%% ---- + +-include_lib("megaco/include/megaco_message_prev3a.hrl"). +-include_lib("megaco/include/megaco.hrl"). + +%% ---- + +-export([chk_MegacoMessage/2, + cre_MegacoMessage/1, cre_MegacoMessage/2, + cre_AuthenticationHeader/3, + cre_Message/3, + cre_ErrorDescriptor/1, cre_ErrorDescriptor/2, + cre_ErrorCode/1, + cre_ErrorText/1, + cre_ContextID/1, + cre_Transaction/1, + cre_TransactionId/1, + cre_TransactionRequest/2, + cre_TransactionPending/1, + cre_TransactionReply/2, cre_TransactionReply/3, + cre_TransactionAck/1, cre_TransactionAck/2, + cre_ActionRequest/2, cre_ActionRequest/3, cre_ActionRequest/4, + cre_ActionReply/2, cre_ActionReply/3, cre_ActionReply/4, + cre_ContextRequest/0, cre_ContextRequest/1, cre_ContextRequest/2, + cre_ContextRequest/3, cre_ContextRequest/4, cre_ContextRequest/5, + cre_ContextAttrAuditRequest/0, cre_ContextAttrAuditRequest/3, + cre_ContextAttrAuditRequest/4, cre_ContextAttrAuditRequest/5, + cre_CommandRequest/1, cre_CommandRequest/2, cre_CommandRequest/3, + cre_Command/2, + cre_CommandReply/2, + cre_TopologyRequest/3, cre_TopologyRequest/4, + cre_AmmRequest/2, + cre_AmmDescriptor/1, + cre_AmmsReply/1, cre_AmmsReply/2, + cre_SubtractRequest/1, cre_SubtractRequest/2, + cre_AuditRequest/2, + cre_AuditReply/1, + cre_AuditResult/2, + cre_AuditReturnParameter/1, + cre_AuditDescriptor/0, cre_AuditDescriptor/1, cre_AuditDescriptor/2, + cre_IndAuditParameter/1, + cre_IndAudMediaDescriptor/0, cre_IndAudMediaDescriptor/1, + cre_IndAudMediaDescriptor/2, + cre_IndAudStreamDescriptor/2, + cre_IndAudStreamParms/0, cre_IndAudStreamParms/1, + cre_IndAudStreamParms/3, cre_IndAudStreamParms/4, + cre_IndAudLocalControlDescriptor/0, + cre_IndAudLocalControlDescriptor/4, + cre_IndAudPropertyParm/1, + cre_IndAudLocalRemoteDescriptor/1, + cre_IndAudLocalRemoteDescriptor/2, + cre_IndAudPropertyGroup/1, + cre_IndAudTerminationStateDescriptor/1, + cre_IndAudTerminationStateDescriptor/3, + cre_IndAudEventsDescriptor/1, cre_IndAudEventsDescriptor/2, + cre_IndAudEventsDescriptor/3, + cre_IndAudEventBufferDescriptor/1, + cre_IndAudEventBufferDescriptor/2, + cre_IndAudSignalsDescriptor/1, + cre_IndAudSeqSigList/1, + cre_IndAudSeqSigList/2, + cre_IndAudSignal/1, cre_IndAudSignal/2, + cre_IndAudDigitMapDescriptor/0, cre_IndAudDigitMapDescriptor/1, + cre_IndAudStatisticsDescriptor/1, + cre_IndAudPackagesDescriptor/2, + cre_NotifyRequest/2, cre_NotifyRequest/3, + cre_NotifyReply/1, cre_NotifyReply/2, + cre_ObservedEventsDescriptor/2, + cre_ObservedEvent/2, cre_ObservedEvent/3, cre_ObservedEvent/4, + cre_EventName/1, + cre_EventParameter/2, cre_EventParameter/4, + cre_ServiceChangeRequest/2, + cre_ServiceChangeReply/2, + cre_ServiceChangeResult/1, + %% cre_WildcardField/1, + cre_TerminationAudit/1, + cre_TerminationID/2, + cre_TerminationIDList/1, + cre_MediaDescriptor/0, cre_MediaDescriptor/1, cre_MediaDescriptor/2, + cre_StreamDescriptor/2, + cre_StreamParms/0, cre_StreamParms/1, cre_StreamParms/2, + cre_StreamParms/3, cre_StreamParms/4, + cre_LocalControlDescriptor/1, cre_LocalControlDescriptor/2, + cre_LocalControlDescriptor/4, + cre_StreamMode/1, + cre_PropertyParm/2, cre_PropertyParm/4, + cre_Name/1, + cre_PkgdName/1, + cre_PkgdName/2, + cre_Relation/1, + cre_LocalRemoteDescriptor/1, + cre_PropertyGroup/1, + cre_TerminationStateDescriptor/1, + cre_TerminationStateDescriptor/2, + cre_TerminationStateDescriptor/3, + cre_EventBufferControl/1, + cre_ServiceState/1, + cre_MuxDescriptor/2, %% cre_MuxDescriptor/3, + cre_MuxType/1, + cre_StreamID/1, + cre_EventsDescriptor/0, cre_EventsDescriptor/2, + cre_RequestedEvent/1, + cre_RequestedEvent/2, cre_RequestedEvent/3, cre_RequestedEvent/4, + cre_RequestedActions/0, + cre_RequestedActions/1, cre_RequestedActions/4, + cre_EventDM/1, + cre_SecondEventsDescriptor/1, cre_SecondEventsDescriptor/2, + cre_SecondRequestedEvent/2, cre_SecondRequestedEvent/3, + cre_SecondRequestedEvent/4, + cre_SecondRequestedActions/0, cre_SecondRequestedActions/1, + cre_SecondRequestedActions/2, cre_SecondRequestedActions/3, + cre_EventBufferDescriptor/1, + cre_EventSpec/2, + cre_EventSpec/3, + cre_SignalsDescriptor/1, + cre_SignalRequest/1, + cre_SeqSigList/2, + cre_Signal/1, cre_Signal/2, cre_Signal/7, cre_Signal/9, + cre_SignalDirection/1, + cre_SignalType/1, + cre_SignalName/1, + cre_NotifyCompletion/1, + cre_SigParameter/2, cre_SigParameter/4, + cre_RequestID/1, + cre_ModemDescriptor/2, %% cre_ModemDescriptor/3, + cre_ModemType/1, + cre_DigitMapDescriptor/0, cre_DigitMapDescriptor/1, + cre_DigitMapDescriptor/2, + cre_DigitMapName/1, + cre_DigitMapValue/1, cre_DigitMapValue/4, cre_DigitMapValue/5, + cre_ServiceChangeParm/2, cre_ServiceChangeParm/4, + cre_ServiceChangeParm/9, cre_ServiceChangeParm/10, + cre_ServiceChangeAddress/2, + cre_ServiceChangeResParm/0, cre_ServiceChangeResParm/2, + cre_ServiceChangeResParm/5, + cre_ServiceChangeMethod/1, + cre_ServiceChangeProfile/1, cre_ServiceChangeProfile/2, + cre_PackagesDescriptor/1, + cre_PackagesItem/2, + cre_StatisticsDescriptor/1, + cre_StatisticsParameter/1, cre_StatisticsParameter/2, +%% cre_NonStandardData/2, +%% cre_NonStandardIdentifier/1, +%% cre_H221NonStandard/4, + cre_TimeNotation/2, + cre_Value/1, + cre_BOOLEAN/1 + ]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +cre_MegacoMessage(M) when is_record(M, 'Message') -> + #'MegacoMessage'{mess = M}. + +cre_MegacoMessage(AH, M) + when is_record(AH, 'AuthenticationHeader') andalso + is_record(M, 'Message') -> + #'MegacoMessage'{authHeader = AH, + mess = M}. + +cre_AuthenticationHeader(SPI, SN, AD) -> + #'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AD}. + +cre_Message(V, Mid, ED) when is_record(ED, 'ErrorDescriptor') -> + Body = {errorDescriptor, ED}, + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, Transactions) when is_list(Transactions) -> + Body = {transactions, Transactions}, + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, {transactions, T} = Body) when is_list(T) -> + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, {errorDescriptor, ED} = Body) + when is_record(ED, 'ErrorDescriptor') -> + #'Message'{version = V, + mId = Mid, + messageBody = Body}. + + +cre_ErrorDescriptor(EC) when is_integer(EC) -> + #'ErrorDescriptor'{errorCode = EC}. + +cre_ErrorDescriptor(EC, ET) when is_integer(EC) andalso is_list(ET) -> + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + +cre_ErrorCode(C) when is_integer(C) andalso (0 =< C) andalso (C =< 65535) -> + C; +cre_ErrorCode(C) -> + exit({invalid_ErrorCode, C}). + +cre_ErrorText(T) when is_list(T) -> + T. + +cre_ContextID(Val) when 0 =< Val, Val =< 4294967295 -> + Val; +cre_ContextID(Val) -> + exit({invalid_ContextID, Val}). + +cre_Transaction(TR) when is_record(TR, 'TransactionRequest') -> + {transactionRequest, TR}; +cre_Transaction(TP) when is_record(TP, 'TransactionPending') -> + {transactionPending, TP}; +cre_Transaction(TR) when is_record(TR, 'TransactionReply') -> + {transactionReply, TR}; +cre_Transaction(TRA) when is_list(TRA) -> + {transactionResponseAck, TRA}. + +cre_TransactionId(Val) when (0 =< Val) andalso (Val =< 4294967295) -> + Val; +cre_TransactionId(Val) -> + exit({invalid_TransactionId, Val}). + +cre_TransactionRequest(TransID, ARs) when is_integer(TransID) andalso is_list(ARs) -> + #'TransactionRequest'{transactionId = TransID, + actions = ARs}. + +cre_TransactionPending(TransID) when is_integer(TransID) -> + #'TransactionPending'{transactionId = TransID}. + +cre_TransactionReply(TransID, ED) + when is_integer(TransID) andalso is_record(ED, 'ErrorDescriptor') -> + Res = {transactionError, ED}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}; +cre_TransactionReply(TransID, ARs) + when is_integer(TransID) andalso is_list(ARs) -> + Res = {actionReplies, ARs}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}. + +cre_TransactionReply(TransID, IAR, ED) + when is_integer(TransID) and + ((IAR == 'NULL') or (IAR == asn1_NOVALUE)) and + is_record(ED, 'ErrorDescriptor') -> + Res = {transactionError, ED}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}; +cre_TransactionReply(TransID, IAR, ARs) + when is_integer(TransID) and + ((IAR == 'NULL') or (IAR == asn1_NOVALUE)) and + is_list(ARs) -> + Res = {actionReplies, ARs}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}. + +cre_TransactionAck(FirstAck) -> + #'TransactionAck'{firstAck = FirstAck}. + +cre_TransactionAck(FirstAck, FirstAck) -> + #'TransactionAck'{firstAck = FirstAck}; +cre_TransactionAck(FirstAck, LastAck) -> + #'TransactionAck'{firstAck = FirstAck, + lastAck = LastAck}. + +cre_ActionRequest(CtxID, CmdReqs) + when is_integer(CtxID) and is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + commandRequests = CmdReqs}. + +cre_ActionRequest(CtxID, CtxReq, CmdReqs) + when is_integer(CtxID) and + is_record(CtxReq, 'ContextRequest') and + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextRequest = CtxReq, + commandRequests = CmdReqs}; +cre_ActionRequest(CtxID, CAAR, CmdReqs) + when is_integer(CtxID) and + is_record(CAAR, 'ContextAttrAuditRequest') and + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextAttrAuditReq = CAAR, + commandRequests = CmdReqs}. + +cre_ActionRequest(CtxID, CtxReq, CAAR, CmdReqs) + when is_integer(CtxID) and + (is_record(CtxReq, 'ContextRequest') or + (CtxReq == asn1_NOVALUE)) and + (is_record(CAAR, 'ContextAttrAuditRequest') or + (CAAR == asn1_NOVALUE)) and + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextRequest = CtxReq, + contextAttrAuditReq = CAAR, + commandRequests = CmdReqs}. + +cre_ActionReply(CtxID, CmdReps) + when is_integer(CtxID) andalso + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + commandReply = CmdReps}. + +cre_ActionReply(CtxID, ED, CmdReps) + when is_integer(CtxID) andalso + is_record(ED, 'ErrorDescriptor') andalso + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + errorDescriptor = ED, + commandReply = CmdReps}; +cre_ActionReply(CtxID, CtxReq, CmdReps) + when is_integer(CtxID) andalso + is_record(CtxReq, 'ContextRequest') andalso + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + contextReply = CtxReq, + commandReply = CmdReps}. + +cre_ActionReply(CtxID, ED, CtxReq, CmdReps) + when is_integer(CtxID) andalso + (is_record(ED, 'ErrorDescriptor') orelse (ED =:= asn1_NOVALUE)) andalso + (is_record(CtxReq, 'ContextRequest') orelse (CtxReq =:= asn1_NOVALUE)) andalso + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + errorDescriptor = ED, + contextReply = CtxReq, + commandReply = CmdReps}. + +cre_ContextRequest() -> + strip_ContextRequest(#'ContextRequest'{}). + +cre_ContextRequest(Prio) when is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15) -> + strip_ContextRequest(#'ContextRequest'{priority = Prio}); +cre_ContextRequest(Em) when (Em =:= true) orelse (Em =:= false) orelse (Em =:= asn1_NOVALUE) -> + strip_ContextRequest(#'ContextRequest'{emergency = Em}); +cre_ContextRequest(Top) when is_list(Top) -> + strip_ContextRequest(#'ContextRequest'{topologyReq = Top}). + +cre_ContextRequest(Prio, Em) + when (is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em}, + strip_ContextRequest(CR); +cre_ContextRequest(Prio, Top) + when is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15) andalso is_list(Top) -> + CR = #'ContextRequest'{priority = Prio, + topologyReq = Top}, + strip_ContextRequest(CR). + +cre_ContextRequest(Prio, Em, Top) + when (is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) and + (is_list(Top) or (Top == asn1_NOVALUE)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top}, + strip_ContextRequest(CR). + +cre_ContextRequest(Prio, Em, Top, Ieps) + when (is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) and + (is_list(Top) or (Top == asn1_NOVALUE)) and + ((Ieps == true) or (Ieps == false)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + iepsCallind = Ieps}, + strip_ContextRequest(CR); +cre_ContextRequest(Prio, Em, Top, Ctx) + when ((is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) or + (Prio == asn1_NOVALUE)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) and + (is_list(Top) or (Top == asn1_NOVALUE)) and + (is_list(Ctx)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + contextProp = Ctx}, + strip_ContextRequest(CR). + +cre_ContextRequest(Prio, Em, Top, Ieps, Ctx) + when ((is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) or + (Prio == asn1_NOVALUE)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) and + (is_list(Top) or (Top == asn1_NOVALUE)) and + ((Ieps == true) or (Ieps == false) or (Ieps == asn1_NOVALUE)) and + (is_list(Ctx) or (Ctx == asn1_NOVALUE)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + iepsCallind = Ieps, + contextProp = Ctx}, + strip_ContextRequest(CR). + +strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE, + emergency = asn1_NOVALUE, + topologyReq = asn1_NOVALUE, + iepsCallind = asn1_NOVALUE, + contextProp = asn1_NOVALUE}) -> + asn1_NOVALUE; +strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE, + emergency = asn1_NOVALUE, + topologyReq = Top, + iepsCallind = Ieps, + contextProp = Prop} = CR) -> + case (((Top == []) or (Top == asn1_NOVALUE)) and + ((Ieps == false) or (Ieps == asn1_NOVALUE)) and + ((Prop == []) or (Prop == asn1_NOVALUE))) of + true -> + asn1_NOVALUE; + false -> + CR + end; +strip_ContextRequest(CR) -> + CR. + +cre_ContextAttrAuditRequest() -> + strip_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{}). + +cre_ContextAttrAuditRequest(Top, Em, Prio) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio}, + strip_ContextAttrAuditRequest(CAAR). + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) and + ((Ieps == 'NULL') or (Ieps == asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepsCallind = Ieps}, + strip_ContextAttrAuditRequest(CAAR). + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) and + ((Ieps == 'NULL') or (Ieps == asn1_NOVALUE)) and + (is_list(Ctx) or (Ctx == asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepsCallind = Ieps, + contextPropAud = Ctx}, + strip_ContextAttrAuditRequest(CAAR). + +strip_ContextAttrAuditRequest( + #'ContextAttrAuditRequest'{topology = asn1_NOVALUE, + emergency = asn1_NOVALUE, + priority = asn1_NOVALUE, + iepsCallind = asn1_NOVALUE, + contextPropAud = asn1_NOVALUE}) -> + asn1_NOVALUE; +strip_ContextAttrAuditRequest( + #'ContextAttrAuditRequest'{topology = asn1_NOVALUE, + emergency = asn1_NOVALUE, + priority = asn1_NOVALUE, + iepsCallind = asn1_NOVALUE, + contextPropAud = []}) -> + asn1_NOVALUE; +strip_ContextAttrAuditRequest(CAAR) -> + CAAR. + +cre_CommandRequest(Cmd) -> + #'CommandRequest'{command = Cmd}. + +cre_CommandRequest(Cmd, Opt) + when ((Opt == 'NULL') or (Opt == asn1_NOVALUE)) -> + #'CommandRequest'{command = Cmd, + optional = Opt}. + +cre_CommandRequest(Cmd, Opt, WR) + when ((Opt == 'NULL') or (Opt == asn1_NOVALUE)) and + ((WR == 'NULL') or (WR == asn1_NOVALUE)) -> + #'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = WR}. + +cre_Command(addReq = Tag, Req) + when is_record(Req, 'AmmRequest') -> + {Tag, Req}; +cre_Command(moveReq = Tag, Req) + when is_record(Req, 'AmmRequest') -> + {Tag, Req}; +cre_Command(modReq = Tag, Req) + when is_record(Req, 'AmmRequest') -> + {Tag, Req}; +cre_Command(subtractReq = Tag, Req) + when is_record(Req, 'SubtractRequest') -> + {Tag, Req}; +cre_Command(auditCapRequest = Tag, Req) + when is_record(Req, 'AuditRequest') -> + {Tag, Req}; +cre_Command(auditValueRequest = Tag, Req) + when is_record(Req, 'AuditRequest') -> + {Tag, Req}; +cre_Command(notifyReq = Tag, Req) + when is_record(Req, 'NotifyRequest') -> + {Tag, Req}; +cre_Command(serviceChangeReq = Tag, Req) + when is_record(Req, 'ServiceChangeRequest') -> + {Tag, Req}. + +cre_CommandReply(addReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(moveReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(modReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(subtractReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(auditCapReply = Tag, Rep) + when is_tuple(Rep) -> + {Tag, Rep}; +cre_CommandReply(auditValueReply = Tag, Rep) + when is_tuple(Rep) -> + {Tag, Rep}; +cre_CommandReply(notifyReply = Tag, Rep) + when is_record(Rep, 'NotifyReply') -> + {Tag, Rep}; +cre_CommandReply(serviceChangeReply = Tag, Rep) + when is_record(Rep, 'ServiceChangeReply') -> + {Tag, Rep}. + +cre_TopologyRequest(From, To, Dir) + when (is_record(From, 'TerminationID') or + is_record(From, megaco_term_id)) and + (is_record(To, 'TerminationID') or + is_record(To, megaco_term_id)) and + ((Dir == bothway) or (Dir == isolate) or (Dir == oneway)) -> + #'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = Dir}. + +cre_TopologyRequest(From, To, Dir, SID) + when (is_record(From, 'TerminationID') or + is_record(From, megaco_term_id)) and + (is_record(To, 'TerminationID') or + is_record(To, megaco_term_id)) and + ((Dir == bothway) or (Dir == isolate) or (Dir == oneway)) and + (is_integer(SID) or (SID == asn1_NOVALUE)) -> + #'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = Dir, + streamID = SID}. + +cre_AmmRequest(TermIDs, Descs) -> + d("cre_AmmRequest -> entry with" + "~n TermIDs: ~p" + "~n Descs: ~p", [TermIDs, Descs]), + case is_TerminationIDList(TermIDs) andalso + is_AmmRequest_descriptors(Descs) of + true -> + #'AmmRequest'{terminationID = TermIDs, + descriptors = Descs}; + false -> + error({invalid_AmmRequest, {TermIDs, Descs}}) + end. + +cre_AmmDescriptor(D) when is_record(D, 'MediaDescriptor') -> + {mediaDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'ModemDescriptor') -> + {modemDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'MuxDescriptor') -> + {muxDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'EventsDescriptor') -> + {eventsDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'DigitMapDescriptor') -> + {digitMapDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'AuditDescriptor') -> + {auditDescriptor, D}; +cre_AmmDescriptor(D) when is_list(D) -> + case is_EventBufferDescriptor(D) of + true -> + {eventBufferDescriptor, D}; + false -> + case is_SignalsDescriptor(D) of + true -> + {signalsDescriptor, D}; + false -> + case is_StatisticsDescriptor(D) of + true -> + {statisticsDescriptor, D}; + false -> + error({invalid_AmmDescriptor, D}) + end + end + end. + +cre_AmmsReply(TermIDs) when is_list(TermIDs) -> + #'AmmsReply'{terminationID = TermIDs}. + +cre_AmmsReply(TermIDs, TAs) when is_list(TermIDs) andalso is_list(TAs) -> + #'AmmsReply'{terminationID = TermIDs, + terminationAudit = TAs}. + +cre_SubtractRequest(TermIDs) when is_list(TermIDs) -> + #'SubtractRequest'{terminationID = TermIDs}. + +cre_SubtractRequest(TermIDs, Audit) + when is_list(TermIDs) andalso is_record(Audit, 'AuditDescriptor') -> + #'SubtractRequest'{terminationID = TermIDs, + auditDescriptor = Audit}. + +cre_AuditRequest(TermID, Audit) + when is_record(TermID, megaco_term_id) andalso is_record(Audit, 'AuditDescriptor') -> + #'AuditRequest'{terminationID = TermID, + auditDescriptor = Audit}. + +cre_AuditReply(TermIDs) when is_list(TermIDs) -> + {contextAuditResult, TermIDs}; +cre_AuditReply(ED) when is_record(ED, 'ErrorDescriptor') -> + {error, ED}; +cre_AuditReply(Audit) when is_record(Audit, 'AuditResult') -> + {auditResult, Audit}. + +cre_AuditResult(TermID, TAs) + when is_record(TermID, megaco_term_id) andalso is_list(TAs) -> + #'AuditResult'{terminationID = TermID, + terminationAuditResult = TAs}. + +cre_TerminationAudit(D) -> + true = is_TerminationAudit(D), + D. + +cre_AuditReturnParameter(D) when is_record(D, 'ErrorDescriptor') -> + {errorDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'MediaDescriptor') -> + {mediaDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'ModemDescriptor') -> + {modemDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'MuxDescriptor') -> + {muxDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'EventsDescriptor') -> + {eventsDescriptor, D}; +cre_AuditReturnParameter([H|_] = D) when is_record(H, 'EventSpec') -> + {eventBufferDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'DigitMapDescriptor') -> + {digitMapDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'ObservedEventsDescriptor') -> + {observedEventsDescriptor, D}; +cre_AuditReturnParameter([H|_] = D) when is_record(H, 'StatisticsParameter') -> + {statisticsDescriptor, D}; +cre_AuditReturnParameter([H|_] = D) when is_record(H, 'PackagesItem') -> + {packagesDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'AuditDescriptor') -> + {emptyDescriptors, D}; +cre_AuditReturnParameter([H|_] = D) when is_tuple(H) -> + {signalsDescriptor, D}. + +cre_AuditDescriptor() -> + #'AuditDescriptor'{}. + +cre_AuditDescriptor([H|_] = AT) when is_atom(H) -> + #'AuditDescriptor'{auditToken = AT}; +cre_AuditDescriptor(APT) -> + #'AuditDescriptor'{auditPropertyToken = APT}. + +cre_AuditDescriptor(AT, APT) -> + #'AuditDescriptor'{auditToken = AT, + auditPropertyToken = APT}. + +cre_IndAuditParameter(D) when is_record(D, 'IndAudMediaDescriptor') -> + {indAudMediaDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudEventsDescriptor') -> + {indAudEventsDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudEventBufferDescriptor') -> + {indAudEventBufferDescriptor, D}; +cre_IndAuditParameter({signal, _} = D) -> + {indAudSignalsDescriptor, D}; +cre_IndAuditParameter({seqSigList, _} = D) -> + {indAudSignalsDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudDigitMapDescriptor') -> + {indAudDigitMapDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudStatisticsDescriptor') -> + {indAudStatisticsDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudPackagesDescriptor') -> + {indAudPackagesDescriptor, D}. + +cre_IndAudMediaDescriptor() -> + #'IndAudMediaDescriptor'{}. + +cre_IndAudMediaDescriptor(TSD) + when is_record(TSD, 'IndAudTerminationStateDescriptor') -> + #'IndAudMediaDescriptor'{termStateDescr = TSD}; +cre_IndAudMediaDescriptor(Parms) when is_record(Parms, 'IndAudStreamParms') -> + Streams = {oneStream, Parms}, + #'IndAudMediaDescriptor'{streams = Streams}; +cre_IndAudMediaDescriptor(Descs) when is_list(Descs) -> + Streams = {multiStream, Descs}, + #'IndAudMediaDescriptor'{streams = Streams}. + +cre_IndAudMediaDescriptor(TSD, Parms) + when is_record(TSD, 'IndAudTerminationStateDescriptor') andalso + is_record(Parms, 'IndAudStreamParms') -> + Streams = {oneStream, Parms}, + #'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = Streams}; +cre_IndAudMediaDescriptor(TSD, Descs) + when is_record(TSD, 'IndAudTerminationStateDescriptor') andalso is_list(Descs) -> + Streams = {multiStream, Descs}, + #'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = Streams}. + +cre_IndAudStreamDescriptor(SID, Parms) + when is_integer(SID) andalso is_record(Parms, 'IndAudStreamParms') -> + #'IndAudStreamDescriptor'{streamID = SID, + streamParms = Parms}. + +cre_IndAudStreamParms() -> + #'IndAudStreamParms'{}. + +cre_IndAudStreamParms(LCD) when is_record(LCD, 'IndAudLocalControlDescriptor') -> + #'IndAudStreamParms'{localControlDescriptor = LCD}; +cre_IndAudStreamParms(SD) when is_record(SD, 'IndAudStatisticsDescriptor') -> + #'IndAudStreamParms'{statisticsDescriptor = SD}. + +cre_IndAudStreamParms(LC, L, R) + when is_record(LC, 'IndAudLocalControlDescriptor') andalso + is_record(L, 'IndAudLocalRemoteDescriptor') andalso + is_record(R, 'IndAudLocalRemoteDescriptor') -> + #'IndAudStreamParms'{localControlDescriptor = LC, + localDescriptor = L, + remoteDescriptor = R}. + +cre_IndAudStreamParms(LC, L, R, S) + when is_record(LC, 'IndAudLocalControlDescriptor') andalso + is_record(L, 'IndAudLocalRemoteDescriptor') andalso + is_record(R, 'IndAudLocalRemoteDescriptor') andalso + is_record(S, 'IndAudStatisticsDescriptor') -> + #'IndAudStreamParms'{localControlDescriptor = LC, + localDescriptor = L, + remoteDescriptor = R, + statisticsDescriptor = S}. + +cre_IndAudLocalControlDescriptor() -> + #'IndAudLocalControlDescriptor'{}. + +cre_IndAudLocalControlDescriptor(SM, RV, RG, PP) + when ((SM == 'NULL') or (SM == asn1_NOVALUE)) and + ((RV == 'NULL') or (RV == asn1_NOVALUE)) and + ((RG == 'NULL') or (RG == asn1_NOVALUE)) and + (is_list(PP) or (PP == asn1_NOVALUE)) -> + #'IndAudLocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP}. + +cre_IndAudPropertyParm(PkgdName) when is_list(PkgdName) -> + #'IndAudPropertyParm'{name = PkgdName}. + +cre_IndAudLocalRemoteDescriptor(Grps) + when is_list(Grps) -> + #'IndAudLocalRemoteDescriptor'{propGrps = Grps}. + +cre_IndAudLocalRemoteDescriptor(GrpID, Grps) + when is_integer(GrpID) andalso (0 =< GrpID) andalso (GrpID =< 65535) andalso is_list(Grps) -> + #'IndAudLocalRemoteDescriptor'{propGroupID = GrpID, + propGrps = Grps}. + +cre_IndAudPropertyGroup([]) -> + []; +cre_IndAudPropertyGroup([H|_] = PG) + when is_record(H, 'IndAudPropertyParm') -> + PG. + +cre_IndAudTerminationStateDescriptor([] = PP) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP}; +cre_IndAudTerminationStateDescriptor([H|_] = PP) + when is_record(H, 'IndAudPropertyParm') -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP}. + +cre_IndAudTerminationStateDescriptor([] = PP, EBC, SS) + when ((EBC == 'NULL') or (EBC == asn1_NOVALUE)) and + ((SS == 'NULL') or (SS == asn1_NOVALUE)) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS}; +cre_IndAudTerminationStateDescriptor([H|_] = PP, EBC, SS) + when is_record(H, 'IndAudPropertyParm') and + ((EBC == 'NULL') or (EBC == asn1_NOVALUE)) and + ((SS == 'NULL') or (SS == asn1_NOVALUE)) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS}. + +cre_IndAudEventsDescriptor(PkgdName) + when is_list(PkgdName) -> + #'IndAudEventsDescriptor'{pkgdName = PkgdName}. + +cre_IndAudEventsDescriptor(RID, PkgdName) + when is_integer(RID) andalso is_list(PkgdName) -> + #'IndAudEventsDescriptor'{requestID = RID, pkgdName = PkgdName}; +cre_IndAudEventsDescriptor(PkgdName, SID) + when is_list(PkgdName) andalso is_integer(SID) -> + #'IndAudEventsDescriptor'{pkgdName = PkgdName, streamID = SID}. + +cre_IndAudEventsDescriptor(RID, PkgdName, SID) + when is_integer(RID) andalso is_list(PkgdName) andalso is_integer(SID) -> + #'IndAudEventsDescriptor'{requestID = RID, + pkgdName = PkgdName, + streamID = SID}. + +cre_IndAudEventBufferDescriptor(EventName) when is_list(EventName) -> + #'IndAudEventBufferDescriptor'{eventName = EventName}. + +cre_IndAudEventBufferDescriptor(EventName, SID) + when is_list(EventName) andalso is_integer(SID) -> + #'IndAudEventBufferDescriptor'{eventName = EventName, streamID = SID}. + +cre_IndAudSignalsDescriptor(S) when is_record(S, 'IndAudSignal') -> + {signal, S}; +cre_IndAudSignalsDescriptor(S) when is_record(S, 'IndAudSeqSigList') -> + {seqSigList, S}. + +cre_IndAudSeqSigList(ID) when is_integer(ID) andalso (0=< ID) andalso (ID =< 65535) -> + #'IndAudSeqSigList'{id = ID}. + +cre_IndAudSeqSigList(ID, S) + when is_integer(ID) andalso (0=< ID) andalso (ID =< 65535) andalso is_record(S, 'IndAudSignal') -> + #'IndAudSeqSigList'{id = ID, signalList = S}. + +cre_IndAudSignal(SigName) when is_list(SigName) -> + #'IndAudSignal'{signalName = SigName}. + +cre_IndAudSignal(SigName, SID) when is_list(SigName) andalso is_integer(SID) -> + #'IndAudSignal'{signalName = SigName, streamID = SID}. + +cre_IndAudDigitMapDescriptor() -> + #'IndAudDigitMapDescriptor'{}. + +cre_IndAudDigitMapDescriptor(DMN) when is_list(DMN) -> + #'IndAudDigitMapDescriptor'{digitMapName = DMN}. + +cre_IndAudStatisticsDescriptor(StatName) when is_list(StatName) -> + #'IndAudStatisticsDescriptor'{statName = StatName}. + +cre_IndAudPackagesDescriptor(N, V) + when is_list(N) andalso + is_integer(V) andalso (0 =< V) andalso (V =< 99) -> + #'IndAudPackagesDescriptor'{packageName = N, + packageVersion = V}. + +cre_NotifyRequest(TermIDs, D) + when is_list(TermIDs) andalso is_record(D, 'ObservedEventsDescriptor') -> + #'NotifyRequest'{terminationID = TermIDs, + observedEventsDescriptor = D}. + +cre_NotifyRequest(TermIDs, D, ED) + when is_list(TermIDs) andalso + is_record(D, 'ObservedEventsDescriptor') andalso + is_record(ED, 'ErrorDescriptor') -> + #'NotifyRequest'{terminationID = TermIDs, + observedEventsDescriptor = D, + errorDescriptor = ED}. + +cre_NotifyReply(TermIDs) when is_list(TermIDs) -> + #'NotifyReply'{terminationID = TermIDs}. + +cre_NotifyReply(TermIDs, ED) + when is_list(TermIDs) andalso + is_record(ED, 'ErrorDescriptor') -> + #'NotifyReply'{terminationID = TermIDs, + errorDescriptor = ED}. + +cre_ObservedEventsDescriptor(RID, [H|_] = L) + when is_integer(RID) andalso is_record(H, 'ObservedEvent') -> + #'ObservedEventsDescriptor'{requestId = RID, + observedEventLst = L}. + +cre_ObservedEvent(EN, EPL) when is_list(EN) andalso is_list(EPL) -> + #'ObservedEvent'{eventName = EN, + eventParList = EPL}; +cre_ObservedEvent(EN, TN) when is_list(EN) andalso is_record(TN, 'TimeNotation') -> + #'ObservedEvent'{eventName = EN, + timeNotation = TN}. + +cre_ObservedEvent(EN, SID, EPL) when is_list(EN) andalso is_integer(SID) andalso is_list(EPL) -> + #'ObservedEvent'{eventName = EN, + streamID = SID, + eventParList = EPL}; +cre_ObservedEvent(EN, EPL, TN) + when is_list(EN) andalso is_list(EPL) andalso is_record(TN, 'TimeNotation') -> + #'ObservedEvent'{eventName = EN, + eventParList = EPL, + timeNotation = TN}. + +cre_ObservedEvent(EN, SID, EPL, TN) + when is_list(EN) andalso + is_integer(SID) andalso + is_list(EPL) andalso + is_record(TN, 'TimeNotation') -> + #'ObservedEvent'{eventName = EN, + streamID = SID, + eventParList = EPL, + timeNotation = TN}. + +cre_EventName(N) when is_list(N) -> + N. + +cre_EventParameter(N, V) + when is_list(N) andalso + is_list(V) -> + #'EventParameter'{eventParameterName = N, + value = V}. + +cre_EventParameter(N, V, relation = Tag, R) + when is_list(N) andalso + is_list(V) andalso + is_atom(R) -> + EI = {Tag, R}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}; +cre_EventParameter(N, V, range = Tag, B) + when is_list(N) andalso + is_list(V) andalso + is_atom(B) -> + EI = {Tag, B}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}; +cre_EventParameter(N, V, sublist = Tag, B) + when is_list(N) andalso + is_list(V) andalso + is_atom(B) -> + EI = {Tag, B}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}. + +cre_ServiceChangeRequest(TermIDs, SCP) + when is_list(TermIDs) andalso + is_record(SCP, 'ServiceChangeParm') -> + #'ServiceChangeRequest'{terminationID = TermIDs, + serviceChangeParms = SCP}. + +cre_ServiceChangeReply(TermIDs, {Tag, R} = SCR) + when is_list(TermIDs) andalso + is_atom(Tag) andalso + is_tuple(R) -> + #'ServiceChangeReply'{terminationID = TermIDs, + serviceChangeResult = SCR}. + +cre_ServiceChangeResult(ED) when is_record(ED, 'ErrorDescriptor') -> + {errorDescriptor, ED}; +cre_ServiceChangeResult(SCRP) when is_record(SCRP, 'ServiceChangeResParm') -> + {serviceChangeResParms, SCRP}. + +%% cre_WildcardField(L) when list(L), length(L) == 1 -> L. + +cre_TerminationID(W, ID) + when is_list(W) andalso + is_list(ID) andalso + (1 =< length(ID)) andalso + (length(ID) =< 8) -> + #'TerminationID'{wildcard = W, + id = ID}. + +cre_TerminationIDList(L) when is_list(L) -> + L. + +cre_MediaDescriptor() -> + #'MediaDescriptor'{}. + +cre_MediaDescriptor(TSD) when is_record(TSD, 'TerminationStateDescriptor') -> + #'MediaDescriptor'{termStateDescr = TSD}; +cre_MediaDescriptor(SP) when is_record(SP, 'StreamParms') -> + Streams = {oneStream, SP}, + #'MediaDescriptor'{streams = Streams}; +cre_MediaDescriptor([H|_] = SDs) when is_record(H, 'StreamDescriptor') -> + Streams = {multiStream, SDs}, + #'MediaDescriptor'{streams = Streams}. + +cre_MediaDescriptor(TSD, SP) + when is_record(TSD, 'TerminationStateDescriptor') andalso + is_record(SP, 'StreamParms') -> + Streams = {oneStream, SP}, + #'MediaDescriptor'{termStateDescr = TSD, + streams = Streams}; +cre_MediaDescriptor(TSD, [H|_] = SDs) + when is_record(TSD, 'TerminationStateDescriptor') andalso + is_record(H, 'StreamDescriptor') -> + Streams = {multiStream, SDs}, + #'MediaDescriptor'{termStateDescr = TSD, + streams = Streams}. + +cre_StreamDescriptor(SID, SP) when is_integer(SID) andalso is_record(SP, 'StreamParms') -> + #'StreamDescriptor'{streamID = SID, + streamParms = SP}. + +cre_StreamParms() -> + #'StreamParms'{}. + +cre_StreamParms(LCD) when is_record(LCD, 'LocalControlDescriptor') -> + #'StreamParms'{localControlDescriptor = LCD}; +cre_StreamParms(LD) when is_record(LD, 'LocalRemoteDescriptor') -> + #'StreamParms'{localDescriptor = LD}; +cre_StreamParms(SD) when is_list(SD) -> + #'StreamParms'{statisticsDescriptor = SD}. + +cre_StreamParms(LCD, LD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD}. + +cre_StreamParms(LCD, LD, RD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) and + (is_record(RD, 'LocalRemoteDescriptor') or (RD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD}; +cre_StreamParms(LCD, LD, SD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + statisticsDescriptor = SD}. + +cre_StreamParms(LCD, LD, RD, SD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) and + (is_record(RD, 'LocalRemoteDescriptor') or (RD == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}. + +cre_LocalControlDescriptor(SM) when is_atom(SM) -> + #'LocalControlDescriptor'{streamMode = SM, propertyParms = []}; +cre_LocalControlDescriptor([H|_] = PP) when is_record(H, 'PropertyParm') -> + #'LocalControlDescriptor'{propertyParms = PP}. + +cre_LocalControlDescriptor(SM, [H|_] = PP) + when is_atom(SM) andalso is_record(H, 'PropertyParm') -> + #'LocalControlDescriptor'{streamMode = SM, + propertyParms = PP}. + +cre_LocalControlDescriptor(SM, RV, RG, [H|_] = PP) + when is_atom(SM) and + ((RV == true) or (RV == false) or (RV == asn1_NOVALUE)) and + ((RG == true) or (RG == false) or (RG == asn1_NOVALUE)) and + is_record(H, 'PropertyParm') -> + #'LocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP}. + +cre_StreamMode(sendOnly = M) -> + M; +cre_StreamMode(recvOnly = M) -> + M; +cre_StreamMode(sendRecv = M) -> + M; +cre_StreamMode(inactive = M) -> + M; +cre_StreamMode(loopBack = M) -> + M. + +cre_PropertyParm(N, [H|_] = V) when is_list(N) andalso is_list(H) -> + #'PropertyParm'{name = N, value = V}. + +cre_PropertyParm(N, [H|_] = V, relation = Tag, R) + when is_list(N) andalso is_list(H) andalso is_atom(R) -> + EI = {Tag, R}, + #'PropertyParm'{name = N, value = V, extraInfo = EI}; +cre_PropertyParm(N, [H|_] = V, range = Tag, B) + when is_list(N) andalso is_list(H) andalso is_atom(B) -> + EI = {Tag, B}, + #'PropertyParm'{name = N, value = V, extraInfo = EI}; +cre_PropertyParm(N, [H|_] = V, sublist = Tag, B) + when is_list(N) andalso is_list(H) andalso is_atom(B) -> + EI = {Tag, B}, + #'PropertyParm'{name = N, value = V, extraInfo = EI}. + + +cre_Name(N) when is_list(N) and (length(N) == 2) -> + N. + +cre_PkgdName(N) when is_list(N) -> + case string:tokens(N, [$\\]) of + [_PkgName, _ItemID] -> + N; + _ -> + error({invalid_PkgdName, N}) + end. +cre_PkgdName(root, root) -> + "*/*"; +cre_PkgdName(PackageName, root) + when is_list(PackageName) and (length(PackageName) =< 64) -> + PackageName ++ "/*"; +cre_PkgdName(PackageName, ItemID) + when ((is_list(PackageName) and (length(PackageName) =< 64)) and + (is_list(ItemID) and (length(ItemID) =< 64))) -> + PackageName ++ "/" ++ ItemID; +cre_PkgdName(PackageName, ItemID) -> + error({invalid_PkgdName, {PackageName, ItemID}}). + +cre_Relation(greaterThan = R) -> + R; +cre_Relation(smallerThan = R) -> + R; +cre_Relation(unequalTo = R) -> + R. + +cre_LocalRemoteDescriptor([H|_] = PGs) when is_list(H) -> + #'LocalRemoteDescriptor'{propGrps = PGs}. + +cre_PropertyGroup([H|_] = PG) when is_record(H, 'PropertyParm') -> + PG. + +cre_TerminationStateDescriptor([H|_] = PPs) when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs}. + +cre_TerminationStateDescriptor([H|_] = PPs, off = EBC) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + eventBufferControl = EBC}; +cre_TerminationStateDescriptor([H|_] = PPs, lockStep = EBC) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + eventBufferControl = EBC}; +cre_TerminationStateDescriptor([H|_] = PPs, test = SS) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + serviceState = SS}; +cre_TerminationStateDescriptor([H|_] = PPs, outOfSvc = SS) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + serviceState = SS}; +cre_TerminationStateDescriptor([H|_] = PPs, inSvc = SS) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + serviceState = SS}. + +cre_TerminationStateDescriptor([H|_] = PPs, EMC, SS) + when is_record(H, 'PropertyParm') andalso + ((EMC == off) or (EMC == lockStep)) and + ((SS == test) or (SS == outOfSvc) or (SS == inSvc)) -> + #'TerminationStateDescriptor'{propertyParms = PPs, + eventBufferControl = EMC, + serviceState = SS}. + +cre_EventBufferControl(off = EBC) -> + EBC; +cre_EventBufferControl(lockStep = EBC) -> + EBC. + +cre_ServiceState(test = SS) -> + SS; +cre_ServiceState(outOfSvc = SS) -> + SS; +cre_ServiceState(inSvc = SS) -> + SS. + +cre_MuxDescriptor(MT, [H|_] = TL) + when is_atom(MT) andalso is_record(H, 'TerminationID') -> + #'MuxDescriptor'{muxType = MT, termList = TL}. + +%% cre_MuxDescriptor(MT, [H|_] = TL, NSD) +%% when atom(MT), record(H, 'TerminationID'), record(NSD, 'NonStandardData') -> +%% #'MuxDescriptor'{muxType = MT, termList = TL, nonStandardData = NSD}. + +cre_MuxType(h221 = MT) -> + MT; +cre_MuxType(h223 = MT) -> + MT; +cre_MuxType(h226 = MT) -> + MT; +cre_MuxType(v76 = MT) -> + MT; +cre_MuxType(nx64k = MT) -> + MT. + +cre_StreamID(Val) when (0 =< Val) andalso (Val =< 65535) -> + Val; +cre_StreamID(Val) -> + exit({invalid_ContextID, Val}). + +%% RequestID must be present if eventList is non empty +cre_EventsDescriptor() -> + #'EventsDescriptor'{eventList = []}. + +cre_EventsDescriptor(RID, [H|_] = EL) + when is_integer(RID) andalso is_record(H, 'RequestedEvent') -> + #'EventsDescriptor'{requestID = RID, eventList = EL}. + +cre_RequestedEvent(N) -> + #'RequestedEvent'{pkgdName = N}. + +cre_RequestedEvent(N, [H|_] = EPL) + when is_list(N) andalso + is_record(H, 'EventParameter') -> + #'RequestedEvent'{pkgdName = N, + evParList = EPL}; +cre_RequestedEvent(N, EA) + when is_list(N) andalso + is_record(EA, 'RequestedActions')-> + #'RequestedEvent'{pkgdName = N, + eventAction = EA}. + + +cre_RequestedEvent(N, SID, [H|_] = EPL) + when is_list(N) andalso + is_integer(SID) andalso + is_record(H, 'EventParameter') -> + #'RequestedEvent'{pkgdName = N, + streamID = SID, + evParList = EPL}; +cre_RequestedEvent(N, EA, [H|_] = EPL) + when is_list(N) andalso + is_record(EA, 'RequestedActions') andalso + is_record(H, 'EventParameter') -> + #'RequestedEvent'{pkgdName = N, + eventAction = EA, + evParList = EPL}. + +cre_RequestedEvent(N, SID, EA, [H|_] = EPL) + when is_list(N) andalso + is_integer(SID) andalso + is_record(EA, 'RequestedActions') andalso + is_record(H, 'EventParameter') -> + #'RequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}. + +cre_RequestedActions() -> + #'RequestedActions'{}. + +cre_RequestedActions(KA) + when (KA == true) or (KA == true) or (KA == asn1_NOVALUE) -> + #'RequestedActions'{keepActive = KA}; +cre_RequestedActions(SE) + when is_record(SE, 'SecondEventsDescriptor') or (SE == asn1_NOVALUE) -> + #'RequestedActions'{secondEvent = SE}; +cre_RequestedActions(SD) + when is_list(SD) or (SD == asn1_NOVALUE) -> + #'RequestedActions'{signalsDescriptor = SD}; +cre_RequestedActions({Tag, _} = EDM) + when is_atom(Tag) or (EDM == asn1_NOVALUE) -> + #'RequestedActions'{eventDM = EDM}. + +cre_RequestedActions(KA, {Tag, _} = EDM, SE, SD) + when ((KA == true) or (KA == true) or (KA == asn1_NOVALUE)) and + (is_atom(Tag) or (EDM == asn1_NOVALUE)) and + (is_record(SE, 'SecondEventsDescriptor') or (SE == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) -> + #'RequestedActions'{keepActive = KA, + eventDM = EDM, + secondEvent = SE, + signalsDescriptor = SD}. + +cre_EventDM(N) when is_list(N) -> + {digitMapName, N}; +cre_EventDM(V) when is_record(V, 'DigitMapValue') -> + {digitMapValue, V}. + +cre_SecondEventsDescriptor([H|_] = EL) + when is_record(H, 'SecondRequestedEvent') -> + #'SecondEventsDescriptor'{eventList = EL}. + +cre_SecondEventsDescriptor(RID, [H|_] = EL) + when is_integer(RID) andalso is_record(H, 'SecondRequestedEvent') -> + #'SecondEventsDescriptor'{requestID = RID, eventList = EL}. + +cre_SecondRequestedEvent(N, [H|_] = EPL) + when is_list(N) andalso + is_record(H, 'EventParameter') -> + #'SecondRequestedEvent'{pkgdName = N, + evParList = EPL}. + +cre_SecondRequestedEvent(N, SID, [H|_] = EPL) + when is_list(N) andalso + is_integer(SID) andalso + is_record(H, 'EventParameter') -> + #'SecondRequestedEvent'{pkgdName = N, + streamID = SID, + evParList = EPL}; +cre_SecondRequestedEvent(N, EA, [H|_] = EPL) + when is_list(N) andalso + is_record(EA, 'SecondRequestedActions') andalso + is_record(H, 'EventParameter') -> + #'SecondRequestedEvent'{pkgdName = N, + eventAction = EA, + evParList = EPL}. + +cre_SecondRequestedEvent(N, SID, EA, [H|_] = EPL) + when is_list(N) andalso + is_integer(SID) andalso + is_record(EA, 'SecondRequestedActions') andalso + is_record(H, 'EventParameter') -> + #'SecondRequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}. + +cre_SecondRequestedActions() -> + #'SecondRequestedActions'{}. + +cre_SecondRequestedActions(KA) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) -> + #'SecondRequestedActions'{keepActive = KA}; +cre_SecondRequestedActions(SD) when is_list(SD) -> + #'SecondRequestedActions'{signalsDescriptor = SD}; +cre_SecondRequestedActions({Tag, _} = EDM) when is_atom(Tag) -> + #'SecondRequestedActions'{eventDM = EDM}. + +cre_SecondRequestedActions(KA, SD) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SD) -> + #'SecondRequestedActions'{keepActive = KA, signalsDescriptor = SD}; +cre_SecondRequestedActions(KA, {Tag, _} = EDM) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_atom(Tag) -> + #'SecondRequestedActions'{keepActive = KA, eventDM = EDM}. + +cre_SecondRequestedActions(KA, {Tag, _} = EDM, SD) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_atom(Tag), + is_list(SD) -> + #'SecondRequestedActions'{keepActive = KA, + eventDM = EDM, + signalsDescriptor = SD}. + +cre_EventBufferDescriptor([H|_] = D) when is_record(H, 'EventSpec') -> + D. + +cre_EventSpec(N, [H|_] = EPL) when is_list(N) andalso is_record(H, 'EventParameter') -> + #'EventSpec'{eventName = N, eventParList = EPL}. + +cre_EventSpec(N, SID, [H|_] = EPL) + when is_list(N) andalso is_integer(SID) andalso is_record(H, 'EventParameter') -> + #'EventSpec'{eventName = N, streamID = SID, eventParList = EPL}. + +cre_SignalsDescriptor(D) -> + case is_SignalsDescriptor(D) of + true -> + D; + false -> + error({invalid_SignalsDescriptor, D}) + end. + +cre_SignalRequest(S) when is_record(S, 'Signal') -> + {signal, S}; +cre_SignalRequest(S) when is_record(S, 'SeqSigList') -> + {seqSigList, S}. + +cre_SeqSigList(ID, [H|_] = SL) + when is_integer(ID) andalso (0 =< ID) andalso (ID =< 65535) andalso is_record(H, 'Signal') -> + #'SeqSigList'{id = ID, signalList = SL}. + +cre_Signal(N) when is_list(N) -> + #'Signal'{signalName = N}. + +cre_Signal(N, SPL) when is_list(N) andalso is_list(SPL) -> + #'Signal'{signalName = N, + sigParList = SPL}. + +cre_Signal(N, SID, ST, Dur, NC, KA, SPL) + when is_list(N) and + (is_integer(SID) or (SID == asn1_NOVALUE)) and + ((ST == brief) or (ST == onOff) or (ST == timeOut) or + (ST == asn1_NOVALUE)) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 65535)) or + (Dur == asn1_NOVALUE)) and + (is_list(NC) or (NC == asn1_NOVALUE)) and + ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SPL) -> + #'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL}. + +cre_Signal(N, SID, ST, Dur, NC, KA, SPL, Dir, RID) + when is_list(N) and + (is_integer(SID) or (SID == asn1_NOVALUE)) and + ((ST == brief) or (ST == onOff) or (ST == timeOut) or + (ST == asn1_NOVALUE)) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 65535)) or + (Dur == asn1_NOVALUE)) and + (is_list(NC) or (NC == asn1_NOVALUE)) and + ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SPL) and + ((Dir == internal) or (Dir == external) or (Dir == both) or + (Dir == asn1_NOVALUE)) and + (is_integer(RID) or (RID == asn1_NOVALUE)) -> + #'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL, + direction = Dir, + requestID = RID}. + +cre_SignalType(brief = ST) -> + ST; +cre_SignalType(onOff = ST) -> + ST; +cre_SignalType(timeOut = ST) -> + ST. + +cre_SignalDirection(internal = SD) -> + SD; +cre_SignalDirection(external = SD) -> + SD; +cre_SignalDirection(both = SD) -> + SD. + +cre_SignalName(N) -> + cre_PkgdName(N). + +cre_NotifyCompletion(L) when is_list(L) -> + Vals = [onTimeOut, onInterruptByEvent, + onInterruptByNewSignalDescr, otherReason], + F = fun(E) -> case lists:member(E, Vals) of + true -> + ok; + false -> + exit({invalid_NotifyCompletion, E}) + end + end, + lists:foreach(F, L), + L. + +cre_SigParameter(N, V) when is_list(N) andalso is_list(V) -> + #'SigParameter'{sigParameterName = N, value = V}. + +cre_SigParameter(N, V, relation = Tag, R) + when is_list(N) andalso is_list(V) andalso is_atom(R) -> + EI = {Tag, R}, + #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}; +cre_SigParameter(N, V, range = Tag, B) + when is_list(N) andalso is_list(V) andalso is_atom(B) -> + EI = {Tag, B}, + #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}; +cre_SigParameter(N, V, sublist = Tag, B) + when is_list(N) andalso is_list(V) andalso is_atom(B) -> + EI = {Tag, B}, + #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}. + +cre_RequestID(Val) when 0 =< Val, Val =< 4294967295 -> + Val; +cre_RequestID(Val) -> + exit({invalid_RequestID, Val}). + +cre_ModemDescriptor(MTL, MPL) when is_list(MTL) andalso is_list(MPL) -> + #'ModemDescriptor'{mtl = MTL, mpl = MPL}. + +%% cre_ModemDescriptor(MTL, MPL, NSD) +%% when list(MTL), list(MPL), record(NSD, 'NonStandardData') -> +%% #'ModemDescriptor'{mtl = MTL, mpl = MPL}. + +cre_ModemType(v18 = MT) -> + MT; +cre_ModemType(v22 = MT) -> + MT; +cre_ModemType(v22bis = MT) -> + MT; +cre_ModemType(v32 = MT) -> + MT; +cre_ModemType(v32bis = MT) -> + MT; +cre_ModemType(v34 = MT) -> + MT; +cre_ModemType(v90 = MT) -> + MT; +cre_ModemType(v91 = MT) -> + MT; +cre_ModemType(synchISDN = MT) -> + MT. + +cre_DigitMapDescriptor() -> + #'DigitMapDescriptor'{}. + +cre_DigitMapDescriptor(N) when is_list(N) -> + #'DigitMapDescriptor'{digitMapName = N}; +cre_DigitMapDescriptor(V) when is_record(V, 'DigitMapValue') -> + #'DigitMapDescriptor'{digitMapValue = V}. + +cre_DigitMapDescriptor(N, V) when is_list(N) andalso is_record(V, 'DigitMapValue') -> + #'DigitMapDescriptor'{digitMapName = N, digitMapValue = V}. + +cre_DigitMapName(N) -> + cre_Name(N). + +cre_DigitMapValue(DMB) when is_list(DMB) -> + #'DigitMapValue'{digitMapBody = DMB}. + +cre_DigitMapValue(Start, Short, Long, DMB) -> + cre_DigitMapValue(Start, Short, Long, DMB, asn1_NOVALUE). + +cre_DigitMapValue(Start, Short, Long, DMB, Dur) + when ((is_integer(Start) and (0 =< Start) and (Start =< 99)) or + (Start == asn1_NOVALUE)) and + ((is_integer(Short) and (0 =< Short) and (Short =< 99)) or + (Short == asn1_NOVALUE)) and + ((is_integer(Long) and (0 =< Long) and (Long =< 99)) or + (Long == asn1_NOVALUE)) and + is_list(DMB) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 99)) or + (Dur == asn1_NOVALUE)) -> + #'DigitMapValue'{startTimer = Start, + shortTimer = Short, + longTimer = Long, + digitMapBody = DMB, + durationTimer = Dur}. + +cre_ServiceChangeParm(M, R) when is_atom(M) andalso is_list(R) -> + #'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeReason = R}. + +cre_ServiceChangeParm(M, Addr, Prof, Reason) -> + cre_ServiceChangeParm(M, Addr, asn1_NOVALUE, Prof, Reason, asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE). + +%% Addr = asn1_NOVALUE | {AddrTag, AddrVal} +cre_ServiceChangeParm(M, Addr, Ver, Prof, R, D, Mid, TS, I) -> + cre_ServiceChangeParm(M, Addr, Ver, Prof, R, D, Mid, TS, I, asn1_NOVALUE). + +cre_ServiceChangeParm(M, Addr, Ver, Prof, R, D, Mid, TS, I, IF) + when is_atom(M) and + ((is_integer(Ver) and (0 =< Ver) and (Ver =< 99)) or + (Ver == asn1_NOVALUE)) and + (is_record(Prof, 'ServiceChangeProfile') or (Prof == asn1_NOVALUE)) and + is_list(R) and + ((is_integer(D) and (0 =< D) and (D =< 4294967295)) or + (D == asn1_NOVALUE)) and + (is_record(TS, 'TimeNotation') or (TS == asn1_NOVALUE)) and + (is_record(I, 'AuditDescriptor') or (I == asn1_NOVALUE)) and + ((IF == 'NULL') or (IF == asn1_NOVALUE)) -> + F = fun(A) -> + (A == asn1_NOVALUE) orelse + (is_tuple(A) + andalso is_atom(element(1, A))) + end, + case (F(Addr) andalso F(Mid)) of + true -> + #'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeAddress = Addr, + serviceChangeVersion = Ver, + serviceChangeProfile = Prof, + serviceChangeReason = R, + serviceChangeDelay = D, + serviceChangeMgcId = Mid, + timeStamp = TS, + serviceChangeInfo = I, + serviceChangeIncompleteFlag = IF}; + _ -> + exit({invalid_ServiceChangeParm_args, {Addr, Mid}}) + end. + +cre_ServiceChangeAddress(portNumber = Tag, P) + when is_integer(P) andalso (0 =< P) andalso (P =< 65535) -> + {Tag, P}; +cre_ServiceChangeAddress(ip4Address = Tag, A) when is_record(A, 'IP4Address') -> + {Tag, A}; +cre_ServiceChangeAddress(ip6Address = Tag, A) when is_record(A, 'IP6Address') -> + {Tag, A}; +cre_ServiceChangeAddress(domainName = Tag, N) when is_record(N, 'DomainName') -> + {Tag, N}; +cre_ServiceChangeAddress(deviceName = Tag, N) when is_list(N) -> + {Tag, N}; +cre_ServiceChangeAddress(mtpAddress = Tag, A) when is_list(A) -> + {Tag, A}. + +cre_ServiceChangeResParm() -> + #'ServiceChangeResParm'{}. +cre_ServiceChangeResParm(Addr, Prof) -> + cre_ServiceChangeResParm(asn1_NOVALUE, Addr, asn1_NOVALUE, + Prof, asn1_NOVALUE). +cre_ServiceChangeResParm(Mid, Addr, Ver, Prof, TS) + when ((is_integer(Ver) and (0 =< Ver) and (Ver =< 99)) or + (Ver == asn1_NOVALUE)) and + (is_record(Prof, 'ServiceChangeProfile') or (Prof == asn1_NOVALUE)) and + (is_record(TS, 'TimeNotation') or (TS == asn1_NOVALUE)) -> + F = fun(A) -> + (A == asn1_NOVALUE) orelse + (is_tuple(A) + andalso is_atom(element(1, A))) + end, + case (F(Addr) andalso F(Mid)) of + true -> + #'ServiceChangeResParm'{serviceChangeMgcId = Mid, + serviceChangeAddress = Addr, + serviceChangeVersion = Ver, + serviceChangeProfile = Prof, + timeStamp = TS}; + _ -> + exit({invalid_ServiceChangeResParm_args, {Addr, Mid}}) + end. + +cre_ServiceChangeMethod(failover = M) -> + M; +cre_ServiceChangeMethod(forced = M) -> + M; +cre_ServiceChangeMethod(graceful = M) -> + M; +cre_ServiceChangeMethod(restart = M) -> + M; +cre_ServiceChangeMethod(disconnected = M) -> + M; +cre_ServiceChangeMethod(handOff = M) -> + M. + +%% The version field is added to make it look more like ABNF +cre_ServiceChangeProfile(N) -> + cre_ServiceChangeProfile(N, 1). + +cre_ServiceChangeProfile(N, V) + when is_list(N) andalso is_integer(V) andalso (0 =< V) andalso (V =< 99) -> + #'ServiceChangeProfile'{profileName = N, version = V}. + +cre_PackagesDescriptor([H|_] = D) when is_record(H, 'PackagesItem') -> + D. + +cre_PackagesItem(N, Ver) + when is_list(N) andalso is_integer(Ver) andalso (0 =< Ver) andalso (Ver =< 99) -> + #'PackagesItem'{packageName = N, + packageVersion = Ver}. + +cre_StatisticsDescriptor(D) -> + true = is_StatisticsDescriptor(D), + D. + +cre_StatisticsParameter(N) when is_list(N) -> + #'StatisticsParameter'{statName = N}. + +cre_StatisticsParameter(N, V) when is_list(N) andalso is_list(V) -> + #'StatisticsParameter'{statName = N, statValue = V}. + +%% cre_NonStandardData({Tag, _} = Id, Data) when atom(Tag), list(Data) -> +%% #'NonStandardData'{nonStandardIdentifier = Id, data = Data}. + +%% cre_NonStandardIdentifier(H221) when record(H221, 'H221NonStandard') -> +%% {h221NonStandard, H221}; +%% cre_NonStandardIdentifier(Obj) when tuple(Obj) -> +%% {object, Obj}; +%% cre_NonStandardIdentifier(Exp) when list(Exp), length(Exp) == 8 -> +%% {experimental, Exp}. + +%% cre_H221NonStandard(CC1, CC2, Ext, MC) +%% when (is_integer(CC1) and (0 =< CC1) and (CC1 =< 255)) and +%% (is_integer(CC2) and (0 =< CC2) and (CC2 =< 255)) and +%% (is_integer(Ext) and (0 =< Ext) and (Ext =< 255)) and +%% (is_integer(MC) and (0 =< MC) and (MC =< 255)) -> +%% #'H221NonStandard'{t35CountryCode1 = CC1, +%% t35CountryCode2 = CC2, +%% t35Extension = Ext, +%% manufacturerCode = MC}. + +cre_TimeNotation(D, T) + when is_list(D) andalso + (length(D) =:= 8) andalso + is_list(T), length(T) == 8 -> + #'TimeNotation'{date = D, time = T}. + +cre_Value([H|_] = V) when is_list(H) -> + V. + +cre_BOOLEAN(true = B) -> + B; +cre_BOOLEAN(false = B) -> + B. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% -- MegacoMessage -- + +is_MegacoMessage(#'MegacoMessage'{authHeader = Auth, + mess = Mess}) -> + d("is_MegacoMessage -> entry"), + is_opt_AuthenticationHeader(Auth) andalso is_Message(Mess); +is_MegacoMessage(_) -> + false. + + +chk_MegacoMessage(M, M) -> + d("chk_MegacoMessage -> entry (1)"), + chk_type(fun is_MegacoMessage/1, 'MegacoMessage', M); +chk_MegacoMessage(#'MegacoMessage'{authHeader = Auth1, + mess = Mess1}, + #'MegacoMessage'{authHeader = Auth2, + mess = Mess2}) -> + d("chk_MegacoMessage -> entry (2)"), + chk_opt_AuthenticationHeader(Auth1,Auth2), + chk_Message(Mess1,Mess2), + ok; +chk_MegacoMessage(M1, M2) -> + wrong_type('MegacoMessage', M1, M2). + + +%% -- AuthenticationHeader -- + +is_opt_AuthenticationHeader(AH) -> + is_OPTIONAL(fun is_AuthenticationHeader/1, AH). + +is_AuthenticationHeader(#'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AD}) -> + is_SecurityParmIndex(SPI) andalso + is_SequenceNum(SN) andalso + is_AuthData(AD); +is_AuthenticationHeader(_) -> + false. + +%% This stuff is not really used, so make it simple... +chk_opt_AuthenticationHeader(A1, A2) -> + chk_OPTIONAL('AuthenticationHeader', A1, A2, + fun is_AuthenticationHeader/1, + fun chk_AuthenticationHeader/2). + +chk_AuthenticationHeader(A, A) -> + chk_type(fun is_AuthenticationHeader/1, 'AuthenticationHeader', A); +chk_AuthenticationHeader(A1, A2) -> + case (is_AuthenticationHeader(A1) andalso is_AuthenticationHeader(A2)) of + true -> + not_equal('AuthenticationHeader', A1, A2); + false -> + wrong_type('AuthenticationHeader', A1, A2) + end. + + +%% -- SecurityParmIndex -- + +is_SecurityParmIndex(V) -> is_OCTET_STRING(V, {exact, 4}). + + +%% -- SequenceNum -- + +is_SequenceNum(V) -> is_OCTET_STRING(V, {exact, 4}). + + +%% -- AuthData -- + +is_AuthData(V) -> is_OCTET_STRING(V, {range, 12, 32}). + + +%% -- Message -- + +is_Message(#'Message'{version = V, + mId = MID, + messageBody = Body}) -> + d("is_Message -> entry"), + is_INTEGER(V, {range, 0, 99}) andalso + is_MId(MID) andalso + is_Message_messageBody(Body); +is_Message(_) -> + false. + +chk_Message(M, M) -> + d("chk_Message -> entry (1)"), + chk_type(fun is_Message/1, 'Message', M); +chk_Message(#'Message'{version = V1, + mId = MID1, + messageBody = Body1}, + #'Message'{version = V2, + mId = MID2, + messageBody = Body2}) -> + d("chk_Message -> entry with" + "~n V1: ~p" + "~n MID1: ~p" + "~n Body1: ~p" + "~n V2: ~p" + "~n MID2: ~p" + "~n Body2: ~p", + [V1, MID1, Body1, V2, MID2, Body2]), + validate(fun() -> chk_INTEGER(V1, V2, {range, 0, 99}) end, 'Message'), + validate(fun() -> chk_MId(MID1, MID2) end, 'Message'), + chk_Message_messageBody(Body1, Body2), + ok; +chk_Message(M1, M2) -> + wrong_type('Message', M1, M2). + + +is_Message_messageBody({Tag, Val}) -> + d("is_Message_messageBody -> entry"), + is_Message_messageBody_tag(Tag) andalso + is_Message_messageBody_val(Tag, Val); +is_Message_messageBody(_) -> + false. + +is_Message_messageBody_tag(Tag) -> + Tags = [messageError, transactions], + lists:member(Tag, Tags). + +is_Message_messageBody_val(messageError, Val) -> + is_ErrorDescriptor(Val); +is_Message_messageBody_val(transactions, Val) -> + is_Message_messageBody_transactions(Val). + +is_Message_messageBody_transactions([]) -> + d("is_Message_messageBody_transactions -> entry when done"), + true; +is_Message_messageBody_transactions([H|T]) -> + d("is_Message_messageBody_transactions -> entry"), + is_Transaction(H) andalso is_Message_messageBody_transactions(T); +is_Message_messageBody_transactions(_) -> + false. + +chk_Message_messageBody(B, B) -> + d("chk_Message_messageBody -> entry (1)"), + chk_type(fun is_Message_messageBody/1, 'Message_messageBody', B); +chk_Message_messageBody({Tag, Val1} = B1, {Tag, Val2} = B2) -> + d("chk_Message_messageBody -> entry (2)"), + case (is_Message_messageBody_tag(Tag) andalso + is_Message_messageBody_val(Tag, Val1) andalso + is_Message_messageBody_val(Tag, Val2)) of + true -> + chk_Message_messageBody_val(Tag, Val1, Val2); + false -> + wrong_type('Message_messageBody', B1, B2) + end; +chk_Message_messageBody({Tag1, Val1} = B1, {Tag2, Val2} = B2) -> + d("chk_Message_messageBody -> entry (3)"), + case ((is_Message_messageBody_tag(Tag1) andalso + is_Message_messageBody_val(Tag1, Val1)) andalso + (is_Message_messageBody_tag(Tag2) andalso + is_Message_messageBody_val(Tag2, Val2))) of + true -> + not_equal('Message_messageBody', B1, B2); + false -> + wrong_type('Message_messageBody', B1, B2) + end; +chk_Message_messageBody(B1, B2) -> + wrong_type('Message_messageBody', B1, B2). + +chk_Message_messageBody_val(messageError, Val1, Val2) -> + validate(fun() -> chk_ErrorDescriptor(Val1, Val2) end, + 'Message_messageBody'); +chk_Message_messageBody_val(transactions, Val1, Val2) -> + chk_Message_messageBody_transactions(lists:sort(Val1), + lists:sort(Val2)). + +chk_Message_messageBody_transactions([], []) -> + d("chk_Message_messageBody_transactions -> entry - ok (1)"), + ok; +chk_Message_messageBody_transactions([] = T1, T2) -> + d("chk_Message_messageBody_transactions -> entry - not-equal (2)"), + not_equal('Message_messageBody_transactions', T1, T2); +chk_Message_messageBody_transactions(T1, [] = T2) -> + d("chk_Message_messageBody_transactions -> entry - not-equal (3)"), + not_equal('Message_messageBody_transactions', T1, T2); +chk_Message_messageBody_transactions([H|T1], [H|T2]) -> + d("chk_Message_messageBody_transactions -> entry (4)"), + case is_Transaction(H) of + true -> + chk_Message_messageBody_transactions(T1, T2); + false -> + wrong_type('Message_messageBody_transactions_val', H) + end; +chk_Message_messageBody_transactions([H1|T1], [H2|T2]) -> + d("chk_Message_messageBody_transactions -> entry (5)"), + validate(fun() -> chk_Transaction(H1, H2) end, + 'Message_messageBody_transactions_val'), + chk_Message_messageBody_transactions(T1, T2); +chk_Message_messageBody_transactions(T1, T2) -> + d("chk_Message_messageBody_transactions -> entry - wrong-type (6)"), + wrong_type('Message_messageBody_transactions', T1, T2). + + +%% -- MId -- + +is_opt_MId(M) -> + is_OPTIONAL(fun is_MId/1, M). + +is_MId({Tag, Val}) -> + is_MId_tag(Tag) andalso is_MId_val(Tag, Val); +is_MId(_) -> + false. + +is_MId_tag(Tag) -> + Tags = [ip4Address, ip6Address, domainName, deviceName, mtpAddress], + lists:member(Tag, Tags). + +is_MId_val(ip4Address, Val) -> is_IP4Address(Val); +is_MId_val(ip6Address, Val) -> is_IP6Address(Val); +is_MId_val(domainName, Val) -> is_DomainName(Val); +is_MId_val(deviceName, Val) -> is_PathName(Val); +is_MId_val(mtpAddress, Val) -> is_OCTET_STRING(Val, {range, 2, 4}). + +chk_opt_MId(M1, M2) -> + chk_OPTIONAL('MId', M1, M2, fun is_MId/1, fun chk_MId/2). + +chk_MId(M, M) -> + chk_type(fun is_MId/1, 'MId', M); +chk_MId({Tag, Val1} = M1, {Tag, Val2} = M2) -> + case (is_MId_tag(Tag) andalso + is_MId_val(Tag, Val1) andalso + is_MId_val(Tag, Val2)) of + true -> + chk_MId_val(Tag, Val1, Val2); + false -> + wrong_type('MId', M1, M2) + end; +chk_MId({Tag1, Val1} = M1, {Tag2, Val2} = M2) -> + case ((is_MId_tag(Tag1) andalso + is_MId_val(Tag1, Val1)) andalso + (is_MId_tag(Tag2) andalso + is_MId_val(Tag2, Val2))) of + true -> + not_equal('MId', M1, M2); + false -> + wrong_type('MId', M1, M2) + end; +chk_MId(M1, M2) -> + wrong_type('MId', M1, M2). + +chk_MId_val(ip4Address, M1, M2) -> chk_IP4Address(M1, M2); +chk_MId_val(ip6Address, M1, M2) -> chk_IP6Address(M1, M2); +chk_MId_val(domainName, M1, M2) -> chk_DomainName(M1, M2); +chk_MId_val(deviceName, M1, M2) -> chk_PathName(M1, M2); +chk_MId_val(mtpAddress, M1, M2) -> chk_OCTET_STRING(M1, M2, {range, 2, 4}). + + +%% -- DomainName -- + +is_DomainName(#'DomainName'{name = N, portNumber = PN}) -> + is_IA5String(N) andalso is_opt_INTEGER(PN, {range, 0, 65535}); +is_DomainName(_) -> + false. + +chk_DomainName(N, N) -> + ok; +chk_DomainName(N1, N2) -> + not_equal('DomainName', N1, N2). + + +%% -- IP4Address -- + +is_IP4Address(#'IP4Address'{address = A, portNumber = PN}) -> + is_OCTET_STRING(A, {exact, 4}) andalso + is_opt_INTEGER(PN, {range, 0, 65535}); +is_IP4Address(_) -> + false. + +chk_IP4Address(A, A) -> + ok; +chk_IP4Address(A1, A2) -> + not_equal('IP4Address', A1, A2). + + +%% -- IP6Address -- + +is_IP6Address(#'IP6Address'{address = A, portNumber = PN}) -> + is_OCTET_STRING(A, {exact, 16}) andalso + is_opt_INTEGER(PN, {range, 0, 65535}); +is_IP6Address(_) -> + false. + +chk_IP6Address(A, A) -> + ok; +chk_IP6Address(A1, A2) -> + not_equal('IP6Address', A1, A2). + + +%% -- PathName -- + +is_PathName(N) -> is_IA5String(N, {range, 1, 64}). + +chk_PathName(N, N) -> + ok; +chk_PathName(N1, N2) -> + not_equal('PathName', N1, N2). + + +%% -- Transaction -- + +is_Transaction({Tag, Val}) -> + d("is_Transaction -> entry"), + is_Transaction_tag(Tag) andalso is_Transaction_val(Tag, Val); +is_Transaction(_) -> + false. + +is_Transaction_tag(Tag) -> + Tags = [transactionRequest, + transactionPending, + transactionReply, + transactionResponseAck], + lists:member(Tag, Tags). + +is_Transaction_val(transactionRequest, V) -> is_TransactionRequest(V); +is_Transaction_val(transactionPending, V) -> is_TransactionPending(V); +is_Transaction_val(transactionReply, V) -> is_TransactionReply(V); +is_Transaction_val(transactionResponseAck, V) -> is_TransactionResponseAck(V). + + +chk_Transaction({Tag, Val} = Trans, Trans) -> + d("chk_Transaction -> entry (1)"), + case (is_Transaction_tag(Tag) andalso is_Transaction_val(Tag, Val)) of + true -> + ok; + false -> + wrong_type('Transaction', Trans, Trans) + end; +chk_Transaction({Tag, Val1} = Trans1, {Tag, Val2} = Trans2) -> + d("chk_Transaction -> entry (2)"), + case (is_Transaction_tag(Tag) and + is_Transaction_val(Tag, Val1) and + is_Transaction_val(Tag, Val2)) of + true -> + chk_Transaction_val(Tag, Val1, Val2); + false -> + wrong_type('Transaction', Trans1, Trans2) + end; +chk_Transaction({Tag1, Val1} = Trans1, {Tag2, Val2} = Trans2) -> + d("chk_Transaction -> entry (3)"), + case ((is_Transaction_tag(Tag1) andalso + is_Transaction_val(Tag1, Val1)) andalso + (is_Transaction_tag(Tag2) andalso + is_Transaction_val(Tag2, Val2))) of + true -> + not_equal('Transaction', Trans1, Trans2); + false -> + wrong_type('Transaction', Trans1, Trans2) + end; +chk_Transaction(Trans1, Trans2) -> + d("chk_Transaction -> entry - wrong-type - (4)"), + wrong_type('Transaction', Trans1, Trans2). + +chk_Transaction_val(transactionRequest, T1, T2) -> + chk_TransactionRequest(T1, T2); +chk_Transaction_val(transactionPending, T1, T2) -> + chk_TransactionPending(T1, T2); +chk_Transaction_val(transactionReply, T1, T2) -> + chk_TransactionReply(T1,T2); +chk_Transaction_val(transactionResponseAck, T1, T2) -> + chk_TransactionResponseAck(T1, T2). + + +%% -- TransactionId -- + +is_opt_TransactionId(TID) -> + is_OPTIONAL(fun is_TransactionId/1, TID). + +is_TransactionId(TID) -> + d("is_TransactionId -> entry"), + is_INTEGER(TID, {range, 0, 4294967295}). + +chk_opt_TransactionId(TID1, TID2) -> + chk_OPTIONAL('TransactionId', TID1, TID2, + fun is_TransactionId/1, fun chk_TransactionId/2). + +chk_TransactionId(TID, TID) -> + chk_type(fun is_TransactionId/1, 'TransactionId', TID); +chk_TransactionId(TID1, TID2) -> + case (is_TransactionId(TID1) andalso is_TransactionId(TID2)) of + true -> + not_equal('TransactionId', TID1, TID2); + false -> + wrong_type('TransactionId', TID1, TID2) + end. + + +%% -- TransactionRequest -- + +is_TransactionRequest(#'TransactionRequest'{transactionId = TID, + actions = Acts}) -> + d("is_TransactionRequest -> entry"), + is_TransactionId(TID) andalso is_TransactionRequest_actions(Acts); +is_TransactionRequest(_) -> + false. + +chk_TransactionRequest(T, T) -> + chk_type(fun is_TransactionRequest/1, 'TransactionRequest', T); +chk_TransactionRequest(#'TransactionRequest'{transactionId = TID1, + actions = Acts1}, + #'TransactionRequest'{transactionId = TID2, + actions = Acts2}) -> + validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionRequest'), + chk_TransactionRequest_actions(lists:sort(Acts1), + lists:sort(Acts2)), + ok; +chk_TransactionRequest(T1, T2) -> + wrong_type('TransactionRequest', T1, T2). + +is_TransactionRequest_actions([]) -> + d("is_TransactionRequest_actions -> entry when done"), + true; +is_TransactionRequest_actions([H|T]) -> + d("is_TransactionRequest_actions -> entry"), + is_ActionRequest(H) andalso is_TransactionRequest_actions(T); +is_TransactionRequest_actions(_) -> + false. + +chk_TransactionRequest_actions([], []) -> + ok; +chk_TransactionRequest_actions([] = Acts1, Acts2) -> + not_equal('TransactionRequest_actions', Acts1, Acts2); +chk_TransactionRequest_actions(Acts1, [] = Acts2) -> + not_equal('TransactionRequest_actions', Acts1, Acts2); +chk_TransactionRequest_actions([H|T1], [H|T2]) -> + case is_ActionRequest(H) of + true -> + chk_TransactionRequest_actions(T1, T2); + false -> + wrong_type('TransactionRequest_actions_val', H) + end; +chk_TransactionRequest_actions([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ActionRequest(H1, H2) end, + 'TransactionRequest_actions_val'), + chk_TransactionRequest_actions(T1, T2); +chk_TransactionRequest_actions(Acts1, Acts2) -> + wrong_type('TransactionRequest_actions', Acts1, Acts2). + + +%% -- TransactionPending -- + +is_TransactionPending(#'TransactionPending'{transactionId = TID}) -> + d("is_TransactionPending -> entry"), + is_TransactionId(TID); +is_TransactionPending(_) -> + false. + +chk_TransactionPending(T, T) -> + chk_type(fun is_TransactionPending/1, 'TransactionPending', T); +chk_TransactionPending(#'TransactionPending'{transactionId = TID1}, + #'TransactionPending'{transactionId = TID2}) -> + validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionPending'), + ok; +chk_TransactionPending(T1, T2) -> + wrong_type('TransactionPending', T1, T2). + + +%% -- TransactionReply -- + +is_TransactionReply(#'TransactionReply'{transactionId = TID, + immAckRequired = IAR, + transactionResult = TR}) -> + d("is_TransactionReply -> entry"), + is_TransactionId(TID) andalso + is_opt_NULL(IAR) andalso + is_TransactionReply_transactionResult(TR); +is_TransactionReply(_) -> + false. + +chk_TransactionReply(T, T) -> + chk_type(fun is_TransactionReply/1, 'TransactionReply', T); +chk_TransactionReply(#'TransactionReply'{transactionId = TID1, + immAckRequired = IAR1, + transactionResult = TR1}, + #'TransactionReply'{transactionId = TID2, + immAckRequired = IAR2, + transactionResult = TR2}) -> + validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionReply'), + validate(fun() -> chk_opt_NULL(IAR1, IAR2) end, 'TransactionReply'), + chk_TransactionReply_transactionResult(TR1, TR2), + ok; +chk_TransactionReply(T1, T2) -> + wrong_type('TransactionReply', T1, T2). + +is_TransactionReply_transactionResult({Tag, Val}) -> + d("is_TransactionReply_transactionResult -> entry"), + is_TransactionReply_transactionResult_tag(Tag) andalso + is_TransactionReply_transactionResult_val(Tag, Val); +is_TransactionReply_transactionResult(_) -> + false. + +is_TransactionReply_transactionResult_tag(T) -> + lists:member(T, [transactionError, actionReplies]). + +is_TransactionReply_transactionResult_val(transactionError, V) -> + is_ErrorDescriptor(V); +is_TransactionReply_transactionResult_val(actionReplies, V) -> + is_TransactionReply_actionReplies(V). + +chk_TransactionReply_transactionResult(Res, Res) -> + chk_type(fun is_TransactionReply_transactionResult/1, + 'TransactionReply_transactionResult', Res); +chk_TransactionReply_transactionResult({Tag, Val1} = Res1, + {Tag, Val2} = Res2) -> + case (is_TransactionReply_transactionResult_tag(Tag) and + is_TransactionReply_transactionResult_val(Tag, Val1) and + is_TransactionReply_transactionResult_val(Tag, Val2)) of + true -> + chk_TransactionReply_transactionResult_val(Tag, Val1, Val2); + false -> + wrong_type('TransactionReply_transactionResult', Res1, Res2) + end; +chk_TransactionReply_transactionResult({Tag1, Val1} = Res1, + {Tag2, Val2} = Res2) -> + case ((is_TransactionReply_transactionResult_tag(Tag1) and + is_TransactionReply_transactionResult_val(Tag1, Val1)) and + (is_TransactionReply_transactionResult_tag(Tag2) and + is_TransactionReply_transactionResult_val(Tag2, Val2))) of + true -> + not_equal('TransactionReply_transactionResult', Res1, Res2); + false -> + wrong_type('TransactionReply_transactionResult', Res1, Res2) + end; +chk_TransactionReply_transactionResult(Res1, Res2) -> + wrong_type('TransactionReply_transactionResult', Res1, Res2). + +chk_TransactionReply_transactionResult_val(transactionError, E1, E2) -> + validate(fun() -> chk_ErrorDescriptor(E1, E2) end, + 'TransactionReply_transactionResult'); +chk_TransactionReply_transactionResult_val(actionReplies, R1, R2) -> + validate(fun() -> + chk_TransactionReply_actionReplies(lists:sort(R1), + lists:sort(R2)) + end, + 'TransactionReply_transactionResult'). + +is_TransactionReply_actionReplies([]) -> + d("is_TransactionReply_actionReplies -> entry when done"), + true; +is_TransactionReply_actionReplies([H|T]) -> + d("is_TransactionReply_actionReplies -> entry"), + is_ActionReply(H) andalso is_TransactionReply_actionReplies(T); +is_TransactionReply_actionReplies(_) -> + false. + +chk_TransactionReply_actionReplies([], []) -> + ok; +chk_TransactionReply_actionReplies([] = AR1, AR2) -> + not_equal('TransactionReply_actionReplies', AR1, AR2); +chk_TransactionReply_actionReplies(AR1, [] = AR2) -> + not_equal('TransactionReply_actionReplies', AR1, AR2); +chk_TransactionReply_actionReplies([H|T1], [H|T2]) -> + case is_ActionReply(H) of + true -> + chk_TransactionReply_actionReplies(T1, T2); + false -> + wrong_type('TransactionReply_actionReplies_val', H) + end; +chk_TransactionReply_actionReplies([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ActionReply(H1, H2) end, + 'TransactionReply_actionReplies_val'), + chk_TransactionReply_actionReplies(T1, T2); +chk_TransactionReply_actionReplies(AR1, AR2) -> + wrong_type('TransactionReply_actionReplies', AR1, AR2). + + +%% -- TransactionResponseAck -- + +is_TransactionResponseAck([]) -> + d("is_TransactionResponseAck -> entry when done"), + true; +is_TransactionResponseAck([H|T]) -> + d("is_TransactionResponseAck -> entry"), + is_TransactionAck(H) andalso is_TransactionResponseAck(T); +is_TransactionResponseAck(_) -> + false. + +chk_TransactionResponseAck([], []) -> + ok; +chk_TransactionResponseAck([] = AR1, AR2) -> + not_equal('TransactionResponseAck', AR1, AR2); +chk_TransactionResponseAck(AR1, [] = AR2) -> + not_equal('TransactionResponseAck', AR1, AR2); +chk_TransactionResponseAck([H|T1], [H|T2]) -> + case is_TransactionAck(H) of + true -> + chk_TransactionResponseAck(T1, T2); + false -> + wrong_type('TransactionResponseAck_val', H) + end; +chk_TransactionResponseAck([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TransactionAck(H1, H2) end, + 'TransactionResponseAck'), + chk_TransactionResponseAck(T1, T2); +chk_TransactionResponseAck(AR1, AR2) -> + wrong_type('TransactionResponseAck', AR1, AR2). + + +%% -- TransactionAck -- + +is_TransactionAck(#'TransactionAck'{firstAck = F, + lastAck = L}) -> + d("is_TransactionAck -> entry"), + is_TransactionId(F) andalso is_opt_TransactionId(L); +is_TransactionAck(_) -> + false. + +chk_TransactionAck(T, T) -> + chk_type(fun is_TransactionAck/1, 'TransactionAck', T); +chk_TransactionAck(#'TransactionAck'{firstAck = F1, + lastAck = L1}, + #'TransactionAck'{firstAck = F2, + lastAck = L2}) -> + validate(fun() -> chk_TransactionId(F1, F2) end, 'TransactionAck'), + validate(fun() -> chk_opt_TransactionId(L1, L2) end, 'TransactionAck'), + ok; +chk_TransactionAck(T1, T2) -> + wrong_type('TransactionAck', T1, T2). + + +%% -- ErrorDescriptor -- + +is_opt_ErrorDescriptor(V) -> + is_OPTIONAL(fun is_ErrorDescriptor/1, V). + +is_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code, + errorText = Text}) -> + d("is_ErrorDescriptor -> entry"), + is_ErrorCode(Code) andalso is_opt_ErrorText(Text); +is_ErrorDescriptor(_) -> + false. + +chk_opt_ErrorDescriptor(E1, E2) -> + chk_OPTIONAL('ErrorDescriptor', E1, E2, + fun is_ErrorDescriptor/1, fun chk_ErrorDescriptor/2). + +chk_ErrorDescriptor(E, E) -> + chk_type(fun is_ErrorDescriptor/1, 'ErrorDescriptor', E); +chk_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code1, + errorText = Text1}, + #'ErrorDescriptor'{errorCode = Code2, + errorText = Text2}) -> + chk_ErrorCode(Code1, Code2), + chk_opt_ErrorText(Text1, Text2), + ok; +chk_ErrorDescriptor(E1, E2) -> + wrong_type('ErrorDescriptor', E1, E2). + + +%% -- ErrorCode -- + +is_ErrorCode(C) -> is_INTEGER(C, {range, 0, 65535}). + +chk_ErrorCode(C, C) -> + case is_ErrorCode(C) of + true -> + ok; + false -> + wrong_type(errorCode, C, C) + end; +chk_ErrorCode(C1, C2) -> + case (is_ErrorCode(C1) andalso is_ErrorCode(C2)) of + true -> + not_equal(errorCode, C1, C2); + false -> + wrong_type(errorCode, C1, C2) + end. + + +%% -- ErrorText -- + +is_opt_ErrorText(V) -> + is_OPTIONAL(fun is_ErrorText/1, V). + +is_ErrorText(V) -> is_IA5String(V). + +chk_opt_ErrorText(T1, T2) -> + chk_OPTIONAL('ErrorText', T1, T2, fun is_ErrorText/1, fun chk_ErrorText/2). + +chk_ErrorText(T, T) -> + chk_type(fun is_ErrorText/1, 'ErrorText', T); +chk_ErrorText(T1, T2) -> + case (is_ErrorText(T1) andalso is_ErrorText(T2)) of + true -> + case {to_lower(T1), to_lower(T2)} of + {T, T} -> + ok; + _ -> + not_equal('ErrorText', T1, T2) + end; + false -> + wrong_type('ErrorText', T1, T2) + end. + + +%% -- ContextID -- + +is_ContextID(Id) -> is_INTEGER(Id, {range, 0, 4294967295}). + +chk_ContextID(Id, Id) -> + chk_type(fun is_ContextID/1, 'ContextID', Id); +chk_ContextID(Id1, Id2) -> + case (is_ContextID(Id1) andalso is_ContextID(Id2)) of + true -> + not_equal('ContextID', Id1, Id2); + false -> + wrong_type('ContextID', Id1, Id2) + end. + + +%% -- ActionRequest -- + +is_ActionRequest(#'ActionRequest'{contextId = Id, + contextRequest = CtxReq, + contextAttrAuditReq = AuditReq, + commandRequests = CmdReqs}) -> + d("is_ActionRequest -> entry"), + is_ContextID(Id) andalso + is_opt_ContextRequest(CtxReq) andalso + is_opt_ContextAttrAuditRequest(AuditReq) andalso + is_ActionRequest_commandRequests(CmdReqs); +is_ActionRequest(_) -> + false. + +chk_ActionRequest(A, A) -> + chk_type(fun is_ActionRequest/1, 'ActionRequest', A); +chk_ActionRequest(#'ActionRequest'{contextId = Id1, + contextRequest = Req1, + contextAttrAuditReq = AuditReq1, + commandRequests = CmdReqs1}, + #'ActionRequest'{contextId = Id2, + contextRequest = Req2, + contextAttrAuditReq = AuditReq2, + commandRequests = CmdReqs2}) -> + validate(fun() -> chk_ContextID(Id1, Id2) end, 'ActionRequest'), + validate(fun() -> chk_opt_ContextRequest(Req1, Req2) end, 'ActionRequest'), + validate(fun() -> + chk_opt_ContextAttrAuditRequest(AuditReq1, AuditReq2) + end, + 'ActionRequest'), + chk_ActionRequest_commandRequests(CmdReqs1, CmdReqs2), + ok. + + +is_ActionRequest_commandRequests([]) -> + d("is_ActionRequest_commandRequests -> entry when done"), + true; +is_ActionRequest_commandRequests([H|T]) -> + d("is_ActionRequest_commandRequests -> entry"), + is_CommandRequest(H) andalso is_ActionRequest_commandRequests(T); +is_ActionRequest_commandRequests(_) -> + false. + +chk_ActionRequest_commandRequests([], []) -> + ok; +chk_ActionRequest_commandRequests([] = CmdReqs1, CmdReqs2) -> + not_equal('ActionRequest_commandRequests', CmdReqs1, CmdReqs2); +chk_ActionRequest_commandRequests(CmdReqs1, [] = CmdReqs2) -> + not_equal('ActionRequest_commandRequests', CmdReqs1, CmdReqs2); +chk_ActionRequest_commandRequests([H|T1], [H|T2]) -> + case is_CommandRequest(H) of + true -> + chk_ActionRequest_commandRequests(T1, T2); + false -> + wrong_type('ActionRequest_commandRequest_val', H) + end; +chk_ActionRequest_commandRequests([H1|T1], [H2|T2]) -> + validate(fun() -> chk_CommandRequest(H1, H2) end, + 'ActionRequest_commandRequests_val'), + chk_ActionRequest_commandRequests(T1, T2); +chk_ActionRequest_commandRequests(R1, R2) -> + wrong_type('ActionRequest_commandRequests', R1, R2). + + +%% -- ActionReply -- + +is_ActionReply(#'ActionReply'{contextId = Id, + errorDescriptor = ED, + contextReply = CtxRep, + commandReply = CmdRep}) -> + d("is_ActionReply -> entry"), + is_ContextID(Id) andalso + is_opt_ErrorDescriptor(ED) andalso + is_opt_ContextRequest(CtxRep) andalso + is_ActionReply_commandReply(CmdRep); +is_ActionReply(_) -> + false. + +is_ActionReply_commandReply([]) -> + d("is_ActionReply_commandReply -> entry when done"), + true; +is_ActionReply_commandReply([H|T]) -> + d("is_ActionReply_commandReply -> entry"), + is_CommandReply(H) andalso is_ActionReply_commandReply(T); +is_ActionReply_commandReply(_) -> + false. + +chk_ActionReply(A, A) -> + chk_type(fun is_ActionReply/1, 'ActionReply', A); +chk_ActionReply(#'ActionReply'{contextId = Id1, + errorDescriptor = ED1, + contextReply = CtxRep1, + commandReply = CmdRep1}, + #'ActionReply'{contextId = Id2, + errorDescriptor = ED2, + contextReply = CtxRep2, + commandReply = CmdRep2}) -> + chk_ContextID(Id1, Id2), + chk_opt_ErrorDescriptor(ED1, ED2), + chk_opt_ContextRequest(CtxRep1, CtxRep2), + chk_ActionReply_commandReply(CmdRep1, CmdRep2). + +chk_ActionReply_commandReply([], []) -> + ok; +chk_ActionReply_commandReply([] = Reps1, Reps2) -> + not_equal('ActionReply_commandReply', Reps1, Reps2); +chk_ActionReply_commandReply(Reps1, [] = Reps2) -> + not_equal('ActionReply_commandReply', Reps1, Reps2); +chk_ActionReply_commandReply([H|T1], [H|T2]) -> + case is_CommandReply(H) of + true -> + chk_ActionReply_commandReply(T1, T2); + false -> + wrong_type('ActionReply_commandReply_val', H) + end; +chk_ActionReply_commandReply([H1|T1], [H2|T2]) -> + validate(fun() -> chk_CommandReply(H1, H2) end, + 'ActionReply_commandReply_val'), + chk_ActionReply_commandReply(T1, T2); +chk_ActionReply_commandReply(R1, R2) -> + wrong_type('ActionReply_commandReply', R1, R2). + + +%% -- ContextRequest -- + +is_opt_ContextRequest(V) -> + is_OPTIONAL(fun is_ContextRequest/1, V). + +is_ContextRequest(#'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = TopReq, + iepsCallind = Ieps, + contextProp = Ctx}) -> + d("is_ContextRequest -> entry"), + is_ContextRequest_priority(Prio) andalso + is_ContextRequest_emergency(Em) andalso + is_ContextRequest_topologyReq(TopReq) andalso + is_ContextRequest_iepsCallind(Ieps) andalso + is_ContextRequest_contextProp(Ctx); +is_ContextRequest(_) -> + false. + +is_ContextRequest_priority(asn1_NOVALUE) -> + true; +is_ContextRequest_priority(V) -> + is_INTEGER(V, {range, 1, 15}). + +is_ContextRequest_emergency(asn1_NOVALUE) -> + true; +is_ContextRequest_emergency(V) -> + is_BOOLEAN(V). + +is_ContextRequest_topologyReq(asn1_NOVALUE) -> + true; +is_ContextRequest_topologyReq([]) -> + true; +is_ContextRequest_topologyReq([H|T]) -> + is_TopologyRequest(H) andalso is_ContextRequest_topologyReq(T); +is_ContextRequest_topologyReq(_) -> + false. + +is_ContextRequest_iepsCallind(asn1_NOVALUE) -> + true; +is_ContextRequest_iepsCallind(V) -> + is_BOOLEAN(V). + +is_ContextRequest_contextProp(asn1_NOVALUE) -> + true; +is_ContextRequest_contextProp([]) -> + true; +is_ContextRequest_contextProp([H|T]) -> + is_PropertyParm(H) andalso is_ContextRequest_contextProp(T); +is_ContextRequest_contextProp(_) -> + false. + +chk_opt_ContextRequest(R1, R2) -> + chk_OPTIONAL('ContextRequest', R1, R2, + fun is_ContextRequest/1, fun chk_ContextRequest/2). + +chk_ContextRequest(R, R) -> + chk_type(fun is_ContextRequest/1, 'ContextRequest', R); +chk_ContextRequest(#'ContextRequest'{priority = Prio1, + emergency = Em1, + topologyReq = TopReq1, + iepsCallind = Ieps1, + contextProp = Ctx1}, + #'ContextRequest'{priority = Prio2, + emergency = Em2, + topologyReq = TopReq2, + iepsCallind = Ieps2, + contextProp = Ctx2}) -> + chk_ContextRequest_priority(Prio1, Prio2), + chk_ContextRequest_emergency(Em1, Em2), + chk_ContextRequest_topologyReq(TopReq1, TopReq2), + chk_ContextRequest_iepsCallind(Ieps1, Ieps2), + chk_ContextRequest_contextProp(Ctx1, Ctx2), + ok; +chk_ContextRequest(R1, R2) -> + wrong_type('ContextRequest', R1, R2). + + +chk_ContextRequest_priority(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_ContextRequest_priority(P, P) -> + chk_type(fun is_ContextRequest_priority/1, 'ContextRequest_priority', P); +chk_ContextRequest_priority(P1, P2) -> + case (is_ContextRequest_priority(P1) andalso + is_ContextRequest_priority(P2)) of + true -> + not_equal('ContextRequest_priority', P1, P2); + false -> + wrong_type(contextRequest_priority, P1, P2) + end. + + +chk_ContextRequest_emergency(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_emergency(E, E) -> + chk_type(fun is_ContextRequest_emergency/1, 'ContextRequest_emergency', E); +chk_ContextRequest_emergency(E1, E2) -> + case (is_ContextRequest_emergency(E1) andalso + is_ContextRequest_emergency(E2)) of + true -> + not_equal('ContextRequest_emergency', E1, E2); + false -> + wrong_type('ContextRequest_emergency', E1, E2) + end. + +chk_ContextRequest_topologyReq(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_topologyReq([], []) -> + ok; +chk_ContextRequest_topologyReq([] = T1, T2) -> + not_equal('ContextRequest_topologyReq', T1, T2); +chk_ContextRequest_topologyReq(T1, [] = T2) -> + not_equal('ContextRequest_topologyReq', T1, T2); +chk_ContextRequest_topologyReq([H|T1], [H|T2]) -> + case is_TopologyRequest(H) of + true -> + chk_ContextRequest_topologyReq(T1, T2); + false -> + wrong_type('ContextRequest_topologyReq_val', H) + end; +chk_ContextRequest_topologyReq([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TopologyRequest(H1, H2) end, + 'ContextRequest_topologyReq_val'), + chk_ContextRequest_topologyReq(T1, T2); +chk_ContextRequest_topologyReq(T1, T2) -> + wrong_type('ContextRequest_topologyReq', T1, T2). + + +chk_ContextRequest_iepsCallind(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_iepsCallind(E, E) -> + chk_type(fun is_ContextRequest_iepsCallind/1, + 'ContextRequest_iepsCallind', E); +chk_ContextRequest_iepsCallind(E1, E2) -> + case (is_ContextRequest_iepsCallind(E1) andalso + is_ContextRequest_iepsCallind(E2)) of + true -> + case (((E1 == false) and (E2 == asn1_NOVALUE)) or + ((E1 == asn1_NOVALUE) and (E2 == false))) of + true -> + ok; + false -> + not_equal('ContextRequest_iepsCallind', E1, E2) + end; + + false -> + wrong_type('ContextRequest_iepsCallind', E1, E2) + end. + +chk_ContextRequest_contextProp(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_contextProp([], []) -> + ok; +chk_ContextRequest_contextProp([] = T1, T2) -> + not_equal('ContextRequest_contextProp', T1, T2); +chk_ContextRequest_contextProp(T1, [] = T2) -> + not_equal('ContextRequest_contextProp', T1, T2); +chk_ContextRequest_contextProp([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_ContextRequest_contextProp(T1, T2); + false -> + wrong_type('ContextRequest_contextProp_val', H) + end; +chk_ContextRequest_contextProp([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, + 'ContextRequest_contextProp_val'), + chk_ContextRequest_contextProp(T1, T2); +chk_ContextRequest_contextProp(T1, T2) -> + wrong_type('ContextRequest_contextProp', T1, T2). + + +%% -- ContextAttrAuditRequest -- + +is_opt_ContextAttrAuditRequest(asn1_NOVALUE) -> + true; +is_opt_ContextAttrAuditRequest(V) -> + is_ContextAttrAuditRequest(V). + +is_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{topology = T, + emergency = E, + priority = P, + iepsCallind = I, + contextPropAud = A}) -> + d("is_ContextAttrAuditRequest -> entry"), + is_opt_NULL(T) andalso + is_opt_NULL(E) andalso + is_opt_NULL(P) andalso + is_opt_NULL(I) andalso + is_ContextAttrAuditRequest_contextPropAud(A); +is_ContextAttrAuditRequest(_) -> + false. + +is_ContextAttrAuditRequest_contextPropAud(asn1_NOVALUE) -> + true; +is_ContextAttrAuditRequest_contextPropAud([]) -> + true; +is_ContextAttrAuditRequest_contextPropAud([H|T]) -> + d("is_ContextAttrAuditRequest_contextPropAud -> entry"), + is_IndAudPropertyParm(H) andalso + is_ContextAttrAuditRequest_contextPropAud(T). + +chk_opt_ContextAttrAuditRequest(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_ContextAttrAuditRequest(R1, R2) -> + chk_ContextAttrAuditRequest(R1, R2). + +chk_ContextAttrAuditRequest(R, R) -> + chk_type(fun is_ContextAttrAuditRequest/1, 'ContextAttrAuditRequest', R); +chk_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{topology = T1, + emergency = E1, + priority = P1, + iepsCallind = I1, + contextPropAud = A1}, + #'ContextAttrAuditRequest'{topology = T2, + emergency = E2, + priority = P2, + iepsCallind = I2, + contextPropAud = A2}) -> + validate(fun() -> chk_opt_NULL(T1, T2) end, + 'ContextAttrAuditRequest_topology'), + validate(fun() -> chk_opt_NULL(E1, E2) end, + 'ContextAttrAuditRequest_emergency'), + validate(fun() -> chk_opt_NULL(P1, P2) end, + 'ContextAttrAuditRequest_priority'), + validate(fun() -> chk_opt_NULL(I1, I2) end, + 'ContextAttrAuditRequest_iepsCallind'), + chk_ContextAttrAuditRequest_contextPropAud(lists:sort(A1), + lists:sort(A2)), + ok. + +chk_ContextAttrAuditRequest_contextPropAud(A, A) -> + chk_type(fun is_ContextAttrAuditRequest_contextPropAud/1, + 'ContextAttrAuditRequest_contextPropAud', A); +chk_ContextAttrAuditRequest_contextPropAud([], []) -> + ok; +chk_ContextAttrAuditRequest_contextPropAud([] = T1, T2) -> + not_equal('ContextAttrAuditRequest_contextPropAud', T1, T2); +chk_ContextAttrAuditRequest_contextPropAud(T1, [] = T2) -> + not_equal('ContextAttrAuditRequest_contextPropAud', T1, T2); +chk_ContextAttrAuditRequest_contextPropAud([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_ContextAttrAuditRequest_contextPropAud(T1, T2); + false -> + wrong_type('ContextAttrAuditRequest_contextPropAud_val', H) + end; +chk_ContextAttrAuditRequest_contextPropAud([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, + 'ContextAttrAuditRequest_contextPropAud_val'), + chk_ContextAttrAuditRequest_contextPropAud(T1, T2); +chk_ContextAttrAuditRequest_contextPropAud(T1, T2) -> + wrong_type('ContextAttrAuditRequest_contextPropAud', T1, T2). + + +%% -- CommandRequest -- + +is_CommandRequest(#'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = WR}) -> + d("is_CommandRequest -> entry"), + is_Command(Cmd) andalso is_opt_NULL(Opt) andalso is_opt_NULL(WR); +is_CommandRequest(_) -> + false. + +chk_CommandRequest(C, C) -> + chk_type(fun is_CommandRequest/1, 'CommandRequest', C); +chk_CommandRequest(#'CommandRequest'{command = Cmd1, + optional = Opt1, + wildcardReturn = WR1}, + #'CommandRequest'{command = Cmd2, + optional = Opt2, + wildcardReturn = WR2}) -> + validate(fun() -> chk_Command(Cmd1, Cmd2) end, 'CommandRequest'), + validate(fun() -> chk_opt_NULL(Opt1, Opt2) end, 'CommandRequest'), + validate(fun() -> chk_opt_NULL(WR1, WR2) end, 'CommandRequest'), + ok; +chk_CommandRequest(R1, R2) -> + wrong_type('CommandRequest', R1, R2). + + +%% -- Command -- + +is_Command({Tag, Val}) -> + d("is_Command -> entry"), + is_Command_tag(Tag) andalso is_Command_val(Tag, Val); +is_Command(_) -> + false. + +is_Command_tag(Tag) -> + Tags = [addReq, moveReq, modReq, subtractReq, auditCapRequest, + auditValueRequest, notifyReq, serviceChangeReq], + lists:member(Tag, Tags). + +is_Command_val(addReq, V) -> is_AmmRequest(V); +is_Command_val(moveReq, V) -> is_AmmRequest(V); +is_Command_val(modReq, V) -> is_AmmRequest(V); +is_Command_val(subtractReq, V) -> is_SubtractRequest(V); +is_Command_val(auditCapRequest, V) -> is_AuditRequest(V); +is_Command_val(auditValueRequest, V) -> is_AuditRequest(V); +is_Command_val(notifyReq, V) -> is_NotifyRequest(V); +is_Command_val(serviceChangeReq, V) -> is_ServiceChangeRequest(V). + +chk_Command(Cmd, Cmd) -> + chk_type(fun is_Command/1, 'Command', Cmd); +chk_Command({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> + case (is_Command_tag(Tag) andalso + is_Command_val(Tag, Val1) andalso + is_Command_val(Tag, Val2)) of + true -> + chk_Command_val(Tag, Val1, Val2); + false -> + wrong_type('Command', Cmd1, Cmd2) + end; +chk_Command({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> + case ((is_Command_tag(Tag1) andalso is_Command_val(Tag1, Val1)) andalso + (is_Command_tag(Tag2) andalso is_Command_val(Tag2, Val2))) of + true -> + not_equal('Command', Cmd1, Cmd2); + false -> + wrong_type('Command', Cmd1, Cmd2) + end; +chk_Command(Cmd1, Cmd2) -> + wrong_type('Command', Cmd1, Cmd2). + + +chk_Command_val(addReq, R1, R2) -> + validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_addReq'); +chk_Command_val(moveReq, R1, R2) -> + validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_moveReq'); +chk_Command_val(modReq, R1, R2) -> + validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_modReq'); +chk_Command_val(subtractReq, R1, R2) -> + validate(fun() -> chk_SubtractRequest(R1, R2) end, 'Command_subtractReq'); +chk_Command_val(auditCapRequest, R1, R2) -> + validate(fun() -> chk_AuditRequest(R1, R2) end, 'Command_auditCapRequest'); +chk_Command_val(auditValueRequest, R1, R2) -> + validate(fun() -> chk_AuditRequest(R1, R2) end, + 'Command_auditValueRequest'); +chk_Command_val(notifyReq, R1, R2) -> + validate(fun() -> chk_NotifyRequest(R1, R2) end, 'Command_notifyReq'); +chk_Command_val(serviceChangeReq, R1, R2) -> + validate(fun() -> chk_ServiceChangeRequest(R1, R2) end, + 'Command_serviceChangeReq'). + + +%% -- CommandReply -- + +is_CommandReply({Tag, Val}) -> + d("is_CommandReply -> entry"), + is_CommandReply_tag(Tag) andalso is_CommandReply_val(Tag, Val); +is_CommandReply(_) -> + false. + +is_CommandReply_tag(Tag) -> + Tags = [addReply, moveReply, modReply, subtractReply, + auditCapReply, auditValueReply, notifyReply, serviceChangeReply], + lists:member(Tag, Tags). + +is_CommandReply_val(addReply, V) -> is_AmmsReply(V); +is_CommandReply_val(moveReply, V) -> is_AmmsReply(V); +is_CommandReply_val(modReply, V) -> is_AmmsReply(V); +is_CommandReply_val(subtractReply, V) -> is_AmmsReply(V); +is_CommandReply_val(auditCapReply, V) -> is_AuditReply(V); +is_CommandReply_val(auditValueReply, V) -> is_AuditReply(V); +is_CommandReply_val(notifyReply, V) -> is_NotifyReply(V); +is_CommandReply_val(serviceChangeReply, V) -> is_ServiceChangeReply(V). + +chk_CommandReply({Tag, Val} = Cmd, Cmd) -> + case (is_CommandReply_tag(Tag) andalso is_CommandReply_val(Tag, Val)) of + true -> + ok; + false -> + wrong_type('CommandReply', Cmd) + end; +chk_CommandReply({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> + case (is_CommandReply_tag(Tag) andalso + is_CommandReply_val(Tag, Val1) andalso + is_CommandReply_val(Tag, Val2)) of + true -> + chk_CommandReply_val(Tag, Val1, Val2); + false -> + wrong_type('CommandReply', Cmd1, Cmd2) + end; +chk_CommandReply({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> + case ((is_CommandReply_tag(Tag1) andalso + is_CommandReply_val(Tag1, Val1)) andalso + (is_CommandReply_tag(Tag2) andalso + is_CommandReply_val(Tag2, Val2))) of + true -> + not_equal('CommandReply', Cmd1, Cmd2); + false -> + wrong_type('CommandReply', Cmd1, Cmd2) + end; +chk_CommandReply(Cmd1, Cmd2) -> + wrong_type('CommandReply', Cmd1, Cmd2). + +chk_CommandReply_val(addReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_addReply'); +chk_CommandReply_val(moveReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_moveReply'); +chk_CommandReply_val(modReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_modReply'); +chk_CommandReply_val(subtractReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_subtractReply'); +chk_CommandReply_val(auditCapReply, V1, V2) -> + validate(fun() -> chk_AuditReply(V1, V2) end, + 'CommandReply_auditCapReply'); +chk_CommandReply_val(auditValueReply, V1, V2) -> + validate(fun() -> chk_AuditReply(V1, V2) end, + 'CommandReply_auditValueReply'); +chk_CommandReply_val(notifyReply, V1, V2) -> + validate(fun() -> chk_NotifyReply(V1, V2) end, 'CommandReply_notifyReply'); +chk_CommandReply_val(serviceChangeReply, V1, V2) -> + validate(fun() -> chk_ServiceChangeReply(V1, V2) end, + 'CommandReply_serviceChangeReply'). + + +%% -- TopologyRequest -- + +is_TopologyRequest(#'TopologyRequest'{terminationFrom = F, + terminationTo = T, + topologyDirection = D, + streamID = S}) -> + d("is_TopologyRequest -> entry"), + is_TerminationID(F) andalso + is_TerminationID(T) andalso + is_TopologyRequest_topologyDirection(D) andalso + is_opt_StreamID(S); +is_TopologyRequest(_) -> + false. + +is_TopologyRequest_topologyDirection(D) -> + lists:member(D, [bothway, isolate, oneway]). + + +chk_TopologyRequest(T, T) when is_record(T,'TopologyRequest') -> + ok; +chk_TopologyRequest(#'TopologyRequest'{terminationFrom = F1, + terminationTo = T1, + topologyDirection = D1, + streamID = S1}, + #'TopologyRequest'{terminationFrom = F2, + terminationTo = T2, + topologyDirection = D2, + streamID = S2}) -> + validate(fun() -> chk_TerminationID(F1, F2) end, + 'TopologyRequest_terminationFrom'), + validate(fun() -> chk_TerminationID(T1, T2) end, + 'TopologyRequest_terminationTo'), + chk_TopologyRequest_topologyDirection(D1,D2), + validate(fun() -> chk_StreamID(S1, S2) end, 'TopologyRequest_streamID'), + ok. + +chk_TopologyRequest_topologyDirection(D, D) -> + case is_TopologyRequest_topologyDirection(D) of + true -> + ok; + false -> + wrong_type('TopologyRequest_topologyDirection', D) + end; +chk_TopologyRequest_topologyDirection(D1, D2) -> + case (is_TopologyRequest_topologyDirection(D1) andalso + is_TopologyRequest_topologyDirection(D1)) of + true -> + not_equal('TopologyRequest_topologyDirection', D1, D2); + false -> + wrong_type('TopologyRequest_topologyDirection', D1, D2) + end. + + +%% -- AmmRequest -- + +is_AmmRequest(#'AmmRequest'{terminationID = Tids, + descriptors = Descs}) -> + d("is_AmmRequest -> entry with" + "~n Tids: ~p", [Tids]), + is_TerminationIDList(Tids) andalso is_AmmRequest_descriptors(Descs); +is_AmmRequest(_) -> + false. + +is_AmmRequest_descriptors(Descs) -> + d("is_AmmRequest_descriptors -> entry"), + is_AmmRequest_descriptors(Descs, []). + +is_AmmRequest_descriptors([], _) -> + true; +is_AmmRequest_descriptors([{Tag, _} = Desc|Descs], FoundDescs) -> + d("is_AmmRequest_descriptors -> entry with" + "~n Tag: ~p" + "~n FoundDescs: ~p", [Tag, FoundDescs]), + case lists:member(Tag, FoundDescs) of + true -> + atmost_once('AmmRequest_descriptors', Tag); + false -> + case is_AmmDescriptor(Desc) of + true -> + is_AmmRequest_descriptors(Descs, [Tag|FoundDescs]); + false -> + wrong_type('AmmRequest_descriptors', Desc) + end + end; +is_AmmRequest_descriptors(Descs, _) -> + d("is_AmmRequest_descriptors -> entry with WRONG TYPE" + "~n Descs: ~p", [Descs]), + wrong_type('AmmRequest_descriptors', Descs). + + +chk_AmmRequest(R, R) when is_record(R, 'AmmRequest') -> + d("chk_AmmRequest -> entry when equal"), + chk_type(fun is_AmmRequest/1, 'AmmRequest', R); +chk_AmmRequest(#'AmmRequest'{terminationID = Tids1, + descriptors = Descs1}, + #'AmmRequest'{terminationID = Tids2, + descriptors = Descs2}) -> + d("chk_AmmRequest -> entry with not equal" + "~n Tids1: ~p" + "~n Tids2: ~p", [Tids1, Tids2]), + validate( + fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'AmmRequest'), + validate( + fun() -> chk_AmmRequest_descriptors(Descs1, Descs2) end, + 'AmmRequest'), + ok. + + +chk_AmmRequest_descriptors([], []) -> + d("chk_AmmRequest_descriptors -> done when OK"), + ok; +chk_AmmRequest_descriptors([] = Descs1, Descs2) -> + d("chk_AmmRequest_descriptors -> done when NOT EQUAL:" + "~n Descs1: ~p" + "~n Descs1: ~p", [Descs1, Descs2]), + not_equal('AmmRequest_descriptors', Descs1, Descs2); +chk_AmmRequest_descriptors(Descs1, [] = Descs2) -> + d("chk_AmmRequest_descriptors -> done when NOT EQUAL:" + "~n Descs1: ~p" + "~n Descs1: ~p", [Descs1, Descs2]), + not_equal('AmmRequest_descriptors', Descs1, Descs2); +chk_AmmRequest_descriptors([H|T1], [H|T2]) -> + d("chk_AmmRequest_descriptors -> entry when equal"), + case is_AmmDescriptor(H) of + true -> + chk_AmmRequest_descriptors(T1, T2); + false -> + wrong_type('AmmRequest_descriptors_val', H) + end; +chk_AmmRequest_descriptors([H1|T1], [H2|T2]) -> + d("chk_AmmRequest_descriptors -> entry when not equal"), + validate(fun() -> chk_AmmDescriptor(H1, H2) end, + 'AmmRequest_descriptors_val'), + chk_AmmRequest_descriptors(T1, T2); +chk_AmmRequest_descriptors(Descs1, Descs2) -> + d("chk_AmmRequest_descriptors -> done when WRONG TYPE:" + "~n Descs1: ~p" + "~n Descs1: ~p", [Descs1, Descs2]), + wrong_type('AmmRequest_descriptors', Descs1, Descs2). + + +%% -- AmmDescriptor -- + +is_AmmDescriptor({Tag, Val}) -> + d("is_AmmDescriptor -> entry with" + "~n Tag: ~p" + "~n Val: ~p",[Tag, Val]), + is_AmmDescriptor_tag(Tag) andalso is_AmmDescriptor_val(Tag, Val); +is_AmmDescriptor(_) -> + false. + +is_AmmDescriptor_tag(Tag) -> + Tags = [mediaDescriptor, modemDescriptor, muxDescriptor, eventsDescriptor, + eventBufferDescriptor, signalsDescriptor, digitMapDescriptor, + auditDescriptor, statisticsDescriptor], + lists:member(Tag, Tags). + +is_AmmDescriptor_val(mediaDescriptor, D) -> + is_MediaDescriptor(D); +is_AmmDescriptor_val(modemDescriptor, D) -> + is_ModemDescriptor(D); +is_AmmDescriptor_val(muxDescriptor, D) -> + is_MuxDescriptor(D); +is_AmmDescriptor_val(eventsDescriptor, D) -> + is_EventsDescriptor(D); +is_AmmDescriptor_val(eventBufferDescriptor, D) -> + is_EventBufferDescriptor(D); +is_AmmDescriptor_val(signalsDescriptor, D) -> + is_SignalsDescriptor(D); +is_AmmDescriptor_val(digitMapDescriptor, D) -> + is_DigitMapDescriptor(D); +is_AmmDescriptor_val(auditDescriptor, D) -> + is_AuditDescriptor(D); +is_AmmDescriptor_val(statisticsDescriptor, D) -> + is_StatisticsDescriptor(D). + +chk_AmmDescriptor(D, D) -> + chk_type(fun is_AmmDescriptor_tag/1, 'AmmDescriptor', D); +chk_AmmDescriptor({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> + case (is_AmmDescriptor_tag(Tag) andalso + is_AmmDescriptor_val(Tag, Val1) andalso + is_AmmDescriptor_val(Tag, Val2)) of + true -> + chk_AmmDescriptor_val(Tag, Val1, Val2); + false -> + wrong_type('AmmDescriptor', Cmd1, Cmd2) + end; +chk_AmmDescriptor({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> + case ((is_AmmDescriptor_tag(Tag1) andalso + is_AmmDescriptor_val(Tag1, Val1)) andalso + (is_AmmDescriptor_tag(Tag2) andalso + is_AmmDescriptor_val(Tag2, Val2))) of + true -> + not_equal('AmmDescriptor', Cmd1, Cmd2); + false -> + wrong_type('AmmDescriptor', Cmd1, Cmd2) + end; +chk_AmmDescriptor(Cmd1, Cmd2) -> + wrong_type('AmmDescriptor', Cmd1, Cmd2). + +chk_AmmDescriptor_val(mediaDescriptor, D1, D2) -> + validate(fun() -> chk_MediaDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(modemDescriptor, D1, D2) -> + validate(fun() -> chk_ModemDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(muxDescriptor, D1, D2) -> + validate(fun() -> chk_MuxDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(eventsDescriptor, D1, D2) -> + validate(fun() -> chk_EventsDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(eventBufferDescriptor, D1, D2) -> + validate(fun() -> chk_EventBufferDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(signalsDescriptor, D1, D2) -> + validate(fun() -> chk_SignalsDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(digitMapDescriptor, D1, D2) -> + validate(fun() -> chk_DigitMapDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(auditDescriptor, D1, D2) -> + validate(fun() -> chk_AuditDescriptor(D1, D2) end, 'AmmDescriptor'). + + +%% -- AmmsReply -- + +is_AmmsReply(#'AmmsReply'{terminationID = Tids, + terminationAudit = TA}) -> + is_TerminationIDList(Tids) andalso is_opt_TerminationAudit(TA); +is_AmmsReply(_) -> + false. + +chk_AmmsReply(R, R) -> + is_AmmsReply(R); +chk_AmmsReply(#'AmmsReply'{terminationID = TID1, + terminationAudit = TA1}, + #'AmmsReply'{terminationID = TID2, + terminationAudit = TA2}) -> + validate(fun() -> chk_TerminationIDList(TID1, TID2) end, 'AmmsReply'), + validate(fun() -> chk_opt_TerminationAudit(TA1, TA2) end, 'AmmsReply'), + ok; +chk_AmmsReply(R1, R2) -> + wrong_type('AmmsReply', R1, R2). + + +%% -- SubtractRequest -- + +is_SubtractRequest(#'SubtractRequest'{terminationID = Tids, + auditDescriptor = AD}) -> + is_TerminationIDList(Tids) andalso is_opt_AuditDescriptor(AD); +is_SubtractRequest(_) -> + false. + +chk_SubtractRequest(R, R) -> + chk_type(fun is_SubtractRequest/1, 'SubtractRequest', R); +chk_SubtractRequest(#'SubtractRequest'{terminationID = Tids1, + auditDescriptor = AD1}, + #'SubtractRequest'{terminationID = Tids2, + auditDescriptor = AD2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'SubtractRequest'), + validate(fun() -> chk_opt_AuditDescriptor(AD1, AD2) end, + 'SubtractRequest'), + ok; +chk_SubtractRequest(SR1, SR2) -> + wrong_type('SubtractRequest', SR1, SR2). + + +%% -- AuditRequest -- + +is_AuditRequest(#'AuditRequest'{terminationID = Tid, + auditDescriptor = AD}) -> + is_TerminationID(Tid) andalso is_AuditDescriptor(AD); +is_AuditRequest(_) -> + false. + +chk_AuditRequest(R, R) -> + chk_type(fun is_AuditRequest/1, 'AuditRequest', R); +chk_AuditRequest(#'AuditRequest'{terminationID = Tids1, + auditDescriptor = AD1}, + #'AuditRequest'{terminationID = Tids2, + auditDescriptor = AD2}) -> + validate(fun() -> chk_TerminationID(Tids1, Tids2) end, + 'AuditRequest'), + validate(fun() -> chk_AuditDescriptor(AD1, AD2) end, + 'AuditRequest'), + ok; +chk_AuditRequest(AR1, AR2) -> + wrong_type('AuditRequest', AR1, AR2). + + +%% -- AuditReply -- + +is_AuditReply({Tag, Val}) -> + is_AuditReply_tag(Tag) andalso is_AuditReply_val(Tag, Val); +is_AuditReply(_) -> + false. + +is_AuditReply_tag(Tag) -> + Tags = [contextAuditResult, error, auditResult], + lists:member(Tag, Tags). + +is_AuditReply_val(contextAuditResult, Val) -> + is_TerminationIDList(Val); +is_AuditReply_val(error, Val) -> + is_ErrorDescriptor(Val); +is_AuditReply_val(auditResult, Val) -> + is_AuditResult(Val). + +chk_AuditReply(R, R) -> + chk_type(fun is_AuditReply/1, 'AuditReply', R); +chk_AuditReply({Tag, Val1} = R1, {Tag, Val2} = R2) -> + case (is_AuditReply_tag(Tag) andalso + is_AuditReply_val(Tag, Val1)andalso + is_AuditReply_val(Tag, Val2)) of + true -> + chk_AuditReply_val(Tag, Val1, Val2); + false -> + wrong_type('AuditReply', R1, R2) + end; +chk_AuditReply({Tag1, Val1} = R1, {Tag2, Val2} = R2) -> + case ((is_AuditReply_tag(Tag1) andalso + is_AuditReply_val(Tag1, Val1)) andalso + (is_AuditReply_tag(Tag2) andalso + is_AuditReply_val(Tag2, Val2))) of + true -> + not_equal('AuditReply', R1, R2); + false -> + wrong_type('AuditReply', R1, R2) + end; +chk_AuditReply(AR1, AR2) -> + wrong_type('AuditReply', AR1, AR2). + +chk_AuditReply_val(contextAuditResult, Val1, Val2) -> + chk_TerminationIDList(Val1, Val2); +chk_AuditReply_val(error, Val1, Val2) -> + chk_ErrorDescriptor(Val1, Val2); +chk_AuditReply_val(auditResult, Val1, Val2) -> + chk_AuditResult(Val1, Val2). + + +%% -- AuditResult -- + +is_AuditResult(#'AuditResult'{terminationID = TID, + terminationAuditResult = TAR}) -> + is_TerminationID(TID) andalso is_TerminationAudit(TAR); +is_AuditResult(_) -> + false. + +chk_AuditResult(R, R) -> + chk_type(fun is_AuditResult/1, 'AuditResult', R); +chk_AuditResult(#'AuditResult'{terminationID = TID1, + terminationAuditResult = TAR1}, + #'AuditResult'{terminationID = TID2, + terminationAuditResult = TAR2}) -> + validate(fun() -> chk_TerminationID(TID1, TID2) end, 'AuditResult'), + validate(fun() -> chk_TerminationAudit(TAR1, TAR2) end, 'AuditResult'), + ok; +chk_AuditResult(AR1, AR2) -> + wrong_type('AuditResult', AR1, AR2). + + +%% -- TerminationAudit -- + +is_opt_TerminationAudit(TA) -> + is_OPTIONAL(fun is_TerminationAudit/1, TA). + +is_TerminationAudit([]) -> + true; +is_TerminationAudit([H|T]) -> + is_AuditReturnParameter(H) andalso is_TerminationAudit(T); +is_TerminationAudit(_) -> + false. + +chk_opt_TerminationAudit(TA1, TA2) -> + chk_OPTIONAL('TerminationAudit', TA1, TA2, + fun is_TerminationAudit/1, fun chk_TerminationAudit/2). + +chk_TerminationAudit([], []) -> + ok; +chk_TerminationAudit([] = TA1, TA2) -> + not_equal('TerminationAudit', TA1, TA2); +chk_TerminationAudit(TA1, [] = TA2) -> + not_equal('TerminationAudit', TA1, TA2); +chk_TerminationAudit([H|T1], [H|T2]) -> + case is_AuditReturnParameter(H) of + true -> + chk_TerminationAudit(T1, T2); + false -> + wrong_type('TerminationAudit', H) + end; +chk_TerminationAudit([H1|_], [H2|_]) -> + chk_AuditReturnParameter(H1, H2), + not_equal('TerminationAudit_val', H1, H2); +chk_TerminationAudit(TA1, TA2) -> + not_equal('TerminationAudit', TA1, TA2). + + +%% -- AuditReturnParameter -- + +is_AuditReturnParameter({Tag, Val}) -> + is_AuditReturnParameter_tag(Tag) andalso + is_AuditReturnParameter_val(Tag, Val); +is_AuditReturnParameter(_) -> + false. + +is_AuditReturnParameter_tag(Tag) -> + Tags = [errorDescriptor, + mediaDescriptor, + modemDescriptor, + muxDescriptor, + eventsDescriptor, + eventBufferDescriptor, + signalsDescriptor, + digitMapDescriptor, + observedEventsDescriptor, + statisticsDescriptor, + packagesDescriptor, + emptyDescriptors], + lists:member(Tag, Tags). + +is_AuditReturnParameter_val(errorDescriptor, V) -> + is_ErrorDescriptor(V); +is_AuditReturnParameter_val(mediaDescriptor, V) -> + is_MediaDescriptor(V); +is_AuditReturnParameter_val(modemDescriptor, V) -> + is_ModemDescriptor(V); +is_AuditReturnParameter_val(muxDescriptor, V) -> + is_MuxDescriptor(V); +is_AuditReturnParameter_val(eventsDescriptor, V) -> + is_EventsDescriptor(V); +is_AuditReturnParameter_val(eventBufferDescriptor, V) -> + is_EventBufferDescriptor(V); +is_AuditReturnParameter_val(signalsDescriptor, V) -> + is_SignalsDescriptor(V); +is_AuditReturnParameter_val(digitMapDescriptor, V) -> + is_DigitMapDescriptor(V); +is_AuditReturnParameter_val(observedEventsDescriptor, V) -> + is_ObservedEventsDescriptor(V); +is_AuditReturnParameter_val(statisticsDescriptor, V) -> + is_StatisticsDescriptor(V); +is_AuditReturnParameter_val(packagesDescriptor, V) -> + is_PackagesDescriptor(V); +is_AuditReturnParameter_val(emptyDescriptors, V) -> + is_AuditDescriptor(V). + +chk_AuditReturnParameter(ARP, ARP) -> + chk_type(fun is_AuditReturnParameter/1, 'AuditReturnParameter', ARP); +chk_AuditReturnParameter({Tag, Val1} = ARP1, {Tag, Val2} = ARP2) -> + case (is_AuditReturnParameter_tag(Tag) andalso + is_AuditReturnParameter_val(Tag, Val1) andalso + is_AuditReturnParameter_val(Tag, Val2)) of + true -> + chk_AuditReturnParameter_val(Tag, Val1, Val2); + false -> + wrong_type('AuditReturnParameter', ARP1, ARP2) + end; +chk_AuditReturnParameter({Tag1, Val1} = ARP1, {Tag2, Val2} = ARP2) -> + case ((is_AuditReturnParameter_tag(Tag1) andalso + is_AuditReturnParameter_val(Tag1, Val1)) andalso + (is_AuditReturnParameter_tag(Tag2) andalso + is_AuditReturnParameter_val(Tag2, Val2))) of + true -> + not_equal('AuditReturnParameter', ARP1, ARP2); + false -> + wrong_type('AuditReturnParameter', ARP1, ARP2) + end; +chk_AuditReturnParameter(ARP1, ARP2) -> + wrong_type('AuditReturnParameter', ARP1, ARP2). + +chk_AuditReturnParameter_val(errorDescriptor, V1, V2) -> + validate(fun() -> chk_ErrorDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(mediaDescriptor, V1, V2) -> + validate(fun() -> chk_MediaDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(modemDescriptor, V1, V2) -> + validate(fun() -> chk_ModemDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(muxDescriptor, V1, V2) -> + validate(fun() -> chk_MuxDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(eventsDescriptor, V1, V2) -> + validate(fun() -> chk_EventsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(eventBufferDescriptor, V1, V2) -> + validate(fun() -> chk_EventBufferDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(signalsDescriptor, V1, V2) -> + validate(fun() -> chk_SignalsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(digitMapDescriptor, V1, V2) -> + validate(fun() -> chk_DigitMapDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(observedEventsDescriptor, V1, V2) -> + validate(fun() -> chk_ObservedEventsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(statisticsDescriptor, V1, V2) -> + validate(fun() -> chk_StatisticsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(packagesDescriptor, V1, V2) -> + validate(fun() -> chk_PackagesDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(emptyDescriptors, V1, V2) -> + validate(fun() -> chk_AuditDescriptor(V1, V2) end, + 'AuditReturnParameter'). + + +%% -- AuditDescriptor -- + +is_opt_AuditDescriptor(asn1_NOVALUE) -> + true; +is_opt_AuditDescriptor(V) -> + is_AuditDescriptor(V). + +is_AuditDescriptor(#'AuditDescriptor'{auditToken = AT, + auditPropertyToken = APT}) -> + is_AuditDescriptor_auditToken(AT) andalso + is_AuditDescriptor_auditPropertyToken(APT); +is_AuditDescriptor(_) -> + false. + +is_AuditDescriptor_auditToken(asn1_NOVALUE) -> + true; +is_AuditDescriptor_auditToken([]) -> + true; +is_AuditDescriptor_auditToken([H|T]) -> + is_AuditDescriptor_auditToken_val(H) andalso + is_AuditDescriptor_auditToken(T); +is_AuditDescriptor_auditToken(_) -> + false. + +is_AuditDescriptor_auditToken_val(V) -> + Toks = [muxToken, modemToken, mediaToken, eventsToken, signalsToken, + digitMapToken, statsToken, observedEventsToken, + packagesToken, eventBufferToken], + lists:member(V, Toks). + +is_AuditDescriptor_auditPropertyToken(asn1_NOVALUE) -> + true; +is_AuditDescriptor_auditPropertyToken([]) -> + true; +is_AuditDescriptor_auditPropertyToken([H|T]) -> + is_IndAuditParameter(H) andalso is_AuditDescriptor_auditPropertyToken(T); +is_AuditDescriptor_auditPropertyToken(_) -> + false. + +chk_opt_AuditDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_AuditDescriptor(AD1, AD2) -> + chk_AuditDescriptor(AD1, AD2). + +chk_AuditDescriptor(AD, AD) -> + chk_type(fun is_AuditDescriptor/1, 'AuditDescriptor', AD); +chk_AuditDescriptor(#'AuditDescriptor'{auditToken = AT1, + auditPropertyToken = APT1}, + #'AuditDescriptor'{auditToken = AT2, + auditPropertyToken = APT2}) -> + chk_AuditDescriptor_auditToken(AT1, AT2), + chk_AuditDescriptor_auditPropertyToken(APT1, APT2), + ok; +chk_AuditDescriptor(AD1, AD2) -> + wrong_type('AuditDescriptor', AD1, AD2). + +chk_AuditDescriptor_auditToken(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_AuditDescriptor_auditToken([], []) -> + ok; +chk_AuditDescriptor_auditToken([] = AT1, AT2) -> + not_equal('AuditDescriptor_auditToken', AT1, AT2); +chk_AuditDescriptor_auditToken(AT1, [] = AT2) -> + not_equal('AuditDescriptor_auditToken', AT1, AT2); +chk_AuditDescriptor_auditToken([H|T1], [H|T2]) -> + case is_AuditDescriptor_auditToken_val(H) of + true -> + chk_AuditDescriptor_auditToken(T1, T2); + false -> + wrong_type('AuditDescriptor_auditToken_val', H) + end; +chk_AuditDescriptor_auditToken([H1|_T1], [H2|_T2]) -> + case (is_AuditDescriptor_auditToken_val(H1) andalso + is_AuditDescriptor_auditToken_val(H2)) of + true -> + not_equal('AuditDescriptor_auditToken_val', H1, H2); + false -> + wrong_type('AuditDescriptor_auditToken_val', H1, H2) + end; +chk_AuditDescriptor_auditToken(AT1, AT2) -> + wrong_type('AuditDescriptor_auditToken', AT1, AT2). + +chk_AuditDescriptor_auditPropertyToken(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_AuditDescriptor_auditPropertyToken([], []) -> + ok; +chk_AuditDescriptor_auditPropertyToken([] = AT1, AT2) -> + not_equal('AuditDescriptor_auditPropertyToken', AT1, AT2); +chk_AuditDescriptor_auditPropertyToken(AT1, [] = AT2) -> + not_equal('AuditDescriptor_auditPropertyToken', AT1, AT2); +chk_AuditDescriptor_auditPropertyToken([H|T1], [H|T2]) -> + case is_IndAuditParameter(H) of + true -> + chk_AuditDescriptor_auditPropertyToken(T1, T2); + false -> + wrong_type('AuditDescriptor_auditPropertyToken_val', H) + end; +chk_AuditDescriptor_auditPropertyToken([H1|_], [H2|_]) -> + chk_IndAuditParameter(H1, H2), + not_equal('AuditDescriptor_auditPropertyToken_val', H1, H2); +chk_AuditDescriptor_auditPropertyToken(AT1, AT2) -> + wrong_type('AuditDescriptor_auditPropertyToken', AT1, AT2). + + +%% -- IndAuditParameter -- + +is_IndAuditParameter({Tag, Val}) -> + is_IndAuditParameter_tag(Tag) andalso is_IndAuditParameter_val(Tag, Val); +is_IndAuditParameter(_) -> + false. + +is_IndAuditParameter_tag(Tag) -> + Tags = [indAudMediaDescriptor, + indAudEventsDescriptor, + indAudEventBufferDescriptor, + indAudSignalsDescriptor, + indAudDigitMapDescriptor, + indAudStatisticsDescriptor, + indAudPackagesDescriptor], + lists:member(Tag, Tags). + +is_IndAuditParameter_val(indAudMediaDescriptor, Val) -> + is_IndAudMediaDescriptor(Val); +is_IndAuditParameter_val(indAudEventsDescriptor, Val) -> + is_IndAudEventsDescriptor(Val); +is_IndAuditParameter_val(indAudEventBufferDescriptor, Val) -> + is_IndAudEventBufferDescriptor(Val); +is_IndAuditParameter_val(indAudSignalsDescriptor, Val) -> + is_IndAudSignalsDescriptor(Val); +is_IndAuditParameter_val(indAudDigitMapDescriptor, Val) -> + is_IndAudDigitMapDescriptor(Val); +is_IndAuditParameter_val(indAudStatisticsDescriptor, Val) -> + is_IndAudStatisticsDescriptor(Val); +is_IndAuditParameter_val(indAudPackagesDescriptor, Val) -> + is_IndAudPackagesDescriptor(Val). + +chk_IndAuditParameter(IAP, IAP) -> + chk_type(fun is_IndAuditParameter/1, 'IndAuditParameter', IAP); +chk_IndAuditParameter({Tag, Val1} = IAP1, {Tag, Val2} = IAP2) -> + case (is_IndAuditParameter_tag(Tag) andalso + is_IndAuditParameter_val(Tag, Val1) andalso + is_IndAuditParameter_val(Tag, Val2)) of + true -> + chk_IndAuditParameter_val(Tag, Val1, Val2); + false -> + wrong_type('IndAuditParameter', IAP1, IAP2) + end; +chk_IndAuditParameter({Tag1, Val1} = IAP1, {Tag2, Val2} = IAP2) -> + case ((is_IndAuditParameter_tag(Tag1) andalso + is_IndAuditParameter_val(Tag1, Val1)) andalso + (is_IndAuditParameter_tag(Tag2) andalso + is_IndAuditParameter_val(Tag2, Val2))) of + true -> + not_equal('IndAuditParameter', IAP1, IAP2); + false -> + wrong_type('IndAuditParameter', IAP1, IAP2) + end; +chk_IndAuditParameter(IAP1, IAP2) -> + wrong_type('IndAuditParameter', IAP1, IAP2). + +chk_IndAuditParameter_val(indAudMediaDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudMediaDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudEventsDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudEventsDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudEventBufferDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudEventBufferDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudSignalsDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudSignalsDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudDigitMapDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudDigitMapDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudStatisticsDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudStatisticsDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudPackagesDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudPackagesDescriptor(Val1, Val2) end, + 'IndAuditParameter'). + + +%% -- IndAudMediaDescriptor -- + +is_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = S}) -> + is_opt_IndAudTerminationStateDescriptor(TSD) andalso + is_IndAudMediaDescriptor_streams(S); +is_IndAudMediaDescriptor(_) -> + false. + +is_IndAudMediaDescriptor_streams(asn1_NOVALUE) -> + true; +is_IndAudMediaDescriptor_streams({Tag, Val}) -> + is_IndAudMediaDescriptor_streams_tag(Tag) andalso + is_IndAudMediaDescriptor_streams_val(Tag, Val); +is_IndAudMediaDescriptor_streams(_) -> + false. + +is_IndAudMediaDescriptor_streams_tag(Tag) -> + Tags = [oneStream, multiStream], + lists:member(Tag, Tags). + +is_IndAudMediaDescriptor_streams_val(oneStream, Val) -> + is_IndAudStreamParms(Val); +is_IndAudMediaDescriptor_streams_val(multiStream, Val) -> + is_IndAudMediaDescriptor_multiStream(Val). + +is_IndAudMediaDescriptor_multiStream([]) -> + true; +is_IndAudMediaDescriptor_multiStream([H|T]) -> + is_IndAudStreamDescriptor(H) andalso + is_IndAudMediaDescriptor_multiStream(T); +is_IndAudMediaDescriptor_multiStream(_) -> + false. + +chk_IndAudMediaDescriptor(IAMD, IAMD) -> + chk_type(fun is_IndAudMediaDescriptor/1, 'IndAudMediaDescriptor', IAMD); +chk_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD1, + streams = S1}, + #'IndAudMediaDescriptor'{termStateDescr = TSD2, + streams = S2}) -> + validate(fun() -> chk_opt_IndAudTerminationStateDescriptor(TSD1, TSD2) end, + 'IndAudMediaDescriptor'), + validate(fun() -> chk_IndAudMediaDescriptor_streams(S1, S2) end, + 'IndAudMediaDescriptor'), + ok; +chk_IndAudMediaDescriptor(IAMD1, IAMD2) -> + wrong_type('IndAudMediaDescriptor', IAMD1, IAMD2). + +chk_IndAudMediaDescriptor_streams(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_IndAudMediaDescriptor_streams({Tag, Val1} = S1, + {Tag, Val2} = S2) -> + case (is_IndAudMediaDescriptor_streams_tag(Tag) andalso + is_IndAudMediaDescriptor_streams_val(Tag, Val1) andalso + is_IndAudMediaDescriptor_streams_val(Tag, Val2)) of + true -> + chk_IndAudMediaDescriptor_streams_val(Tag, Val1, Val2); + false -> + wrong_type('IndAudMediaDescriptor_streams', S1, S2) + end; +chk_IndAudMediaDescriptor_streams({Tag1, Val1} = S1, + {Tag2, Val2} = S2) -> + case ((is_IndAudMediaDescriptor_streams_tag(Tag1) andalso + is_IndAudMediaDescriptor_streams_val(Tag1, Val1)) andalso + (is_IndAudMediaDescriptor_streams_tag(Tag2) andalso + is_IndAudMediaDescriptor_streams_val(Tag2, Val2))) of + true -> + not_equal('IndAudMediaDescriptor_streams', S1, S2); + false -> + wrong_type('IndAudMediaDescriptor_streams', S1, S2) + end; +chk_IndAudMediaDescriptor_streams(S1, S2) -> + wrong_type('IndAudMediaDescriptor_streams', S1, S2). + +chk_IndAudMediaDescriptor_streams_val(oneStream, Val1, Val2) -> + validate(fun() -> chk_IndAudStreamParms(Val1, Val2) end, + 'IndAudMediaDescriptor_streams'); +chk_IndAudMediaDescriptor_streams_val(multiStream, Val1, Val2) -> + validate(fun() -> chk_IndAudMediaDescriptor_multiStream(Val1, Val2) end, + 'IndAudMediaDescriptor_streams'). + +chk_IndAudMediaDescriptor_multiStream([], []) -> + ok; +chk_IndAudMediaDescriptor_multiStream([] = MS1, MS2) -> + not_equal('IndAudMediaDescriptor_multiStream', MS1, MS2); +chk_IndAudMediaDescriptor_multiStream(MS1, [] = MS2) -> + not_equal('IndAudMediaDescriptor_multiStream', MS1, MS2); +chk_IndAudMediaDescriptor_multiStream([H|T1], [H|T2]) -> + case is_IndAudStreamDescriptor(H) of + true -> + chk_IndAudMediaDescriptor_multiStream(T1, T2); + false -> + wrong_type('IndAudMediaDescriptor_multiStream_val', H) + end; +chk_IndAudMediaDescriptor_multiStream([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudStreamDescriptor(H1, H2) end, + 'IndAudMediaDescriptor_multiStream_val'), + chk_IndAudMediaDescriptor_multiStream(T1, T2); +chk_IndAudMediaDescriptor_multiStream(MS1, MS2) -> + wrong_type('IndAudMediaDescriptor_multiStream', MS1, MS2). + + +%% -- IndAudStreamDescriptor -- + +is_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID, + streamParms = Parms}) -> + is_StreamID(SID) andalso is_IndAudStreamParms(Parms); +is_IndAudStreamDescriptor(_) -> + false. + +chk_IndAudStreamDescriptor(D, D) -> + chk_type(fun is_IndAudStreamDescriptor/1, 'IndAudStreamDescriptor', D); +chk_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID1, + streamParms = Parms1}, + #'IndAudStreamDescriptor'{streamID = SID2, + streamParms = Parms2}) -> + validate(fun() -> chk_StreamID(SID1, SID2) end, 'IndAudStreamDescriptor'), + validate(fun() -> chk_IndAudStreamParms(Parms1, Parms2) end, + 'IndAudStreamDescriptor'), + ok; +chk_IndAudStreamDescriptor(D1, D2) -> + wrong_type('IndAudStreamDescriptor', D1, D2). + + +%% -- IndAudStreamParms -- + +is_IndAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD}) -> + is_opt_IndAudLocalControlDescriptor(LCD) andalso + is_opt_IndAudLocalRemoteDescriptor(LD) andalso + is_opt_IndAudLocalRemoteDescriptor(RD); +is_IndAudStreamParms(_) -> + false. + +chk_IndAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD1, + localDescriptor = LD1, + remoteDescriptor = RD1}, + #'IndAudStreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2}) -> + validate(fun() -> chk_opt_IndAudLocalControlDescriptor(LCD1, LCD2) end, + 'IndAudStreamParms'), + validate(fun() -> chk_opt_IndAudLocalRemoteDescriptor(LD1, LD2) end, + 'IndAudStreamParms'), + validate(fun() -> chk_opt_IndAudLocalRemoteDescriptor(RD1, RD2) end, + 'IndAudStreamParms'), + ok; +chk_IndAudStreamParms(D1, D2) -> + wrong_type('IndAudStreamParms', D1, D2). + + +%% -- IndAudLocalControlDescriptor -- + +is_opt_IndAudLocalControlDescriptor(asn1_NOVALUE) -> + true; +is_opt_IndAudLocalControlDescriptor(D) -> + is_IndAudLocalControlDescriptor(D). + +is_IndAudLocalControlDescriptor( + #'IndAudLocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PPs}) -> + is_opt_NULL(SM) andalso is_opt_NULL(RV) andalso is_opt_NULL(RG) andalso + is_IndAudLocalControlDescriptor_propertyParms(PPs); +is_IndAudLocalControlDescriptor(_) -> + false. + +is_IndAudLocalControlDescriptor_propertyParms(asn1_NOVALUE) -> + true; +is_IndAudLocalControlDescriptor_propertyParms([]) -> + true; +is_IndAudLocalControlDescriptor_propertyParms([H|T]) -> + is_IndAudPropertyParm(H) andalso + is_IndAudLocalControlDescriptor_propertyParms(T); +is_IndAudLocalControlDescriptor_propertyParms(_) -> + false. + +chk_opt_IndAudLocalControlDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudLocalControlDescriptor( + #'IndAudLocalControlDescriptor'{streamMode = SM1, + reserveValue = RV1, + reserveGroup = RG1, + propertyParms = PPs1}, + #'IndAudLocalControlDescriptor'{streamMode = SM2, + reserveValue = RV2, + reserveGroup = RG2, + propertyParms = PPs2}) -> + chk_opt_NULL(SM1, SM2), + chk_opt_NULL(RV1, RV2), + chk_opt_NULL(RG1, RG2), + chk_IndAudLocalControlDescriptor_propertyParms(PPs1, PPs2), + ok; +chk_opt_IndAudLocalControlDescriptor(D1, D2) -> + wrong_type('IndAudLocalControlDescriptor', D1, D2). + +chk_IndAudLocalControlDescriptor_propertyParms(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_IndAudLocalControlDescriptor_propertyParms([], []) -> + ok; +chk_IndAudLocalControlDescriptor_propertyParms([] = PPs1, PPs2) -> + not_equal('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2); +chk_IndAudLocalControlDescriptor_propertyParms(PPs1, [] = PPs2) -> + not_equal('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2); +chk_IndAudLocalControlDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_IndAudLocalControlDescriptor_propertyParms(T1, T2); + false -> + wrong_type('IndAudLocalControlDescriptor_propertyParms_val', H) + end; +chk_IndAudLocalControlDescriptor_propertyParms([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, + 'IndAudLocalControlDescriptor_propertyParms_val'), + chk_IndAudLocalControlDescriptor_propertyParms(T1, T2); +chk_IndAudLocalControlDescriptor_propertyParms(PPs1, PPs2) -> + wrong_type('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2). + + +%% -- IndAudPropertyParm -- + +is_IndAudPropertyParm(#'IndAudPropertyParm'{name = Name}) -> + d("is_IndAudPropertyParm -> entry"), + is_PkgdName(Name); +is_IndAudPropertyParm(_) -> + false. + +chk_IndAudPropertyParm(#'IndAudPropertyParm'{name = Name1}, + #'IndAudPropertyParm'{name = Name2}) -> + chk_PkgdName(Name1, Name2), + ok; +chk_IndAudPropertyParm(P1, P2) -> + wrong_type('IndAudPropertyParm', P1, P2). + + +%% -- IndAudLocalRemoteDescriptor -- + +is_opt_IndAudLocalRemoteDescriptor(asn1_NOVALUE) -> + true; +is_opt_IndAudLocalRemoteDescriptor(D) -> + is_IndAudLocalRemoteDescriptor(D). + +is_IndAudLocalRemoteDescriptor( + #'IndAudLocalRemoteDescriptor'{propGroupID = ID, + propGrps = Grps}) -> + is_IndAudLocalRemoteDescriptor_propGroupID(ID) andalso + is_IndAudPropertyGroup(Grps); +is_IndAudLocalRemoteDescriptor(_) -> + false. + +is_IndAudLocalRemoteDescriptor_propGroupID(asn1_NOVALUE) -> + true; +is_IndAudLocalRemoteDescriptor_propGroupID(V) -> + is_INTEGER(V, {range, 0, 65535}). + +chk_opt_IndAudLocalRemoteDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudLocalRemoteDescriptor(D1, D2) -> + chk_IndAudLocalRemoteDescriptor(D1, D2). + +chk_IndAudLocalRemoteDescriptor(D, D) -> + chk_type(fun is_IndAudLocalRemoteDescriptor/1, + 'IndAudLocalRemoteDescriptor', D); +chk_IndAudLocalRemoteDescriptor( + #'IndAudLocalRemoteDescriptor'{propGroupID = ID1, + propGrps = Grps1}, + #'IndAudLocalRemoteDescriptor'{propGroupID = ID2, + propGrps = Grps2}) -> + chk_IndAudLocalRemoteDescriptor_propGroupID(ID1, ID2), + chk_IndAudPropertyGroup(Grps1, Grps2), + ok; +chk_IndAudLocalRemoteDescriptor(D1, D2) -> + wrong_type('IndAudLocalRemoteDescriptor', D1, D2). + +chk_IndAudLocalRemoteDescriptor_propGroupID(ID, ID) -> + chk_type(fun is_IndAudLocalRemoteDescriptor_propGroupID/1, + 'IndAudLocalRemoteDescriptor_propGroupID', ID); +chk_IndAudLocalRemoteDescriptor_propGroupID(ID1, ID2) -> + case (is_IndAudLocalRemoteDescriptor_propGroupID(ID1) andalso + is_IndAudLocalRemoteDescriptor_propGroupID(ID2)) of + true -> + not_equal('IndAudLocalRemoteDescriptor_propGroupID', ID1, ID2); + false -> + wrong_type('IndAudLocalRemoteDescriptor_propGroupID', ID1, ID2) + end. + + +%% -- IndAudPropertyGroup -- + +is_IndAudPropertyGroup([]) -> + true; +is_IndAudPropertyGroup([H|T]) -> + is_IndAudPropertyParm(H) andalso is_IndAudPropertyGroup(T); +is_IndAudPropertyGroup(_) -> + false. + +chk_IndAudPropertyGroup([], []) -> + ok; +chk_IndAudPropertyGroup([] = PG1, PG2) -> + not_equal('IndAudPropertyGroup', PG1, PG2); +chk_IndAudPropertyGroup(PG1, [] = PG2) -> + not_equal('IndAudPropertyGroup', PG1, PG2); +chk_IndAudPropertyGroup([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_IndAudPropertyGroup(T1, T2); + false -> + wrong_type('IndAudPropertyGroup_val', H) + end; +chk_IndAudPropertyGroup([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, + 'IndAudPropertyGroup_val'), + chk_IndAudPropertyGroup(T1, T2); +chk_IndAudPropertyGroup(P1, P2) -> + wrong_type('IndAudPropertyGroup', P1, P2). + + +%% -- IndAudTerminationStateDescriptor -- + +is_opt_IndAudTerminationStateDescriptor(asn1_NOVALUE) -> + true; +is_opt_IndAudTerminationStateDescriptor(D) -> + is_IndAudTerminationStateDescriptor(D). + +is_IndAudTerminationStateDescriptor( + #'IndAudTerminationStateDescriptor'{propertyParms = Parms, + eventBufferControl = EBC, + serviceState = SS}) -> + is_IndAudTerminationStateDescriptor_propertyParms(Parms) andalso + is_opt_NULL(EBC) andalso is_opt_NULL(SS); +is_IndAudTerminationStateDescriptor(_) -> + false. + +is_IndAudTerminationStateDescriptor_propertyParms([]) -> + true; +is_IndAudTerminationStateDescriptor_propertyParms([H|T]) -> + is_IndAudPropertyParm(H) andalso + is_IndAudTerminationStateDescriptor_propertyParms(T); +is_IndAudTerminationStateDescriptor_propertyParms(_) -> + false. + +chk_opt_IndAudTerminationStateDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudTerminationStateDescriptor(D1, D2) -> + chk_IndAudTerminationStateDescriptor(D1, D2). + +chk_IndAudTerminationStateDescriptor( + #'IndAudTerminationStateDescriptor'{propertyParms = Parms1, + eventBufferControl = EBC1, + serviceState = SS1}, + #'IndAudTerminationStateDescriptor'{propertyParms = Parms2, + eventBufferControl = EBC2, + serviceState = SS2}) -> + chk_IndAudTerminationStateDescriptor_propertyParms(Parms1, Parms2), + validate(fun() -> chk_opt_NULL(EBC1, EBC2) end, + 'IndAudTerminationStateDescriptor'), + validate(fun() -> chk_opt_NULL(SS1, SS2) end, + 'IndAudTerminationStateDescriptor'), + ok; +chk_IndAudTerminationStateDescriptor(D1, D2) -> + wrong_type('IndAudTerminationStateDescriptor', D1, D2). + +chk_IndAudTerminationStateDescriptor_propertyParms([], []) -> + ok; +chk_IndAudTerminationStateDescriptor_propertyParms([] = PP1, PP2) -> + not_equal('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2); +chk_IndAudTerminationStateDescriptor_propertyParms(PP1, [] = PP2) -> + not_equal('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2); +chk_IndAudTerminationStateDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_IndAudTerminationStateDescriptor_propertyParms(T1, T2); + false -> + wrong_type('IndAudTerminationStateDescriptor_propertyParms', H) + end; +chk_IndAudTerminationStateDescriptor_propertyParms([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, + 'IndAudTerminationStateDescriptor_propertyParms'), + chk_IndAudTerminationStateDescriptor_propertyParms(T1, T2); +chk_IndAudTerminationStateDescriptor_propertyParms(PP1, PP2) -> + wrong_type('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2). + + +%% -- IndAudEventsDescriptor -- + +is_IndAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID, + pkgdName = Name, + streamID = SID}) -> + is_opt_RequestID(RID) andalso + is_PkgdName(Name) andalso + is_opt_StreamID(SID); +is_IndAudEventsDescriptor(_) -> + false. + +chk_IndAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID1, + pkgdName = Name1, + streamID = SID1}, + #'IndAudEventsDescriptor'{requestID = RID2, + pkgdName = Name2, + streamID = SID2}) -> + chk_opt_RequestID(RID1, RID2), + chk_PkgdName(Name1, Name2), + chk_opt_StreamID(SID1, SID2), + ok; +chk_IndAudEventsDescriptor(D1, D2) -> + wrong_type('IndAudEventsDescriptor', D1, D2). + + +%% -- IndAudEventBufferDescriptor -- + +is_IndAudEventBufferDescriptor( + #'IndAudEventBufferDescriptor'{eventName = Name, + streamID = SID}) -> + is_PkgdName(Name) andalso is_opt_StreamID(SID); +is_IndAudEventBufferDescriptor(_) -> + false. + +chk_IndAudEventBufferDescriptor( + #'IndAudEventBufferDescriptor'{eventName = Name1, + streamID = SID1}, + #'IndAudEventBufferDescriptor'{eventName = Name2, + streamID = SID2}) -> + chk_PkgdName(Name1, Name2), + chk_opt_StreamID(SID1, SID2), + ok; +chk_IndAudEventBufferDescriptor(D1, D2) -> + wrong_type('IndAudEventBufferDescriptor', D1, D2). + + +%% -- IndAudSignalsDescriptor -- + +is_IndAudSignalsDescriptor({Tag, Val}) -> + is_IndAudSignalsDescriptor_tag(Tag) andalso + is_IndAudSignalsDescriptor_val(Tag, Val); +is_IndAudSignalsDescriptor(_) -> + false. + +is_IndAudSignalsDescriptor_tag(Tag) -> + Tags = [signal, seqSigList], + lists:member(Tag, Tags). + +is_IndAudSignalsDescriptor_val(signal, Val) -> + is_IndAudSignal(Val); +is_IndAudSignalsDescriptor_val(seqSigList, Val) -> + is_IndAudSeqSigList(Val). + +chk_IndAudSignalsDescriptor(D, D) -> + chk_type(fun is_IndAudSignalsDescriptor/1, 'IndAudSignalsDescriptor', D); +chk_IndAudSignalsDescriptor({Tag, Val1} = D1, {Tag, Val2} = D2) -> + case (is_IndAudSignalsDescriptor_tag(Tag) andalso + is_IndAudSignalsDescriptor_val(Tag, Val1) andalso + is_IndAudSignalsDescriptor_val(Tag, Val2)) of + true -> + chk_IndAudSignalsDescriptor_val(Tag, Val1, Val2); + false -> + wrong_type('IndAudSignalsDescriptor', D1, D2) + end; +chk_IndAudSignalsDescriptor({Tag1, Val1} = D1, {Tag2, Val2} = D2) -> + case ((is_IndAudSignalsDescriptor_tag(Tag1) andalso + is_IndAudSignalsDescriptor_val(Tag1, Val1)) andalso + (is_IndAudSignalsDescriptor_tag(Tag2) andalso + is_IndAudSignalsDescriptor_val(Tag2, Val2))) of + true -> + not_equal('IndAudSignalsDescriptor', D1, D2); + false -> + wrong_type('IndAudSignalsDescriptor', D1, D2) + end; +chk_IndAudSignalsDescriptor(D1, D2) -> + wrong_type('IndAudSignalsDescriptor', D1, D2). + +chk_IndAudSignalsDescriptor_val(signal, Val1, Val2) -> + chk_IndAudSignal(Val1, Val2); +chk_IndAudSignalsDescriptor_val(seqSigList, Val1, Val2) -> + chk_IndAudSeqSigList(Val1, Val2). + + +%% -- IndAudSeqSigList -- + +is_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID, + signalList = SL}) -> + is_IndAudSeqSigList_id(ID) andalso is_opt_IndAudSignal(SL); +is_IndAudSeqSigList(_) -> + false. + +is_IndAudSeqSigList_id(ID) -> is_INTEGER(ID, {range, 0, 65535}). + +chk_IndAudSeqSigList(L, L) -> + chk_type(fun is_IndAudSeqSigList/1, 'IndAudSeqSigList', L); +chk_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID1, + signalList = SL1}, + #'IndAudSeqSigList'{id = ID2, + signalList = SL2}) -> + chk_IndAudSeqSigList_id(ID1, ID2), + chk_opt_IndAudSignal(SL1, SL2), + ok; +chk_IndAudSeqSigList(L1, L2) -> + wrong_type('IndAudSeqSigList', L1, L2). + +chk_IndAudSeqSigList_id(ID, ID) -> + chk_type(fun is_IndAudSeqSigList_id/1, 'IndAudSeqSigList_id', ID); +chk_IndAudSeqSigList_id(ID1, ID2) -> + case (is_IndAudSeqSigList_id(ID1) andalso + is_IndAudSeqSigList_id(ID2)) of + true -> + not_equal('IndAudSeqSigList_id', ID1, ID2); + false -> + wrong_type('IndAudSeqSigList_id', ID1, ID2) + end. + + +%% -- IndAudSignal -- + +is_opt_IndAudSignal(asn1_NOVALUE) -> + true; +is_opt_IndAudSignal(V) -> + is_IndAudSignal(V). + +is_IndAudSignal(#'IndAudSignal'{signalName = Name, + streamID = SID}) -> + is_PkgdName(Name) andalso is_opt_StreamID(SID); +is_IndAudSignal(_) -> + false. + +chk_opt_IndAudSignal(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudSignal(S1, S2) -> + chk_IndAudSignal(S1, S2). + +chk_IndAudSignal(S, S) -> + chk_type(fun is_IndAudSignal/1, 'IndAudSignal', S); +chk_IndAudSignal(#'IndAudSignal'{signalName = Name1, + streamID = SID1}, + #'IndAudSignal'{signalName = Name2, + streamID = SID2}) -> + chk_PkgdName(Name1, Name2), + chk_opt_StreamID(SID1, SID2), + ok; +chk_IndAudSignal(S1, S2) -> + wrong_type('IndAudSignal', S1, S2). + + +%% -- IndAudDigitMapDescriptor -- + +is_IndAudDigitMapDescriptor( + #'IndAudDigitMapDescriptor'{digitMapName = Name}) -> + is_opt_DigitMapName(Name); +is_IndAudDigitMapDescriptor(_) -> + false. + +chk_IndAudDigitMapDescriptor(D, D) -> + chk_type(fun is_IndAudDigitMapDescriptor/1, 'IndAudDigitMapDescriptor', D); +chk_IndAudDigitMapDescriptor( + #'IndAudDigitMapDescriptor'{digitMapName = Name1}, + #'IndAudDigitMapDescriptor'{digitMapName = Name2}) -> + validate(fun() -> chk_opt_DigitMapName(Name1, Name2) end, + 'IndAudDigitMapDescriptor'), + ok; +chk_IndAudDigitMapDescriptor(D1, D2) -> + wrong_type('IndAudDigitMapDescriptor', D1, D2). + + +%% -- IndAudStatisticsDescriptor -- + +is_IndAudStatisticsDescriptor( + #'IndAudStatisticsDescriptor'{statName = Name}) -> + is_PkgdName(Name); +is_IndAudStatisticsDescriptor(_) -> + false. + +chk_IndAudStatisticsDescriptor(D, D) -> + chk_type(fun is_IndAudStatisticsDescriptor/1, + 'IndAudStatisticsDescriptor', D); +chk_IndAudStatisticsDescriptor( + #'IndAudStatisticsDescriptor'{statName = Name1}, + #'IndAudStatisticsDescriptor'{statName = Name2}) -> + validate(fun() -> chk_PkgdName(Name1, Name2) end, + 'IndAudStatisticsDescriptor'), + ok; +chk_IndAudStatisticsDescriptor(D1, D2) -> + wrong_type('IndAudStatisticsDescriptor', D1, D2). + + +%% -- IndAudPackagesDescriptor -- + +is_IndAudPackagesDescriptor( + #'IndAudPackagesDescriptor'{packageName = Name, + packageVersion = Ver}) -> + is_Name(Name) andalso is_IndAudPackagesDescriptor_packageVersion(Ver); +is_IndAudPackagesDescriptor(_) -> + false. + +is_IndAudPackagesDescriptor_packageVersion(V) -> + is_INTEGER(V, {range, 0, 99}). + +chk_IndAudPackagesDescriptor( + #'IndAudPackagesDescriptor'{packageName = Name1, + packageVersion = Ver1}, + #'IndAudPackagesDescriptor'{packageName = Name2, + packageVersion = Ver2}) -> + validate(fun() -> chk_Name(Name1, Name2) end, 'IndAudPackagesDescriptor'), + chk_IndAudPackagesDescriptor_packageVersion(Ver1, Ver2), + ok; +chk_IndAudPackagesDescriptor(D1, D2) -> + wrong_type('IndAudPackagesDescriptor', D1, D2). + +chk_IndAudPackagesDescriptor_packageVersion(V, V) -> + chk_type(fun is_IndAudPackagesDescriptor_packageVersion/1, + 'IndAudPackagesDescriptor_packageVersion', V); +chk_IndAudPackagesDescriptor_packageVersion(V1, V2) -> + case (is_IndAudPackagesDescriptor_packageVersion(V1) andalso + is_IndAudPackagesDescriptor_packageVersion(V2)) of + true -> + not_equal('IndAudPackagesDescriptor_packageVersion', V1, V2); + false -> + wrong_type('IndAudPackagesDescriptor_packageVersion', V1, V2) + end. + + +%% -- NotifyRequest -- + +is_NotifyRequest(#'NotifyRequest'{terminationID = Tids, + observedEventsDescriptor = OED, + errorDescriptor = ED}) -> + is_TerminationIDList(Tids) andalso + is_ObservedEventsDescriptor(OED) andalso + is_opt_ErrorDescriptor(ED); +is_NotifyRequest(_) -> + false. + +chk_NotifyRequest(#'NotifyRequest'{terminationID = Tids1, + observedEventsDescriptor = OED1, + errorDescriptor = ED1}, + #'NotifyRequest'{terminationID = Tids2, + observedEventsDescriptor = OED2, + errorDescriptor = ED2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'NotifyRequest'), + validate(fun() -> chk_ObservedEventsDescriptor(OED1, OED2) end, + 'NotifyRequest'), + validate(fun() -> chk_opt_ErrorDescriptor(ED1, ED2) end, + 'NotifyRequest'), + ok; +chk_NotifyRequest(NR1, NR2) -> + wrong_type('NotifyRequest', NR1, NR2). + + +%% -- NotifyReply -- + +is_NotifyReply(#'NotifyReply'{terminationID = Tids, + errorDescriptor = ED}) -> + is_TerminationIDList(Tids) andalso is_opt_ErrorDescriptor(ED); +is_NotifyReply(_) -> + false. + +chk_NotifyReply(#'NotifyReply'{terminationID = Tids1, + errorDescriptor = ED1}, + #'NotifyReply'{terminationID = Tids2, + errorDescriptor = ED2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, 'NotifyReply'), + validate(fun() -> chk_opt_ErrorDescriptor(ED1, ED2) end, 'NotifyReply'), + ok; +chk_NotifyReply(NR1, NR2) -> + wrong_type('NotifyReply', NR1, NR2). + + +%% -- ObservedEventsDescriptor -- + +is_ObservedEventsDescriptor( + #'ObservedEventsDescriptor'{requestId = RID, + observedEventLst = OEL}) -> + is_RequestID(RID) andalso + is_ObservedEventsDescriptor_observedEventLst(OEL); +is_ObservedEventsDescriptor(_) -> + false. + +is_ObservedEventsDescriptor_observedEventLst([]) -> + true; +is_ObservedEventsDescriptor_observedEventLst([H|T]) -> + is_ObservedEvent(H) andalso + is_ObservedEventsDescriptor_observedEventLst(T); +is_ObservedEventsDescriptor_observedEventLst(_) -> + false. + +chk_ObservedEventsDescriptor( + #'ObservedEventsDescriptor'{requestId = RID1, + observedEventLst = OEL1}, + #'ObservedEventsDescriptor'{requestId = RID2, + observedEventLst = OEL2}) -> + validate(fun() -> chk_RequestID(RID1, RID2) end, + 'ObservedEventsDescriptor'), + validate( + fun() -> + chk_ObservedEventsDescriptor_observedEventLst(OEL1, OEL2) + end, + 'ObservedEventsDescriptor'), + ok; +chk_ObservedEventsDescriptor(D1, D2) -> + wrong_type('ObservedEventsDescriptor', D1, D2). + +chk_ObservedEventsDescriptor_observedEventLst([], []) -> + ok; +chk_ObservedEventsDescriptor_observedEventLst([] = L1, L2) -> + not_equal('ObservedEventsDescriptor_observedEventLst', L1, L2); +chk_ObservedEventsDescriptor_observedEventLst(L1, [] = L2) -> + not_equal('ObservedEventsDescriptor_observedEventLst', L1, L2); +chk_ObservedEventsDescriptor_observedEventLst([H|T1], [H|T2]) -> + case is_ObservedEvent(H) of + true -> + chk_ObservedEventsDescriptor_observedEventLst(T1, T2); + false -> + wrong_type('ObservedEventsDescriptor_observedEventLst_val', H) + end; +chk_ObservedEventsDescriptor_observedEventLst([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ObservedEvent(H1, H2) end, + 'ObservedEventsDescriptor_observedEventLst_val'), + chk_ObservedEventsDescriptor_observedEventLst(T1, T2); +chk_ObservedEventsDescriptor_observedEventLst(L1, L2) -> + wrong_type('ObservedEventsDescriptor_observedEventLst', L1, L2). + + +%% -- ObservedEvent -- + +is_ObservedEvent(#'ObservedEvent'{eventName = Name, + streamID = SID, + eventParList = EPL, + timeNotation = TN}) -> + is_EventName(Name) andalso + is_opt_StreamID(SID) andalso + is_ObservedEvent_eventParList(EPL) andalso + is_opt_TimeNotation(TN); +is_ObservedEvent(_) -> + false. + +is_ObservedEvent_eventParList([]) -> + true; +is_ObservedEvent_eventParList([H|T]) -> + is_EventParameter(H) andalso is_ObservedEvent_eventParList(T); +is_ObservedEvent_eventParList(_) -> + false. + +chk_ObservedEvent(E, E) -> + chk_type(fun is_ObservedEvent/1, 'ObservedEvent', E); +chk_ObservedEvent(#'ObservedEvent'{eventName = Name1, + streamID = SID1, + eventParList = EPL1, + timeNotation = TN1}, + #'ObservedEvent'{eventName = Name2, + streamID = SID2, + eventParList = EPL2, + timeNotation = TN2}) -> + validate(fun() -> chk_EventName(Name1, Name2) end, 'ObservedEvent'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'ObservedEvent'), + chk_ObservedEvent_eventParList(EPL1, EPL2), + validate(fun() -> chk_opt_TimeNotation(TN1, TN2) end, 'ObservedEvent'), + ok; +chk_ObservedEvent(E1, E2) -> + wrong_type('ObservedEvent', E1, E2). + +chk_ObservedEvent_eventParList([], []) -> + ok; +chk_ObservedEvent_eventParList([] = EPL1, EPL2) -> + not_equal('ObservedEvent_eventParList', EPL1, EPL2); +chk_ObservedEvent_eventParList(EPL1, [] = EPL2) -> + not_equal('ObservedEvent_eventParList', EPL1, EPL2); +chk_ObservedEvent_eventParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_ObservedEvent_eventParList(T1, T2); + false -> + wrong_type('ObservedEvent_eventParList_val', H) + end; +chk_ObservedEvent_eventParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'ObservedEvent_eventParList'), + chk_ObservedEvent_eventParList(T1, T2); +chk_ObservedEvent_eventParList(L1, L2) -> + wrong_type('ObservedEvent_eventParList', L1, L2). + + +%% -- EventName -- + +is_EventName(N) -> is_PkgdName(N). + +chk_EventName(N, N) -> + chk_type(fun is_EventName/1, 'EventName', N); +chk_EventName(N1, N2) -> + case (is_EventName(N1) andalso is_EventName(N2)) of + true -> + not_equal('EventName', N1, N2); + false -> + wrong_type('EventName', N1, N2) + end. + + +%% -- EventParameter -- + +is_EventParameter(#'EventParameter'{eventParameterName = Name, + value = Val, + extraInfo = EI}) -> + d("is_EventParameter -> entery with" + "~n Name: ~p" + "~n Val: ~p" + "~n EI: ~p", [Name, Val, EI]), + is_Name(Name) andalso + is_Value(Val) andalso + is_EventParameter_extraInfo(EI); +is_EventParameter(_) -> + false. + +is_EventParameter_extraInfo(asn1_NOVALUE) -> + true; +is_EventParameter_extraInfo({Tag, Val}) -> + is_EventParameter_extraInfo_tag(Tag) andalso + is_EventParameter_extraInfo_val(Tag, Val); +is_EventParameter_extraInfo(_) -> + false. + +is_EventParameter_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_EventParameter_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_EventParameter_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_EventParameter_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + +chk_EventParameter(#'EventParameter'{eventParameterName = Name1, + value = Val1, + extraInfo = EI1}, + #'EventParameter'{eventParameterName = Name2, + value = Val2, + extraInfo = EI2}) -> + validate(fun() -> chk_Name(Name1, Name2) end, 'EventParameter'), + validate(fun() -> chk_Value(Val1, Val2) end, 'EventParameter'), + chk_EventParameter_extraInfo(EI1, EI2), + ok; +chk_EventParameter(P1, P2) -> + wrong_type('EventParameter', P1, P2). + +chk_EventParameter_extraInfo(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_EventParameter_extraInfo(EI, EI) -> + chk_type(fun is_EventParameter_extraInfo/1, + 'EventParameter_extraInfo', EI); +chk_EventParameter_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> + case (is_EventParameter_extraInfo_tag(Tag) andalso + is_EventParameter_extraInfo_val(Tag, Val1) andalso + is_EventParameter_extraInfo_val(Tag, Val2)) of + true -> + chk_EventParameter_extraInfo_val(Tag, Val1, Val2); + false -> + wrong_type('EventParameter_extraInfo', EI1, EI2) + end; +chk_EventParameter_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> + case ((is_EventParameter_extraInfo_tag(Tag1) andalso + is_EventParameter_extraInfo_val(Tag1, Val1)) andalso + (is_EventParameter_extraInfo_tag(Tag2) andalso + is_EventParameter_extraInfo_val(Tag2, Val2))) of + true -> + not_equal('EventParameter_extraInfo', EI1, EI2); + false -> + wrong_type('EventParameter_extraInfo', EI1, EI2) + end; +chk_EventParameter_extraInfo(EI1, EI2) -> + wrong_type('EventParameter_extraInfo', EI1, EI2). + +chk_EventParameter_extraInfo_val(relation, Val1, Val2) -> + validate(fun() -> chk_Relation(Val1, Val2) end, + 'EventParameter_extraInfo_val'); +chk_EventParameter_extraInfo_val(range, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, + 'EventParameter_extraInfo_val'); +chk_EventParameter_extraInfo_val(sublist, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, + 'EventParameter_extraInfo_val'). + + +%% -- ServiceChangeRequest -- + +is_ServiceChangeRequest(#'ServiceChangeRequest'{terminationID = Tids, + serviceChangeParms = Parms}) -> + is_TerminationIDList(Tids) andalso is_ServiceChangeParm(Parms); +is_ServiceChangeRequest(_) -> + false. + +chk_ServiceChangeRequest(R, R) -> + chk_type(fun is_ServiceChangeRequest/1, 'ServiceChangeRequest', R); +chk_ServiceChangeRequest( + #'ServiceChangeRequest'{terminationID = Tids1, + serviceChangeParms = Parms1}, + #'ServiceChangeRequest'{terminationID = Tids2, + serviceChangeParms = Parms2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'ServiceChangeRequest'), + validate(fun() -> chk_ServiceChangeParm(Parms1, Parms2) end, + 'ServiceChangeRequest'), + ok; +chk_ServiceChangeRequest(R1, R2) -> + wrong_type('ServiceChangeRequest', R1, R2). + + +%% -- ServiceChangeReply -- + +is_ServiceChangeReply(#'ServiceChangeReply'{terminationID = Tids, + serviceChangeResult = Res}) -> + is_TerminationIDList(Tids) andalso is_ServiceChangeResult(Res); +is_ServiceChangeReply(_) -> + false. + +chk_ServiceChangeReply(R, R) -> + chk_type(fun is_ServiceChangeReply/1, 'ServiceChangeReply', R); +chk_ServiceChangeReply( + #'ServiceChangeReply'{terminationID = Tids1, + serviceChangeResult = Res1}, + #'ServiceChangeReply'{terminationID = Tids2, + serviceChangeResult = Res2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'ServiceChangeReply'), + validate(fun() -> chk_ServiceChangeResult(Res1, Res2) end, + 'ServiceChangeReply'), + ok; +chk_ServiceChangeReply(R1, R2) -> + wrong_type('ServiceChangeReply', R1, R2). + + +%% -- ServiceChangeResult -- + +is_ServiceChangeResult({Tag, Val}) -> + is_ServiceChangeResult_tag(Tag) andalso + is_ServiceChangeResult_val(Tag, Val); +is_ServiceChangeResult(_) -> + false. + +is_ServiceChangeResult_tag(Tag) -> + Tags = [errorDescriptor, serviceChangeResParms], + lists:member(Tag, Tags). + +is_ServiceChangeResult_val(errorDescriptor, Val) -> + is_ErrorDescriptor(Val); +is_ServiceChangeResult_val(serviceChangeResParms, Val) -> + is_ServiceChangeResParm(Val). + +chk_ServiceChangeResult(Res, Res) -> + chk_type(fun is_ServiceChangeResult/1, 'ServiceChangeResult', Res); +chk_ServiceChangeResult({Tag, Val1} = Res1, {Tag, Val2} = Res2) -> + case (is_ServiceChangeResult_tag(Tag) andalso + is_ServiceChangeResult_val(Tag, Val1) andalso + is_ServiceChangeResult_val(Tag, Val2)) of + true -> + chk_ServiceChangeResult_val(Tag, Val1, Val2); + false -> + wrong_type('ServiceChangeResult', Res1, Res2) + end; +chk_ServiceChangeResult({Tag1, Val1} = Res1, {Tag2, Val2} = Res2) -> + case ((is_ServiceChangeResult_tag(Tag1) andalso + is_ServiceChangeResult_val(Tag1, Val1)) andalso + (is_ServiceChangeResult_tag(Tag2) andalso + is_ServiceChangeResult_val(Tag2, Val2))) of + true -> + not_equal('ServiceChangeResult', Res1, Res2); + false -> + wrong_type('ServiceChangeResult', Res1, Res2) + end; +chk_ServiceChangeResult(Res1, Res2) -> + wrong_type('ServiceChangeResult', Res1, Res2). + +chk_ServiceChangeResult_val(errorDescriptor, Val1, Val2) -> + validate(fun() -> chk_ErrorDescriptor(Val1, Val2) end, + 'ServiceChangeResult'); +chk_ServiceChangeResult_val(serviceChangeResParms, Val1, Val2) -> + validate(fun() -> chk_ServiceChangeResParm(Val1, Val2) end, + 'ServiceChangeResult'). + + +%% -- WildcardField -- + +is_WildcardField(WF) -> is_OCTET_STRING(WF, {exact, 1}). + +chk_WildcardField(WF, WF) -> + case is_WildcardField(WF) of + true -> + ok; + false -> + wrong_type('WildcardField', WF) + end; +chk_WildcardField(WF1, WF2) -> + case (is_WildcardField(WF1) andalso is_WildcardField(WF2)) of + true -> + not_equal('WildcardField', WF1, WF2); + false -> + wrong_type('WildcardField', WF1, WF2) + end. + + +%% -- TerminationID -- + +is_TerminationID(#'TerminationID'{wildcard = W, + id = ID}) -> + is_TerminationID_wildcard(W) andalso is_TerminationID_id(ID); +is_TerminationID(#megaco_term_id{contains_wildcards = _W, + id = _ID}) -> + true; % What are the types? +is_TerminationID(_) -> + false. + +is_TerminationID_wildcard([]) -> + true; +is_TerminationID_wildcard([H|T]) -> + is_WildcardField(H) andalso is_TerminationID_wildcard(T); +is_TerminationID_wildcard(_) -> + false. + +is_TerminationID_id(ID) -> is_OCTET_STRING(ID, {range, 1, 8}). + +chk_TerminationID(Id,Id) -> + chk_type(fun is_TerminationID/1, 'TerminationID', Id); +chk_TerminationID(#'TerminationID'{wildcard = W1, + id = I1}, + #'TerminationID'{wildcard = W2, + id = I2}) -> + chk_TerminationID_wildcard(W1, W2), + chk_TerminationID_id(I1, I2), + ok; +chk_TerminationID(#megaco_term_id{contains_wildcards = W1, + id = I1}, + #megaco_term_id{contains_wildcards = W2, + id = I2}) -> + chk_TerminationID_wildcard(W1, W2), + chk_TerminationID_id(I1, I2), + ok; +chk_TerminationID(Tid1, Tid2) -> + wrong_type('TerminationID', Tid1, Tid2). + +chk_TerminationID_wildcard([], []) -> + ok; +chk_TerminationID_wildcard([] = WF1, WF2) -> + not_equal('TerminationID_wildcard', WF1, WF2); +chk_TerminationID_wildcard(WF1, [] = WF2) -> + not_equal('TerminationID_wildcard', WF1, WF2); +chk_TerminationID_wildcard([H|T1], [H|T2]) -> + case is_WildcardField(H) of + true -> + chk_TerminationID_wildcard(T1, T2); + false -> + wrong_type('TerminationID_wildcard_val', H) + end; +chk_TerminationID_wildcard([H1|T1], [H2|T2]) -> + validate(fun() -> chk_WildcardField(H1, H2) end, + 'TerminationID_wildcard_val'), + chk_TerminationID_wildcard(T1, T2); +chk_TerminationID_wildcard(WF1,WF2) -> + not_equal('TerminationId_wildcard', WF1, WF2). + +chk_TerminationID_id(Id, Id) -> + case is_OCTET_STRING(Id, {range, 1, 8}) of + true -> + ok; + false -> + wrong_type('TerminationID_id', Id, Id) + end; +chk_TerminationID_id(Id1, Id2) -> + not_equal(terminationId_id, Id1, Id2). + + +%% -- TerminationIDList -- + +is_TerminationIDList([]) -> + true; +is_TerminationIDList([H|T]) -> + is_TerminationID(H) andalso is_TerminationIDList(T); +is_TerminationIDList(_) -> + false. + +chk_TerminationIDList([], []) -> + ok; +chk_TerminationIDList([] = L1, L2) -> + not_equal('TerminationIDList', L1, L2); +chk_TerminationIDList(L1, [] = L2) -> + not_equal('TerminationIDList', L1, L2); +chk_TerminationIDList([H|T1], [H|T2]) -> + case is_TerminationID(H) of + true -> + chk_TerminationIDList(T1, T2); + false -> + wrong_type('TerminationIDList', H) + end; +chk_TerminationIDList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TerminationID(H1, H2) end, 'TerminationIDList'), + chk_TerminationIDList(T1, T2); +chk_TerminationIDList(L1, L2) -> + wrong_type('TerminationIDList', L1, L2). + + +%% -- MediaDescriptor -- + +is_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TSD, + streams = S}) -> + d("is_MediaDescriptor -> entry with" + "~n TSD: ~p" + "~n S: ~p", [TSD, S]), + is_opt_TerminationStateDescriptor(TSD) andalso + is_MediaDescriptor_streams(S); +is_MediaDescriptor(_) -> + false. + +is_MediaDescriptor_streams(asn1_NOVALUE) -> + true; +is_MediaDescriptor_streams({Tag, Val}) -> + is_MediaDescriptor_streams_tag(Tag) andalso + is_MediaDescriptor_streams_val(Tag, Val); +is_MediaDescriptor_streams(_) -> + false. + +is_MediaDescriptor_streams_tag(Tag) -> + Tags = [oneStream, multiStream], + lists:member(Tag, Tags). + +is_MediaDescriptor_streams_val(oneStream, SP) -> + is_StreamParms(SP); +is_MediaDescriptor_streams_val(multiStream, SDL) -> + is_MediaDescriptor_multiStream(SDL). + +is_MediaDescriptor_multiStream([]) -> + true; +is_MediaDescriptor_multiStream([H|T]) -> + is_StreamDescriptor(H) andalso is_MediaDescriptor_multiStream(T); +is_MediaDescriptor_multiStream(_) -> + false. + +chk_MediaDescriptor(D, D) -> + chk_type(fun is_MediaDescriptor/1, 'MediaDescriptor', D); +chk_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TSD1, + streams = S1}, + #'MediaDescriptor'{termStateDescr = TSD2, + streams = S2}) -> + validate( + fun() -> + chk_opt_TerminationStateDescriptor(TSD1, TSD2) + end, + 'MediaDescriptor'), + validate( + fun() -> + chk_MediaDescriptor_streams(S1, S2) + end, + 'MediaDescriptor'), + ok; +chk_MediaDescriptor(D1, D2) -> + wrong_type('MediaDescriptor', D1, D2). + + +chk_MediaDescriptor_streams(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_MediaDescriptor_streams({oneStream, SP1}, {oneStream, SP2}) -> + validate(fun() -> + chk_StreamParms(SP1, SP2) + end, + 'MediaDescriptor_streams'); +chk_MediaDescriptor_streams({multiStream, SDs1}, {multiStream, SDs2}) -> + validate(fun() -> + chk_MediaDescriptor_multiStream(SDs1, SDs2) + end, + 'MediaDescriptor_streams'); +chk_MediaDescriptor_streams(S1, S2) -> + wrong_type('MediaDescriptor_streams', S1, S2). + +chk_MediaDescriptor_multiStream([], []) -> + ok; +chk_MediaDescriptor_multiStream([] = MS1, MS2) -> + not_equal('MediaDescriptor_multiStream', MS1, MS2); +chk_MediaDescriptor_multiStream(MS1, [] = MS2) -> + not_equal('MediaDescriptor_multiStream', MS1, MS2); +chk_MediaDescriptor_multiStream([H|T1], [H|T2]) -> + case is_StreamDescriptor(H) of + true -> + chk_MediaDescriptor_multiStream(T1, T2); + false -> + wrong_type('MediaDescriptor_multiStream_val', H) + end; +chk_MediaDescriptor_multiStream([H1|T1], [H2|T2]) -> + validate(fun() -> chk_StreamDescriptor(H1, H2) end, + 'MediaDescriptor_multiStream_val'), + chk_MediaDescriptor_multiStream(T1, T2); +chk_MediaDescriptor_multiStream(MS1, MS2) -> + wrong_type('MediaDescriptor_multiStream_val', MS1, MS2). + + +%% -- StreamDescriptor -- + +is_StreamDescriptor(#'StreamDescriptor'{streamID = SID, + streamParms = Parms}) -> + d("is_StreamDescriptor -> entry with" + "~n SID: ~p" + "~n Parms: ~p", [SID, Parms]), + is_StreamID(SID) andalso is_StreamParms(Parms); +is_StreamDescriptor(X) -> + d("is_StreamDescriptor -> entry when ERROR with" + "~n X: ~p", [X]), + false. + +chk_StreamDescriptor(D, D) -> + chk_type(fun is_StreamDescriptor/1, 'StreamDescriptor', D); +chk_StreamDescriptor(#'StreamDescriptor'{streamID = SID1, + streamParms = Parms1}, + #'StreamDescriptor'{streamID = SID2, + streamParms = Parms2}) -> + validate(fun() -> chk_StreamID(SID1, SID2) end, 'StreamDescriptor'), + validate(fun() -> chk_StreamParms(Parms1, Parms2) end, 'StreamDescriptor'), + ok; +chk_StreamDescriptor(D1, D2) -> + wrong_type('StreamDescriptor', D1, D2). + + +%% -- StreamParms -- + +is_StreamParms(#'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}) -> + d("is_StreamParms -> entry with" + "~n LCD: ~p" + "~n LD: ~p" + "~n RD: ~p" + "~n SD: ~p", [LCD, LD, RD, SD]), + is_opt_LocalControlDescriptor(LCD) andalso + is_opt_LocalRemoteDescriptor(LD) andalso + is_opt_LocalRemoteDescriptor(RD) andalso + is_opt_StatisticsDescriptor(SD); +is_StreamParms(X) -> + d("is_StreamParms -> entry when ERROR with" + "~n X: ~p", [X]), + false. + +chk_StreamParms(SP, SP) -> + chk_type(fun is_StreamParms/1, 'StreamParms', SP); +chk_StreamParms(#'StreamParms'{localControlDescriptor = LCD1, + localDescriptor = LD1, + remoteDescriptor = RD1, + statisticsDescriptor = SD1}, + #'StreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2, + statisticsDescriptor = SD2}) -> + validate(fun() -> chk_opt_LocalControlDescriptor(LCD1, LCD2) end, + 'StreamParms_localControlDescriptor'), + validate(fun() -> chk_opt_LocalRemoteDescriptor(LD1, LD2) end, + 'StreamParms_localDescriptor'), + validate(fun() -> chk_opt_LocalRemoteDescriptor(RD1, RD2) end, + 'StreamParms_remoteDescriptor'), + validate(fun() -> chk_opt_StatisticsDescriptor(SD1, SD2) end, + 'StreamParms_statisticsDescriptor'), + ok; +chk_StreamParms(P1, P2) -> + wrong_type('StreamParms', P1, P2). + + +%% -- LocalControlDescriptor -- + +is_opt_LocalControlDescriptor(D) -> + d("is_opt_LocalControlDescriptor -> entry"), + is_OPTIONAL(fun is_LocalControlDescriptor/1, D). + +is_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP}) -> + d("is_LocalControlDescriptor -> entry with" + "~n SM: ~p" + "~n RV: ~p" + "~n RG: ~p" + "~n PP: ~p", [SM, RV, RG, PP]), + is_opt_StreamMode(SM) andalso + is_opt_BOOLEAN(RV) andalso + is_opt_BOOLEAN(RG) andalso + is_LocalControlDescriptor_propertyParms(PP); +is_LocalControlDescriptor(_) -> + false. + +is_LocalControlDescriptor_propertyParms([]) -> + d("is_LocalControlDescriptor_propertyParms -> entry when done"), + true; +is_LocalControlDescriptor_propertyParms([H|T]) -> + d("is_LocalControlDescriptor_propertyParms -> entry with" + "~n H: ~p" + "~n T: ~p", [H, T]), + is_PropertyParm(H) andalso is_LocalControlDescriptor_propertyParms(T); +is_LocalControlDescriptor_propertyParms(_) -> + false. + +chk_opt_LocalControlDescriptor(LCD1, LCD2) -> + chk_OPTIONAL('LocalControlDescriptor', LCD1, LCD2, + fun is_LocalControlDescriptor/1, + fun chk_LocalControlDescriptor/2). + +chk_LocalControlDescriptor(LCD, LCD) -> + chk_type(fun is_LocalControlDescriptor/1, 'LocalControlDescriptor', LCD); +chk_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = SM1, + reserveValue = RV1, + reserveGroup = RG1, + propertyParms = PP1}, + #'LocalControlDescriptor'{streamMode = SM2, + reserveValue = RV2, + reserveGroup = RG2, + propertyParms = PP2}) -> + validate( + fun() -> chk_opt_StreamMode(SM1, SM2) end, + 'LocalControlDescriptor'), + validate( + fun() -> chk_opt_BOOLEAN(RV1, RV2) end, + 'LocalControlDescriptor_reserveValue'), + validate( + fun() -> chk_opt_BOOLEAN(RG1, RG2) end, + 'LocalControlDescriptor_reserveGroup'), + chk_LocalControlDescriptor_propertyParms(PP1, PP2), + ok; +chk_LocalControlDescriptor(LCD1, LCD2) -> + wrong_type('LocalControlDescriptor', LCD1, LCD2). + + +chk_LocalControlDescriptor_propertyParms([], []) -> + ok; +chk_LocalControlDescriptor_propertyParms([] = PP1, PP2) -> + not_equal('LocalControlDescriptor_propertyParms', PP1, PP2); +chk_LocalControlDescriptor_propertyParms(PP1, [] = PP2) -> + not_equal('LocalControlDescriptor_propertyParms', PP1, PP2); +chk_LocalControlDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_LocalControlDescriptor_propertyParms(T1, T2); + false -> + wrong_type('LocalControlDescriptor_propertyParms_val', H) + end; +chk_LocalControlDescriptor_propertyParms([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, + 'LocalControlDescriptor_propertyParms_val'), + chk_LocalControlDescriptor_propertyParms(T1, T2); +chk_LocalControlDescriptor_propertyParms(PP1, PP2) -> + wrong_type('LocalControlDescriptor_propertyParms', PP1, PP2). + + +%% -- StreamMode -- + +is_opt_StreamMode(asn1_NOVALUE) -> + true; +is_opt_StreamMode(SM) -> + is_StreamMode(SM). + +is_StreamMode(SM) -> + lists:member(SM, [sendOnly, recvOnly, sendRecv, inactive, loopBack]). + +chk_opt_StreamMode(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_StreamMode(SM1, SM2) -> + chk_StreamMode(SM1, SM2). + +chk_StreamMode(SM, SM) -> + chk_type(fun is_StreamMode/1, 'StreamMode', SM); +chk_StreamMode(SM1, SM2) -> + case (is_StreamMode(SM1) andalso is_StreamMode(SM2)) of + true -> + not_equal('StreamMode', SM1, SM2); + false -> + wrong_type('StreamMode', SM1, SM2) + end. + + +%% -- PropertyParm -- + +is_PropertyParm(#'PropertyParm'{name = N, + value = V, + extraInfo = I}) -> + d("is_PropertyParm -> entry with" + "~n N: ~p" + "~n V: ~p" + "~n I: ~p", [N, V, I]), + is_PkgdName(N) andalso + is_PropertyParm_value(V) andalso + is_PropertyParm_extraInfo(I); +is_PropertyParm(_) -> + false. + +is_PropertyParm_value([]) -> + d("is_PropertyParm_value -> entry when done"), + true; +is_PropertyParm_value([H|T]) -> + d("is_PropertyParm_value -> entry with" + "~n H: ~p", [H]), + is_OCTET_STRING(H) andalso is_PropertyParm_value(T); +is_PropertyParm_value(_) -> + false. + +is_PropertyParm_extraInfo(asn1_NOVALUE) -> + true; +is_PropertyParm_extraInfo({Tag, Val}) -> + d("is_PropertyParm_extraInfo -> entry with" + "~n Tag: ~p" + "~n Val: ~p", [Tag, Val]), + is_PropertyParm_extraInfo_tag(Tag) andalso + is_PropertyParm_extraInfo_val(Tag, Val); +is_PropertyParm_extraInfo(_) -> + false. + +is_PropertyParm_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_PropertyParm_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_PropertyParm_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_PropertyParm_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + +chk_PropertyParm(P, P) -> + chk_type(fun is_PropertyParm/1, 'PropertyParm', P); +chk_PropertyParm(#'PropertyParm'{name = N1, + value = V1, + extraInfo = I1}, + #'PropertyParm'{name = N2, + value = V2, + extraInfo = I2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'PropertyParm'), + chk_PropertyParm_value(V1, V2), + chk_PropertyParm_extraInfo(I1, I2), + ok; +chk_PropertyParm(P1, P2) -> + wrong_type('PropertyParm', P1, P2). + +chk_PropertyParm_value([], []) -> + ok; +chk_PropertyParm_value([] = V1, V2) -> + not_equal('PropertyParm_value', V1, V2); +chk_PropertyParm_value(V1, [] = V2) -> + not_equal('PropertyParm_value', V1, V2); +chk_PropertyParm_value([H|T1], [H|T2]) -> + case is_OCTET_STRING(H) of + true -> + chk_PropertyParm_value(T1, T2); + false -> + wrong_type('PropertyParm_value_val', H) + end; +chk_PropertyParm_value([H1|_], [H2|_]) -> + case (is_OCTET_STRING(H1) andalso is_OCTET_STRING(H2)) of + true -> + not_equal('PropertyParm_value_val', H1, H2); + false -> + wrong_type('PropertyParm_value_val', H1, H2) + end; +chk_PropertyParm_value(V1, V2) -> + wrong_type('PropertyParm_value', V1, V2). + +chk_PropertyParm_extraInfo(EI, EI) -> + chk_type(fun is_PropertyParm_extraInfo/1, 'PropertyParm_extraInfo', EI); +chk_PropertyParm_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> + case (is_PropertyParm_extraInfo_tag(Tag) and + is_PropertyParm_extraInfo_val(Tag, Val1) and + is_PropertyParm_extraInfo_val(Tag, Val2)) of + true -> + chk_PropertyParm_extraInfo_val(Tag, Val1, Val2); + false -> + wrong_type('PropertyParm_extraInfo', EI1, EI2) + end; +chk_PropertyParm_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> + case ((is_PropertyParm_extraInfo_tag(Tag1) and + is_PropertyParm_extraInfo_val(Tag1, Val1)) and + (is_PropertyParm_extraInfo_tag(Tag2) and + is_PropertyParm_extraInfo_val(Tag2, Val2))) of + true -> + not_equal('PropertyParm_extraInfo', EI1, EI2); + false -> + wrong_type('PropertyParm_extraInfo', EI1, EI2) + end; +chk_PropertyParm_extraInfo(EI1, EI2) -> + wrong_type('PropertyParm_extraInfo', EI1, EI2). + +chk_PropertyParm_extraInfo_val(relation, Val1, Val2) -> + validate(fun() -> chk_Relation(Val1, Val2) end, 'PropertyParm_extraInfo'); +chk_PropertyParm_extraInfo_val(range, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'PropertyParm_extraInfo'); +chk_PropertyParm_extraInfo_val(sublist, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'PropertyParm_extraInfo'). + + +%% -- Name -- + +is_Name(N) -> + %% Binary: is_OCTET_STRING(N, {exact, 2}). + case is_OCTET_STRING(N, {range, 1, 64}) of + true -> + is_NAME(N); + false -> + false + end. + +is_NAME([H|T]) when H =< $z, $a =< H -> + is_NAME2(T); +is_NAME([H|T]) when H =< $Z, $A =< H -> + is_NAME2(T); +is_NAME(_) -> + false. + +is_NAME2([]) -> + true; +is_NAME2([$_|T]) -> + is_NAME2(T); +is_NAME2([H|T]) when H =< $z, $a =< H -> + is_NAME2(T); +is_NAME2([H|T]) when H =< $Z, $A =< H -> + is_NAME2(T); +is_NAME2([H|T]) when H =< $9, $0 =< H -> + is_NAME2(T); +is_NAME2(_) -> + false. + + + +chk_Name(N, N) -> + chk_type(fun is_Name/1, 'Name', N); +chk_Name(N1, N2) -> + case (is_Name(N1) andalso is_Name(N2)) of + true -> + not_equal('Name', N1, N2); + false -> + wrong_type('Name', N1, N2) + end. + + +%% -- PkgdName -- + +%% PkgdName is either "AB/CD" or just plain "ABCD" +%% Note that in ASN.1 the parts is exactly 2 char +%% each, unless you don't use the native config +%% option. In text and in binary without the native +%% option, it is 63 + 1 chars for each. +is_PkgdName(N) -> + d("is_PkgdName -> entry with" + "~n N: ~p", [N]), + case string:tokens(N, "/") of + ["*" = PackageName, "*" = ItemID] -> + d("is_PkgdName -> tokenized (0): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + true; + [PackageName, "*" = ItemID] -> + d("is_PkgdName -> tokenized (1): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + is_Name(PackageName); + [PackageName, ItemID] -> + d("is_PkgdName -> tokenized (2): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + is_Name(PackageName) andalso is_Name(ItemID); + _ -> + is_Name(N) + end. + +chk_PkgdName(N, N) -> + case is_PkgdName(N) of + true -> + ok; + false -> + wrong_type('PkgdName', N, N) + end; +chk_PkgdName(N1, N2) -> + case (is_PkgdName(N1) andalso is_PkgdName(N2)) of + true -> + not_equal('PkgdName', N1, N2); + false -> + wrong_type('PkgdName', N1, N2) + end. + + +%% -- Relation -- + +is_Relation(R) -> + lists:member(R, [greaterThan, smallerThan, unequalTo]). + +chk_Relation(R, R) -> + chk_type(fun is_Relation/1, 'Relation', R); +chk_Relation(R1, R2) -> + case (is_Relation(R1) andalso is_Relation(R2)) of + true -> + not_equal('Relation', R1, R2); + false -> + wrong_type('Relation', R1, R2) + end. + + +%% -- LocalRemoteDescriptor -- + +is_opt_LocalRemoteDescriptor(D) -> + d("is_LocalRemoteDescriptor -> entry"), + is_OPTIONAL(fun is_LocalRemoteDescriptor/1, D). + +is_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = PGs}) -> + d("is_LocalRemoteDescriptor -> entry with" + "~n PGs: ~p", [PGs]), + is_LocalRemoteDescriptor_propGrps(PGs); +is_LocalRemoteDescriptor(_) -> + false. + +is_LocalRemoteDescriptor_propGrps([]) -> + true; +is_LocalRemoteDescriptor_propGrps([H|T]) -> + is_PropertyGroup(H) andalso is_LocalRemoteDescriptor_propGrps(T); +is_LocalRemoteDescriptor_propGrps(_) -> + false. + +chk_opt_LocalRemoteDescriptor(D1, D2) -> + chk_OPTIONAL('LocalRemoteDescriptor', D1, D2, + fun is_LocalRemoteDescriptor/1, + fun chk_LocalRemoteDescriptor/2). + +chk_LocalRemoteDescriptor(LRD, LRD) -> + chk_type(fun is_LocalRemoteDescriptor/1, 'LocalRemoteDescriptor', LRD); +chk_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = PG1}, + #'LocalRemoteDescriptor'{propGrps = PG2}) -> + chk_LocalRemoteDescriptor_propGrps(PG1, PG2), + ok; +chk_LocalRemoteDescriptor(LRD1, LRD2) -> + wrong_type('LocalRemoteDescriptor', LRD1, LRD2). + +chk_LocalRemoteDescriptor_propGrps([], []) -> + ok; +chk_LocalRemoteDescriptor_propGrps([] = PG1, PG2) -> + not_equal('LocalRemoteDescriptor_propGrps', PG1, PG2); +chk_LocalRemoteDescriptor_propGrps(PG1, [] = PG2) -> + not_equal('LocalRemoteDescriptor_propGrps', PG1, PG2); +chk_LocalRemoteDescriptor_propGrps([H|T1], [H|T2]) -> + case is_PropertyGroup(H) of + true -> + chk_LocalRemoteDescriptor_propGrps(T1, T2); + false -> + wrong_type('LocalRemoteDescriptor_propGrps_val', H) + end; +chk_LocalRemoteDescriptor_propGrps([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyGroup(H1, H2) end, + 'LocalRemoteDescriptor_propGrps_val'), + chk_LocalRemoteDescriptor_propGrps(T1, T2); +chk_LocalRemoteDescriptor_propGrps(PG1, PG2) -> + wrong_type('LocalRemoteDescriptor_propGrps', PG1, PG2). + + +%% -- PropertyGroup -- + +is_PropertyGroup([]) -> + true; +is_PropertyGroup([H|T]) -> + is_PropertyParm(H) andalso is_PropertyGroup(T); +is_PropertyGroup(_) -> + false. + +chk_PropertyGroup([], []) -> + ok; +chk_PropertyGroup([] = PG1, PG2) -> + not_equal('PropertyGroup', PG1, PG2); +chk_PropertyGroup(PG1, [] = PG2) -> + not_equal('PropertyGroup', PG1, PG2); +chk_PropertyGroup([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_PropertyGroup(T1, T2); + false -> + wrong_type('PropertyGroup_val', H) + end; +chk_PropertyGroup([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, 'PropertyGroup_val'), + chk_PropertyGroup(T1, T2); +chk_PropertyGroup(PG1, PG2) -> + wrong_type('PropertyGroup', PG1, PG2). + + +%% -- TerminationStateDescriptor -- + +is_opt_TerminationStateDescriptor(D) -> + is_OPTIONAL(fun is_TerminationStateDescriptor/1, D). + +is_TerminationStateDescriptor( + #'TerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS}) -> + is_TerminationStateDescriptor_propertyParms(PP) andalso + is_opt_EventBufferControl(EBC) andalso + is_opt_ServiceState(SS); +is_TerminationStateDescriptor(_) -> + false. + +is_TerminationStateDescriptor_propertyParms([]) -> + true; +is_TerminationStateDescriptor_propertyParms([H|T]) -> + is_PropertyParm(H) andalso is_TerminationStateDescriptor_propertyParms(T); +is_TerminationStateDescriptor_propertyParms(_) -> + false. + +chk_opt_TerminationStateDescriptor(D1, D2) -> + chk_OPTIONAL('TerminationStateDescriptor', D1, D2, + fun is_TerminationStateDescriptor/1, + fun chk_TerminationStateDescriptor/2). + +chk_TerminationStateDescriptor(D, D) -> + chk_type(fun is_TerminationStateDescriptor/1, + 'TerminationStateDescriptor', D); +chk_TerminationStateDescriptor( + #'TerminationStateDescriptor'{propertyParms = PP1, + eventBufferControl = EBC1, + serviceState = SS1}, + #'TerminationStateDescriptor'{propertyParms = PP2, + eventBufferControl = EBC2, + serviceState = SS2}) -> + chk_TerminationStateDescriptor_propertyParms(PP1, PP2), + validate( + fun() -> + chk_opt_EventBufferControl(EBC1, EBC2) + end, + 'TerminationStateDescriptor'), + validate( + fun() -> + chk_opt_ServiceState(SS1, SS2) + end, + 'TerminationStateDescriptor'), + ok; +chk_TerminationStateDescriptor(D1, D2) -> + wrong_type('TerminationStateDescriptor', D1, D2). + + +chk_TerminationStateDescriptor_propertyParms([], []) -> + ok; +chk_TerminationStateDescriptor_propertyParms([] = P1, P2) -> + not_equal('TerminationStateDescriptor_propertyParms', P1, P2); +chk_TerminationStateDescriptor_propertyParms(P1, [] = P2) -> + not_equal('TerminationStateDescriptor_propertyParms', P1, P2); +chk_TerminationStateDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_TerminationStateDescriptor_propertyParms(T1, T2); + false -> + wrong_type('TerminationStateDescriptor_propertyParms_val', H) + end; +chk_TerminationStateDescriptor_propertyParms([H1|_], [H2|_]) -> + case (is_PropertyParm(H1) andalso is_PropertyParm(H2)) of + true -> + not_equal('TerminationStateDescriptor_propertyParms_val', H1, H2); + false -> + wrong_type('TerminationStateDescriptor_propertyParms_val', H1, H2) + end; +chk_TerminationStateDescriptor_propertyParms(P1, P2) -> + wrong_type('TerminationStateDescriptor_propertyParms', P1, P2). + + +%% -- EventBufferControl -- + +is_opt_EventBufferControl(asn1_NOVALUE) -> + true; +is_opt_EventBufferControl(EBC) -> + is_EventBufferControl(EBC). + +is_EventBufferControl(EBC) -> + lists:member(EBC, [off, lockStep]). + +chk_opt_EventBufferControl(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_EventBufferControl(EBC1, EBC2) -> + chk_EventBufferControl(EBC1, EBC2). + +chk_EventBufferControl(EBC, EBC) -> + chk_type(fun is_EventBufferControl/1, 'EventBufferControl', EBC); +chk_EventBufferControl(EBC1, EBC2) -> + case (is_EventBufferControl(EBC1) andalso is_EventBufferControl(EBC2)) of + true -> + not_equal('EventBufferControl', EBC1, EBC2); + false -> + wrong_type('EventBufferControl', EBC1, EBC2) + end. + + +%% -- ServiceState -- + +is_opt_ServiceState(asn1_NOVALUE) -> + true; +is_opt_ServiceState(SS) -> + is_ServiceState(SS). + +is_ServiceState(SS) -> + lists:member(SS, [test, outOfSvc, inSvc]). + +chk_opt_ServiceState(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_ServiceState(SS1, SS2) -> + chk_ServiceState(SS1, SS2). + +chk_ServiceState(SS, SS) -> + chk_type(fun is_ServiceState/1, 'ServiceState', SS); +chk_ServiceState(SS1, SS2) -> + case (is_ServiceState(SS1) andalso is_ServiceState(SS2)) of + true -> + not_equal('ServiceState', SS1, SS2); + false -> + wrong_type('ServiceState', SS1, SS2) + end. + + +%% -- MuxDescriptor -- + +is_MuxDescriptor(#'MuxDescriptor'{muxType = MT, + termList = TL, + nonStandardData = NSD}) -> + is_MuxType(MT) andalso + is_MuxDescriptor_termList(TL) andalso + is_NonStandardData(NSD); +is_MuxDescriptor(_) -> + false. + +is_MuxDescriptor_termList([]) -> + true; +is_MuxDescriptor_termList([H|T]) -> + is_TerminationID(H) andalso is_MuxDescriptor_termList(T); +is_MuxDescriptor_termList(_) -> + false. + +chk_MuxDescriptor(D, D) -> + chk_type(fun is_MuxDescriptor/1, 'MuxDescriptor', D); +chk_MuxDescriptor(#'MuxDescriptor'{muxType = MT1, + termList = TL1, + nonStandardData = NSD1}, + #'MuxDescriptor'{muxType = MT2, + termList = TL2, + nonStandardData = NSD2}) -> + validate(fun() -> chk_MuxType(MT1, MT2) end, 'MuxDescriptor'), + chk_MuxDescriptor_termList(TL1, TL2), + validate(fun() -> chk_NonStandardData(NSD1, NSD2) end, 'MuxDescriptor'), + ok; +chk_MuxDescriptor(D1, D2) -> + wrong_type('MuxDescriptor', D1, D2). + +chk_MuxDescriptor_termList([], []) -> + ok; +chk_MuxDescriptor_termList([] = TL1, TL2) -> + not_equal('MuxDescriptor_termList', TL1, TL2); +chk_MuxDescriptor_termList(TL1, [] = TL2) -> + not_equal('MuxDescriptor_termList', TL1, TL2); +chk_MuxDescriptor_termList([H|T1], [H|T2]) -> + case is_TerminationID(H) of + true -> + chk_MuxDescriptor_termList(T1, T2); + false -> + wrong_type('MuxDescriptor_termList_val', H) + end; +chk_MuxDescriptor_termList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TerminationID(H1, H2) end, + 'MuxDescriptor_termList_val'), + chk_MuxDescriptor_termList(T1, T2); +chk_MuxDescriptor_termList(TL1, TL2) -> + wrong_type('MuxDescriptor_termList', TL1, TL2). + + +%% -- MuxType -- + +is_MuxType(MT) -> + lists:member(MT, [h221, h223, h226, v76, nx64k]). + +chk_MuxType(MT, MT) -> + chk_type(fun is_MuxType/1, 'MuxType', MT); +chk_MuxType(MT1, MT2) -> + case (is_MuxType(MT1) andalso is_MuxType(MT2)) of + true -> + not_equal('MuxType', MT1, MT2); + false -> + wrong_type('MuxType', MT1, MT2) + end. + + +%% -- StreamID -- + +is_opt_StreamID(V) -> + is_OPTIONAL(fun is_StreamID/1, V). + +is_StreamID(V) -> + d("is_StreamID -> entry with" + "~n V: ~p", [V]), + is_INTEGER(V, {range, 0, 65535}). + +chk_opt_StreamID(V1, V2) -> + chk_OPTIONAL('StreamID', V1, V2, fun is_StreamID/1, fun chk_StreamID/2). + +chk_StreamID(ID, ID) -> + chk_type(fun is_StreamID/1, 'StreamID', ID); +chk_StreamID(ID1, ID2) -> + case (is_StreamID(ID1) andalso is_StreamID(ID2)) of + true -> + not_equal('StreamID', ID1, ID2); + false -> + wrong_type('StreamID', ID1, ID2) + end. + + +%% -- EventsDescriptor -- + +is_EventsDescriptor(#'EventsDescriptor'{requestID = RID, + eventList = EVL}) -> + d("is_EventsDescriptor -> entry with" + "~n RID: ~p" + "~n EVL: ~p", [RID, EVL]), + is_opt_RequestID(RID) andalso is_EventsDescriptor_eventList(EVL); +is_EventsDescriptor(_) -> + false. + +is_EventsDescriptor_eventList([]) -> + true; +is_EventsDescriptor_eventList([H|T]) -> + is_RequestedEvent(H) andalso is_EventsDescriptor_eventList(T); +is_EventsDescriptor_eventList(_) -> + false. + +chk_EventsDescriptor(D, D) -> + chk_type(fun is_EventsDescriptor/1, 'EventsDescriptor', D); +chk_EventsDescriptor(#'EventsDescriptor'{requestID = RID1, + eventList = EVL1}, + #'EventsDescriptor'{requestID = RID2, + eventList = EVL2}) -> + validate(fun() -> chk_opt_RequestID(RID1, RID2) end, 'EventsDescriptor'), + chk_EventsDescriptor_eventList(EVL1, EVL2), + ok; +chk_EventsDescriptor(D1, D2) -> + wrong_type('EventsDescriptor', D1, D2). + +chk_EventsDescriptor_eventList([], []) -> + ok; +chk_EventsDescriptor_eventList([] = EVL1, EVL2) -> + not_equal('EventsDescriptor_eventList', EVL1, EVL2); +chk_EventsDescriptor_eventList(EVL1, [] = EVL2) -> + not_equal('EventsDescriptor_eventList', EVL1, EVL2); +chk_EventsDescriptor_eventList([H|T1], [H|T2]) -> + case is_RequestedEvent(H) of + true -> + chk_EventsDescriptor_eventList(T1, T2); + false -> + wrong_type('EventsDescriptor_eventList_val', H) + end; +chk_EventsDescriptor_eventList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_RequestedEvent(H1, H2) end, + 'EventsDescriptor_eventList_val'), + chk_EventsDescriptor_eventList(T1, T2); +chk_EventsDescriptor_eventList(EVL1, EVL2) -> + wrong_type('EventsDescriptor_eventList', EVL1, EVL2). + + +%% -- RequestedEvent -- + +is_RequestedEvent(#'RequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}) -> + d("is_RequestedEvent -> entry with" + "~n N: ~p" + "~n SID: ~p" + "~n EA: ~p" + "~n EPL: ~p", [N, SID, EA, EPL]), + is_PkgdName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_RequestedActions(EA) andalso + is_RequestedEvent_evParList(EPL); +is_RequestedEvent(_) -> + false. + +is_RequestedEvent_evParList([]) -> + true; +is_RequestedEvent_evParList([H|T]) -> + is_EventParameter(H) andalso is_RequestedEvent_evParList(T); +is_RequestedEvent_evParList(_) -> + false. + +chk_RequestedEvent(RE, RE) -> + chk_type(fun is_RequestedEvent/1, 'RequestedEvent', RE); +chk_RequestedEvent(#'RequestedEvent'{pkgdName = N1, + streamID = SID1, + eventAction = EA1, + evParList = EPL1}, + #'RequestedEvent'{pkgdName = N2, + streamID = SID2, + eventAction = EA2, + evParList = EPL2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'RequestedEvent'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'RequestedEvent'), + validate(fun() -> chk_opt_RequestedActions(EA1, EA2) end, + 'RequestedEvent'), + chk_RequestedEvent_evParList(EPL1, EPL2), + ok; +chk_RequestedEvent(RE1, RE2) -> + wrong_type('RequestedEvent', RE1, RE2). + +chk_RequestedEvent_evParList([], []) -> + ok; +chk_RequestedEvent_evParList([] = EPL1, EPL2) -> + not_equal('RequestedEvent_evParList', EPL1, EPL2); +chk_RequestedEvent_evParList(EPL1, [] = EPL2) -> + not_equal('RequestedEvent_evParList', EPL1, EPL2); +chk_RequestedEvent_evParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_RequestedEvent_evParList(T1, T2); + false -> + wrong_type('RequestedEvent_evParList_val', H) + end; +chk_RequestedEvent_evParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'RequestedEvent_evParList_val'), + chk_RequestedEvent_evParList(T1, T2); +chk_RequestedEvent_evParList(EPL1, EPL2) -> + wrong_type('RequestedEvent_evParList', EPL1, EPL2). + + +%% -- RequestedActions -- + +is_opt_RequestedActions(asn1_NOVALUE) -> + true; +is_opt_RequestedActions(RA) -> + is_RequestedActions(RA). + +is_RequestedActions(#'RequestedActions'{keepActive = KA, + eventDM = EDM, + secondEvent = SE, + signalsDescriptor = SD}) -> + d("is_RequestedActions -> entry with" + "~n KA: ~p" + "~n EDM: ~p" + "~n SE: ~p" + "~n SD: ~p", [KA, EDM, SE, SD]), + is_opt_BOOLEAN(KA) andalso + is_opt_EventDM(EDM) andalso + is_opt_SecondEventsDescriptor(SE) andalso + is_opt_SignalsDescriptor(SD); +is_RequestedActions(_) -> + false. + +chk_opt_RequestedActions(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_RequestedActions(RA1, RA2) -> + chk_RequestedActions(RA1, RA2). + +chk_RequestedActions(RA, RA) -> + chk_type(fun is_RequestedActions/1, 'RequestedActions', RA); +chk_RequestedActions(#'RequestedActions'{keepActive = KA1, + eventDM = EDM1, + secondEvent = SA1, + signalsDescriptor = SD1}, + #'RequestedActions'{keepActive = KA2, + eventDM = EDM2, + secondEvent = SA2, + signalsDescriptor = SD2}) -> + validate(fun() -> chk_opt_BOOLEAN(KA1, KA2) end, 'RequestedActions'), + validate(fun() -> chk_opt_EventDM(EDM1, EDM2) end, 'RequestedActions'), + validate(fun() -> chk_opt_SecondEventsDescriptor(SA1, SA2) end, + 'RequestedActions'), + validate(fun() -> chk_opt_SignalsDescriptor(SD1, SD2) end, + 'RequestedActions'), + ok; +chk_RequestedActions(RA1, RA2) -> + wrong_type('RequestedActions', RA1, RA2). + + +%% -- EventDM -- + +is_opt_EventDM(EDM) -> + is_OPTIONAL(fun is_EventDM/1, EDM). + +is_EventDM({Tag, Val}) -> + is_EventDM_tag(Tag) andalso is_EventDM_val(Tag, Val); +is_EventDM(_) -> + false. + +is_EventDM_tag(Tag) -> + Tags = [digitMapName, digitMapValue], + lists:member(Tag, Tags). + +is_EventDM_val(digitMapName, Val) -> + is_DigitMapName(Val); +is_EventDM_val(digitMapValue, Val) -> + is_DigitMapValue(Val). + +chk_opt_EventDM(EDM1, EDM2) -> + chk_OPTIONAL('EventDM', EDM1, EDM2, fun is_EventDM/1, fun chk_EventDM/2). + +chk_EventDM(EDM, EDM) -> + chk_type(fun is_EventDM/1, 'EventDM', EDM); +chk_EventDM({Tag, Val1} = EDM1, {Tag, Val2} = EDM2) -> + case (is_EventDM_tag(Tag) andalso + is_EventDM_val(Tag, Val1) andalso + is_EventDM_val(Tag, Val2)) of + true -> + chk_EventDM_val(Tag, Val1, Val2); + false -> + wrong_type('EventDM', EDM1, EDM2) + end; +chk_EventDM({Tag1, Val1} = EDM1, {Tag2, Val2} = EDM2) -> + case ((is_EventDM_tag(Tag1) andalso + is_EventDM_val(Tag1, Val1)) andalso + (is_EventDM_tag(Tag2) andalso + is_EventDM_val(Tag2, Val2))) of + true -> + not_equal('EventDM', EDM1, EDM2); + false -> + wrong_type('EventDM', EDM1, EDM2) + end; +chk_EventDM(EDM1, EDM2) -> + wrong_type('EventDM', EDM1, EDM2). + +chk_EventDM_val(digitMapName, Val1, Val2) -> + validate(fun() -> chk_DigitMapName(Val1, Val2) end, 'EventDM'); +chk_EventDM_val(digitMapValue, Val1, Val2) -> + validate(fun() -> chk_DigitMapValue(Val1, Val2) end, 'EventDM'). + + +%% -- SecondEventsDescriptor -- + +is_opt_SecondEventsDescriptor(asn1_NOVALUE) -> + true; +is_opt_SecondEventsDescriptor(D) -> + is_SecondEventsDescriptor(D). + +is_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = RID, + eventList = EL}) -> + is_opt_RequestID(RID) andalso is_SecondEventsDescriptor_eventList(EL); +is_SecondEventsDescriptor(_) -> + false. + +is_SecondEventsDescriptor_eventList([]) -> + true; +is_SecondEventsDescriptor_eventList([H|T]) -> + is_SecondRequestedEvent(H) andalso is_SecondEventsDescriptor_eventList(T); +is_SecondEventsDescriptor_eventList(_) -> + false. + +chk_opt_SecondEventsDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SecondEventsDescriptor(D1, D2) -> + chk_SecondEventsDescriptor(D1, D2). + +chk_SecondEventsDescriptor(D, D) -> + chk_type(fun is_SecondEventsDescriptor/1, 'SecondEventsDescriptor', D); +chk_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = RID1, + eventList = EL1}, + #'SecondEventsDescriptor'{requestID = RID2, + eventList = EL2}) -> + validate(fun() -> chk_opt_RequestID(RID1, RID2) end, + 'SecondEventsDescriptor'), + chk_SecondEventsDescriptor_eventList(EL1, EL2), + ok; +chk_SecondEventsDescriptor(D1, D2) -> + wrong_type('SecondEventsDescriptor', D1, D2). + +chk_SecondEventsDescriptor_eventList([], []) -> + ok; +chk_SecondEventsDescriptor_eventList([] = EL1, EL2) -> + not_equal('SecondEventsDescriptor_eventList', EL1, EL2); +chk_SecondEventsDescriptor_eventList(EL1, [] = EL2) -> + not_equal('SecondEventsDescriptor_eventList', EL1, EL2); +chk_SecondEventsDescriptor_eventList([H|T1], [H|T2]) -> + case is_SecondRequestedEvent(H) of + true -> + chk_SecondEventsDescriptor_eventList(T1, T2); + false -> + wrong_type('SecondEventsDescriptor_eventList_val', H) + end; +chk_SecondEventsDescriptor_eventList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_SecondRequestedEvent(H1, H2) end, + 'SecondEventsDescriptor_eventList_val'), + chk_SecondEventsDescriptor_eventList(T1, T2); +chk_SecondEventsDescriptor_eventList(L1, L2) -> + wrong_type('SecondEventsDescriptor_eventList_val', L1, L2). + + +%% -- SecondRequestedEvent -- + +is_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}) -> + is_PkgdName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_SecondRequestedActions(EA) andalso + is_SecondRequestedEvent_evParList(EPL); +is_SecondRequestedEvent(_) -> + false. + +is_SecondRequestedEvent_evParList([]) -> + true; +is_SecondRequestedEvent_evParList([H|T]) -> + is_EventParameter(H) andalso is_SecondRequestedEvent_evParList(T); +is_SecondRequestedEvent_evParList(_) -> + false. + +chk_SecondRequestedEvent(RE, RE) -> + chk_type(fun is_SecondRequestedEvent/1, 'SecondRequestedEvent', RE); +chk_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N1, + streamID = SID1, + eventAction = EA1, + evParList = EPL1}, + #'SecondRequestedEvent'{pkgdName = N2, + streamID = SID2, + eventAction = EA2, + evParList = EPL2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'SecondRequestedEvent'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, + 'SecondRequestedEvent'), + validate(fun() -> chk_opt_SecondRequestedActions(EA1, EA2) end, + 'SecondRequestedEvent'), + chk_SecondRequestedEvent_evParList(EPL1, EPL2), + ok; +chk_SecondRequestedEvent(RE1, RE2) -> + wrong_type('SecondRequestedEvent', RE1, RE2). + +chk_SecondRequestedEvent_evParList([], []) -> + ok; +chk_SecondRequestedEvent_evParList([] = EPL1, EPL2) -> + not_equal('SecondRequestedEvent_evParList', EPL1, EPL2); +chk_SecondRequestedEvent_evParList(EPL1, [] = EPL2) -> + not_equal('SecondRequestedEvent_evParList', EPL1, EPL2); +chk_SecondRequestedEvent_evParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_SecondRequestedEvent_evParList(T1, T2); + false -> + wrong_type('SecondRequestedEvent_evParList_val', H) + end; +chk_SecondRequestedEvent_evParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'SecondRequestedEvent_evParList_val'), + chk_SecondRequestedEvent_evParList(T1, T2); +chk_SecondRequestedEvent_evParList(EPL1, EPL2) -> + wrong_type('SecondRequestedEvent_evParList', EPL1, EPL2). + + +%% -- SecondRequestedActions -- + +is_opt_SecondRequestedActions(asn1_NOVALUE) -> + true; +is_opt_SecondRequestedActions(SRA) -> + is_SecondRequestedActions(SRA). + +is_SecondRequestedActions(#'SecondRequestedActions'{keepActive = KA, + eventDM = EDM, + signalsDescriptor = SD}) -> + is_opt_BOOLEAN(KA) andalso + is_opt_EventDM(EDM) andalso + is_opt_SignalsDescriptor(SD); +is_SecondRequestedActions(_) -> + false. + +chk_opt_SecondRequestedActions(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SecondRequestedActions(SRA1, SRA2) -> + chk_SecondRequestedActions(SRA1, SRA2). + +chk_SecondRequestedActions(SRA, SRA) -> + chk_type(fun is_SecondRequestedActions/1, 'SecondRequestedActions', SRA); +chk_SecondRequestedActions( + #'SecondRequestedActions'{keepActive = KA1, + eventDM = EDM1, + signalsDescriptor = SD1}, + #'SecondRequestedActions'{keepActive = KA2, + eventDM = EDM2, + signalsDescriptor = SD2}) -> + validate(fun() -> chk_opt_BOOLEAN(KA1, KA2) end, + 'SecondRequestedActions'), + validate(fun() -> chk_opt_EventDM(EDM1, EDM2) end, + 'SecondRequestedActions'), + validate(fun() -> chk_opt_SignalsDescriptor(SD1, SD2) end, + 'SecondRequestedActions'), + ok; +chk_SecondRequestedActions(SRA1, SRA2) -> + wrong_type('SecondRequestedActions', SRA1, SRA2). + + +%% -- EventBufferDescriptor -- + +is_EventBufferDescriptor([]) -> + true; +is_EventBufferDescriptor([H|T]) -> + is_EventSpec(H) andalso is_EventBufferDescriptor(T); +is_EventBufferDescriptor(_) -> + false. + +chk_EventBufferDescriptor([], []) -> + ok; +chk_EventBufferDescriptor([] = D1, D2) -> + not_equal('EventBufferDescriptor', D1, D2); +chk_EventBufferDescriptor(D1, [] = D2) -> + not_equal('EventBufferDescriptor', D1, D2); +chk_EventBufferDescriptor([H|T1], [H|T2]) -> + case is_EventSpec(H) of + true -> + chk_EventBufferDescriptor(T1, T2); + false -> + wrong_type('EventBufferDescriptor_val', H) + end; +chk_EventBufferDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventSpec(H1, H2) end, + 'EventBufferDescriptor_val'), + chk_EventBufferDescriptor(T1, T2); +chk_EventBufferDescriptor(D1, D2) -> + wrong_type('EventBufferDescriptor_val', D1, D2). + + +%% -- EventSpec -- + +is_EventSpec(#'EventSpec'{eventName = N, + streamID = SID, + eventParList = EPL}) -> + is_EventName(N) andalso + is_opt_StreamID(SID) andalso + is_EventSpec_eventParList(EPL); +is_EventSpec(_) -> + false. + +is_EventSpec_eventParList([]) -> + true; +is_EventSpec_eventParList([H|T]) -> + is_EventParameter(H) andalso is_EventSpec_eventParList(T); +is_EventSpec_eventParList(_) -> + false. + +chk_EventSpec(ES, ES) -> + chk_type(fun is_EventSpec/1, 'EventSpec', ES); +chk_EventSpec(#'EventSpec'{eventName = N1, + streamID = SID1, + eventParList = EPL1}, + #'EventSpec'{eventName = N2, + streamID = SID2, + eventParList = EPL2}) -> + validate(fun() -> chk_EventName(N1, N2) end, 'EventSpec'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'EventSpec'), + chk_EventSpec_eventParList(EPL1, EPL2), + ok; +chk_EventSpec(ES1, ES2) -> + wrong_type('EventSpec', ES1, ES2). + +chk_EventSpec_eventParList([], []) -> + ok; +chk_EventSpec_eventParList([] = EPL1, EPL2) -> + not_equal('EventSpec_eventParList', EPL1, EPL2); +chk_EventSpec_eventParList(EPL1, [] = EPL2) -> + not_equal('EventSpec_eventParList', EPL1, EPL2); +chk_EventSpec_eventParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_EventSpec_eventParList(T1, T2); + false -> + wrong_type('EventSpec_eventParList_val', H) + end; +chk_EventSpec_eventParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'EventSpec_eventParList_val'), + chk_EventSpec_eventParList(T1, T2); +chk_EventSpec_eventParList(EPL1, EPL2) -> + wrong_type('EventSpec_eventParList', EPL1, EPL2). + + +%% -- SignalsDescriptor -- + +is_opt_SignalsDescriptor(asn1_NOVALUE) -> + true; +is_opt_SignalsDescriptor(D) -> + is_SignalsDescriptor(D). + +is_SignalsDescriptor([]) -> + true; +is_SignalsDescriptor([H|T]) -> + is_SignalRequest(H) andalso is_SignalsDescriptor(T); +is_SignalsDescriptor(_) -> + false. + +chk_opt_SignalsDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SignalsDescriptor(D1, D2) -> + chk_SignalsDescriptor(D1, D2). + +chk_SignalsDescriptor([], []) -> + ok; +chk_SignalsDescriptor([] = D1, D2) -> + not_equal('SignalsDescriptor', D1, D2); +chk_SignalsDescriptor(D1, [] = D2) -> + not_equal('SignalsDescriptor', D1, D2); +chk_SignalsDescriptor([H|T1], [H|T2]) -> + case is_SignalRequest(H) of + true -> + chk_SignalsDescriptor(T1, T2); + false -> + wrong_type('SignalsDescriptor_val', H) + end; +chk_SignalsDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_SignalRequest(H1, H2) end, 'SignalsDescriptor_val'), + chk_SignalsDescriptor(T1, T2); +chk_SignalsDescriptor(D1, D2) -> + wrong_type('SignalsDescriptor', D1, D2). + + +%% -- SignalRequest -- + +is_SignalRequest({Tag, Val}) -> + is_SignalRequest_tag(Tag) andalso is_SignalRequest_val(Tag, Val); +is_SignalRequest(_) -> + false. + +is_SignalRequest_tag(Tag) -> + Tags = [signal, seqSigList], + lists:member(Tag, Tags). + +is_SignalRequest_val(signal, Val) -> + is_Signal(Val); +is_SignalRequest_val(seqSigList, Val) -> + is_SeqSigList(Val). + +chk_SignalRequest(R, R) -> + chk_type(fun is_SignalRequest/1, 'SignalRequest', R); +chk_SignalRequest({Tag, Val1} = R1, {Tag, Val2} = R2) -> + case (is_SignalRequest_tag(Tag) andalso + is_SignalRequest_val(Tag, Val1) andalso + is_SignalRequest_val(Tag, Val2)) of + true -> + chk_SignalRequest_val(Tag, Val1, Val2); + false -> + wrong_type('SignalRequest', R1, R2) + end; +chk_SignalRequest({Tag1, Val1} = R1, {Tag2, Val2} = R2) -> + case ((is_SignalRequest_tag(Tag1) andalso + is_SignalRequest_val(Tag1, Val1)) andalso + (is_SignalRequest_tag(Tag2) andalso + is_SignalRequest_val(Tag2, Val2))) of + true -> + not_equal('SignalRequest', R1, R2); + false -> + wrong_type('SignalRequest', R1, R2) + end; +chk_SignalRequest(R1, R2) -> + wrong_type('SignalRequest', R1, R2). + +chk_SignalRequest_val(signal, Val1, Val2) -> + validate(fun() -> chk_Signal(Val1, Val2) end, 'SignalRequest'); +chk_SignalRequest_val(seqSigList, Val1, Val2) -> + validate(fun() -> chk_SeqSigList(Val1, Val2) end, 'SignalRequest'). + + +%% -- SeqSigList -- + +is_SeqSigList(#'SeqSigList'{id = ID, + signalList = SL}) -> + is_INTEGER(ID, {range, 0, 65535}) andalso + is_SeqSigList_signalList(SL); +is_SeqSigList(_) -> + false. + +is_SeqSigList_signalList([]) -> + true; +is_SeqSigList_signalList([H|T]) -> + is_Signal(H) andalso is_SeqSigList_signalList(T); +is_SeqSigList_signalList(_) -> + false. + +chk_SeqSigList(L, L) -> + chk_type(fun is_SeqSigList/1, 'SeqSigList', L); +chk_SeqSigList(#'SeqSigList'{id = ID1, + signalList = SL1}, + #'SeqSigList'{id = ID2, + signalList = SL2}) -> + validate(fun() -> chk_INTEGER(ID1, ID2, {range, 0, 65535}) end, + 'SeqSigList'), + chk_SeqSigList_signalList(SL1, SL2), + ok; +chk_SeqSigList(L1, L2) -> + wrong_type('SeqSigList', L1, L2). + +chk_SeqSigList_signalList([], []) -> + ok; +chk_SeqSigList_signalList([] = L1, L2) -> + not_equal('SeqSigList_signalList', L1, L2); +chk_SeqSigList_signalList(L1, [] = L2) -> + not_equal('SeqSigList_signalList', L1, L2); +chk_SeqSigList_signalList([H|T1], [H|T2]) -> + case is_Signal(H) of + true -> + chk_SeqSigList_signalList(T1, T2); + false -> + wrong_type('SeqSigList_signalList_val', H) + end; +chk_SeqSigList_signalList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_Signal(H1, H2) end, + 'SeqSigList_signalList_val'), + chk_SeqSigList_signalList(T1, T2); +chk_SeqSigList_signalList(L1, L2) -> + wrong_type('SeqSigList_signalList', L1, L2). + + +%% -- Signal -- + +is_Signal(#'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL, + direction = Dir, + requestID = RID}) -> + is_SignalName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_SignalType(ST) andalso + is_opt_INTEGER(Dur, {range, 0, 65535}) andalso + is_opt_NotifyCompletion(NC) andalso + is_opt_BOOLEAN(KA) andalso + is_Signal_sigParList(SPL) andalso + is_opt_SignalDirection(Dir) andalso + is_opt_RequestID(RID). + +is_Signal_sigParList([]) -> + true; +is_Signal_sigParList([H|T]) -> + is_SigParameter(H) andalso is_Signal_sigParList(T); +is_Signal_sigParList(_) -> + false. + +chk_Signal(S, S) -> + chk_type(fun is_Signal/1, 'Signal', S); +chk_Signal(#'Signal'{signalName = N1, + streamID = SID1, + sigType = ST1, + duration = Dur1, + notifyCompletion = NC1, + keepActive = KA1, + sigParList = SPL1, + direction = Dir1, + requestID = RID1}, + #'Signal'{signalName = N2, + streamID = SID2, + sigType = ST2, + duration = Dur2, + notifyCompletion = NC2, + keepActive = KA2, + sigParList = SPL2, + direction = Dir2, + requestID = RID2}) -> + validate(fun() -> chk_SignalName(N1, N2) end, 'Signal'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'Signal'), + validate(fun() -> chk_opt_SignalType(ST1, ST2) end, 'Signal'), + validate(fun() -> chk_opt_INTEGER(Dur1, Dur2, {range, 0, 65535}) end, + 'Signal'), + validate(fun() -> chk_opt_NotifyCompletion(NC1, NC2) end, 'Signal'), + validate(fun() -> chk_opt_BOOLEAN(KA1, KA2) end, 'Signal'), + chk_Signal_sigParList(SPL1, SPL2), + validate(fun() -> chk_opt_SignalDirection(Dir1, Dir2) end, 'Signal'), + validate(fun() -> chk_opt_RequestID(RID1, RID2) end, 'Signal'), + ok; +chk_Signal(S1, S2) -> + wrong_type('Signal', S1, S2). + +chk_Signal_sigParList([], []) -> + ok; +chk_Signal_sigParList([] = L1, L2) -> + not_equal('Signal_sigParList', L1, L2); +chk_Signal_sigParList(L1, [] = L2) -> + not_equal('Signal_sigParList', L1, L2); +chk_Signal_sigParList([H|T1], [H|T2]) -> + case is_SigParameter(H) of + true -> + chk_Signal_sigParList(T1, T2); + false -> + wrong_type('Signal_sigParList_val', H) + end; +chk_Signal_sigParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_SigParameter(H1, H2) end, + 'Signal_sigParList_val'), + chk_Signal_sigParList(T1, T2); +chk_Signal_sigParList(L1, L2) -> + wrong_type('Signal_sigParList', L1, L2). + + +%% -- SignalType -- + +is_opt_SignalType(T) -> + is_OPTIONAL(fun is_SignalType/1, T). + +is_SignalType(T) -> + Types = [brief, onOff, timeOut], + lists:member(T, Types). + +chk_opt_SignalType(T1, T2) -> + chk_OPTIONAL('SignalType', T1, T2, + fun is_SignalType/1, fun chk_SignalType/2). + +chk_SignalType(T, T) -> + chk_type(fun is_SignalType/1, 'SignalType', T); +chk_SignalType(T1, T2) -> + case (is_SignalType(T1) andalso is_SignalType(T2)) of + true -> + not_equal('SignalType', T1, T2); + false -> + wrong_type('SignalType', T1, T2) + end. + + +%% -- SignalDirection -- + +is_opt_SignalDirection(T) -> + is_OPTIONAL(fun is_SignalDirection/1, T). + +is_SignalDirection(Dir) -> + Dirs = [internal, external, both], + lists:member(Dir, Dirs). + +chk_opt_SignalDirection(T1, T2) -> + chk_OPTIONAL('SignalDirection', T1, T2, + fun is_SignalDirection/1, fun chk_SignalDirection/2). + +chk_SignalDirection(Dir, Dir) -> + chk_type(fun is_SignalDirection/1, 'SignalDirection', Dir); +chk_SignalDirection(Dir1, Dir2) -> + case (is_SignalDirection(Dir1) andalso is_SignalDirection(Dir2)) of + true -> + not_equal('SignalDirection', Dir1, Dir2); + false -> + wrong_type('SignalDirection', Dir1, Dir2) + end. + + +%% -- SignalName -- + +is_SignalName(N) -> is_PkgdName(N). + +chk_SignalName(N1, N2) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'SignalName'). + + +%% -- NotifyCompletion -- + +is_opt_NotifyCompletion(NC) -> + is_OPTIONAL(fun is_NotifyCompletion/1, NC). + +is_NotifyCompletion(NC) -> + Valids = [onTimeOut, + onInterruptByEvent, + onInterruptByNewSignalDescr, + otherReason], + lists:all(fun(X) -> lists:member(X, Valids) end, NC). + +chk_opt_NotifyCompletion(NC1, NC2) -> + chk_OPTIONAL('NotifyCompletion', NC1, NC2, + fun is_NotifyCompletion/1, + fun chk_NotifyCompletion/2). + +chk_NotifyCompletion(NC, NC) -> + chk_type(fun is_NotifyCompletion/1, 'NotifyCompletion', NC); +chk_NotifyCompletion(NC1, NC2) -> + case (is_NotifyCompletion(NC1) andalso is_NotifyCompletion(NC2)) of + true -> + not_equal('NotifyCompletion', NC1, NC2); + false -> + wrong_type('NotifyCompletion', NC1, NC2) + end. + + +%% -- SigParameter -- + +is_SigParameter(#'SigParameter'{sigParameterName = N, + value = V, + extraInfo = I}) -> + is_Name(N) andalso + is_Value(V) andalso + is_SigParameter_extraInfo(I); +is_SigParameter(_) -> + false. + +is_SigParameter_extraInfo({Tag, Val}) -> + is_SigParameter_extraInfo_tag(Tag) andalso + is_SigParameter_extraInfo_val(Tag, Val); +is_SigParameter_extraInfo(_) -> + false. + +is_SigParameter_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_SigParameter_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_SigParameter_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_SigParameter_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + +chk_SigParameter(P, P) -> + chk_type(fun is_SigParameter/1, 'SigParameter', P); +chk_SigParameter(#'SigParameter'{sigParameterName = N1, + value = V1, + extraInfo = I1}, + #'SigParameter'{sigParameterName = N2, + value = V2, + extraInfo = I2}) -> + validate(fun() -> chk_Name(N1, N2) end, 'SigParameter'), + validate(fun() -> chk_Value(V1, V2) end, 'SigParameter'), + chk_SigParameter_extraInfo(I1, I2), + ok; +chk_SigParameter(P1, P2) -> + wrong_type('SigParameter', P1, P2). + +chk_SigParameter_extraInfo(EI, EI) -> + chk_type(fun is_SigParameter_extraInfo/1, 'SigParameter_extraInfo', EI); +chk_SigParameter_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> + case (is_SigParameter_extraInfo_tag(Tag) and + is_SigParameter_extraInfo_val(Tag, Val1) and + is_SigParameter_extraInfo_val(Tag, Val2)) of + true -> + chk_SigParameter_extraInfo_val(Tag, Val1, Val2); + false -> + wrong_type('SigParameter_extraInfo', EI1, EI2) + end; +chk_SigParameter_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> + case ((is_SigParameter_extraInfo_tag(Tag1) and + is_SigParameter_extraInfo_val(Tag1, Val1)) and + (is_SigParameter_extraInfo_tag(Tag2) and + is_SigParameter_extraInfo_val(Tag2, Val2))) of + true -> + not_equal('SigParameter_extraInfo', EI1, EI2); + false -> + wrong_type('SigParameter_extraInfo', EI1, EI2) + end; +chk_SigParameter_extraInfo(EI1, EI2) -> + wrong_type('SigParameter_extraInfo', EI1, EI2). + +chk_SigParameter_extraInfo_val(relation, Val1, Val2) -> + validate(fun() -> chk_Relation(Val1, Val2) end, 'SigParameter_extraInfo'); +chk_SigParameter_extraInfo_val(range, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'SigParameter_extraInfo'); +chk_SigParameter_extraInfo_val(sublist, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'SigParameter_extraInfo'). + + +%% -- RequestID -- + +is_opt_RequestID(asn1_NOVALUE) -> + true; +is_opt_RequestID(V) -> + is_RequestID(V). + +is_RequestID(V) -> is_INTEGER(V, {range, 0, 4294967295}). + +chk_opt_RequestID(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_RequestID(V1, V2) -> + chk_RequestID(V1, V2). + +chk_RequestID(ID, ID) -> + chk_type(fun is_RequestID/1, 'RequestID', ID); +chk_RequestID(ID1, ID2) -> + case (is_RequestID(ID1) andalso is_RequestID(ID2)) of + true -> + not_equal('RequestID', ID1, ID2); + false -> + wrong_type('RequestID', ID1, ID2) + end. + + +%% -- ModemDescriptor -- + +is_ModemDescriptor(D) when is_record(D, 'ModemDescriptor') -> + true; +is_ModemDescriptor(_) -> + false. + +chk_ModemDescriptor(D, D) when is_record(D, 'ModemDescriptor') -> + ok; +chk_ModemDescriptor(#'ModemDescriptor'{mtl = MTL1, + mpl = MPL1, + nonStandardData = NSD1}, + #'ModemDescriptor'{mtl = MTL2, + mpl = MPL2, + nonStandardData = NSD2}) -> + chk_ModemDescriptor_mtl(MTL1, MTL2), + chk_ModemDescriptor_mpl(MPL1, MPL2), + chk_opt_NonStandardData(NSD1, NSD2), + ok; +chk_ModemDescriptor(D1, D2) -> + wrong_type('ModemDescriptor', D1, D2). + +chk_ModemDescriptor_mtl([], []) -> + ok; +chk_ModemDescriptor_mtl([] = MTL1, MTL2) -> + not_equal('ModemDescriptor_mtl', MTL1, MTL2); +chk_ModemDescriptor_mtl(MTL1, [] = MTL2) -> + not_equal('ModemDescriptor_mtl', MTL1, MTL2); +chk_ModemDescriptor_mtl([H|T1], [H|T2]) -> + case is_ModemType(H) of + true -> + chk_ModemDescriptor_mtl(T1, T2); + false -> + wrong_type('ModemDescriptor_mtl_val', H) + end; +chk_ModemDescriptor_mtl([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ModemType(H1, H2) end, 'ModemDescriptor_mtl_val'), + chk_ModemDescriptor_mtl(T1, T2); +chk_ModemDescriptor_mtl(MTL1, MTL2) -> + wrong_type('ModemDescriptor_mtl', MTL1, MTL2). + + +chk_ModemDescriptor_mpl([], []) -> + ok; +chk_ModemDescriptor_mpl([] = MPL1, MPL2) -> + not_equal('ModemDescriptor_mpl', MPL1, MPL2); +chk_ModemDescriptor_mpl(MPL1, [] = MPL2) -> + not_equal('ModemDescriptor_mpl', MPL1, MPL2); +chk_ModemDescriptor_mpl([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_ModemDescriptor_mpl(T1, T2); + false -> + wrong_type('ModemDescriptor_mpl_val', H) + end; +chk_ModemDescriptor_mpl([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, 'ModemDescriptor_mpl_val'), + chk_ModemDescriptor_mpl(T1, T2); +chk_ModemDescriptor_mpl(MPL1, MPL2) -> + wrong_type('ModemDescriptor_mpl', MPL1, MPL2). + + +%% -- ModemType -- + +chk_ModemType(MT, MT) -> + case is_ModemType(MT) of + true -> + ok; + false -> + wrong_type('ModemType', MT, MT) + end; +chk_ModemType(MT1, MT2) -> + case (is_ModemType(MT1) andalso is_ModemType(MT2)) of + true -> + not_equal('ModemType', MT1, MT2); + false -> + wrong_type('ModemType', MT1, MT2) + end. + +is_ModemType(MT) -> + lists:member(MT, + [v18, v22, v22bis, v32, v32bis, v34, v90, v91, synchISDN]). + + +%% -- DigitMapDescriptor -- + +is_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Val}) -> + is_opt_DigitMapName(Name) andalso is_opt_DigitMapValue(Val); +is_DigitMapDescriptor(_) -> + false. + +chk_DigitMapDescriptor(D, D) -> + chk_type(fun is_DigitMapDescriptor/1, 'DigitMapDescriptor', D); +chk_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name1, + digitMapValue = Val1}, + #'DigitMapDescriptor'{digitMapName = Name2, + digitMapValue = Val2}) -> + d("chk_DigitMapDescriptor -> entry with" + "~n Name1: ~p" + "~n Name2: ~p" + "~n Val1: ~p" + "~n Val2: ~p", [Name1, Name2, Val1, Val2]), + validate(fun() -> chk_opt_DigitMapName(Name1, Name2) end, + 'DigitMapDescriptor'), + validate(fun() -> chk_opt_DigitMapValue(Val1, Val2) end, + 'DigitMapDescriptor'), + ok; +chk_DigitMapDescriptor(D1, D2) -> + wrong_type('DigitMapDescriptor', D1, D2). + + +%% -- DigitMapName -- + +is_opt_DigitMapName(asn1_NOVALUE) -> + true; +is_opt_DigitMapName(N) -> + is_DigitMapName(N). + +is_DigitMapName(N) -> is_Name(N). + +chk_opt_DigitMapName(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_DigitMapName(N1, N2) -> + chk_DigitMapName(N1, N2). + +chk_DigitMapName(N, N) -> + chk_type(fun is_DigitMapName/1, 'DigitMapName', N); +chk_DigitMapName(N1, N2) -> + case (is_DigitMapName(N1) andalso is_DigitMapName(N2)) of + true -> + not_equal('DigitMapName', N1, N2); + false -> + wrong_type('DigitMapName', N1, N2) + end. + + +%% -- DigitMapValue -- + +is_opt_DigitMapValue(V) -> + is_OPTIONAL(fun is_DigitMapValue/1, V). + +is_DigitMapValue(#'DigitMapValue'{startTimer = Start, + shortTimer = Short, + longTimer = Long, + digitMapBody = Body, + durationTimer = Dur}) -> + is_DigitMapValue_startTimer(Start) andalso + is_DigitMapValue_shortTimer(Short) andalso + is_DigitMapValue_longTimer(Long) andalso + is_IA5String(Body) andalso + is_DigitMapValue_durationTimer(Dur); +is_DigitMapValue(_) -> + false. + +is_DigitMapValue_startTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_startTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +is_DigitMapValue_shortTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_shortTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +is_DigitMapValue_longTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_longTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +is_DigitMapValue_durationTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_durationTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +chk_opt_DigitMapValue(V1, V2) -> + chk_OPTIONAL('DigitMapValue', V1, V2, + fun is_DigitMapValue/1, fun chk_DigitMapValue/2). + +chk_DigitMapValue(#'DigitMapValue'{startTimer = Start1, + shortTimer = Short1, + longTimer = Long1, + digitMapBody = Body1, + durationTimer = Dur1}, + #'DigitMapValue'{startTimer = Start2, + shortTimer = Short2, + longTimer = Long2, + digitMapBody = Body2, + durationTimer = Dur2}) -> + d("chk_DigitMapValue -> entry with" + "~n Start1: ~p" + "~n Start2: ~p" + "~n Short1: ~p" + "~n Short2: ~p" + "~n Long1: ~p" + "~n Long2: ~p" + "~n Body1: ~p" + "~n Body2: ~p" + "~n Dur1: ~p" + "~n Dur2: ~p", [Start1, Start2, + Short1, Short2, + Long1, Long2, + Body1, Body2, + Dur1, Dur2]), + chk_DigitMapValue_startTimer(Start1, Start2), + chk_DigitMapValue_shortTimer(Short1, Short2), + chk_DigitMapValue_longTimer(Long1, Long2), + chk_DigitMapValue_digitMapBody(Body1, Body2), + chk_DigitMapValue_durationTimer(Dur1, Dur2), + ok; +chk_DigitMapValue(V1, V2) -> + wrong_type('DigitMapValue', V1, V2). + +chk_DigitMapValue_startTimer(T, T) -> + chk_type(fun is_DigitMapValue_startTimer/1, 'DigitMapValue_startTimer', T); +chk_DigitMapValue_startTimer(T1, T2) -> + case (is_DigitMapValue_startTimer(T1) andalso + is_DigitMapValue_startTimer(T2)) of + true -> + not_equal('DigitMapValue_startTimer', T1, T2); + false -> + wrong_type('DigitMapValue_startTimer', T1, T2) + end. + +chk_DigitMapValue_shortTimer(T, T) -> + chk_type(fun is_DigitMapValue_shortTimer/1, 'DigitMapValue_shortTimer', T); +chk_DigitMapValue_shortTimer(T1, T2) -> + case (is_DigitMapValue_shortTimer(T1) andalso + is_DigitMapValue_shortTimer(T2)) of + true -> + not_equal('DigitMapValue_shortTimer', T1, T2); + false -> + wrong_type('DigitMapValue_shortTimer', T1, T2) + end. + +chk_DigitMapValue_longTimer(T, T) -> + chk_type(fun is_DigitMapValue_longTimer/1, 'DigitMapValue_longTimer', T); +chk_DigitMapValue_longTimer(T1, T2) -> + case (is_DigitMapValue_longTimer(T1) andalso + is_DigitMapValue_longTimer(T2)) of + true -> + not_equal('DigitMapValue_longTimer', T1, T2); + false -> + wrong_type('DigitMapValue_longTimer', T1, T2) + end. + +chk_DigitMapValue_durationTimer(T, T) -> + chk_type(fun is_DigitMapValue_durationTimer/1, + 'DigitMapValue_durationTimer', T); +chk_DigitMapValue_durationTimer(T1, T2) -> + case (is_DigitMapValue_durationTimer(T1) andalso + is_DigitMapValue_durationTimer(T2)) of + true -> + not_equal('DigitMapValue_durationTimer', T1, T2); + false -> + wrong_type('DigitMapValue_durationTimer', T1, T2) + end. + +chk_DigitMapValue_digitMapBody(B, B) -> + d("chk_DigitMapValue_digitMapBody -> entry with" + "~n B: ~p", [B]), + chk_type(fun is_IA5String/1, 'DigitMapValue_digitMapBody', B); +chk_DigitMapValue_digitMapBody(B1, B2) -> + d("chk_DigitMapValue_digitMapBody -> entry with" + "~n B1: ~p" + "~n B2: ~p", [B1, B2]), + case (is_IA5String(B1) andalso is_IA5String(B2)) of + true -> + %% If they are different it could be because + %% of trailing tab's and newline's. + case compare_strings(B1, B2) of + {[], []} -> + ok; + {Str1, []} -> + case strip_tab_and_newline(Str1) of + [] -> + ok; + _ -> + not_equal('DigitMapValue_digitMapBody', B1, B2) + end; + {[], Str2} -> + case strip_tab_and_newline(Str2) of + [] -> + ok; + _ -> + not_equal('DigitMapValue_digitMapBody', B1, B2) + end; + _ -> + not_equal('DigitMapValue_digitMapBody', B1, B2) + end; + false -> + wrong_type('DigitMapValue_digitMapBody', B1, B2) + end. + +%% -- ServiceChangeParm -- + +is_ServiceChangeParm(#'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeAddress = A, + serviceChangeVersion = V, + serviceChangeProfile = P, + serviceChangeReason = R, + serviceChangeDelay = D, + serviceChangeMgcId = Id, + timeStamp = TS, + nonStandardData = NSD, + serviceChangeInfo = I}) -> + is_ServiceChangeMethod(M) andalso + is_opt_ServiceChangeAddress(A) andalso + is_opt_INTEGER(V, {range, 0, 99}) andalso + is_opt_ServiceChangeProfile(P) andalso + is_Value(R) andalso + is_opt_INTEGER(D, {range, 0, 4294967295}) andalso + is_opt_MId(Id) andalso + is_opt_TimeNotation(TS) andalso + is_opt_NonStandardData(NSD) andalso + is_opt_AuditDescriptor(I); +is_ServiceChangeParm(_) -> + false. + +chk_ServiceChangeParm(P, P) -> + chk_type(fun is_ServiceChangeParm/1, 'ServiceChangeParm', P); +chk_ServiceChangeParm(#'ServiceChangeParm'{serviceChangeMethod = M1, + serviceChangeAddress = A1, + serviceChangeVersion = V1, + serviceChangeProfile = P1, + serviceChangeReason = R1, + serviceChangeDelay = D1, + serviceChangeMgcId = Id1, + timeStamp = TS1, + nonStandardData = NSD1, + serviceChangeInfo = I1}, + #'ServiceChangeParm'{serviceChangeMethod = M2, + serviceChangeAddress = A2, + serviceChangeVersion = V2, + serviceChangeProfile = P2, + serviceChangeReason = R2, + serviceChangeDelay = D2, + serviceChangeMgcId = Id2, + timeStamp = TS2, + nonStandardData = NSD2, + serviceChangeInfo = I2}) -> + validate(fun() -> chk_ServiceChangeMethod(M1, M2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_ServiceChangeAddress(A1, A2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_INTEGER(V1, V2, {range, 0, 99}) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_ServiceChangeProfile(P1, P2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_Value(R1, R2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_INTEGER(D1, D2, {range, 0, 4294967295}) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_MId(Id1, Id2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_TimeNotation(TS1, TS2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_NonStandardData(NSD1, NSD2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_AuditDescriptor(I1, I2) end, + 'ServiceChangeParm'), + ok; +chk_ServiceChangeParm(P1, P2) -> + wrong_type('ServiceChangeParm', P1, P2). + + +%% -- ServiceChangeAddress -- + +is_opt_ServiceChangeAddress(A) -> + is_OPTIONAL(fun is_ServiceChangeAddress/1, A). + +is_ServiceChangeAddress({Tag, Val}) -> + is_ServiceChangeAddress_tag(Tag) andalso + is_ServiceChangeAddress_val(Tag, Val); +is_ServiceChangeAddress(_) -> + false. + +is_ServiceChangeAddress_tag(Tag) -> + Tags = [portNumber, ip4Address, ip6Address, domainName, deviceName, + mtpAddress], + lists:member(Tag, Tags). + +is_ServiceChangeAddress_val(portNumber, Val) -> + is_INTEGER(Val, {range, 0, 65535}); +is_ServiceChangeAddress_val(ip4Address, Val) -> + is_IP4Address(Val); +is_ServiceChangeAddress_val(ip6Address, Val) -> + is_IP6Address(Val); +is_ServiceChangeAddress_val(domainName, Val) -> + is_DomainName(Val); +is_ServiceChangeAddress_val(deviceName, Val) -> + is_PathName(Val); +is_ServiceChangeAddress_val(mtpAddress, Val) -> + is_OCTET_STRING(Val, {range, 2, 4}). + + +chk_opt_ServiceChangeAddress(A1, A2) -> + chk_OPTIONAL('ServiceChangeAddress', A1, A2, + fun is_ServiceChangeAddress/1, + fun chk_ServiceChangeAddress/2). + +chk_ServiceChangeAddress(A, A) -> + chk_type(fun is_ServiceChangeAddress/1, 'ServiceChangeAddress', A); +chk_ServiceChangeAddress({Tag, Val1} = A1, {Tag, Val2} = A2) -> + case (is_ServiceChangeAddress_tag(Tag) andalso + is_ServiceChangeAddress_val(Tag, Val1) andalso + is_ServiceChangeAddress_val(Tag, Val2)) of + true -> + chk_ServiceChangeAddress_val(Tag, Val1, Val2); + false -> + wrong_type('ServiceChangeAddress', A1, A2) + end; +chk_ServiceChangeAddress({Tag1, Val1} = A1, {Tag2, Val2} = A2) -> + case ((is_ServiceChangeAddress_tag(Tag1) andalso + is_ServiceChangeAddress_val(Tag1, Val1)) andalso + (is_ServiceChangeAddress_tag(Tag2) andalso + is_ServiceChangeAddress_val(Tag2, Val2))) of + true -> + not_equal('ServiceChangeAddress', A1, A2); + false -> + wrong_type('ServiceChangeAddress', A1, A2) + end; +chk_ServiceChangeAddress(A1, A2) -> + wrong_type('ServiceChangeAddress', A1, A2). + +chk_ServiceChangeAddress_val(portNumber, Val1, Val2) -> + validate(fun() -> chk_INTEGER(Val1, Val2, {range, 0, 99}) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(ip4Address, Val1, Val2) -> + validate(fun() -> chk_IP4Address(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(ip6Address, Val1, Val2) -> + validate(fun() -> chk_IP6Address(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(domainName, Val1, Val2) -> + validate(fun() -> chk_DomainName(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(deviceName, Val1, Val2) -> + validate(fun() -> chk_PathName(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(mtpAddress, Val1, Val2) -> + validate(fun() -> chk_OCTET_STRING(Val1, Val2, {range, 2, 4}) end, + 'ServiceChangeAddress'). + + +%% -- ServiceChangeResParm -- + +is_ServiceChangeResParm(#'ServiceChangeResParm'{serviceChangeMgcId = Id, + serviceChangeAddress = A, + serviceChangeVersion = V, + serviceChangeProfile = P, + timeStamp = TS}) -> + is_opt_MId(Id) andalso + is_opt_ServiceChangeAddress(A) andalso + is_opt_INTEGER(V, {range, 0, 99}) andalso + is_opt_ServiceChangeProfile(P) andalso + is_opt_TimeNotation(TS); +is_ServiceChangeResParm(_) -> + false. + +chk_ServiceChangeResParm(P, P) -> + chk_type(fun is_ServiceChangeResParm/1, 'ServiceChangeResParm', P); +chk_ServiceChangeResParm( + #'ServiceChangeResParm'{serviceChangeMgcId = Id1, + serviceChangeAddress = A1, + serviceChangeVersion = V1, + serviceChangeProfile = P1, + timeStamp = TS1}, + #'ServiceChangeResParm'{serviceChangeMgcId = Id2, + serviceChangeAddress = A2, + serviceChangeVersion = V2, + serviceChangeProfile = P2, + timeStamp = TS2}) -> + validate(fun() -> chk_opt_MId(Id1, Id2) end, 'ServiceChangeResParm'), + validate(fun() -> chk_opt_ServiceChangeAddress(A1, A2) end, + 'ServiceChangeResParm'), + validate(fun() -> chk_opt_INTEGER(V1, V2, {range, 0, 99}) end, + 'ServiceChangeResParm'), + validate(fun() -> chk_opt_ServiceChangeProfile(P1, P2) end, + 'ServiceChangeResParm'), + validate(fun() -> chk_opt_TimeNotation(TS1, TS2) end, + 'ServiceChangeResParm'), + ok; +chk_ServiceChangeResParm(P1, P2) -> + wrong_type('ServiceChangeResParm', P1, P2). + + +%% -- ServiceChangeMethod -- + +is_ServiceChangeMethod(M) -> + Methods = [failover, forced, graceful, restart, disconnected, handOff], + lists:member(M, Methods). + +chk_ServiceChangeMethod(M, M) -> + chk_type(fun is_ServiceChangeMethod/1, 'ServiceChangeMethod', M); +chk_ServiceChangeMethod(M1, M2) -> + case (is_ServiceChangeMethod(M1) andalso is_ServiceChangeMethod(M2)) of + true -> + not_equal('ServiceChangeMethod', M1, M2); + false -> + wrong_type('ServiceChangeMethod', M1, M2) + end. + + +%% -- ServiceChangeProfile -- + +is_opt_ServiceChangeProfile(P) -> + is_OPTIONAL(fun is_ServiceChangeProfile/1, P). + +is_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = N}) -> + is_IA5String(N, {range, 1, 67}); +is_ServiceChangeProfile(_) -> + false. + +chk_opt_ServiceChangeProfile(P1, P2) -> + chk_OPTIONAL('ServiceChangeProfile', P1, P2, + fun is_ServiceChangeProfile/1, + fun chk_ServiceChangeProfile/2). + +chk_ServiceChangeProfile(P, P) -> + chk_type(fun is_ServiceChangeProfile/1, 'ServiceChangeProfile', P); +chk_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = N1}, + #'ServiceChangeProfile'{profileName = N2}) -> + validate(fun() -> chk_IA5String(N1, N2, {range, 1, 67}) end, + 'ServiceChangeProfile'), + ok; +chk_ServiceChangeProfile(P1, P2) -> + wrong_type('ServiceChangeProfile', P1, P2). + + +%% -- PackagesDescriptor -- + +is_PackagesDescriptor([]) -> + true; +is_PackagesDescriptor([H|T]) -> + is_PackagesItem(H) andalso is_PackagesDescriptor(T); +is_PackagesDescriptor(_) -> + false. + +chk_PackagesDescriptor([], []) -> + ok; +chk_PackagesDescriptor([] = D1, D2) -> + not_equal('PackagesDescriptor', D1, D2); +chk_PackagesDescriptor(D1, [] = D2) -> + not_equal('PackagesDescriptor', D1, D2); +chk_PackagesDescriptor([H|T1], [H|T2]) -> + case is_PackagesItem(H) of + true -> + chk_PackagesDescriptor(T1, T2); + false -> + wrong_type('PackagesDescriptor_val', H) + end; +chk_PackagesDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PackagesItem(H1, H2) end, + 'PackagesDescriptor_val'), + chk_PackagesDescriptor(T1, T2); +chk_PackagesDescriptor(D1, D2) -> + wrong_type('PackagesDescriptor_val', D1, D2). + + +%% -- PackagesItem -- + +is_PackagesItem(#'PackagesItem'{packageName = N, + packageVersion = V}) -> + is_Name(N) andalso is_INTEGER(V, {range, 0, 99}); +is_PackagesItem(_) -> + false. + +chk_PackagesItem(I, I) -> + chk_type(fun is_PackagesItem/1, 'PackagesItem', I); +chk_PackagesItem(#'PackagesItem'{packageName = N1, + packageVersion = V1}, + #'PackagesItem'{packageName = N2, + packageVersion = V2}) -> + validate(fun() -> chk_Name(N1, N2) end, 'PackagesItem'), + validate(fun() -> chk_INTEGER(V1, V2, {range, 0, 99}) end, 'PackagesItem'), + ok; +chk_PackagesItem(I1, I2) -> + wrong_type('PackagesItem', I1, I2). + + +%% -- StatisticsDescriptor -- + +is_opt_StatisticsDescriptor(D) -> + is_OPTIONAL(fun is_StatisticsDescriptor/1, D). + +is_StatisticsDescriptor([]) -> + true; +is_StatisticsDescriptor([H|T]) -> + is_StatisticsParameter(H) andalso is_StatisticsDescriptor(T); +is_StatisticsDescriptor(_) -> + false. + +chk_opt_StatisticsDescriptor(D1, D2) -> + chk_OPTIONAL('StatisticsDescriptor', D1, D2, + fun is_StatisticsDescriptor/1, + fun chk_StatisticsDescriptor/2). + +chk_StatisticsDescriptor([], []) -> + ok; +chk_StatisticsDescriptor([] = D1, D2) -> + not_equal('StatisticsDescriptor', D1, D2); +chk_StatisticsDescriptor(D1, [] = D2) -> + not_equal('StatisticsDescriptor', D1, D2); +chk_StatisticsDescriptor([H|T1], [H|T2]) -> + case is_StatisticsParameter(H) of + true -> + chk_StatisticsDescriptor(T1, T2); + false -> + wrong_type('StatisticsDescriptor_val', H) + end; +chk_StatisticsDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_StatisticsParameter(H1, H2) end, + 'StatisticsDescriptor_val'), + chk_StatisticsDescriptor(T1, T2); +chk_StatisticsDescriptor(D1, D2) -> + wrong_type('StatisticsDescriptor_val', D1, D2). + + +%% -- StatisticsParameter -- + +is_StatisticsParameter(#'StatisticsParameter'{statName = N, + statValue = V}) -> + is_PkgdName(N) andalso is_opt_Value(V); +is_StatisticsParameter(_) -> + false. + +chk_StatisticsParameter(P, P) -> + chk_type(fun is_StatisticsParameter/1, 'StatisticsParameter', P); +chk_StatisticsParameter(#'StatisticsParameter'{statName = N1, + statValue = V1}, + #'StatisticsParameter'{statName = N2, + statValue = V2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'StatisticsParameter'), + validate(fun() -> chk_opt_Value(V1, V2) end, 'StatisticsParameter'), + ok; +chk_StatisticsParameter(P1, P2) -> + wrong_type('StatisticsParameter', P1, P2). + + +%% -- NonStandardData -- + +is_opt_NonStandardData(asn1_NOVALUE) -> + true; +is_opt_NonStandardData(NSD) -> + is_NonStandardData(NSD). + +%% is_NonStandardData(#'NonStandardData'{nonStandardIdentifier = Id, +%% data = D}) -> +%% is_NonStandardIdentifier(Id) andalso is_OCTET_STRING(D); +%% is_NonStandardData(_) -> +%% false. + +is_NonStandardData(_) -> + true. + +chk_opt_NonStandardData(asn1_NOVALUE, asn1_NOVALUE) -> + true; +chk_opt_NonStandardData(NSD1, NSD2) -> + chk_NonStandardData(NSD1, NSD2). + +chk_NonStandardData(NSD, NSD) -> + chk_type(fun is_NonStandardData/1, 'NonStandardData', NSD); +%% chk_NonStandardData(#'NonStandardData'{nonStandardIdentifier = Id1, +%% data = D1}, +%% #'NonStandardData'{nonStandardIdentifier = Id2, +%% data = D2}) -> +%% validate(fun() -> chk_NonStandardIdentifier(Id1, Id2) end, +%% 'NonStandardData'), +%% validate(fun() -> chk_OCTET_STRING(D1, D2) end, 'NonStandardData'), +%% ok; +%% chk_NonStandardData(NSD1, NSD2) -> +%% wrong_type('NonStandardData', NSD1, NSD2). +chk_NonStandardData(NSD1, NSD2) -> + not_equal('NonStandardData', NSD1, NSD2). + + +%% -- NonStandardIdentifier -- + +%% is_NonStandardIdentifier({Tag, Val}) -> +%% is_NonStandardIdentifier_tag(Tag) andalso +%% is_NonStandardIdentifier_val(Tag, Val); +%% is_NonStandardIdentifier(_) -> +%% false. + +%% is_NonStandardIdentifier_tag(Tag) -> +%% Tags = [object, h221NonStandard, experimental], +%% lists:member(Tag, Tags). + +%% is_NonStandardIdentifier_val(object, Val) -> +%% is_OBJECT_IDENTIFIER(Val); +%% is_NonStandardIdentifier_val(h221NonStandard, Val) -> +%% is_H221NonStandard(Val); +%% is_NonStandardIdentifier_val(experimental, Val) -> +%% is_IA5String(Val, {exact, 8}). + +%% chk_NonStandardIdentifier(Id, Id) -> +%% chk_type(fun is_NonStandardIdentifier/1, 'NonStandardIdentifier', Id); +%% chk_NonStandardIdentifier({Tag, Val1} = Id1, {Tag, Val2} = Id2) -> +%% case (is_NonStandardIdentifier_tag(Tag) andalso +%% is_NonStandardIdentifier_val(Tag, Val1) andalso +%% is_NonStandardIdentifier_val(Tag, Val1)) of +%% true -> +%% chk_NonStandardIdentifier_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('NonStandardIdentifier', Id1, Id2) +%% end; +%% chk_NonStandardIdentifier({Tag1, Val1} = Id1, {Tag2, Val2} = Id2) -> +%% case ((is_NonStandardIdentifier_tag(Tag1) andalso +%% is_NonStandardIdentifier_val(Tag1, Val1)) andalso +%% (is_NonStandardIdentifier_tag(Tag2) andalso +%% is_NonStandardIdentifier_val(Tag2, Val1))) of +%% true -> +%% not_equal('NonStandardIdentifier', Id1, Id2); +%% false -> +%% wrong_type('NonStandardIdentifier', Id1, Id2) +%% end; +%% chk_NonStandardIdentifier(Id1, Id2) -> +%% wrong_type('NonStandardIdentifier', Id1, Id2). + +%% chk_NonStandardIdentifier_val(object, Val1, Val2) -> +%% chk_OBJECT_IDENTIFIER(Val1, Val2); +%% chk_NonStandardIdentifier_val(h221NonStandard, Val1, Val2) -> +%% chk_H221NonStandard(Val1, Val2); +%% chk_NonStandardIdentifier_val(experimental, Val1, Val2) -> +%% chk_IA5String(Val1, Val2, {exact, 8}). + + +%% -- H221NonStandard -- + +%% is_H221NonStandard(#'H221NonStandard'{t35CountryCode1 = CC1, +%% t35CountryCode2 = CC2, +%% t35Extension = Ext, +%% manufacturerCode = MC}) -> +%% is_INTEGER(CC1, {range, 0, 255}) andalso +%% is_INTEGER(CC2, {range, 0, 255}) andalso +%% is_INTEGER(Ext, {range, 0, 255}) andalso +%% is_INTEGER(Ext, {range, 0, 65535}); +%% is_H221NonStandard(_) -> +%% false. + +%% chk_H221NonStandard(NS, NS) -> +%% chk_type(fun is_H221NonStandard/1, 'H221NonStandard', NS); +%% chk_H221NonStandard(#'H221NonStandard'{t35CountryCode1 = CC11, +%% t35CountryCode2 = CC21, +%% t35Extension = Ext1, +%% manufacturerCode = MC1}, +%% #'H221NonStandard'{t35CountryCode1 = CC12, +%% t35CountryCode2 = CC22, +%% t35Extension = Ext2, +%% manufacturerCode = MC2}) -> +%% validate(fun() -> chk_INTEGER(CC11, CC12, {range, 0, 255}) end, +%% 'H221NonStandard'), +%% validate(fun() -> chk_INTEGER(CC21, CC22, {range, 0, 255}) end, +%% 'H221NonStandard'), +%% validate(fun() -> chk_INTEGER(Ext1, Ext2, {range, 0, 255}) end, +%% 'H221NonStandard'), +%% validate(fun() -> chk_INTEGER(MC1, MC2, {range, 0, 65535}) end, +%% 'H221NonStandard'), +%% ok; +%% chk_H221NonStandard(NS1, NS2) -> +%% wrong_type('H221NonStandard', NS1, NS2). + + +%% -- TimeNotation -- + +is_opt_TimeNotation(asn1_NOVALUE) -> + true; +is_opt_TimeNotation(TN) -> + is_TimeNotation(TN). + +is_TimeNotation(#'TimeNotation'{date = D, time = T}) -> + is_IA5String(D, {exact, 8}) andalso is_IA5String(T, {exact, 8}); +is_TimeNotation(_) -> + false. + +chk_opt_TimeNotation(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_TimeNotation(TN1, TN2) -> + chk_TimeNotation(TN1, TN2). + +chk_TimeNotation(TN, TN) -> + chk_type(fun is_TimeNotation/1, 'TimeNotation', TN); +chk_TimeNotation(#'TimeNotation'{date = D1, time = T1}, + #'TimeNotation'{date = D2, time = T2}) -> + validate(fun() -> chk_IA5String(D1, D2, {exact, 8}) end, 'TimeNotation'), + validate(fun() -> chk_IA5String(T1, T2, {exact, 8}) end, 'TimeNotation'), + ok; +chk_TimeNotation(TN1, TN2) -> + wrong_type('TimeNotation', TN1, TN2). + + +%% -- Value -- + +is_opt_Value(V) -> + is_OPTIONAL(fun is_Value/1, V). + +is_Value([]) -> + true; +is_Value([H|T]) -> + is_OCTET_STRING(H) andalso is_Value(T); +is_Value(_) -> + false. + +chk_opt_Value(V1, V2) -> + chk_OPTIONAL('Value', V1, V2, fun is_Value/1, fun chk_Value/2). + +chk_Value(V, V) -> + case is_Value(V) of + true -> + ok; + false -> + wrong_type('Value', V, V) + end; +chk_Value(V1, V2) -> + case (is_Value(V1) andalso is_Value(V2)) of + true -> + not_equal('Value', V1, V2); + false -> + wrong_type('Value', V1, V2) + end. + + +%% ---------------------------------------------------------------------- +%% Basic type check functions +%% ---------------------------------------------------------------------- + + +is_opt_BOOLEAN(B) -> + is_OPTIONAL(fun is_BOOLEAN/1, B). + +is_BOOLEAN(B) -> + lists:member(B, [true, false]). + +chk_opt_BOOLEAN(B1, B2) -> + chk_OPTIONAL('BOOLEAN', B1, B2, fun is_BOOLEAN/1, fun chk_BOOLEAN/2). + +chk_BOOLEAN(B, B) -> + chk_type(fun is_BOOLEAN/1, 'BOOLEAN', B); +chk_BOOLEAN(B1, B2) -> + case (is_BOOLEAN(B1) andalso is_BOOLEAN(B2)) of + true -> + not_equal('BOOLEAN', B1, B2); + false -> + wrong_type('BOOLEAN', B1, B2) + end. + + +is_IA5String(S) when is_list(S) -> + true; +is_IA5String(_) -> + false. + +% chk_IA5String(S, S) -> +% chk_type(fun is_IA5String/1, 'IA5String', S); +% chk_IA5String(S1, S2) -> +% case (is_IA5String(S1) andalso is_IA5String(S2)) of +% true -> +% not_equal('IA5String', S1, S2); +% false -> +% wrong_type('IA5String', S1, S2) +% end. + +is_IA5String(S, _) when is_list(S) -> + true; +is_IA5String(_, _) -> + false. + +chk_IA5String(S, S, R) -> + chk_type(fun is_IA5String/2, 'IA5String', S, R); +chk_IA5String(S1, S2, R) -> + case (is_IA5String(S1, R) andalso is_IA5String(S2, R)) of + true -> + not_equal('IA5String', S1, S2); + false -> + wrong_type('IA5String', S1, S2) + end. + + +is_OCTET_STRING(L) -> is_OCTET_STRING(L, any). + +is_OCTET_STRING(L, any) when is_list(L) -> + true; +is_OCTET_STRING(L, {exact, Len}) when is_list(L) andalso (length(L) =:= Len) -> + true; +is_OCTET_STRING(L, {atleast, Len}) when is_list(L) andalso (Len =< length(L)) -> + true; +is_OCTET_STRING(L, {atmost, Len}) when is_list(L) andalso (length(L) =< Len) -> + true; +is_OCTET_STRING(L, {range, Min, Max}) + when is_list(L) andalso (Min =< length(L)) andalso (length(L) =< Max) -> + true; +is_OCTET_STRING(_, _) -> + false. + +%% chk_OCTET_STRING(L1, L2) -> +%% chk_OCTET_STRING(L1, L2, any). + +chk_OCTET_STRING(L, L, R) -> + chk_type(fun is_OCTET_STRING/2, 'OCTET STRING', L, R); +chk_OCTET_STRING(L1, L2, R) -> + case (is_OCTET_STRING(L1, R) andalso is_OCTET_STRING(L2, R)) of + true -> + not_equal('OCTET STRING', L1, L2); + false -> + wrong_type('OCTET STRING', L1, L2) + end. + + +%% is_OBJECT_IDENTIFIER(_) -> +%% true. + +%% chk_OBJECT_IDENTIFIER(X, X) -> +%% ok; +%% chk_OBJECT_IDENTIFIER(X1, X2) -> +%% not_equal('OBJECT IDENTIFIER', X1, X2). + + +is_opt_NULL(N) -> + is_OPTIONAL(fun is_NULL/1, N). + +is_NULL('NULL') -> + true; +is_NULL(_) -> + false. + +chk_opt_NULL(N1, N2) -> + chk_OPTIONAL('NULL', N1, N2, fun is_NULL/1, fun chk_NULL/2). + +chk_NULL(N, N) -> + chk_type(fun is_NULL/1, 'NULL', N); +chk_NULL(N1, N2) -> + case (is_NULL(N1) andalso is_NULL(N2)) of + true -> + not_equal('NULL', N1, N2); + false -> + wrong_type('NULL', N1, N2) + end. + + +is_opt_INTEGER(I, R) -> + is_OPTIONAL(fun(X) -> is_INTEGER(X, R) end, I). + +is_INTEGER(I, any) when is_integer(I) -> + true; +is_INTEGER(I, {exact, I}) when is_integer(I) -> + true; +is_INTEGER(I, {atleast, Min}) + when is_integer(I) andalso + is_integer(Min) andalso + (Min =< I) -> + true; +is_INTEGER(I, {atmost, Max}) + when is_integer(I) andalso + is_integer(Max) andalso + (I =< Max) -> + true; +is_INTEGER(I, {range, Min, Max}) + when is_integer(I) andalso + is_integer(Min) andalso + is_integer(Max) andalso + (Min =< I) andalso + (I =< Max) -> + true; +is_INTEGER(_, _) -> + false. + +chk_opt_INTEGER(I1, I2, R) -> + chk_OPTIONAL('INTEGER', I1, I2, + fun(X) -> is_INTEGER(X, R) end, + fun(Y1, Y2) -> chk_INTEGER(Y1, Y2, R) end). + +chk_INTEGER(I, I, R) -> + chk_type(fun is_INTEGER/2, 'INTEGER', I, R); +chk_INTEGER(I1, I2, R) -> + case (is_INTEGER(I1, R) andalso is_INTEGER(I2, R)) of + true -> + not_equal('INTEGER', I1, I2); + false -> + wrong_type('INTEGER', I1, I2) + end. + + +%% ---------------------------------------------------------------------- +%% Various utility functions +%% ---------------------------------------------------------------------- + + +to_lower([C|Cs]) when C >= $A, C =< $Z -> + [C+($a-$A)|to_lower(Cs)]; +to_lower([C|Cs]) -> + [C|to_lower(Cs)]; +to_lower([]) -> + []. + + +validate(F, Type) when is_function(F) -> + case (catch F()) of + {error, Reason} -> + error({Type, Reason}); + ok -> + ok + end. + + +chk_type(F, T, V) when is_function(F) andalso is_atom(T) -> + case F(V) of + true -> + ok; + false -> + wrong_type(T, V) + end. + +chk_type(F, T, V1, V2) when is_function(F) andalso is_atom(T) -> + case F(V1, V2) of + true -> + ok; + false -> + wrong_type(T, V1) + end. + + +is_OPTIONAL(_, asn1_NOVALUE) -> + true; +is_OPTIONAL(F, Val) when is_function(F) -> + F(Val). + +chk_OPTIONAL(_, asn1_NOVALUE, asn1_NOVALUE, _, _) -> + ok; +chk_OPTIONAL(Type, asn1_NOVALUE = V1, V2, IS, _CHK) when is_function(IS) -> + case IS(V2) of + true -> + not_equal(Type, V1, V2); + false -> + wrong_type(Type, V1, V2) + end; +chk_OPTIONAL(Type, V1, asn1_NOVALUE = V2, IS, _CHK) when is_function(IS) -> + case IS(V1) of + true -> + not_equal(Type, V1, V2); + false -> + wrong_type(Type, V1, V2) + end; +chk_OPTIONAL(_Type, V1, V2, _IS, CHK) when is_function(CHK) -> + CHK(V1, V2). + + +%% ---------------------------------------------------------------------- + +compare_strings([] = L1, L2) -> + {L1, L2}; +compare_strings(L1, [] = L2) -> + {L1, L2}; +compare_strings([H|T1], [H|T2]) -> + compare_strings(T1, T2); +compare_strings(L1, L2) -> + {L1, L2}. + +strip_tab_and_newline([]) -> + []; +strip_tab_and_newline([$\n|T]) -> + strip_tab_and_newline(T); +strip_tab_and_newline([$\t|T]) -> + strip_tab_and_newline(T); +strip_tab_and_newline([H|T]) -> + [H|strip_tab_and_newline(T)]. + + +%% ---------------------------------------------------------------------- + +atmost_once(Type, Val) -> + error({atmost_once, {Type, Val}}). + +wrong_type(Type, Val) -> + error({wrong_type, {Type, Val}}). + +wrong_type(Type, Val1, Val2) -> + error({wrong_type, {Type, Val1, Val2}}). + +not_equal(What, Val1, Val2) -> + error({not_equal, {What, Val1, Val2}}). + +error(Reason) -> + throw({error, Reason}). + + +%% ---------------------------------------------------------------------- + +d(F) -> + d(F, []). + +d(F, A) -> + d(get(dbg), F, A). + +d(true, F, A) -> + io:format("DBG:" ++ F ++ "~n", A); +d(_, _, _) -> + ok. + diff --git a/lib/megaco/test/megaco_test_msg_prev3b_lib.erl b/lib/megaco/test/megaco_test_msg_prev3b_lib.erl new file mode 100644 index 0000000000..be87dc9a41 --- /dev/null +++ b/lib/megaco/test/megaco_test_msg_prev3b_lib.erl @@ -0,0 +1,7489 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Utility functions for creating the megaco types +%%---------------------------------------------------------------------- + +-module(megaco_test_msg_prev3b_lib). + +%% ---- + +-include_lib("megaco/include/megaco_message_prev3b.hrl"). +-include_lib("megaco/include/megaco.hrl"). + +%% ---- + +-export([chk_MegacoMessage/2, + cre_MegacoMessage/1, cre_MegacoMessage/2, + cre_AuthenticationHeader/3, + cre_Message/3, + cre_ErrorDescriptor/1, cre_ErrorDescriptor/2, + cre_ErrorCode/1, + cre_ErrorText/1, + cre_ContextID/1, + cre_Transaction/1, + cre_TransactionId/1, + cre_TransactionRequest/2, + cre_TransactionPending/1, + cre_TransactionReply/2, cre_TransactionReply/3, + cre_TransactionAck/1, cre_TransactionAck/2, + cre_ActionRequest/2, cre_ActionRequest/3, cre_ActionRequest/4, + cre_ActionReply/2, cre_ActionReply/3, cre_ActionReply/4, + cre_ContextRequest/0, cre_ContextRequest/1, cre_ContextRequest/2, + cre_ContextRequest/3, cre_ContextRequest/4, cre_ContextRequest/5, + cre_ContextAttrAuditRequest/0, cre_ContextAttrAuditRequest/3, + cre_ContextAttrAuditRequest/4, cre_ContextAttrAuditRequest/5, + cre_CommandRequest/1, cre_CommandRequest/2, cre_CommandRequest/3, + cre_Command/2, + cre_CommandReply/2, + cre_TopologyRequest/3, cre_TopologyRequest/4, + cre_AmmRequest/2, + cre_AmmDescriptor/1, + cre_AmmsReply/1, cre_AmmsReply/2, + cre_SubtractRequest/1, cre_SubtractRequest/2, + cre_AuditRequest/2, + cre_AuditReply/1, + cre_AuditResult/2, + cre_AuditReturnParameter/1, + cre_AuditDescriptor/0, cre_AuditDescriptor/1, cre_AuditDescriptor/2, + cre_IndAuditParameter/1, + cre_IndAudMediaDescriptor/0, cre_IndAudMediaDescriptor/1, + cre_IndAudMediaDescriptor/2, + cre_IndAudStreamDescriptor/2, + cre_IndAudStreamParms/0, cre_IndAudStreamParms/1, + cre_IndAudStreamParms/3, cre_IndAudStreamParms/4, + cre_IndAudLocalControlDescriptor/0, + cre_IndAudLocalControlDescriptor/4, + cre_IndAudPropertyParm/1, + cre_IndAudLocalRemoteDescriptor/1, + cre_IndAudLocalRemoteDescriptor/2, + cre_IndAudPropertyGroup/1, + cre_IndAudTerminationStateDescriptor/1, + cre_IndAudTerminationStateDescriptor/3, + cre_IndAudEventsDescriptor/1, cre_IndAudEventsDescriptor/2, + cre_IndAudEventsDescriptor/3, + cre_IndAudEventBufferDescriptor/1, + cre_IndAudEventBufferDescriptor/2, + cre_IndAudSignalsDescriptor/1, + cre_IndAudSeqSigList/1, + cre_IndAudSeqSigList/2, + cre_IndAudSignal/1, cre_IndAudSignal/2, + cre_IndAudDigitMapDescriptor/0, cre_IndAudDigitMapDescriptor/1, + cre_IndAudStatisticsDescriptor/1, + cre_IndAudPackagesDescriptor/2, + cre_NotifyRequest/2, cre_NotifyRequest/3, + cre_NotifyReply/1, cre_NotifyReply/2, + cre_ObservedEventsDescriptor/2, + cre_ObservedEvent/2, cre_ObservedEvent/3, cre_ObservedEvent/4, + cre_EventName/1, + cre_EventParameter/2, cre_EventParameter/4, + cre_ServiceChangeRequest/2, + cre_ServiceChangeReply/2, + cre_ServiceChangeResult/1, + %% cre_WildcardField/1, + cre_TerminationAudit/1, + cre_TerminationID/2, + cre_TerminationIDList/1, + cre_MediaDescriptor/0, cre_MediaDescriptor/1, cre_MediaDescriptor/2, + cre_StreamDescriptor/2, + cre_StreamParms/0, cre_StreamParms/1, cre_StreamParms/2, + cre_StreamParms/3, cre_StreamParms/4, + cre_LocalControlDescriptor/1, cre_LocalControlDescriptor/2, + cre_LocalControlDescriptor/4, + cre_StreamMode/1, + cre_PropertyParm/2, cre_PropertyParm/4, + cre_Name/1, + cre_PkgdName/1, + cre_PkgdName/2, + cre_Relation/1, + cre_LocalRemoteDescriptor/1, + cre_PropertyGroup/1, + cre_TerminationStateDescriptor/1, + cre_TerminationStateDescriptor/2, + cre_TerminationStateDescriptor/3, + cre_EventBufferControl/1, + cre_ServiceState/1, + cre_MuxDescriptor/2, %% cre_MuxDescriptor/3, + cre_MuxType/1, + cre_StreamID/1, + cre_EventsDescriptor/0, cre_EventsDescriptor/2, + cre_RequestedEvent/1, + cre_RequestedEvent/2, cre_RequestedEvent/3, cre_RequestedEvent/4, + cre_RequestedActions/0, + cre_RequestedActions/1, cre_RequestedActions/4, + cre_EventDM/1, + cre_SecondEventsDescriptor/1, cre_SecondEventsDescriptor/2, + cre_SecondRequestedEvent/2, cre_SecondRequestedEvent/3, + cre_SecondRequestedEvent/4, + cre_SecondRequestedActions/0, cre_SecondRequestedActions/1, + cre_SecondRequestedActions/2, cre_SecondRequestedActions/3, + cre_EventBufferDescriptor/1, + cre_EventSpec/2, + cre_EventSpec/3, + cre_SignalsDescriptor/1, + cre_SignalRequest/1, + cre_SeqSigList/2, + cre_Signal/1, cre_Signal/2, cre_Signal/7, cre_Signal/9, + cre_SignalDirection/1, + cre_SignalType/1, + cre_SignalName/1, + cre_NotifyCompletion/1, + cre_SigParameter/2, cre_SigParameter/4, + cre_RequestID/1, + cre_ModemDescriptor/2, %% cre_ModemDescriptor/3, + cre_ModemType/1, + cre_DigitMapDescriptor/0, cre_DigitMapDescriptor/1, + cre_DigitMapDescriptor/2, + cre_DigitMapName/1, + cre_DigitMapValue/1, cre_DigitMapValue/4, cre_DigitMapValue/5, + cre_ServiceChangeParm/2, cre_ServiceChangeParm/4, + cre_ServiceChangeParm/9, cre_ServiceChangeParm/10, + cre_ServiceChangeAddress/2, + cre_ServiceChangeResParm/0, cre_ServiceChangeResParm/2, + cre_ServiceChangeResParm/5, + cre_ServiceChangeMethod/1, + cre_ServiceChangeProfile/1, cre_ServiceChangeProfile/2, + cre_PackagesDescriptor/1, + cre_PackagesItem/2, + cre_StatisticsDescriptor/1, + cre_StatisticsParameter/1, cre_StatisticsParameter/2, +%% cre_NonStandardData/2, +%% cre_NonStandardIdentifier/1, +%% cre_H221NonStandard/4, + cre_TimeNotation/2, + cre_Value/1, + cre_BOOLEAN/1 + ]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +cre_MegacoMessage(M) when is_record(M, 'Message') -> + #'MegacoMessage'{mess = M}. + +cre_MegacoMessage(AH, M) + when is_record(AH, 'AuthenticationHeader') andalso + is_record(M, 'Message') -> + #'MegacoMessage'{authHeader = AH, + mess = M}. + +cre_AuthenticationHeader(SPI, SN, AD) -> + #'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AD}. + +cre_Message(V, Mid, ED) when is_record(ED, 'ErrorDescriptor') -> + Body = {errorDescriptor, ED}, + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, Transactions) when is_list(Transactions) -> + Body = {transactions, Transactions}, + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, {transactions, T} = Body) when is_list(T) -> + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, {errorDescriptor, ED} = Body) + when is_record(ED, 'ErrorDescriptor') -> + #'Message'{version = V, + mId = Mid, + messageBody = Body}. + + +cre_ErrorDescriptor(EC) when is_integer(EC) -> + #'ErrorDescriptor'{errorCode = EC}. + +cre_ErrorDescriptor(EC, ET) when is_integer(EC) andalso is_list(ET) -> + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + +cre_ErrorCode(C) when is_integer(C) andalso (0 =< C) andalso (C =< 65535) -> + C; +cre_ErrorCode(C) -> + exit({invalid_ErrorCode, C}). + +cre_ErrorText(T) when is_list(T) -> + T. + +cre_ContextID(Val) when (0 =< Val) andalso (Val =< 4294967295) -> + Val; +cre_ContextID(Val) -> + exit({invalid_ContextID, Val}). + +cre_Transaction(TR) when is_record(TR, 'TransactionRequest') -> + {transactionRequest, TR}; +cre_Transaction(TP) when is_record(TP, 'TransactionPending') -> + {transactionPending, TP}; +cre_Transaction(TR) when is_record(TR, 'TransactionReply') -> + {transactionReply, TR}; +cre_Transaction(TRA) when is_list(TRA) -> + {transactionResponseAck, TRA}. + +cre_TransactionId(Val) when 0 =< Val, Val =< 4294967295 -> + Val; +cre_TransactionId(Val) -> + exit({invalid_TransactionId, Val}). + +cre_TransactionRequest(TransID, ARs) when is_integer(TransID) andalso is_list(ARs) -> + #'TransactionRequest'{transactionId = TransID, + actions = ARs}. + +cre_TransactionPending(TransID) when is_integer(TransID) -> + #'TransactionPending'{transactionId = TransID}. + +cre_TransactionReply(TransID, ED) + when is_integer(TransID) andalso is_record(ED, 'ErrorDescriptor') -> + Res = {transactionError, ED}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}; +cre_TransactionReply(TransID, ARs) + when is_integer(TransID) andalso is_list(ARs) -> + Res = {actionReplies, ARs}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}. + +cre_TransactionReply(TransID, IAR, ED) + when is_integer(TransID) and + ((IAR == 'NULL') or (IAR == asn1_NOVALUE)) and + is_record(ED, 'ErrorDescriptor') -> + Res = {transactionError, ED}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}; +cre_TransactionReply(TransID, IAR, ARs) + when is_integer(TransID) and + ((IAR == 'NULL') or (IAR == asn1_NOVALUE)) and + is_list(ARs) -> + Res = {actionReplies, ARs}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}. + +cre_TransactionAck(FirstAck) -> + #'TransactionAck'{firstAck = FirstAck}. + +cre_TransactionAck(FirstAck, FirstAck) -> + #'TransactionAck'{firstAck = FirstAck}; +cre_TransactionAck(FirstAck, LastAck) -> + #'TransactionAck'{firstAck = FirstAck, + lastAck = LastAck}. + +cre_ActionRequest(CtxID, CmdReqs) + when is_integer(CtxID) and is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + commandRequests = CmdReqs}. + +cre_ActionRequest(CtxID, CtxReq, CmdReqs) + when is_integer(CtxID) and + is_record(CtxReq, 'ContextRequest') and + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextRequest = CtxReq, + commandRequests = CmdReqs}; +cre_ActionRequest(CtxID, CAAR, CmdReqs) + when is_integer(CtxID) and + is_record(CAAR, 'ContextAttrAuditRequest') and + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextAttrAuditReq = CAAR, + commandRequests = CmdReqs}. + +cre_ActionRequest(CtxID, CtxReq, CAAR, CmdReqs) + when is_integer(CtxID) and + (is_record(CtxReq, 'ContextRequest') or + (CtxReq == asn1_NOVALUE)) and + (is_record(CAAR, 'ContextAttrAuditRequest') or + (CAAR == asn1_NOVALUE)) and + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextRequest = CtxReq, + contextAttrAuditReq = CAAR, + commandRequests = CmdReqs}. + +cre_ActionReply(CtxID, CmdReps) + when is_integer(CtxID) andalso + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + commandReply = CmdReps}. + +cre_ActionReply(CtxID, ED, CmdReps) + when is_integer(CtxID) andalso + is_record(ED, 'ErrorDescriptor') andalso + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + errorDescriptor = ED, + commandReply = CmdReps}; +cre_ActionReply(CtxID, CtxReq, CmdReps) + when is_integer(CtxID) andalso + is_record(CtxReq, 'ContextRequest') andalso + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + contextReply = CtxReq, + commandReply = CmdReps}. + +cre_ActionReply(CtxID, ED, CtxReq, CmdReps) + when is_integer(CtxID) andalso + (is_record(ED, 'ErrorDescriptor') orelse (ED =:= asn1_NOVALUE)) andalso + (is_record(CtxReq, 'ContextRequest') orelse (CtxReq =:= asn1_NOVALUE)) andalso + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + errorDescriptor = ED, + contextReply = CtxReq, + commandReply = CmdReps}. + +cre_ContextRequest() -> + strip_ContextRequest(#'ContextRequest'{}). + +cre_ContextRequest(Prio) when is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15) -> + strip_ContextRequest(#'ContextRequest'{priority = Prio}); +cre_ContextRequest(Em) when (Em =:= true) orelse (Em =:= false) orelse (Em =:= asn1_NOVALUE) -> + strip_ContextRequest(#'ContextRequest'{emergency = Em}); +cre_ContextRequest(Top) when is_list(Top) -> + strip_ContextRequest(#'ContextRequest'{topologyReq = Top}). + +cre_ContextRequest(Prio, Em) + when (is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em}, + strip_ContextRequest(CR); +cre_ContextRequest(Prio, Top) + when is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15) andalso is_list(Top) -> + CR = #'ContextRequest'{priority = Prio, + topologyReq = Top}, + strip_ContextRequest(CR). + +cre_ContextRequest(Prio, Em, Top) + when (is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) and + (is_list(Top) or (Top == asn1_NOVALUE)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top}, + strip_ContextRequest(CR). + +cre_ContextRequest(Prio, Em, Top, Ieps) + when (is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) and + (is_list(Top) or (Top == asn1_NOVALUE)) and + ((Ieps == true) or (Ieps == false)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + iepscallind = Ieps}, + strip_ContextRequest(CR); +cre_ContextRequest(Prio, Em, Top, Ctx) + when ((is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) or + (Prio == asn1_NOVALUE)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) and + (is_list(Top) or (Top == asn1_NOVALUE)) and + (is_list(Ctx)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + contextProp = Ctx}, + strip_ContextRequest(CR). + +cre_ContextRequest(Prio, Em, Top, Ieps, Ctx) + when ((is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) or + (Prio == asn1_NOVALUE)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) and + (is_list(Top) or (Top == asn1_NOVALUE)) and + ((Ieps == true) or (Ieps == false) or (Ieps == asn1_NOVALUE)) and + (is_list(Ctx) or (Ctx == asn1_NOVALUE)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + iepscallind = Ieps, + contextProp = Ctx}, + strip_ContextRequest(CR). + +strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE, + emergency = asn1_NOVALUE, + topologyReq = asn1_NOVALUE, + iepscallind = asn1_NOVALUE, + contextProp = asn1_NOVALUE}) -> + asn1_NOVALUE; +strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE, + emergency = asn1_NOVALUE, + topologyReq = Top, + iepscallind = Ieps, + contextProp = Prop} = CR) -> + case (((Top == []) or (Top == asn1_NOVALUE)) and + ((Ieps == false) or (Ieps == asn1_NOVALUE)) and + ((Prop == []) or (Prop == asn1_NOVALUE))) of + true -> + asn1_NOVALUE; + false -> + CR + end; +strip_ContextRequest(CR) -> + CR. + +cre_ContextAttrAuditRequest() -> + strip_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{}). + +cre_ContextAttrAuditRequest(Top, Em, Prio) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio}, + strip_ContextAttrAuditRequest(CAAR). + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) and + ((Ieps == 'NULL') or (Ieps == asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ieps}, + strip_ContextAttrAuditRequest(CAAR). + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) and + ((Ieps == 'NULL') or (Ieps == asn1_NOVALUE)) and + (is_list(Ctx) or (Ctx == asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ieps, + contextPropAud = Ctx}, + strip_ContextAttrAuditRequest(CAAR). + +strip_ContextAttrAuditRequest( + #'ContextAttrAuditRequest'{topology = asn1_NOVALUE, + emergency = asn1_NOVALUE, + priority = asn1_NOVALUE, + iepscallind = asn1_NOVALUE, + contextPropAud = asn1_NOVALUE}) -> + asn1_NOVALUE; +strip_ContextAttrAuditRequest( + #'ContextAttrAuditRequest'{topology = asn1_NOVALUE, + emergency = asn1_NOVALUE, + priority = asn1_NOVALUE, + iepscallind = asn1_NOVALUE, + contextPropAud = []}) -> + asn1_NOVALUE; +strip_ContextAttrAuditRequest(CAAR) -> + CAAR. + +cre_CommandRequest(Cmd) -> + #'CommandRequest'{command = Cmd}. + +cre_CommandRequest(Cmd, Opt) + when ((Opt == 'NULL') or (Opt == asn1_NOVALUE)) -> + #'CommandRequest'{command = Cmd, + optional = Opt}. + +cre_CommandRequest(Cmd, Opt, WR) + when ((Opt == 'NULL') or (Opt == asn1_NOVALUE)) and + ((WR == 'NULL') or (WR == asn1_NOVALUE)) -> + #'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = WR}. + +cre_Command(addReq = Tag, Req) + when is_record(Req, 'AmmRequest') -> + {Tag, Req}; +cre_Command(moveReq = Tag, Req) + when is_record(Req, 'AmmRequest') -> + {Tag, Req}; +cre_Command(modReq = Tag, Req) + when is_record(Req, 'AmmRequest') -> + {Tag, Req}; +cre_Command(subtractReq = Tag, Req) + when is_record(Req, 'SubtractRequest') -> + {Tag, Req}; +cre_Command(auditCapRequest = Tag, Req) + when is_record(Req, 'AuditRequest') -> + {Tag, Req}; +cre_Command(auditValueRequest = Tag, Req) + when is_record(Req, 'AuditRequest') -> + {Tag, Req}; +cre_Command(notifyReq = Tag, Req) + when is_record(Req, 'NotifyRequest') -> + {Tag, Req}; +cre_Command(serviceChangeReq = Tag, Req) + when is_record(Req, 'ServiceChangeRequest') -> + {Tag, Req}. + +cre_CommandReply(addReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(moveReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(modReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(subtractReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(auditCapReply = Tag, Rep) + when is_tuple(Rep) -> + {Tag, Rep}; +cre_CommandReply(auditValueReply = Tag, Rep) + when is_tuple(Rep) -> + {Tag, Rep}; +cre_CommandReply(notifyReply = Tag, Rep) + when is_record(Rep, 'NotifyReply') -> + {Tag, Rep}; +cre_CommandReply(serviceChangeReply = Tag, Rep) + when is_record(Rep, 'ServiceChangeReply') -> + {Tag, Rep}. + +cre_TopologyRequest(From, To, Dir) + when (is_record(From, 'TerminationID') or + is_record(From, megaco_term_id)) and + (is_record(To, 'TerminationID') or + is_record(To, megaco_term_id)) and + ((Dir == bothway) or (Dir == isolate) or (Dir == oneway)) -> + #'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = Dir}. + +cre_TopologyRequest(From, To, Dir, SID) + when (is_record(From, 'TerminationID') or + is_record(From, megaco_term_id)) and + (is_record(To, 'TerminationID') or + is_record(To, megaco_term_id)) and + ((Dir == bothway) or (Dir == isolate) or (Dir == oneway)) and + (is_integer(SID) or (SID == asn1_NOVALUE)) -> + #'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = Dir, + streamID = SID}. + +cre_AmmRequest(TermIDs, Descs) -> + d("cre_AmmRequest -> entry with" + "~n TermIDs: ~p" + "~n Descs: ~p", [TermIDs, Descs]), + case is_TerminationIDList(TermIDs) andalso + is_AmmRequest_descriptors(Descs) of + true -> + #'AmmRequest'{terminationID = TermIDs, + descriptors = Descs}; + false -> + error({invalid_AmmRequest, {TermIDs, Descs}}) + end. + +cre_AmmDescriptor(D) when is_record(D, 'MediaDescriptor') -> + {mediaDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'ModemDescriptor') -> + {modemDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'MuxDescriptor') -> + {muxDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'EventsDescriptor') -> + {eventsDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'DigitMapDescriptor') -> + {digitMapDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'AuditDescriptor') -> + {auditDescriptor, D}; +cre_AmmDescriptor(D) when is_list(D) -> + case is_EventBufferDescriptor(D) of + true -> + {eventBufferDescriptor, D}; + false -> + case is_SignalsDescriptor(D) of + true -> + {signalsDescriptor, D}; + false -> + case is_StatisticsDescriptor(D) of + true -> + {statisticsDescriptor, D}; + false -> + error({invalid_AmmDescriptor, D}) + end + end + end. + +cre_AmmsReply(TermIDs) when is_list(TermIDs) -> + #'AmmsReply'{terminationID = TermIDs}. + +cre_AmmsReply(TermIDs, TAs) when is_list(TermIDs) andalso is_list(TAs) -> + #'AmmsReply'{terminationID = TermIDs, + terminationAudit = TAs}. + +cre_SubtractRequest(TermIDs) when is_list(TermIDs) -> + #'SubtractRequest'{terminationID = TermIDs}. + +cre_SubtractRequest(TermIDs, Audit) + when is_list(TermIDs) andalso is_record(Audit, 'AuditDescriptor') -> + #'SubtractRequest'{terminationID = TermIDs, + auditDescriptor = Audit}. + +cre_AuditRequest(TermID, Audit) + when is_record(TermID, megaco_term_id) andalso is_record(Audit, 'AuditDescriptor') -> + #'AuditRequest'{terminationID = TermID, + auditDescriptor = Audit}. + +cre_AuditReply(TermIDs) when is_list(TermIDs) -> + {contextAuditResult, TermIDs}; +cre_AuditReply(ED) when is_record(ED, 'ErrorDescriptor') -> + {error, ED}; +cre_AuditReply(Audit) when is_record(Audit, 'AuditResult') -> + {auditResult, Audit}. + +cre_AuditResult(TermID, TAs) + when is_record(TermID, megaco_term_id) andalso is_list(TAs) -> + #'AuditResult'{terminationID = TermID, + terminationAuditResult = TAs}. + +cre_TerminationAudit(D) -> + true = is_TerminationAudit(D), + D. + +cre_AuditReturnParameter(D) when is_record(D, 'ErrorDescriptor') -> + {errorDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'MediaDescriptor') -> + {mediaDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'ModemDescriptor') -> + {modemDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'MuxDescriptor') -> + {muxDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'EventsDescriptor') -> + {eventsDescriptor, D}; +cre_AuditReturnParameter([H|_] = D) when is_record(H, 'EventSpec') -> + {eventBufferDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'DigitMapDescriptor') -> + {digitMapDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'ObservedEventsDescriptor') -> + {observedEventsDescriptor, D}; +cre_AuditReturnParameter([H|_] = D) when is_record(H, 'StatisticsParameter') -> + {statisticsDescriptor, D}; +cre_AuditReturnParameter([H|_] = D) when is_record(H, 'PackagesItem') -> + {packagesDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'AuditDescriptor') -> + {emptyDescriptors, D}; +cre_AuditReturnParameter([H|_] = D) when is_tuple(H) -> + {signalsDescriptor, D}. + +cre_AuditDescriptor() -> + #'AuditDescriptor'{}. + +cre_AuditDescriptor([H|_] = AT) when is_atom(H) -> + #'AuditDescriptor'{auditToken = AT}; +cre_AuditDescriptor(APT) -> + #'AuditDescriptor'{auditPropertyToken = APT}. + +cre_AuditDescriptor(AT, APT) -> + #'AuditDescriptor'{auditToken = AT, + auditPropertyToken = APT}. + +cre_IndAuditParameter(D) when is_record(D, 'IndAudMediaDescriptor') -> + {indAudMediaDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudEventsDescriptor') -> + {indAudEventsDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudEventBufferDescriptor') -> + {indAudEventBufferDescriptor, D}; +cre_IndAuditParameter({signal, _} = D) -> + {indAudSignalsDescriptor, D}; +cre_IndAuditParameter({seqSigList, _} = D) -> + {indAudSignalsDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudDigitMapDescriptor') -> + {indAudDigitMapDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudStatisticsDescriptor') -> + {indAudStatisticsDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudPackagesDescriptor') -> + {indAudPackagesDescriptor, D}. + +cre_IndAudMediaDescriptor() -> + #'IndAudMediaDescriptor'{}. + +cre_IndAudMediaDescriptor(TSD) + when is_record(TSD, 'IndAudTerminationStateDescriptor') -> + #'IndAudMediaDescriptor'{termStateDescr = TSD}; +cre_IndAudMediaDescriptor(Parms) when is_record(Parms, 'IndAudStreamParms') -> + Streams = {oneStream, Parms}, + #'IndAudMediaDescriptor'{streams = Streams}; +cre_IndAudMediaDescriptor(Descs) when is_list(Descs) -> + Streams = {multiStream, Descs}, + #'IndAudMediaDescriptor'{streams = Streams}. + +cre_IndAudMediaDescriptor(TSD, Parms) + when is_record(TSD, 'IndAudTerminationStateDescriptor') andalso + is_record(Parms, 'IndAudStreamParms') -> + Streams = {oneStream, Parms}, + #'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = Streams}; +cre_IndAudMediaDescriptor(TSD, Descs) + when is_record(TSD, 'IndAudTerminationStateDescriptor') andalso is_list(Descs) -> + Streams = {multiStream, Descs}, + #'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = Streams}. + +cre_IndAudStreamDescriptor(SID, Parms) + when is_integer(SID) andalso is_record(Parms, 'IndAudStreamParms') -> + #'IndAudStreamDescriptor'{streamID = SID, + streamParms = Parms}. + +cre_IndAudStreamParms() -> + #'IndAudStreamParms'{}. + +cre_IndAudStreamParms(LCD) when is_record(LCD, 'IndAudLocalControlDescriptor') -> + #'IndAudStreamParms'{localControlDescriptor = LCD}; +cre_IndAudStreamParms(SD) when is_record(SD, 'IndAudStatisticsDescriptor') -> + #'IndAudStreamParms'{statisticsDescriptor = SD}. + +cre_IndAudStreamParms(LC, L, R) + when is_record(LC, 'IndAudLocalControlDescriptor') andalso + is_record(L, 'IndAudLocalRemoteDescriptor') andalso + is_record(R, 'IndAudLocalRemoteDescriptor') -> + #'IndAudStreamParms'{localControlDescriptor = LC, + localDescriptor = L, + remoteDescriptor = R}. + +cre_IndAudStreamParms(LC, L, R, S) + when is_record(LC, 'IndAudLocalControlDescriptor') andalso + is_record(L, 'IndAudLocalRemoteDescriptor') andalso + is_record(R, 'IndAudLocalRemoteDescriptor') andalso + is_record(S, 'IndAudStatisticsDescriptor') -> + #'IndAudStreamParms'{localControlDescriptor = LC, + localDescriptor = L, + remoteDescriptor = R, + statisticsDescriptor = S}. + +cre_IndAudLocalControlDescriptor() -> + #'IndAudLocalControlDescriptor'{}. + +cre_IndAudLocalControlDescriptor(SM, RV, RG, PP) + when ((SM == 'NULL') or (SM == asn1_NOVALUE)) and + ((RV == 'NULL') or (RV == asn1_NOVALUE)) and + ((RG == 'NULL') or (RG == asn1_NOVALUE)) and + (is_list(PP) or (PP == asn1_NOVALUE)) -> + #'IndAudLocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP}. + +cre_IndAudPropertyParm(PkgdName) when is_list(PkgdName) -> + #'IndAudPropertyParm'{name = PkgdName}. + +cre_IndAudLocalRemoteDescriptor(Grps) + when is_list(Grps) -> + #'IndAudLocalRemoteDescriptor'{propGrps = Grps}. + +cre_IndAudLocalRemoteDescriptor(GrpID, Grps) + when is_integer(GrpID) andalso (0 =< GrpID) andalso (GrpID =< 65535) andalso is_list(Grps) -> + #'IndAudLocalRemoteDescriptor'{propGroupID = GrpID, + propGrps = Grps}. + +cre_IndAudPropertyGroup([]) -> + []; +cre_IndAudPropertyGroup([H|_] = PG) + when is_record(H, 'IndAudPropertyParm') -> + PG. + +cre_IndAudTerminationStateDescriptor([] = PP) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP}; +cre_IndAudTerminationStateDescriptor([H|_] = PP) + when is_record(H, 'IndAudPropertyParm') -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP}. + +cre_IndAudTerminationStateDescriptor([] = PP, EBC, SS) + when ((EBC == 'NULL') or (EBC == asn1_NOVALUE)) and + ((SS == 'NULL') or (SS == asn1_NOVALUE)) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS}; +cre_IndAudTerminationStateDescriptor([H|_] = PP, EBC, SS) + when is_record(H, 'IndAudPropertyParm') and + ((EBC == 'NULL') or (EBC == asn1_NOVALUE)) and + ((SS == 'NULL') or (SS == asn1_NOVALUE)) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS}. + +cre_IndAudEventsDescriptor(PkgdName) + when is_list(PkgdName) -> + #'IndAudEventsDescriptor'{pkgdName = PkgdName}. + +cre_IndAudEventsDescriptor(RID, PkgdName) + when is_integer(RID) andalso is_list(PkgdName) -> + #'IndAudEventsDescriptor'{requestID = RID, pkgdName = PkgdName}; +cre_IndAudEventsDescriptor(PkgdName, SID) + when is_list(PkgdName) andalso is_integer(SID) -> + #'IndAudEventsDescriptor'{pkgdName = PkgdName, streamID = SID}. + +cre_IndAudEventsDescriptor(RID, PkgdName, SID) + when is_integer(RID) andalso is_list(PkgdName) andalso is_integer(SID) -> + #'IndAudEventsDescriptor'{requestID = RID, + pkgdName = PkgdName, + streamID = SID}. + +cre_IndAudEventBufferDescriptor(EventName) when is_list(EventName) -> + #'IndAudEventBufferDescriptor'{eventName = EventName}. + +cre_IndAudEventBufferDescriptor(EventName, SID) + when is_list(EventName) andalso is_integer(SID) -> + #'IndAudEventBufferDescriptor'{eventName = EventName, streamID = SID}. + +cre_IndAudSignalsDescriptor(S) when is_record(S, 'IndAudSignal') -> + {signal, S}; +cre_IndAudSignalsDescriptor(S) when is_record(S, 'IndAudSeqSigList') -> + {seqSigList, S}. + +cre_IndAudSeqSigList(ID) when is_integer(ID) andalso (0=< ID) andalso (ID =< 65535) -> + #'IndAudSeqSigList'{id = ID}. + +cre_IndAudSeqSigList(ID, S) + when is_integer(ID) andalso + (0=< ID) andalso + (ID =< 65535) andalso + is_record(S, 'IndAudSignal') -> + #'IndAudSeqSigList'{id = ID, signalList = S}. + +cre_IndAudSignal(SigName) + when is_list(SigName) -> + #'IndAudSignal'{signalName = SigName}. + +cre_IndAudSignal(SigName, SID) + when is_list(SigName) andalso is_integer(SID) -> + #'IndAudSignal'{signalName = SigName, streamID = SID}. + +cre_IndAudDigitMapDescriptor() -> + #'IndAudDigitMapDescriptor'{}. + +cre_IndAudDigitMapDescriptor(DMN) when is_list(DMN) -> + #'IndAudDigitMapDescriptor'{digitMapName = DMN}. + +cre_IndAudStatisticsDescriptor(StatName) when is_list(StatName) -> + #'IndAudStatisticsDescriptor'{statName = StatName}. + +cre_IndAudPackagesDescriptor(N, V) + when is_list(N) andalso is_integer(V) andalso (0 =< V) andalso (V =< 99) -> + #'IndAudPackagesDescriptor'{packageName = N, + packageVersion = V}. + +cre_NotifyRequest(TermIDs, D) + when is_list(TermIDs) andalso is_record(D, 'ObservedEventsDescriptor') -> + #'NotifyRequest'{terminationID = TermIDs, + observedEventsDescriptor = D}. + +cre_NotifyRequest(TermIDs, D, ED) + when is_list(TermIDs) andalso + is_record(D, 'ObservedEventsDescriptor') andalso + is_record(ED, 'ErrorDescriptor') -> + #'NotifyRequest'{terminationID = TermIDs, + observedEventsDescriptor = D, + errorDescriptor = ED}. + +cre_NotifyReply(TermIDs) when is_list(TermIDs) -> + #'NotifyReply'{terminationID = TermIDs}. + +cre_NotifyReply(TermIDs, ED) + when is_list(TermIDs) andalso + is_record(ED, 'ErrorDescriptor') -> + #'NotifyReply'{terminationID = TermIDs, + errorDescriptor = ED}. + +cre_ObservedEventsDescriptor(RID, [H|_] = L) + when is_integer(RID) andalso is_record(H, 'ObservedEvent') -> + #'ObservedEventsDescriptor'{requestId = RID, + observedEventLst = L}. + +cre_ObservedEvent(EN, EPL) when is_list(EN) andalso is_list(EPL) -> + #'ObservedEvent'{eventName = EN, + eventParList = EPL}; +cre_ObservedEvent(EN, TN) when is_list(EN) andalso is_record(TN, 'TimeNotation') -> + #'ObservedEvent'{eventName = EN, + timeNotation = TN}. + +cre_ObservedEvent(EN, SID, EPL) + when is_list(EN) andalso is_integer(SID) andalso is_list(EPL) -> + #'ObservedEvent'{eventName = EN, + streamID = SID, + eventParList = EPL}; +cre_ObservedEvent(EN, EPL, TN) + when is_list(EN) andalso + is_list(EPL) andalso + is_record(TN, 'TimeNotation') -> + #'ObservedEvent'{eventName = EN, + eventParList = EPL, + timeNotation = TN}. + +cre_ObservedEvent(EN, SID, EPL, TN) + when is_list(EN) andalso + is_integer(SID) andalso + is_list(EPL) andalso + is_record(TN, 'TimeNotation') -> + #'ObservedEvent'{eventName = EN, + streamID = SID, + eventParList = EPL, + timeNotation = TN}. + +cre_EventName(N) when is_list(N) -> + N. + +cre_EventParameter(N, V) when is_list(N) andalso is_list(V) -> + #'EventParameter'{eventParameterName = N, + value = V}. + +cre_EventParameter(N, V, relation = Tag, R) + when is_list(N) andalso is_list(V) andalso is_atom(R) -> + EI = {Tag, R}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}; +cre_EventParameter(N, V, range = Tag, B) + when is_list(N) andalso is_list(V) andalso is_atom(B) -> + EI = {Tag, B}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}; +cre_EventParameter(N, V, sublist = Tag, B) + when is_list(N) andalso is_list(V) andalso is_atom(B) -> + EI = {Tag, B}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}. + +cre_ServiceChangeRequest(TermIDs, SCP) + when is_list(TermIDs) andalso + is_record(SCP, 'ServiceChangeParm') -> + #'ServiceChangeRequest'{terminationID = TermIDs, + serviceChangeParms = SCP}. + +cre_ServiceChangeReply(TermIDs, {Tag, R} = SCR) + when is_list(TermIDs) andalso is_atom(Tag) andalso is_tuple(R) -> + #'ServiceChangeReply'{terminationID = TermIDs, + serviceChangeResult = SCR}. + +cre_ServiceChangeResult(ED) when is_record(ED, 'ErrorDescriptor') -> + {errorDescriptor, ED}; +cre_ServiceChangeResult(SCRP) when is_record(SCRP, 'ServiceChangeResParm') -> + {serviceChangeResParms, SCRP}. + +%% cre_WildcardField(L) when list(L), length(L) == 1 -> L. + +cre_TerminationID(W, ID) + when is_list(W) andalso is_list(ID) andalso (1 =< length(ID)) andalso (length(ID) =< 8) -> + #'TerminationID'{wildcard = W, + id = ID}. + +cre_TerminationIDList(L) when is_list(L) -> + L. + +cre_MediaDescriptor() -> + #'MediaDescriptor'{}. + +cre_MediaDescriptor(TSD) when is_record(TSD, 'TerminationStateDescriptor') -> + #'MediaDescriptor'{termStateDescr = TSD}; +cre_MediaDescriptor(SP) when is_record(SP, 'StreamParms') -> + Streams = {oneStream, SP}, + #'MediaDescriptor'{streams = Streams}; +cre_MediaDescriptor([H|_] = SDs) when is_record(H, 'StreamDescriptor') -> + Streams = {multiStream, SDs}, + #'MediaDescriptor'{streams = Streams}. + +cre_MediaDescriptor(TSD, SP) + when is_record(TSD, 'TerminationStateDescriptor') andalso + is_record(SP, 'StreamParms') -> + Streams = {oneStream, SP}, + #'MediaDescriptor'{termStateDescr = TSD, + streams = Streams}; +cre_MediaDescriptor(TSD, [H|_] = SDs) + when is_record(TSD, 'TerminationStateDescriptor') andalso + is_record(H, 'StreamDescriptor') -> + Streams = {multiStream, SDs}, + #'MediaDescriptor'{termStateDescr = TSD, + streams = Streams}. + +cre_StreamDescriptor(SID, SP) when is_integer(SID) andalso is_record(SP, 'StreamParms') -> + #'StreamDescriptor'{streamID = SID, + streamParms = SP}. + +cre_StreamParms() -> + #'StreamParms'{}. + +cre_StreamParms(LCD) when is_record(LCD, 'LocalControlDescriptor') -> + #'StreamParms'{localControlDescriptor = LCD}; +cre_StreamParms(LD) when is_record(LD, 'LocalRemoteDescriptor') -> + #'StreamParms'{localDescriptor = LD}; +cre_StreamParms(SD) when is_list(SD) -> + #'StreamParms'{statisticsDescriptor = SD}. + +cre_StreamParms(LCD, LD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD}. + +cre_StreamParms(LCD, LD, RD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) and + (is_record(RD, 'LocalRemoteDescriptor') or (RD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD}; +cre_StreamParms(LCD, LD, SD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + statisticsDescriptor = SD}. + +cre_StreamParms(LCD, LD, RD, SD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) and + (is_record(RD, 'LocalRemoteDescriptor') or (RD == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}. + +cre_LocalControlDescriptor(SM) when is_atom(SM) -> + #'LocalControlDescriptor'{streamMode = SM, propertyParms = []}; +cre_LocalControlDescriptor([H|_] = PP) when is_record(H, 'PropertyParm') -> + #'LocalControlDescriptor'{propertyParms = PP}. + +cre_LocalControlDescriptor(SM, [H|_] = PP) + when is_atom(SM) andalso is_record(H, 'PropertyParm') -> + #'LocalControlDescriptor'{streamMode = SM, + propertyParms = PP}. + +cre_LocalControlDescriptor(SM, RV, RG, [H|_] = PP) + when is_atom(SM) and + ((RV == true) or (RV == false) or (RV == asn1_NOVALUE)) and + ((RG == true) or (RG == false) or (RG == asn1_NOVALUE)) and + is_record(H, 'PropertyParm') -> + #'LocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP}. + +cre_StreamMode(sendOnly = M) -> + M; +cre_StreamMode(recvOnly = M) -> + M; +cre_StreamMode(sendRecv = M) -> + M; +cre_StreamMode(inactive = M) -> + M; +cre_StreamMode(loopBack = M) -> + M. + +cre_PropertyParm(N, [H|_] = V) when is_list(N) andalso is_list(H) -> + #'PropertyParm'{name = N, value = V}. + +cre_PropertyParm(N, [H|_] = V, relation = Tag, R) + when is_list(N) andalso is_list(H) andalso is_atom(R) -> + EI = {Tag, R}, + #'PropertyParm'{name = N, value = V, extraInfo = EI}; +cre_PropertyParm(N, [H|_] = V, range = Tag, B) + when is_list(N) andalso is_list(H) andalso is_atom(B) -> + EI = {Tag, B}, + #'PropertyParm'{name = N, value = V, extraInfo = EI}; +cre_PropertyParm(N, [H|_] = V, sublist = Tag, B) + when is_list(N) andalso is_list(H) andalso is_atom(B) -> + EI = {Tag, B}, + #'PropertyParm'{name = N, value = V, extraInfo = EI}. + + +cre_Name(N) when is_list(N) and (length(N) == 2) -> + N. + +cre_PkgdName(N) when is_list(N) -> + case string:tokens(N, [$\\]) of + [_PkgName, _ItemID] -> + N; + _ -> + error({invalid_PkgdName, N}) + end. +cre_PkgdName(root, root) -> + "*/*"; +cre_PkgdName(PackageName, root) + when is_list(PackageName) and (length(PackageName) =< 64) -> + PackageName ++ "/*"; +cre_PkgdName(PackageName, ItemID) + when ((is_list(PackageName) and (length(PackageName) =< 64)) and + (is_list(ItemID) and (length(ItemID) =< 64))) -> + PackageName ++ "/" ++ ItemID; +cre_PkgdName(PackageName, ItemID) -> + error({invalid_PkgdName, {PackageName, ItemID}}). + +cre_Relation(greaterThan = R) -> + R; +cre_Relation(smallerThan = R) -> + R; +cre_Relation(unequalTo = R) -> + R. + +cre_LocalRemoteDescriptor([H|_] = PGs) when is_list(H) -> + #'LocalRemoteDescriptor'{propGrps = PGs}. + +cre_PropertyGroup([H|_] = PG) when is_record(H, 'PropertyParm') -> + PG. + +cre_TerminationStateDescriptor([H|_] = PPs) when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs}. + +cre_TerminationStateDescriptor([H|_] = PPs, off = EBC) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + eventBufferControl = EBC}; +cre_TerminationStateDescriptor([H|_] = PPs, lockStep = EBC) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + eventBufferControl = EBC}; +cre_TerminationStateDescriptor([H|_] = PPs, test = SS) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + serviceState = SS}; +cre_TerminationStateDescriptor([H|_] = PPs, outOfSvc = SS) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + serviceState = SS}; +cre_TerminationStateDescriptor([H|_] = PPs, inSvc = SS) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + serviceState = SS}. + +cre_TerminationStateDescriptor([H|_] = PPs, EMC, SS) + when is_record(H, 'PropertyParm') andalso + ((EMC =:= off) orelse (EMC =:= lockStep)) andalso + ((SS =:= test) orelse (SS =:= outOfSvc) orelse (SS =:= inSvc)) -> + #'TerminationStateDescriptor'{propertyParms = PPs, + eventBufferControl = EMC, + serviceState = SS}. + +cre_EventBufferControl(off = EBC) -> + EBC; +cre_EventBufferControl(lockStep = EBC) -> + EBC. + +cre_ServiceState(test = SS) -> + SS; +cre_ServiceState(outOfSvc = SS) -> + SS; +cre_ServiceState(inSvc = SS) -> + SS. + +cre_MuxDescriptor(MT, [H|_] = TL) + when is_atom(MT) andalso is_record(H, 'TerminationID') -> + #'MuxDescriptor'{muxType = MT, termList = TL}. + +%% cre_MuxDescriptor(MT, [H|_] = TL, NSD) +%% when atom(MT), record(H, 'TerminationID'), record(NSD, 'NonStandardData') -> +%% #'MuxDescriptor'{muxType = MT, termList = TL, nonStandardData = NSD}. + +cre_MuxType(h221 = MT) -> + MT; +cre_MuxType(h223 = MT) -> + MT; +cre_MuxType(h226 = MT) -> + MT; +cre_MuxType(v76 = MT) -> + MT; +cre_MuxType(nx64k = MT) -> + MT. + +cre_StreamID(Val) when 0 =< Val, Val =< 65535 -> + Val; +cre_StreamID(Val) -> + exit({invalid_ContextID, Val}). + +%% RequestID must be present if eventList is non empty +cre_EventsDescriptor() -> + #'EventsDescriptor'{eventList = []}. + +cre_EventsDescriptor(RID, [H|_] = EL) + when is_integer(RID) andalso is_record(H, 'RequestedEvent') -> + #'EventsDescriptor'{requestID = RID, eventList = EL}. + +cre_RequestedEvent(N) -> + #'RequestedEvent'{pkgdName = N}. + +cre_RequestedEvent(N, [H|_] = EPL) + when is_list(N) andalso + is_record(H, 'EventParameter') -> + #'RequestedEvent'{pkgdName = N, + evParList = EPL}; +cre_RequestedEvent(N, EA) + when is_list(N) andalso + is_record(EA, 'RequestedActions')-> + #'RequestedEvent'{pkgdName = N, + eventAction = EA}. + + +cre_RequestedEvent(N, SID, [H|_] = EPL) + when is_list(N) andalso + is_integer(SID) andalso + is_record(H, 'EventParameter') -> + #'RequestedEvent'{pkgdName = N, + streamID = SID, + evParList = EPL}; +cre_RequestedEvent(N, EA, [H|_] = EPL) + when is_list(N) andalso + is_record(EA, 'RequestedActions') andalso + is_record(H, 'EventParameter') -> + #'RequestedEvent'{pkgdName = N, + eventAction = EA, + evParList = EPL}. + +cre_RequestedEvent(N, SID, EA, [H|_] = EPL) + when is_list(N) andalso + is_integer(SID) andalso + is_record(EA, 'RequestedActions') andalso + is_record(H, 'EventParameter') -> + #'RequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}. + +cre_RequestedActions() -> + #'RequestedActions'{}. + +cre_RequestedActions(KA) + when (KA == true) or (KA == true) or (KA == asn1_NOVALUE) -> + #'RequestedActions'{keepActive = KA}; +cre_RequestedActions(SE) + when is_record(SE, 'SecondEventsDescriptor') or (SE == asn1_NOVALUE) -> + #'RequestedActions'{secondEvent = SE}; +cre_RequestedActions(SD) + when is_list(SD) or (SD == asn1_NOVALUE) -> + #'RequestedActions'{signalsDescriptor = SD}; +cre_RequestedActions({Tag, _} = EDM) + when is_atom(Tag) or (EDM == asn1_NOVALUE) -> + #'RequestedActions'{eventDM = EDM}. + +cre_RequestedActions(KA, {Tag, _} = EDM, SE, SD) + when ((KA == true) or (KA == true) or (KA == asn1_NOVALUE)) and + (is_atom(Tag) or (EDM == asn1_NOVALUE)) and + (is_record(SE, 'SecondEventsDescriptor') or (SE == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) -> + #'RequestedActions'{keepActive = KA, + eventDM = EDM, + secondEvent = SE, + signalsDescriptor = SD}. + +cre_EventDM(N) when is_list(N) -> + {digitMapName, N}; +cre_EventDM(V) when is_record(V, 'DigitMapValue') -> + {digitMapValue, V}. + +cre_SecondEventsDescriptor([H|_] = EL) + when is_record(H, 'SecondRequestedEvent') -> + #'SecondEventsDescriptor'{eventList = EL}. + +cre_SecondEventsDescriptor(RID, [H|_] = EL) + when is_integer(RID) andalso is_record(H, 'SecondRequestedEvent') -> + #'SecondEventsDescriptor'{requestID = RID, eventList = EL}. + +cre_SecondRequestedEvent(N, [H|_] = EPL) + when is_list(N) andalso + is_record(H, 'EventParameter') -> + #'SecondRequestedEvent'{pkgdName = N, + evParList = EPL}. + +cre_SecondRequestedEvent(N, SID, [H|_] = EPL) + when is_list(N) andalso + is_integer(SID) andalso + is_record(H, 'EventParameter') -> + #'SecondRequestedEvent'{pkgdName = N, + streamID = SID, + evParList = EPL}; +cre_SecondRequestedEvent(N, EA, [H|_] = EPL) + when is_list(N) andalso + is_record(EA, 'SecondRequestedActions') andalso + is_record(H, 'EventParameter') -> + #'SecondRequestedEvent'{pkgdName = N, + eventAction = EA, + evParList = EPL}. + +cre_SecondRequestedEvent(N, SID, EA, [H|_] = EPL) + when is_list(N) andalso + is_integer(SID) andalso + is_record(EA, 'SecondRequestedActions') andalso + is_record(H, 'EventParameter') -> + #'SecondRequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}. + +cre_SecondRequestedActions() -> + #'SecondRequestedActions'{}. + +cre_SecondRequestedActions(KA) + when ((KA =:= true) orelse (KA =:= false) orelse (KA =:= asn1_NOVALUE)) -> + #'SecondRequestedActions'{keepActive = KA}; +cre_SecondRequestedActions(SD) when is_list(SD) -> + #'SecondRequestedActions'{signalsDescriptor = SD}; +cre_SecondRequestedActions({Tag, _} = EDM) when is_atom(Tag) -> + #'SecondRequestedActions'{eventDM = EDM}. + +cre_SecondRequestedActions(KA, SD) + when ((KA =:= true) orelse (KA =:= false) orelse (KA =:= asn1_NOVALUE)) andalso + is_list(SD) -> + #'SecondRequestedActions'{keepActive = KA, signalsDescriptor = SD}; +cre_SecondRequestedActions(KA, {Tag, _} = EDM) + when ((KA =:= true) orelse (KA =:= false) orelse (KA =:= asn1_NOVALUE)) andalso + is_atom(Tag) -> + #'SecondRequestedActions'{keepActive = KA, eventDM = EDM}. + +cre_SecondRequestedActions(KA, {Tag, _} = EDM, SD) + when ((KA =:= true) orelse (KA =:= false) orelse (KA =:= asn1_NOVALUE)) andalso + is_atom(Tag) andalso + is_list(SD) -> + #'SecondRequestedActions'{keepActive = KA, + eventDM = EDM, + signalsDescriptor = SD}. + +cre_EventBufferDescriptor([H|_] = D) when is_record(H, 'EventSpec') -> + D. + +cre_EventSpec(N, [H|_] = EPL) + when is_list(N) andalso is_record(H, 'EventParameter') -> + #'EventSpec'{eventName = N, eventParList = EPL}. + +cre_EventSpec(N, SID, [H|_] = EPL) + when is_list(N) andalso is_integer(SID) andalso is_record(H, 'EventParameter') -> + #'EventSpec'{eventName = N, streamID = SID, eventParList = EPL}. + +cre_SignalsDescriptor(D) -> + case is_SignalsDescriptor(D) of + true -> + D; + false -> + error({invalid_SignalsDescriptor, D}) + end. + +cre_SignalRequest(S) when is_record(S, 'Signal') -> + {signal, S}; +cre_SignalRequest(S) when is_record(S, 'SeqSigList') -> + {seqSigList, S}. + +cre_SeqSigList(ID, [H|_] = SL) + when is_integer(ID) andalso (0 =< ID) andalso (ID =< 65535) andalso is_record(H, 'Signal') -> + #'SeqSigList'{id = ID, signalList = SL}. + +cre_Signal(N) when is_list(N) -> + #'Signal'{signalName = N}. + +cre_Signal(N, SPL) when is_list(N) andalso is_list(SPL) -> + #'Signal'{signalName = N, + sigParList = SPL}. + +cre_Signal(N, SID, ST, Dur, NC, KA, SPL) + when is_list(N) and + (is_integer(SID) or (SID == asn1_NOVALUE)) and + ((ST == brief) or (ST == onOff) or (ST == timeOut) or + (ST == asn1_NOVALUE)) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 65535)) or + (Dur == asn1_NOVALUE)) and + (is_list(NC) or (NC == asn1_NOVALUE)) and + ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SPL) -> + #'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL}. + +cre_Signal(N, SID, ST, Dur, NC, KA, SPL, Dir, RID) + when is_list(N) and + (is_integer(SID) or (SID == asn1_NOVALUE)) and + ((ST == brief) or (ST == onOff) or (ST == timeOut) or + (ST == asn1_NOVALUE)) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 65535)) or + (Dur == asn1_NOVALUE)) and + (is_list(NC) or (NC == asn1_NOVALUE)) and + ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SPL) and + ((Dir == internal) or (Dir == external) or (Dir == both) or + (Dir == asn1_NOVALUE)) and + (is_integer(RID) or (RID == asn1_NOVALUE)) -> + #'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL, + direction = Dir, + requestID = RID}. + +cre_SignalType(brief = ST) -> + ST; +cre_SignalType(onOff = ST) -> + ST; +cre_SignalType(timeOut = ST) -> + ST. + +cre_SignalDirection(internal = SD) -> + SD; +cre_SignalDirection(external = SD) -> + SD; +cre_SignalDirection(both = SD) -> + SD. + +cre_SignalName(N) -> + cre_PkgdName(N). + +cre_NotifyCompletion(L) when is_list(L) -> + Vals = [onTimeOut, onInterruptByEvent, + onInterruptByNewSignalDescr, otherReason], + F = fun(E) -> case lists:member(E, Vals) of + true -> + ok; + false -> + exit({invalid_NotifyCompletion, E}) + end + end, + lists:foreach(F, L), + L. + +cre_SigParameter(N, V) when is_list(N) andalso is_list(V) -> + #'SigParameter'{sigParameterName = N, value = V}. + +cre_SigParameter(N, V, relation = Tag, R) + when is_list(N) and is_list(V) and is_atom(R) -> + EI = {Tag, R}, + #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}; +cre_SigParameter(N, V, range = Tag, B) + when is_list(N) and is_list(V) and is_atom(B) -> + EI = {Tag, B}, + #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}; +cre_SigParameter(N, V, sublist = Tag, B) + when is_list(N) and is_list(V) and is_atom(B) -> + EI = {Tag, B}, + #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}. + +cre_RequestID(Val) when 0 =< Val, Val =< 4294967295 -> + Val; +cre_RequestID(Val) -> + exit({invalid_RequestID, Val}). + +cre_ModemDescriptor(MTL, MPL) when is_list(MTL) andalso is_list(MPL) -> + #'ModemDescriptor'{mtl = MTL, mpl = MPL}. + +%% cre_ModemDescriptor(MTL, MPL, NSD) +%% when list(MTL), list(MPL), record(NSD, 'NonStandardData') -> +%% #'ModemDescriptor'{mtl = MTL, mpl = MPL}. + +cre_ModemType(v18 = MT) -> + MT; +cre_ModemType(v22 = MT) -> + MT; +cre_ModemType(v22bis = MT) -> + MT; +cre_ModemType(v32 = MT) -> + MT; +cre_ModemType(v32bis = MT) -> + MT; +cre_ModemType(v34 = MT) -> + MT; +cre_ModemType(v90 = MT) -> + MT; +cre_ModemType(v91 = MT) -> + MT; +cre_ModemType(synchISDN = MT) -> + MT. + +cre_DigitMapDescriptor() -> + #'DigitMapDescriptor'{}. + +cre_DigitMapDescriptor(N) when is_list(N) -> + #'DigitMapDescriptor'{digitMapName = N}; +cre_DigitMapDescriptor(V) when is_record(V, 'DigitMapValue') -> + #'DigitMapDescriptor'{digitMapValue = V}. + +cre_DigitMapDescriptor(N, V) when is_list(N) andalso is_record(V, 'DigitMapValue') -> + #'DigitMapDescriptor'{digitMapName = N, digitMapValue = V}. + +cre_DigitMapName(N) -> + cre_Name(N). + +cre_DigitMapValue(DMB) when is_list(DMB) -> + #'DigitMapValue'{digitMapBody = DMB}. + +cre_DigitMapValue(Start, Short, Long, DMB) -> + cre_DigitMapValue(Start, Short, Long, DMB, asn1_NOVALUE). + +cre_DigitMapValue(Start, Short, Long, DMB, Dur) + when ((is_integer(Start) and (0 =< Start) and (Start =< 99)) or + (Start == asn1_NOVALUE)) and + ((is_integer(Short) and (0 =< Short) and (Short =< 99)) or + (Short == asn1_NOVALUE)) and + ((is_integer(Long) and (0 =< Long) and (Long =< 99)) or + (Long == asn1_NOVALUE)) and + is_list(DMB) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 99)) or + (Dur == asn1_NOVALUE)) -> + #'DigitMapValue'{startTimer = Start, + shortTimer = Short, + longTimer = Long, + digitMapBody = DMB, + durationTimer = Dur}. + +cre_ServiceChangeParm(M, R) when is_atom(M) andalso is_list(R) -> + #'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeReason = R}. + +cre_ServiceChangeParm(M, Addr, Prof, Reason) -> + cre_ServiceChangeParm(M, Addr, asn1_NOVALUE, Prof, Reason, asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE). + +%% Addr = asn1_NOVALUE | {AddrTag, AddrVal} +cre_ServiceChangeParm(M, Addr, Ver, Prof, R, D, Mid, TS, I) -> + cre_ServiceChangeParm(M, Addr, Ver, Prof, R, D, Mid, TS, I, asn1_NOVALUE). + +cre_ServiceChangeParm(M, Addr, Ver, Prof, R, D, Mid, TS, I, IF) + when is_atom(M) and + ((is_integer(Ver) and (0 =< Ver) and (Ver =< 99)) or + (Ver == asn1_NOVALUE)) and + (is_record(Prof, 'ServiceChangeProfile') or (Prof == asn1_NOVALUE)) and + is_list(R) and + ((is_integer(D) and (0 =< D) and (D =< 4294967295)) or + (D == asn1_NOVALUE)) and + (is_record(TS, 'TimeNotation') or (TS == asn1_NOVALUE)) and + (is_record(I, 'AuditDescriptor') or (I == asn1_NOVALUE)) and + ((IF == 'NULL') or (IF == asn1_NOVALUE)) -> + F = fun(A) -> + (A == asn1_NOVALUE) orelse + (is_tuple(A) + andalso is_atom(element(1, A))) + end, + case (F(Addr) andalso F(Mid)) of + true -> + #'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeAddress = Addr, + serviceChangeVersion = Ver, + serviceChangeProfile = Prof, + serviceChangeReason = R, + serviceChangeDelay = D, + serviceChangeMgcId = Mid, + timeStamp = TS, + serviceChangeInfo = I, + serviceChangeIncompleteFlag = IF}; + _ -> + exit({invalid_ServiceChangeParm_args, {Addr, Mid}}) + end. + +cre_ServiceChangeAddress(portNumber = Tag, P) + when is_integer(P) andalso (0 =< P) andalso (P =< 65535) -> + {Tag, P}; +cre_ServiceChangeAddress(ip4Address = Tag, A) when is_record(A, 'IP4Address') -> + {Tag, A}; +cre_ServiceChangeAddress(ip6Address = Tag, A) when is_record(A, 'IP6Address') -> + {Tag, A}; +cre_ServiceChangeAddress(domainName = Tag, N) when is_record(N, 'DomainName') -> + {Tag, N}; +cre_ServiceChangeAddress(deviceName = Tag, N) when is_list(N) -> + {Tag, N}; +cre_ServiceChangeAddress(mtpAddress = Tag, A) when is_list(A) -> + {Tag, A}. + +cre_ServiceChangeResParm() -> + #'ServiceChangeResParm'{}. +cre_ServiceChangeResParm(Addr, Prof) -> + cre_ServiceChangeResParm(asn1_NOVALUE, Addr, asn1_NOVALUE, + Prof, asn1_NOVALUE). +cre_ServiceChangeResParm(Mid, Addr, Ver, Prof, TS) + when ((is_integer(Ver) and (0 =< Ver) andalso (Ver =< 99)) orelse + (Ver =:= asn1_NOVALUE)) andalso + (is_record(Prof, 'ServiceChangeProfile') orelse (Prof =:= asn1_NOVALUE)) andalso + (is_record(TS, 'TimeNotation') orelse (TS =:= asn1_NOVALUE)) -> + F = fun(A) -> + (A =:= asn1_NOVALUE) orelse + (is_tuple(A) + andalso is_atom(element(1, A))) + end, + case (F(Addr) andalso F(Mid)) of + true -> + #'ServiceChangeResParm'{serviceChangeMgcId = Mid, + serviceChangeAddress = Addr, + serviceChangeVersion = Ver, + serviceChangeProfile = Prof, + timeStamp = TS}; + _ -> + exit({invalid_ServiceChangeResParm_args, {Addr, Mid}}) + end. + +cre_ServiceChangeMethod(failover = M) -> + M; +cre_ServiceChangeMethod(forced = M) -> + M; +cre_ServiceChangeMethod(graceful = M) -> + M; +cre_ServiceChangeMethod(restart = M) -> + M; +cre_ServiceChangeMethod(disconnected = M) -> + M; +cre_ServiceChangeMethod(handOff = M) -> + M. + +%% The version field is added to make it look more like ABNF +cre_ServiceChangeProfile(N) -> + cre_ServiceChangeProfile(N, 1). + +cre_ServiceChangeProfile(N, V) + when is_list(N) andalso is_integer(V) andalso (0 =< V) andalso (V =< 99) -> + #'ServiceChangeProfile'{profileName = N, version = V}. + +cre_PackagesDescriptor([H|_] = D) when is_record(H, 'PackagesItem') -> + D. + +cre_PackagesItem(N, Ver) + when is_list(N) andalso is_integer(Ver) andalso (0 =< Ver) andalso (Ver =< 99) -> + #'PackagesItem'{packageName = N, + packageVersion = Ver}. + +cre_StatisticsDescriptor(D) -> + true = is_StatisticsDescriptor(D), + D. + +cre_StatisticsParameter(N) when is_list(N) -> + #'StatisticsParameter'{statName = N}. + +cre_StatisticsParameter(N, V) when is_list(N) andalso is_list(V) -> + #'StatisticsParameter'{statName = N, statValue = V}. + +%% cre_NonStandardData({Tag, _} = Id, Data) when atom(Tag), list(Data) -> +%% #'NonStandardData'{nonStandardIdentifier = Id, data = Data}. + +%% cre_NonStandardIdentifier(H221) when record(H221, 'H221NonStandard') -> +%% {h221NonStandard, H221}; +%% cre_NonStandardIdentifier(Obj) when tuple(Obj) -> +%% {object, Obj}; +%% cre_NonStandardIdentifier(Exp) when list(Exp), length(Exp) == 8 -> +%% {experimental, Exp}. + +%% cre_H221NonStandard(CC1, CC2, Ext, MC) +%% when (is_integer(CC1) and (0 =< CC1) and (CC1 =< 255)) and +%% (is_integer(CC2) and (0 =< CC2) and (CC2 =< 255)) and +%% (is_integer(Ext) and (0 =< Ext) and (Ext =< 255)) and +%% (is_integer(MC) and (0 =< MC) and (MC =< 255)) -> +%% #'H221NonStandard'{t35CountryCode1 = CC1, +%% t35CountryCode2 = CC2, +%% t35Extension = Ext, +%% manufacturerCode = MC}. + +cre_TimeNotation(D, T) + when is_list(D) andalso (length(D) =:= 8) andalso is_list(T) andalso (length(T) =:= 8) -> + #'TimeNotation'{date = D, time = T}. + +cre_Value([H|_] = V) when is_list(H) -> + V. + +cre_BOOLEAN(true = B) -> + B; +cre_BOOLEAN(false = B) -> + B. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% -- MegacoMessage -- + +is_MegacoMessage(#'MegacoMessage'{authHeader = Auth, + mess = Mess}) -> + d("is_MegacoMessage -> entry"), + is_opt_AuthenticationHeader(Auth) andalso is_Message(Mess); +is_MegacoMessage(_) -> + false. + + +chk_MegacoMessage(M, M) -> + d("chk_MegacoMessage -> entry (1)"), + chk_type(fun is_MegacoMessage/1, 'MegacoMessage', M); +chk_MegacoMessage(#'MegacoMessage'{authHeader = Auth1, + mess = Mess1}, + #'MegacoMessage'{authHeader = Auth2, + mess = Mess2}) -> + d("chk_MegacoMessage -> entry (2)"), + chk_opt_AuthenticationHeader(Auth1,Auth2), + chk_Message(Mess1,Mess2), + ok; +chk_MegacoMessage(M1, M2) -> + wrong_type('MegacoMessage', M1, M2). + + +%% -- AuthenticationHeader -- + +is_opt_AuthenticationHeader(AH) -> + is_OPTIONAL(fun is_AuthenticationHeader/1, AH). + +is_AuthenticationHeader(#'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AD}) -> + is_SecurityParmIndex(SPI) andalso + is_SequenceNum(SN) andalso + is_AuthData(AD); +is_AuthenticationHeader(_) -> + false. + +%% This stuff is not really used, so make it simple... +chk_opt_AuthenticationHeader(A1, A2) -> + chk_OPTIONAL('AuthenticationHeader', A1, A2, + fun is_AuthenticationHeader/1, + fun chk_AuthenticationHeader/2). + +chk_AuthenticationHeader(A, A) -> + chk_type(fun is_AuthenticationHeader/1, 'AuthenticationHeader', A); +chk_AuthenticationHeader(A1, A2) -> + case (is_AuthenticationHeader(A1) andalso is_AuthenticationHeader(A2)) of + true -> + not_equal('AuthenticationHeader', A1, A2); + false -> + wrong_type('AuthenticationHeader', A1, A2) + end. + + +%% -- SecurityParmIndex -- + +is_SecurityParmIndex(V) -> is_OCTET_STRING(V, {exact, 4}). + + +%% -- SequenceNum -- + +is_SequenceNum(V) -> is_OCTET_STRING(V, {exact, 4}). + + +%% -- AuthData -- + +is_AuthData(V) -> is_OCTET_STRING(V, {range, 12, 32}). + + +%% -- Message -- + +is_Message(#'Message'{version = V, + mId = MID, + messageBody = Body}) -> + d("is_Message -> entry"), + is_INTEGER(V, {range, 0, 99}) andalso + is_MId(MID) andalso + is_Message_messageBody(Body); +is_Message(_) -> + false. + +chk_Message(M, M) -> + d("chk_Message -> entry (1)"), + chk_type(fun is_Message/1, 'Message', M); +chk_Message(#'Message'{version = V1, + mId = MID1, + messageBody = Body1}, + #'Message'{version = V2, + mId = MID2, + messageBody = Body2}) -> + d("chk_Message -> entry with" + "~n V1: ~p" + "~n MID1: ~p" + "~n Body1: ~p" + "~n V2: ~p" + "~n MID2: ~p" + "~n Body2: ~p", + [V1, MID1, Body1, V2, MID2, Body2]), + validate(fun() -> chk_INTEGER(V1, V2, {range, 0, 99}) end, 'Message'), + validate(fun() -> chk_MId(MID1, MID2) end, 'Message'), + chk_Message_messageBody(Body1, Body2), + ok; +chk_Message(M1, M2) -> + wrong_type('Message', M1, M2). + + +is_Message_messageBody({Tag, Val}) -> + d("is_Message_messageBody -> entry"), + is_Message_messageBody_tag(Tag) andalso + is_Message_messageBody_val(Tag, Val); +is_Message_messageBody(_) -> + false. + +is_Message_messageBody_tag(Tag) -> + Tags = [messageError, transactions], + lists:member(Tag, Tags). + +is_Message_messageBody_val(messageError, Val) -> + is_ErrorDescriptor(Val); +is_Message_messageBody_val(transactions, Val) -> + is_Message_messageBody_transactions(Val). + +is_Message_messageBody_transactions([]) -> + d("is_Message_messageBody_transactions -> entry when done"), + true; +is_Message_messageBody_transactions([H|T]) -> + d("is_Message_messageBody_transactions -> entry"), + is_Transaction(H) andalso is_Message_messageBody_transactions(T); +is_Message_messageBody_transactions(_) -> + false. + +chk_Message_messageBody(B, B) -> + d("chk_Message_messageBody -> entry (1)"), + chk_type(fun is_Message_messageBody/1, 'Message_messageBody', B); +chk_Message_messageBody({Tag, Val1} = B1, {Tag, Val2} = B2) -> + d("chk_Message_messageBody -> entry (2)"), + case (is_Message_messageBody_tag(Tag) andalso + is_Message_messageBody_val(Tag, Val1) andalso + is_Message_messageBody_val(Tag, Val2)) of + true -> + chk_Message_messageBody_val(Tag, Val1, Val2); + false -> + wrong_type('Message_messageBody', B1, B2) + end; +chk_Message_messageBody({Tag1, Val1} = B1, {Tag2, Val2} = B2) -> + d("chk_Message_messageBody -> entry (3)"), + case ((is_Message_messageBody_tag(Tag1) andalso + is_Message_messageBody_val(Tag1, Val1)) andalso + (is_Message_messageBody_tag(Tag2) andalso + is_Message_messageBody_val(Tag2, Val2))) of + true -> + not_equal('Message_messageBody', B1, B2); + false -> + wrong_type('Message_messageBody', B1, B2) + end; +chk_Message_messageBody(B1, B2) -> + wrong_type('Message_messageBody', B1, B2). + +chk_Message_messageBody_val(messageError, Val1, Val2) -> + validate(fun() -> chk_ErrorDescriptor(Val1, Val2) end, + 'Message_messageBody'); +chk_Message_messageBody_val(transactions, Val1, Val2) -> + chk_Message_messageBody_transactions(lists:sort(Val1), + lists:sort(Val2)). + +chk_Message_messageBody_transactions([], []) -> + d("chk_Message_messageBody_transactions -> entry - ok (1)"), + ok; +chk_Message_messageBody_transactions([] = T1, T2) -> + d("chk_Message_messageBody_transactions -> entry - not-equal (2)"), + not_equal('Message_messageBody_transactions', T1, T2); +chk_Message_messageBody_transactions(T1, [] = T2) -> + d("chk_Message_messageBody_transactions -> entry - not-equal (3)"), + not_equal('Message_messageBody_transactions', T1, T2); +chk_Message_messageBody_transactions([H|T1], [H|T2]) -> + d("chk_Message_messageBody_transactions -> entry (4)"), + case is_Transaction(H) of + true -> + chk_Message_messageBody_transactions(T1, T2); + false -> + wrong_type('Message_messageBody_transactions_val', H) + end; +chk_Message_messageBody_transactions([H1|T1], [H2|T2]) -> + d("chk_Message_messageBody_transactions -> entry (5)"), + validate(fun() -> chk_Transaction(H1, H2) end, + 'Message_messageBody_transactions_val'), + chk_Message_messageBody_transactions(T1, T2); +chk_Message_messageBody_transactions(T1, T2) -> + d("chk_Message_messageBody_transactions -> entry - wrong-type (6)"), + wrong_type('Message_messageBody_transactions', T1, T2). + + +%% -- MId -- + +is_opt_MId(M) -> + is_OPTIONAL(fun is_MId/1, M). + +is_MId({Tag, Val}) -> + is_MId_tag(Tag) andalso is_MId_val(Tag, Val); +is_MId(_) -> + false. + +is_MId_tag(Tag) -> + Tags = [ip4Address, ip6Address, domainName, deviceName, mtpAddress], + lists:member(Tag, Tags). + +is_MId_val(ip4Address, Val) -> is_IP4Address(Val); +is_MId_val(ip6Address, Val) -> is_IP6Address(Val); +is_MId_val(domainName, Val) -> is_DomainName(Val); +is_MId_val(deviceName, Val) -> is_PathName(Val); +is_MId_val(mtpAddress, Val) -> is_OCTET_STRING(Val, {range, 2, 4}). + +chk_opt_MId(M1, M2) -> + chk_OPTIONAL('MId', M1, M2, fun is_MId/1, fun chk_MId/2). + +chk_MId(M, M) -> + chk_type(fun is_MId/1, 'MId', M); +chk_MId({Tag, Val1} = M1, {Tag, Val2} = M2) -> + case (is_MId_tag(Tag) andalso + is_MId_val(Tag, Val1) andalso + is_MId_val(Tag, Val2)) of + true -> + chk_MId_val(Tag, Val1, Val2); + false -> + wrong_type('MId', M1, M2) + end; +chk_MId({Tag1, Val1} = M1, {Tag2, Val2} = M2) -> + case ((is_MId_tag(Tag1) andalso + is_MId_val(Tag1, Val1)) andalso + (is_MId_tag(Tag2) andalso + is_MId_val(Tag2, Val2))) of + true -> + not_equal('MId', M1, M2); + false -> + wrong_type('MId', M1, M2) + end; +chk_MId(M1, M2) -> + wrong_type('MId', M1, M2). + +chk_MId_val(ip4Address, M1, M2) -> chk_IP4Address(M1, M2); +chk_MId_val(ip6Address, M1, M2) -> chk_IP6Address(M1, M2); +chk_MId_val(domainName, M1, M2) -> chk_DomainName(M1, M2); +chk_MId_val(deviceName, M1, M2) -> chk_PathName(M1, M2); +chk_MId_val(mtpAddress, M1, M2) -> chk_OCTET_STRING(M1, M2, {range, 2, 4}). + + +%% -- DomainName -- + +is_DomainName(#'DomainName'{name = N, portNumber = PN}) -> + is_IA5String(N) andalso is_opt_INTEGER(PN, {range, 0, 65535}); +is_DomainName(_) -> + false. + +chk_DomainName(N, N) -> + ok; +chk_DomainName(N1, N2) -> + not_equal('DomainName', N1, N2). + + +%% -- IP4Address -- + +is_IP4Address(#'IP4Address'{address = A, portNumber = PN}) -> + is_OCTET_STRING(A, {exact, 4}) andalso + is_opt_INTEGER(PN, {range, 0, 65535}); +is_IP4Address(_) -> + false. + +chk_IP4Address(A, A) -> + ok; +chk_IP4Address(A1, A2) -> + not_equal('IP4Address', A1, A2). + + +%% -- IP6Address -- + +is_IP6Address(#'IP6Address'{address = A, portNumber = PN}) -> + is_OCTET_STRING(A, {exact, 16}) andalso + is_opt_INTEGER(PN, {range, 0, 65535}); +is_IP6Address(_) -> + false. + +chk_IP6Address(A, A) -> + ok; +chk_IP6Address(A1, A2) -> + not_equal('IP6Address', A1, A2). + + +%% -- PathName -- + +is_PathName(N) -> is_IA5String(N, {range, 1, 64}). + +chk_PathName(N, N) -> + ok; +chk_PathName(N1, N2) -> + not_equal('PathName', N1, N2). + + +%% -- Transaction -- + +is_Transaction({Tag, Val}) -> + d("is_Transaction -> entry"), + is_Transaction_tag(Tag) andalso is_Transaction_val(Tag, Val); +is_Transaction(_) -> + false. + +is_Transaction_tag(Tag) -> + Tags = [transactionRequest, + transactionPending, + transactionReply, + transactionResponseAck], + lists:member(Tag, Tags). + +is_Transaction_val(transactionRequest, V) -> is_TransactionRequest(V); +is_Transaction_val(transactionPending, V) -> is_TransactionPending(V); +is_Transaction_val(transactionReply, V) -> is_TransactionReply(V); +is_Transaction_val(transactionResponseAck, V) -> is_TransactionResponseAck(V). + + +chk_Transaction({Tag, Val} = Trans, Trans) -> + d("chk_Transaction -> entry (1)"), + case (is_Transaction_tag(Tag) andalso is_Transaction_val(Tag, Val)) of + true -> + ok; + false -> + wrong_type('Transaction', Trans, Trans) + end; +chk_Transaction({Tag, Val1} = Trans1, {Tag, Val2} = Trans2) -> + d("chk_Transaction -> entry (2)"), + case (is_Transaction_tag(Tag) and + is_Transaction_val(Tag, Val1) and + is_Transaction_val(Tag, Val2)) of + true -> + chk_Transaction_val(Tag, Val1, Val2); + false -> + wrong_type('Transaction', Trans1, Trans2) + end; +chk_Transaction({Tag1, Val1} = Trans1, {Tag2, Val2} = Trans2) -> + d("chk_Transaction -> entry (3)"), + case ((is_Transaction_tag(Tag1) andalso + is_Transaction_val(Tag1, Val1)) andalso + (is_Transaction_tag(Tag2) andalso + is_Transaction_val(Tag2, Val2))) of + true -> + not_equal('Transaction', Trans1, Trans2); + false -> + wrong_type('Transaction', Trans1, Trans2) + end; +chk_Transaction(Trans1, Trans2) -> + d("chk_Transaction -> entry - wrong-type - (4)"), + wrong_type('Transaction', Trans1, Trans2). + +chk_Transaction_val(transactionRequest, T1, T2) -> + chk_TransactionRequest(T1, T2); +chk_Transaction_val(transactionPending, T1, T2) -> + chk_TransactionPending(T1, T2); +chk_Transaction_val(transactionReply, T1, T2) -> + chk_TransactionReply(T1,T2); +chk_Transaction_val(transactionResponseAck, T1, T2) -> + chk_TransactionResponseAck(T1, T2). + + +%% -- TransactionId -- + +is_opt_TransactionId(TID) -> + is_OPTIONAL(fun is_TransactionId/1, TID). + +is_TransactionId(TID) -> + d("is_TransactionId -> entry"), + is_INTEGER(TID, {range, 0, 4294967295}). + +chk_opt_TransactionId(TID1, TID2) -> + chk_OPTIONAL('TransactionId', TID1, TID2, + fun is_TransactionId/1, fun chk_TransactionId/2). + +chk_TransactionId(TID, TID) -> + chk_type(fun is_TransactionId/1, 'TransactionId', TID); +chk_TransactionId(TID1, TID2) -> + case (is_TransactionId(TID1) andalso is_TransactionId(TID2)) of + true -> + not_equal('TransactionId', TID1, TID2); + false -> + wrong_type('TransactionId', TID1, TID2) + end. + + +%% -- TransactionRequest -- + +is_TransactionRequest(#'TransactionRequest'{transactionId = TID, + actions = Acts}) -> + d("is_TransactionRequest -> entry"), + is_TransactionId(TID) andalso is_TransactionRequest_actions(Acts); +is_TransactionRequest(_) -> + false. + +chk_TransactionRequest(T, T) -> + chk_type(fun is_TransactionRequest/1, 'TransactionRequest', T); +chk_TransactionRequest(#'TransactionRequest'{transactionId = TID1, + actions = Acts1}, + #'TransactionRequest'{transactionId = TID2, + actions = Acts2}) -> + validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionRequest'), + chk_TransactionRequest_actions(lists:sort(Acts1), + lists:sort(Acts2)), + ok; +chk_TransactionRequest(T1, T2) -> + wrong_type('TransactionRequest', T1, T2). + +is_TransactionRequest_actions([]) -> + d("is_TransactionRequest_actions -> entry when done"), + true; +is_TransactionRequest_actions([H|T]) -> + d("is_TransactionRequest_actions -> entry"), + is_ActionRequest(H) andalso is_TransactionRequest_actions(T); +is_TransactionRequest_actions(_) -> + false. + +chk_TransactionRequest_actions([], []) -> + ok; +chk_TransactionRequest_actions([] = Acts1, Acts2) -> + not_equal('TransactionRequest_actions', Acts1, Acts2); +chk_TransactionRequest_actions(Acts1, [] = Acts2) -> + not_equal('TransactionRequest_actions', Acts1, Acts2); +chk_TransactionRequest_actions([H|T1], [H|T2]) -> + case is_ActionRequest(H) of + true -> + chk_TransactionRequest_actions(T1, T2); + false -> + wrong_type('TransactionRequest_actions_val', H) + end; +chk_TransactionRequest_actions([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ActionRequest(H1, H2) end, + 'TransactionRequest_actions_val'), + chk_TransactionRequest_actions(T1, T2); +chk_TransactionRequest_actions(Acts1, Acts2) -> + wrong_type('TransactionRequest_actions', Acts1, Acts2). + + +%% -- TransactionPending -- + +is_TransactionPending(#'TransactionPending'{transactionId = TID}) -> + d("is_TransactionPending -> entry"), + is_TransactionId(TID); +is_TransactionPending(_) -> + false. + +chk_TransactionPending(T, T) -> + chk_type(fun is_TransactionPending/1, 'TransactionPending', T); +chk_TransactionPending(#'TransactionPending'{transactionId = TID1}, + #'TransactionPending'{transactionId = TID2}) -> + validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionPending'), + ok; +chk_TransactionPending(T1, T2) -> + wrong_type('TransactionPending', T1, T2). + + +%% -- TransactionReply -- + +is_TransactionReply(#'TransactionReply'{transactionId = TID, + immAckRequired = IAR, + transactionResult = TR}) -> + d("is_TransactionReply -> entry"), + is_TransactionId(TID) andalso + is_opt_NULL(IAR) andalso + is_TransactionReply_transactionResult(TR); +is_TransactionReply(_) -> + false. + +chk_TransactionReply(T, T) -> + chk_type(fun is_TransactionReply/1, 'TransactionReply', T); +chk_TransactionReply(#'TransactionReply'{transactionId = TID1, + immAckRequired = IAR1, + transactionResult = TR1}, + #'TransactionReply'{transactionId = TID2, + immAckRequired = IAR2, + transactionResult = TR2}) -> + validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionReply'), + validate(fun() -> chk_opt_NULL(IAR1, IAR2) end, 'TransactionReply'), + chk_TransactionReply_transactionResult(TR1, TR2), + ok; +chk_TransactionReply(T1, T2) -> + wrong_type('TransactionReply', T1, T2). + +is_TransactionReply_transactionResult({Tag, Val}) -> + d("is_TransactionReply_transactionResult -> entry"), + is_TransactionReply_transactionResult_tag(Tag) andalso + is_TransactionReply_transactionResult_val(Tag, Val); +is_TransactionReply_transactionResult(_) -> + false. + +is_TransactionReply_transactionResult_tag(T) -> + lists:member(T, [transactionError, actionReplies]). + +is_TransactionReply_transactionResult_val(transactionError, V) -> + is_ErrorDescriptor(V); +is_TransactionReply_transactionResult_val(actionReplies, V) -> + is_TransactionReply_actionReplies(V). + +chk_TransactionReply_transactionResult(Res, Res) -> + chk_type(fun is_TransactionReply_transactionResult/1, + 'TransactionReply_transactionResult', Res); +chk_TransactionReply_transactionResult({Tag, Val1} = Res1, + {Tag, Val2} = Res2) -> + case (is_TransactionReply_transactionResult_tag(Tag) and + is_TransactionReply_transactionResult_val(Tag, Val1) and + is_TransactionReply_transactionResult_val(Tag, Val2)) of + true -> + chk_TransactionReply_transactionResult_val(Tag, Val1, Val2); + false -> + wrong_type('TransactionReply_transactionResult', Res1, Res2) + end; +chk_TransactionReply_transactionResult({Tag1, Val1} = Res1, + {Tag2, Val2} = Res2) -> + case ((is_TransactionReply_transactionResult_tag(Tag1) and + is_TransactionReply_transactionResult_val(Tag1, Val1)) and + (is_TransactionReply_transactionResult_tag(Tag2) and + is_TransactionReply_transactionResult_val(Tag2, Val2))) of + true -> + not_equal('TransactionReply_transactionResult', Res1, Res2); + false -> + wrong_type('TransactionReply_transactionResult', Res1, Res2) + end; +chk_TransactionReply_transactionResult(Res1, Res2) -> + wrong_type('TransactionReply_transactionResult', Res1, Res2). + +chk_TransactionReply_transactionResult_val(transactionError, E1, E2) -> + validate(fun() -> chk_ErrorDescriptor(E1, E2) end, + 'TransactionReply_transactionResult'); +chk_TransactionReply_transactionResult_val(actionReplies, R1, R2) -> + validate(fun() -> + chk_TransactionReply_actionReplies(lists:sort(R1), + lists:sort(R2)) + end, + 'TransactionReply_transactionResult'). + +is_TransactionReply_actionReplies([]) -> + d("is_TransactionReply_actionReplies -> entry when done"), + true; +is_TransactionReply_actionReplies([H|T]) -> + d("is_TransactionReply_actionReplies -> entry"), + is_ActionReply(H) andalso is_TransactionReply_actionReplies(T); +is_TransactionReply_actionReplies(_) -> + false. + +chk_TransactionReply_actionReplies([], []) -> + ok; +chk_TransactionReply_actionReplies([] = AR1, AR2) -> + not_equal('TransactionReply_actionReplies', AR1, AR2); +chk_TransactionReply_actionReplies(AR1, [] = AR2) -> + not_equal('TransactionReply_actionReplies', AR1, AR2); +chk_TransactionReply_actionReplies([H|T1], [H|T2]) -> + case is_ActionReply(H) of + true -> + chk_TransactionReply_actionReplies(T1, T2); + false -> + wrong_type('TransactionReply_actionReplies_val', H) + end; +chk_TransactionReply_actionReplies([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ActionReply(H1, H2) end, + 'TransactionReply_actionReplies_val'), + chk_TransactionReply_actionReplies(T1, T2); +chk_TransactionReply_actionReplies(AR1, AR2) -> + wrong_type('TransactionReply_actionReplies', AR1, AR2). + + +%% -- TransactionResponseAck -- + +is_TransactionResponseAck([]) -> + d("is_TransactionResponseAck -> entry when done"), + true; +is_TransactionResponseAck([H|T]) -> + d("is_TransactionResponseAck -> entry"), + is_TransactionAck(H) andalso is_TransactionResponseAck(T); +is_TransactionResponseAck(_) -> + false. + +chk_TransactionResponseAck([], []) -> + ok; +chk_TransactionResponseAck([] = AR1, AR2) -> + not_equal('TransactionResponseAck', AR1, AR2); +chk_TransactionResponseAck(AR1, [] = AR2) -> + not_equal('TransactionResponseAck', AR1, AR2); +chk_TransactionResponseAck([H|T1], [H|T2]) -> + case is_TransactionAck(H) of + true -> + chk_TransactionResponseAck(T1, T2); + false -> + wrong_type('TransactionResponseAck_val', H) + end; +chk_TransactionResponseAck([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TransactionAck(H1, H2) end, + 'TransactionResponseAck'), + chk_TransactionResponseAck(T1, T2); +chk_TransactionResponseAck(AR1, AR2) -> + wrong_type('TransactionResponseAck', AR1, AR2). + + +%% -- TransactionAck -- + +is_TransactionAck(#'TransactionAck'{firstAck = F, + lastAck = L}) -> + d("is_TransactionAck -> entry"), + is_TransactionId(F) andalso is_opt_TransactionId(L); +is_TransactionAck(_) -> + false. + +chk_TransactionAck(T, T) -> + chk_type(fun is_TransactionAck/1, 'TransactionAck', T); +chk_TransactionAck(#'TransactionAck'{firstAck = F1, + lastAck = L1}, + #'TransactionAck'{firstAck = F2, + lastAck = L2}) -> + validate(fun() -> chk_TransactionId(F1, F2) end, 'TransactionAck'), + validate(fun() -> chk_opt_TransactionId(L1, L2) end, 'TransactionAck'), + ok; +chk_TransactionAck(T1, T2) -> + wrong_type('TransactionAck', T1, T2). + + +%% -- ErrorDescriptor -- + +is_opt_ErrorDescriptor(V) -> + is_OPTIONAL(fun is_ErrorDescriptor/1, V). + +is_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code, + errorText = Text}) -> + d("is_ErrorDescriptor -> entry"), + is_ErrorCode(Code) andalso is_opt_ErrorText(Text); +is_ErrorDescriptor(_) -> + false. + +chk_opt_ErrorDescriptor(E1, E2) -> + chk_OPTIONAL('ErrorDescriptor', E1, E2, + fun is_ErrorDescriptor/1, fun chk_ErrorDescriptor/2). + +chk_ErrorDescriptor(E, E) -> + chk_type(fun is_ErrorDescriptor/1, 'ErrorDescriptor', E); +chk_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code1, + errorText = Text1}, + #'ErrorDescriptor'{errorCode = Code2, + errorText = Text2}) -> + chk_ErrorCode(Code1, Code2), + chk_opt_ErrorText(Text1, Text2), + ok; +chk_ErrorDescriptor(E1, E2) -> + wrong_type('ErrorDescriptor', E1, E2). + + +%% -- ErrorCode -- + +is_ErrorCode(C) -> is_INTEGER(C, {range, 0, 65535}). + +chk_ErrorCode(C, C) -> + case is_ErrorCode(C) of + true -> + ok; + false -> + wrong_type(errorCode, C, C) + end; +chk_ErrorCode(C1, C2) -> + case (is_ErrorCode(C1) andalso is_ErrorCode(C2)) of + true -> + not_equal(errorCode, C1, C2); + false -> + wrong_type(errorCode, C1, C2) + end. + + +%% -- ErrorText -- + +is_opt_ErrorText(V) -> + is_OPTIONAL(fun is_ErrorText/1, V). + +is_ErrorText(V) -> is_IA5String(V). + +chk_opt_ErrorText(T1, T2) -> + chk_OPTIONAL('ErrorText', T1, T2, fun is_ErrorText/1, fun chk_ErrorText/2). + +chk_ErrorText(T, T) -> + chk_type(fun is_ErrorText/1, 'ErrorText', T); +chk_ErrorText(T1, T2) -> + case (is_ErrorText(T1) andalso is_ErrorText(T2)) of + true -> + case {to_lower(T1), to_lower(T2)} of + {T, T} -> + ok; + _ -> + not_equal('ErrorText', T1, T2) + end; + false -> + wrong_type('ErrorText', T1, T2) + end. + + +%% -- ContextID -- + +is_ContextID(Id) -> is_INTEGER(Id, {range, 0, 4294967295}). + +chk_ContextID(Id, Id) -> + chk_type(fun is_ContextID/1, 'ContextID', Id); +chk_ContextID(Id1, Id2) -> + case (is_ContextID(Id1) andalso is_ContextID(Id2)) of + true -> + not_equal('ContextID', Id1, Id2); + false -> + wrong_type('ContextID', Id1, Id2) + end. + + +%% -- ActionRequest -- + +is_ActionRequest(#'ActionRequest'{contextId = Id, + contextRequest = CtxReq, + contextAttrAuditReq = AuditReq, + commandRequests = CmdReqs}) -> + d("is_ActionRequest -> entry"), + is_ContextID(Id) andalso + is_opt_ContextRequest(CtxReq) andalso + is_opt_ContextAttrAuditRequest(AuditReq) andalso + is_ActionRequest_commandRequests(CmdReqs); +is_ActionRequest(_) -> + false. + +chk_ActionRequest(A, A) -> + chk_type(fun is_ActionRequest/1, 'ActionRequest', A); +chk_ActionRequest(#'ActionRequest'{contextId = Id1, + contextRequest = Req1, + contextAttrAuditReq = AuditReq1, + commandRequests = CmdReqs1}, + #'ActionRequest'{contextId = Id2, + contextRequest = Req2, + contextAttrAuditReq = AuditReq2, + commandRequests = CmdReqs2}) -> + validate(fun() -> chk_ContextID(Id1, Id2) end, 'ActionRequest'), + validate(fun() -> chk_opt_ContextRequest(Req1, Req2) end, 'ActionRequest'), + validate(fun() -> + chk_opt_ContextAttrAuditRequest(AuditReq1, AuditReq2) + end, + 'ActionRequest'), + chk_ActionRequest_commandRequests(CmdReqs1, CmdReqs2), + ok. + + +is_ActionRequest_commandRequests([]) -> + d("is_ActionRequest_commandRequests -> entry when done"), + true; +is_ActionRequest_commandRequests([H|T]) -> + d("is_ActionRequest_commandRequests -> entry"), + is_CommandRequest(H) andalso is_ActionRequest_commandRequests(T); +is_ActionRequest_commandRequests(_) -> + false. + +chk_ActionRequest_commandRequests([], []) -> + ok; +chk_ActionRequest_commandRequests([] = CmdReqs1, CmdReqs2) -> + not_equal('ActionRequest_commandRequests', CmdReqs1, CmdReqs2); +chk_ActionRequest_commandRequests(CmdReqs1, [] = CmdReqs2) -> + not_equal('ActionRequest_commandRequests', CmdReqs1, CmdReqs2); +chk_ActionRequest_commandRequests([H|T1], [H|T2]) -> + case is_CommandRequest(H) of + true -> + chk_ActionRequest_commandRequests(T1, T2); + false -> + wrong_type('ActionRequest_commandRequest_val', H) + end; +chk_ActionRequest_commandRequests([H1|T1], [H2|T2]) -> + validate(fun() -> chk_CommandRequest(H1, H2) end, + 'ActionRequest_commandRequests_val'), + chk_ActionRequest_commandRequests(T1, T2); +chk_ActionRequest_commandRequests(R1, R2) -> + wrong_type('ActionRequest_commandRequests', R1, R2). + + +%% -- ActionReply -- + +is_ActionReply(#'ActionReply'{contextId = Id, + errorDescriptor = ED, + contextReply = CtxRep, + commandReply = CmdRep}) -> + d("is_ActionReply -> entry"), + is_ContextID(Id) andalso + is_opt_ErrorDescriptor(ED) andalso + is_opt_ContextRequest(CtxRep) andalso + is_ActionReply_commandReply(CmdRep); +is_ActionReply(_) -> + false. + +is_ActionReply_commandReply([]) -> + d("is_ActionReply_commandReply -> entry when done"), + true; +is_ActionReply_commandReply([H|T]) -> + d("is_ActionReply_commandReply -> entry"), + is_CommandReply(H) andalso is_ActionReply_commandReply(T); +is_ActionReply_commandReply(_) -> + false. + +chk_ActionReply(A, A) -> + chk_type(fun is_ActionReply/1, 'ActionReply', A); +chk_ActionReply(#'ActionReply'{contextId = Id1, + errorDescriptor = ED1, + contextReply = CtxRep1, + commandReply = CmdRep1}, + #'ActionReply'{contextId = Id2, + errorDescriptor = ED2, + contextReply = CtxRep2, + commandReply = CmdRep2}) -> + chk_ContextID(Id1, Id2), + chk_opt_ErrorDescriptor(ED1, ED2), + chk_opt_ContextRequest(CtxRep1, CtxRep2), + chk_ActionReply_commandReply(CmdRep1, CmdRep2). + +chk_ActionReply_commandReply([], []) -> + ok; +chk_ActionReply_commandReply([] = Reps1, Reps2) -> + not_equal('ActionReply_commandReply', Reps1, Reps2); +chk_ActionReply_commandReply(Reps1, [] = Reps2) -> + not_equal('ActionReply_commandReply', Reps1, Reps2); +chk_ActionReply_commandReply([H|T1], [H|T2]) -> + case is_CommandReply(H) of + true -> + chk_ActionReply_commandReply(T1, T2); + false -> + wrong_type('ActionReply_commandReply_val', H) + end; +chk_ActionReply_commandReply([H1|T1], [H2|T2]) -> + validate(fun() -> chk_CommandReply(H1, H2) end, + 'ActionReply_commandReply_val'), + chk_ActionReply_commandReply(T1, T2); +chk_ActionReply_commandReply(R1, R2) -> + wrong_type('ActionReply_commandReply', R1, R2). + + +%% -- ContextRequest -- + +is_opt_ContextRequest(V) -> + is_OPTIONAL(fun is_ContextRequest/1, V). + +is_ContextRequest(#'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = TopReq, + iepscallind = Ieps, + contextProp = Ctx}) -> + d("is_ContextRequest -> entry"), + is_ContextRequest_priority(Prio) andalso + is_ContextRequest_emergency(Em) andalso + is_ContextRequest_topologyReq(TopReq) andalso + is_ContextRequest_iepscallind(Ieps) andalso + is_ContextRequest_contextProp(Ctx); +is_ContextRequest(_) -> + false. + +is_ContextRequest_priority(asn1_NOVALUE) -> + true; +is_ContextRequest_priority(V) -> + is_INTEGER(V, {range, 1, 15}). + +is_ContextRequest_emergency(asn1_NOVALUE) -> + true; +is_ContextRequest_emergency(V) -> + is_BOOLEAN(V). + +is_ContextRequest_topologyReq(asn1_NOVALUE) -> + true; +is_ContextRequest_topologyReq([]) -> + true; +is_ContextRequest_topologyReq([H|T]) -> + is_TopologyRequest(H) andalso is_ContextRequest_topologyReq(T); +is_ContextRequest_topologyReq(_) -> + false. + +is_ContextRequest_iepscallind(asn1_NOVALUE) -> + true; +is_ContextRequest_iepscallind(V) -> + is_BOOLEAN(V). + +is_ContextRequest_contextProp(asn1_NOVALUE) -> + true; +is_ContextRequest_contextProp([]) -> + true; +is_ContextRequest_contextProp([H|T]) -> + is_PropertyParm(H) andalso is_ContextRequest_contextProp(T); +is_ContextRequest_contextProp(_) -> + false. + +chk_opt_ContextRequest(R1, R2) -> + chk_OPTIONAL('ContextRequest', R1, R2, + fun is_ContextRequest/1, fun chk_ContextRequest/2). + +chk_ContextRequest(R, R) -> + chk_type(fun is_ContextRequest/1, 'ContextRequest', R); +chk_ContextRequest(#'ContextRequest'{priority = Prio1, + emergency = Em1, + topologyReq = TopReq1, + iepscallind = Ieps1, + contextProp = Ctx1}, + #'ContextRequest'{priority = Prio2, + emergency = Em2, + topologyReq = TopReq2, + iepscallind = Ieps2, + contextProp = Ctx2}) -> + chk_ContextRequest_priority(Prio1, Prio2), + chk_ContextRequest_emergency(Em1, Em2), + chk_ContextRequest_topologyReq(TopReq1, TopReq2), + chk_ContextRequest_iepscallind(Ieps1, Ieps2), + chk_ContextRequest_contextProp(Ctx1, Ctx2), + ok; +chk_ContextRequest(R1, R2) -> + wrong_type('ContextRequest', R1, R2). + + +chk_ContextRequest_priority(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_ContextRequest_priority(P, P) -> + chk_type(fun is_ContextRequest_priority/1, 'ContextRequest_priority', P); +chk_ContextRequest_priority(P1, P2) -> + case (is_ContextRequest_priority(P1) andalso + is_ContextRequest_priority(P2)) of + true -> + not_equal('ContextRequest_priority', P1, P2); + false -> + wrong_type(contextRequest_priority, P1, P2) + end. + + +chk_ContextRequest_emergency(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_emergency(E, E) -> + chk_type(fun is_ContextRequest_emergency/1, 'ContextRequest_emergency', E); +chk_ContextRequest_emergency(E1, E2) -> + case (is_ContextRequest_emergency(E1) andalso + is_ContextRequest_emergency(E2)) of + true -> + not_equal('ContextRequest_emergency', E1, E2); + false -> + wrong_type('ContextRequest_emergency', E1, E2) + end. + +chk_ContextRequest_topologyReq(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_topologyReq([], []) -> + ok; +chk_ContextRequest_topologyReq([] = T1, T2) -> + not_equal('ContextRequest_topologyReq', T1, T2); +chk_ContextRequest_topologyReq(T1, [] = T2) -> + not_equal('ContextRequest_topologyReq', T1, T2); +chk_ContextRequest_topologyReq([H|T1], [H|T2]) -> + case is_TopologyRequest(H) of + true -> + chk_ContextRequest_topologyReq(T1, T2); + false -> + wrong_type('ContextRequest_topologyReq_val', H) + end; +chk_ContextRequest_topologyReq([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TopologyRequest(H1, H2) end, + 'ContextRequest_topologyReq_val'), + chk_ContextRequest_topologyReq(T1, T2); +chk_ContextRequest_topologyReq(T1, T2) -> + wrong_type('ContextRequest_topologyReq', T1, T2). + + +chk_ContextRequest_iepscallind(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_iepscallind(E, E) -> + chk_type(fun is_ContextRequest_iepscallind/1, + 'ContextRequest_iepscallind', E); +chk_ContextRequest_iepscallind(E1, E2) -> + case (is_ContextRequest_iepscallind(E1) andalso + is_ContextRequest_iepscallind(E2)) of + true -> + case (((E1 == false) and (E2 == asn1_NOVALUE)) or + ((E1 == asn1_NOVALUE) and (E2 == false))) of + true -> + ok; + false -> + not_equal('ContextRequest_iepscallind', E1, E2) + end; + + false -> + wrong_type('ContextRequest_iepscallind', E1, E2) + end. + +chk_ContextRequest_contextProp(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_contextProp([], []) -> + ok; +chk_ContextRequest_contextProp([] = T1, T2) -> + not_equal('ContextRequest_contextProp', T1, T2); +chk_ContextRequest_contextProp(T1, [] = T2) -> + not_equal('ContextRequest_contextProp', T1, T2); +chk_ContextRequest_contextProp([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_ContextRequest_contextProp(T1, T2); + false -> + wrong_type('ContextRequest_contextProp_val', H) + end; +chk_ContextRequest_contextProp([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, + 'ContextRequest_contextProp_val'), + chk_ContextRequest_contextProp(T1, T2); +chk_ContextRequest_contextProp(T1, T2) -> + wrong_type('ContextRequest_contextProp', T1, T2). + + +%% -- ContextAttrAuditRequest -- + +is_opt_ContextAttrAuditRequest(asn1_NOVALUE) -> + true; +is_opt_ContextAttrAuditRequest(V) -> + is_ContextAttrAuditRequest(V). + +is_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{topology = T, + emergency = E, + priority = P, + iepscallind = I, + contextPropAud = A}) -> + d("is_ContextAttrAuditRequest -> entry"), + is_opt_NULL(T) andalso + is_opt_NULL(E) andalso + is_opt_NULL(P) andalso + is_opt_NULL(I) andalso + is_ContextAttrAuditRequest_contextPropAud(A); +is_ContextAttrAuditRequest(_) -> + false. + +is_ContextAttrAuditRequest_contextPropAud(asn1_NOVALUE) -> + true; +is_ContextAttrAuditRequest_contextPropAud([]) -> + true; +is_ContextAttrAuditRequest_contextPropAud([H|T]) -> + d("is_ContextAttrAuditRequest_contextPropAud -> entry"), + is_IndAudPropertyParm(H) andalso + is_ContextAttrAuditRequest_contextPropAud(T). + +chk_opt_ContextAttrAuditRequest(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_ContextAttrAuditRequest(R1, R2) -> + chk_ContextAttrAuditRequest(R1, R2). + +chk_ContextAttrAuditRequest(R, R) -> + chk_type(fun is_ContextAttrAuditRequest/1, 'ContextAttrAuditRequest', R); +chk_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{topology = T1, + emergency = E1, + priority = P1, + iepscallind = I1, + contextPropAud = A1}, + #'ContextAttrAuditRequest'{topology = T2, + emergency = E2, + priority = P2, + iepscallind = I2, + contextPropAud = A2}) -> + validate(fun() -> chk_opt_NULL(T1, T2) end, + 'ContextAttrAuditRequest_topology'), + validate(fun() -> chk_opt_NULL(E1, E2) end, + 'ContextAttrAuditRequest_emergency'), + validate(fun() -> chk_opt_NULL(P1, P2) end, + 'ContextAttrAuditRequest_priority'), + validate(fun() -> chk_opt_NULL(I1, I2) end, + 'ContextAttrAuditRequest_iepscallind'), + chk_ContextAttrAuditRequest_contextPropAud(lists:sort(A1), + lists:sort(A2)), + ok. + +chk_ContextAttrAuditRequest_contextPropAud(A, A) -> + chk_type(fun is_ContextAttrAuditRequest_contextPropAud/1, + 'ContextAttrAuditRequest_contextPropAud', A); +chk_ContextAttrAuditRequest_contextPropAud([], []) -> + ok; +chk_ContextAttrAuditRequest_contextPropAud([] = T1, T2) -> + not_equal('ContextAttrAuditRequest_contextPropAud', T1, T2); +chk_ContextAttrAuditRequest_contextPropAud(T1, [] = T2) -> + not_equal('ContextAttrAuditRequest_contextPropAud', T1, T2); +chk_ContextAttrAuditRequest_contextPropAud([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_ContextAttrAuditRequest_contextPropAud(T1, T2); + false -> + wrong_type('ContextAttrAuditRequest_contextPropAud_val', H) + end; +chk_ContextAttrAuditRequest_contextPropAud([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, + 'ContextAttrAuditRequest_contextPropAud_val'), + chk_ContextAttrAuditRequest_contextPropAud(T1, T2); +chk_ContextAttrAuditRequest_contextPropAud(T1, T2) -> + wrong_type('ContextAttrAuditRequest_contextPropAud', T1, T2). + + +%% -- CommandRequest -- + +is_CommandRequest(#'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = WR}) -> + d("is_CommandRequest -> entry"), + is_Command(Cmd) andalso is_opt_NULL(Opt) andalso is_opt_NULL(WR); +is_CommandRequest(_) -> + false. + +chk_CommandRequest(C, C) -> + chk_type(fun is_CommandRequest/1, 'CommandRequest', C); +chk_CommandRequest(#'CommandRequest'{command = Cmd1, + optional = Opt1, + wildcardReturn = WR1}, + #'CommandRequest'{command = Cmd2, + optional = Opt2, + wildcardReturn = WR2}) -> + validate(fun() -> chk_Command(Cmd1, Cmd2) end, 'CommandRequest'), + validate(fun() -> chk_opt_NULL(Opt1, Opt2) end, 'CommandRequest'), + validate(fun() -> chk_opt_NULL(WR1, WR2) end, 'CommandRequest'), + ok; +chk_CommandRequest(R1, R2) -> + wrong_type('CommandRequest', R1, R2). + + +%% -- Command -- + +is_Command({Tag, Val}) -> + d("is_Command -> entry"), + is_Command_tag(Tag) andalso is_Command_val(Tag, Val); +is_Command(_) -> + false. + +is_Command_tag(Tag) -> + Tags = [addReq, moveReq, modReq, subtractReq, auditCapRequest, + auditValueRequest, notifyReq, serviceChangeReq], + lists:member(Tag, Tags). + +is_Command_val(addReq, V) -> is_AmmRequest(V); +is_Command_val(moveReq, V) -> is_AmmRequest(V); +is_Command_val(modReq, V) -> is_AmmRequest(V); +is_Command_val(subtractReq, V) -> is_SubtractRequest(V); +is_Command_val(auditCapRequest, V) -> is_AuditRequest(V); +is_Command_val(auditValueRequest, V) -> is_AuditRequest(V); +is_Command_val(notifyReq, V) -> is_NotifyRequest(V); +is_Command_val(serviceChangeReq, V) -> is_ServiceChangeRequest(V). + +chk_Command(Cmd, Cmd) -> + chk_type(fun is_Command/1, 'Command', Cmd); +chk_Command({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> + case (is_Command_tag(Tag) andalso + is_Command_val(Tag, Val1) andalso + is_Command_val(Tag, Val2)) of + true -> + chk_Command_val(Tag, Val1, Val2); + false -> + wrong_type('Command', Cmd1, Cmd2) + end; +chk_Command({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> + case ((is_Command_tag(Tag1) andalso is_Command_val(Tag1, Val1)) andalso + (is_Command_tag(Tag2) andalso is_Command_val(Tag2, Val2))) of + true -> + not_equal('Command', Cmd1, Cmd2); + false -> + wrong_type('Command', Cmd1, Cmd2) + end; +chk_Command(Cmd1, Cmd2) -> + wrong_type('Command', Cmd1, Cmd2). + + +chk_Command_val(addReq, R1, R2) -> + validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_addReq'); +chk_Command_val(moveReq, R1, R2) -> + validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_moveReq'); +chk_Command_val(modReq, R1, R2) -> + validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_modReq'); +chk_Command_val(subtractReq, R1, R2) -> + validate(fun() -> chk_SubtractRequest(R1, R2) end, 'Command_subtractReq'); +chk_Command_val(auditCapRequest, R1, R2) -> + validate(fun() -> chk_AuditRequest(R1, R2) end, 'Command_auditCapRequest'); +chk_Command_val(auditValueRequest, R1, R2) -> + validate(fun() -> chk_AuditRequest(R1, R2) end, + 'Command_auditValueRequest'); +chk_Command_val(notifyReq, R1, R2) -> + validate(fun() -> chk_NotifyRequest(R1, R2) end, 'Command_notifyReq'); +chk_Command_val(serviceChangeReq, R1, R2) -> + validate(fun() -> chk_ServiceChangeRequest(R1, R2) end, + 'Command_serviceChangeReq'). + + +%% -- CommandReply -- + +is_CommandReply({Tag, Val}) -> + d("is_CommandReply -> entry"), + is_CommandReply_tag(Tag) andalso is_CommandReply_val(Tag, Val); +is_CommandReply(_) -> + false. + +is_CommandReply_tag(Tag) -> + Tags = [addReply, moveReply, modReply, subtractReply, + auditCapReply, auditValueReply, notifyReply, serviceChangeReply], + lists:member(Tag, Tags). + +is_CommandReply_val(addReply, V) -> is_AmmsReply(V); +is_CommandReply_val(moveReply, V) -> is_AmmsReply(V); +is_CommandReply_val(modReply, V) -> is_AmmsReply(V); +is_CommandReply_val(subtractReply, V) -> is_AmmsReply(V); +is_CommandReply_val(auditCapReply, V) -> is_AuditReply(V); +is_CommandReply_val(auditValueReply, V) -> is_AuditReply(V); +is_CommandReply_val(notifyReply, V) -> is_NotifyReply(V); +is_CommandReply_val(serviceChangeReply, V) -> is_ServiceChangeReply(V). + +chk_CommandReply({Tag, Val} = Cmd, Cmd) -> + case (is_CommandReply_tag(Tag) andalso is_CommandReply_val(Tag, Val)) of + true -> + ok; + false -> + wrong_type('CommandReply', Cmd) + end; +chk_CommandReply({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> + case (is_CommandReply_tag(Tag) andalso + is_CommandReply_val(Tag, Val1) andalso + is_CommandReply_val(Tag, Val2)) of + true -> + chk_CommandReply_val(Tag, Val1, Val2); + false -> + wrong_type('CommandReply', Cmd1, Cmd2) + end; +chk_CommandReply({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> + case ((is_CommandReply_tag(Tag1) andalso + is_CommandReply_val(Tag1, Val1)) andalso + (is_CommandReply_tag(Tag2) andalso + is_CommandReply_val(Tag2, Val2))) of + true -> + not_equal('CommandReply', Cmd1, Cmd2); + false -> + wrong_type('CommandReply', Cmd1, Cmd2) + end; +chk_CommandReply(Cmd1, Cmd2) -> + wrong_type('CommandReply', Cmd1, Cmd2). + +chk_CommandReply_val(addReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_addReply'); +chk_CommandReply_val(moveReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_moveReply'); +chk_CommandReply_val(modReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_modReply'); +chk_CommandReply_val(subtractReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_subtractReply'); +chk_CommandReply_val(auditCapReply, V1, V2) -> + validate(fun() -> chk_AuditReply(V1, V2) end, + 'CommandReply_auditCapReply'); +chk_CommandReply_val(auditValueReply, V1, V2) -> + validate(fun() -> chk_AuditReply(V1, V2) end, + 'CommandReply_auditValueReply'); +chk_CommandReply_val(notifyReply, V1, V2) -> + validate(fun() -> chk_NotifyReply(V1, V2) end, 'CommandReply_notifyReply'); +chk_CommandReply_val(serviceChangeReply, V1, V2) -> + validate(fun() -> chk_ServiceChangeReply(V1, V2) end, + 'CommandReply_serviceChangeReply'). + + +%% -- TopologyRequest -- + +is_TopologyRequest(#'TopologyRequest'{terminationFrom = F, + terminationTo = T, + topologyDirection = D, + streamID = S}) -> + d("is_TopologyRequest -> entry"), + is_TerminationID(F) andalso + is_TerminationID(T) andalso + is_TopologyRequest_topologyDirection(D) andalso + is_opt_StreamID(S); +is_TopologyRequest(_) -> + false. + +is_TopologyRequest_topologyDirection(D) -> + lists:member(D, [bothway, isolate, oneway]). + + +chk_TopologyRequest(T, T) when is_record(T,'TopologyRequest') -> + ok; +chk_TopologyRequest(#'TopologyRequest'{terminationFrom = F1, + terminationTo = T1, + topologyDirection = D1, + streamID = S1}, + #'TopologyRequest'{terminationFrom = F2, + terminationTo = T2, + topologyDirection = D2, + streamID = S2}) -> + validate(fun() -> chk_TerminationID(F1, F2) end, + 'TopologyRequest_terminationFrom'), + validate(fun() -> chk_TerminationID(T1, T2) end, + 'TopologyRequest_terminationTo'), + chk_TopologyRequest_topologyDirection(D1,D2), + validate(fun() -> chk_StreamID(S1, S2) end, 'TopologyRequest_streamID'), + ok. + +chk_TopologyRequest_topologyDirection(D, D) -> + case is_TopologyRequest_topologyDirection(D) of + true -> + ok; + false -> + wrong_type('TopologyRequest_topologyDirection', D) + end; +chk_TopologyRequest_topologyDirection(D1, D2) -> + case (is_TopologyRequest_topologyDirection(D1) andalso + is_TopologyRequest_topologyDirection(D1)) of + true -> + not_equal('TopologyRequest_topologyDirection', D1, D2); + false -> + wrong_type('TopologyRequest_topologyDirection', D1, D2) + end. + + +%% -- AmmRequest -- + +is_AmmRequest(#'AmmRequest'{terminationID = Tids, + descriptors = Descs}) -> + d("is_AmmRequest -> entry with" + "~n Tids: ~p", [Tids]), + is_TerminationIDList(Tids) andalso is_AmmRequest_descriptors(Descs); +is_AmmRequest(_) -> + false. + +is_AmmRequest_descriptors(Descs) -> + d("is_AmmRequest_descriptors -> entry"), + is_AmmRequest_descriptors(Descs, []). + +is_AmmRequest_descriptors([], _) -> + true; +is_AmmRequest_descriptors([{Tag, _} = Desc|Descs], FoundDescs) -> + d("is_AmmRequest_descriptors -> entry with" + "~n Tag: ~p" + "~n FoundDescs: ~p", [Tag, FoundDescs]), + case lists:member(Tag, FoundDescs) of + true -> + atmost_once('AmmRequest_descriptors', Tag); + false -> + case is_AmmDescriptor(Desc) of + true -> + is_AmmRequest_descriptors(Descs, [Tag|FoundDescs]); + false -> + wrong_type('AmmRequest_descriptors', Desc) + end + end; +is_AmmRequest_descriptors(Descs, _) -> + d("is_AmmRequest_descriptors -> entry with WRONG TYPE" + "~n Descs: ~p", [Descs]), + wrong_type('AmmRequest_descriptors', Descs). + + +chk_AmmRequest(R, R) when is_record(R, 'AmmRequest') -> + d("chk_AmmRequest -> entry when equal"), + chk_type(fun is_AmmRequest/1, 'AmmRequest', R); +chk_AmmRequest(#'AmmRequest'{terminationID = Tids1, + descriptors = Descs1}, + #'AmmRequest'{terminationID = Tids2, + descriptors = Descs2}) -> + d("chk_AmmRequest -> entry with not equal" + "~n Tids1: ~p" + "~n Tids2: ~p", [Tids1, Tids2]), + validate( + fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'AmmRequest'), + validate( + fun() -> chk_AmmRequest_descriptors(Descs1, Descs2) end, + 'AmmRequest'), + ok. + + +chk_AmmRequest_descriptors([], []) -> + d("chk_AmmRequest_descriptors -> done when OK"), + ok; +chk_AmmRequest_descriptors([] = Descs1, Descs2) -> + d("chk_AmmRequest_descriptors -> done when NOT EQUAL:" + "~n Descs1: ~p" + "~n Descs1: ~p", [Descs1, Descs2]), + not_equal('AmmRequest_descriptors', Descs1, Descs2); +chk_AmmRequest_descriptors(Descs1, [] = Descs2) -> + d("chk_AmmRequest_descriptors -> done when NOT EQUAL:" + "~n Descs1: ~p" + "~n Descs1: ~p", [Descs1, Descs2]), + not_equal('AmmRequest_descriptors', Descs1, Descs2); +chk_AmmRequest_descriptors([H|T1], [H|T2]) -> + d("chk_AmmRequest_descriptors -> entry when equal"), + case is_AmmDescriptor(H) of + true -> + chk_AmmRequest_descriptors(T1, T2); + false -> + wrong_type('AmmRequest_descriptors_val', H) + end; +chk_AmmRequest_descriptors([H1|T1], [H2|T2]) -> + d("chk_AmmRequest_descriptors -> entry when not equal"), + validate(fun() -> chk_AmmDescriptor(H1, H2) end, + 'AmmRequest_descriptors_val'), + chk_AmmRequest_descriptors(T1, T2); +chk_AmmRequest_descriptors(Descs1, Descs2) -> + d("chk_AmmRequest_descriptors -> done when WRONG TYPE:" + "~n Descs1: ~p" + "~n Descs1: ~p", [Descs1, Descs2]), + wrong_type('AmmRequest_descriptors', Descs1, Descs2). + + +%% -- AmmDescriptor -- + +is_AmmDescriptor({Tag, Val}) -> + d("is_AmmDescriptor -> entry with" + "~n Tag: ~p" + "~n Val: ~p",[Tag, Val]), + is_AmmDescriptor_tag(Tag) andalso is_AmmDescriptor_val(Tag, Val); +is_AmmDescriptor(_) -> + false. + +is_AmmDescriptor_tag(Tag) -> + Tags = [mediaDescriptor, modemDescriptor, muxDescriptor, eventsDescriptor, + eventBufferDescriptor, signalsDescriptor, digitMapDescriptor, + auditDescriptor, statisticsDescriptor], + lists:member(Tag, Tags). + +is_AmmDescriptor_val(mediaDescriptor, D) -> + is_MediaDescriptor(D); +is_AmmDescriptor_val(modemDescriptor, D) -> + is_ModemDescriptor(D); +is_AmmDescriptor_val(muxDescriptor, D) -> + is_MuxDescriptor(D); +is_AmmDescriptor_val(eventsDescriptor, D) -> + is_EventsDescriptor(D); +is_AmmDescriptor_val(eventBufferDescriptor, D) -> + is_EventBufferDescriptor(D); +is_AmmDescriptor_val(signalsDescriptor, D) -> + is_SignalsDescriptor(D); +is_AmmDescriptor_val(digitMapDescriptor, D) -> + is_DigitMapDescriptor(D); +is_AmmDescriptor_val(auditDescriptor, D) -> + is_AuditDescriptor(D); +is_AmmDescriptor_val(statisticsDescriptor, D) -> + is_StatisticsDescriptor(D). + +chk_AmmDescriptor(D, D) -> + chk_type(fun is_AmmDescriptor_tag/1, 'AmmDescriptor', D); +chk_AmmDescriptor({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> + case (is_AmmDescriptor_tag(Tag) andalso + is_AmmDescriptor_val(Tag, Val1) andalso + is_AmmDescriptor_val(Tag, Val2)) of + true -> + chk_AmmDescriptor_val(Tag, Val1, Val2); + false -> + wrong_type('AmmDescriptor', Cmd1, Cmd2) + end; +chk_AmmDescriptor({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> + case ((is_AmmDescriptor_tag(Tag1) andalso + is_AmmDescriptor_val(Tag1, Val1)) andalso + (is_AmmDescriptor_tag(Tag2) andalso + is_AmmDescriptor_val(Tag2, Val2))) of + true -> + not_equal('AmmDescriptor', Cmd1, Cmd2); + false -> + wrong_type('AmmDescriptor', Cmd1, Cmd2) + end; +chk_AmmDescriptor(Cmd1, Cmd2) -> + wrong_type('AmmDescriptor', Cmd1, Cmd2). + +chk_AmmDescriptor_val(mediaDescriptor, D1, D2) -> + validate(fun() -> chk_MediaDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(modemDescriptor, D1, D2) -> + validate(fun() -> chk_ModemDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(muxDescriptor, D1, D2) -> + validate(fun() -> chk_MuxDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(eventsDescriptor, D1, D2) -> + validate(fun() -> chk_EventsDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(eventBufferDescriptor, D1, D2) -> + validate(fun() -> chk_EventBufferDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(signalsDescriptor, D1, D2) -> + validate(fun() -> chk_SignalsDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(digitMapDescriptor, D1, D2) -> + validate(fun() -> chk_DigitMapDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(auditDescriptor, D1, D2) -> + validate(fun() -> chk_AuditDescriptor(D1, D2) end, 'AmmDescriptor'). + + +%% -- AmmsReply -- + +is_AmmsReply(#'AmmsReply'{terminationID = Tids, + terminationAudit = TA}) -> + is_TerminationIDList(Tids) andalso is_opt_TerminationAudit(TA); +is_AmmsReply(_) -> + false. + +chk_AmmsReply(R, R) -> + is_AmmsReply(R); +chk_AmmsReply(#'AmmsReply'{terminationID = TID1, + terminationAudit = TA1}, + #'AmmsReply'{terminationID = TID2, + terminationAudit = TA2}) -> + validate(fun() -> chk_TerminationIDList(TID1, TID2) end, 'AmmsReply'), + validate(fun() -> chk_opt_TerminationAudit(TA1, TA2) end, 'AmmsReply'), + ok; +chk_AmmsReply(R1, R2) -> + wrong_type('AmmsReply', R1, R2). + + +%% -- SubtractRequest -- + +is_SubtractRequest(#'SubtractRequest'{terminationID = Tids, + auditDescriptor = AD}) -> + is_TerminationIDList(Tids) andalso is_opt_AuditDescriptor(AD); +is_SubtractRequest(_) -> + false. + +chk_SubtractRequest(R, R) -> + chk_type(fun is_SubtractRequest/1, 'SubtractRequest', R); +chk_SubtractRequest(#'SubtractRequest'{terminationID = Tids1, + auditDescriptor = AD1}, + #'SubtractRequest'{terminationID = Tids2, + auditDescriptor = AD2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'SubtractRequest'), + validate(fun() -> chk_opt_AuditDescriptor(AD1, AD2) end, + 'SubtractRequest'), + ok; +chk_SubtractRequest(SR1, SR2) -> + wrong_type('SubtractRequest', SR1, SR2). + + +%% -- AuditRequest -- + +is_AuditRequest(#'AuditRequest'{terminationID = Tid, + auditDescriptor = AD}) -> + is_TerminationID(Tid) andalso is_AuditDescriptor(AD); +is_AuditRequest(_) -> + false. + +chk_AuditRequest(R, R) -> + chk_type(fun is_AuditRequest/1, 'AuditRequest', R); +chk_AuditRequest(#'AuditRequest'{terminationID = Tids1, + auditDescriptor = AD1}, + #'AuditRequest'{terminationID = Tids2, + auditDescriptor = AD2}) -> + validate(fun() -> chk_TerminationID(Tids1, Tids2) end, + 'AuditRequest'), + validate(fun() -> chk_AuditDescriptor(AD1, AD2) end, + 'AuditRequest'), + ok; +chk_AuditRequest(AR1, AR2) -> + wrong_type('AuditRequest', AR1, AR2). + + +%% -- AuditReply -- + +is_AuditReply({Tag, Val}) -> + is_AuditReply_tag(Tag) andalso is_AuditReply_val(Tag, Val); +is_AuditReply(_) -> + false. + +is_AuditReply_tag(Tag) -> + Tags = [contextAuditResult, error, auditResult], + lists:member(Tag, Tags). + +is_AuditReply_val(contextAuditResult, Val) -> + is_TerminationIDList(Val); +is_AuditReply_val(error, Val) -> + is_ErrorDescriptor(Val); +is_AuditReply_val(auditResult, Val) -> + is_AuditResult(Val). + +chk_AuditReply(R, R) -> + chk_type(fun is_AuditReply/1, 'AuditReply', R); +chk_AuditReply({Tag, Val1} = R1, {Tag, Val2} = R2) -> + case (is_AuditReply_tag(Tag) andalso + is_AuditReply_val(Tag, Val1)andalso + is_AuditReply_val(Tag, Val2)) of + true -> + chk_AuditReply_val(Tag, Val1, Val2); + false -> + wrong_type('AuditReply', R1, R2) + end; +chk_AuditReply({Tag1, Val1} = R1, {Tag2, Val2} = R2) -> + case ((is_AuditReply_tag(Tag1) andalso + is_AuditReply_val(Tag1, Val1)) andalso + (is_AuditReply_tag(Tag2) andalso + is_AuditReply_val(Tag2, Val2))) of + true -> + not_equal('AuditReply', R1, R2); + false -> + wrong_type('AuditReply', R1, R2) + end; +chk_AuditReply(AR1, AR2) -> + wrong_type('AuditReply', AR1, AR2). + +chk_AuditReply_val(contextAuditResult, Val1, Val2) -> + chk_TerminationIDList(Val1, Val2); +chk_AuditReply_val(error, Val1, Val2) -> + chk_ErrorDescriptor(Val1, Val2); +chk_AuditReply_val(auditResult, Val1, Val2) -> + chk_AuditResult(Val1, Val2). + + +%% -- AuditResult -- + +is_AuditResult(#'AuditResult'{terminationID = TID, + terminationAuditResult = TAR}) -> + is_TerminationID(TID) andalso is_TerminationAudit(TAR); +is_AuditResult(_) -> + false. + +chk_AuditResult(R, R) -> + chk_type(fun is_AuditResult/1, 'AuditResult', R); +chk_AuditResult(#'AuditResult'{terminationID = TID1, + terminationAuditResult = TAR1}, + #'AuditResult'{terminationID = TID2, + terminationAuditResult = TAR2}) -> + validate(fun() -> chk_TerminationID(TID1, TID2) end, 'AuditResult'), + validate(fun() -> chk_TerminationAudit(TAR1, TAR2) end, 'AuditResult'), + ok; +chk_AuditResult(AR1, AR2) -> + wrong_type('AuditResult', AR1, AR2). + + +%% -- TerminationAudit -- + +is_opt_TerminationAudit(TA) -> + is_OPTIONAL(fun is_TerminationAudit/1, TA). + +is_TerminationAudit([]) -> + true; +is_TerminationAudit([H|T]) -> + is_AuditReturnParameter(H) andalso is_TerminationAudit(T); +is_TerminationAudit(_) -> + false. + +chk_opt_TerminationAudit(TA1, TA2) -> + chk_OPTIONAL('TerminationAudit', TA1, TA2, + fun is_TerminationAudit/1, fun chk_TerminationAudit/2). + +chk_TerminationAudit([], []) -> + ok; +chk_TerminationAudit([] = TA1, TA2) -> + not_equal('TerminationAudit', TA1, TA2); +chk_TerminationAudit(TA1, [] = TA2) -> + not_equal('TerminationAudit', TA1, TA2); +chk_TerminationAudit([H|T1], [H|T2]) -> + case is_AuditReturnParameter(H) of + true -> + chk_TerminationAudit(T1, T2); + false -> + wrong_type('TerminationAudit', H) + end; +chk_TerminationAudit([H1|_], [H2|_]) -> + chk_AuditReturnParameter(H1, H2), + not_equal('TerminationAudit_val', H1, H2); +chk_TerminationAudit(TA1, TA2) -> + not_equal('TerminationAudit', TA1, TA2). + + +%% -- AuditReturnParameter -- + +is_AuditReturnParameter({Tag, Val}) -> + is_AuditReturnParameter_tag(Tag) andalso + is_AuditReturnParameter_val(Tag, Val); +is_AuditReturnParameter(_) -> + false. + +is_AuditReturnParameter_tag(Tag) -> + Tags = [errorDescriptor, + mediaDescriptor, + modemDescriptor, + muxDescriptor, + eventsDescriptor, + eventBufferDescriptor, + signalsDescriptor, + digitMapDescriptor, + observedEventsDescriptor, + statisticsDescriptor, + packagesDescriptor, + emptyDescriptors], + lists:member(Tag, Tags). + +is_AuditReturnParameter_val(errorDescriptor, V) -> + is_ErrorDescriptor(V); +is_AuditReturnParameter_val(mediaDescriptor, V) -> + is_MediaDescriptor(V); +is_AuditReturnParameter_val(modemDescriptor, V) -> + is_ModemDescriptor(V); +is_AuditReturnParameter_val(muxDescriptor, V) -> + is_MuxDescriptor(V); +is_AuditReturnParameter_val(eventsDescriptor, V) -> + is_EventsDescriptor(V); +is_AuditReturnParameter_val(eventBufferDescriptor, V) -> + is_EventBufferDescriptor(V); +is_AuditReturnParameter_val(signalsDescriptor, V) -> + is_SignalsDescriptor(V); +is_AuditReturnParameter_val(digitMapDescriptor, V) -> + is_DigitMapDescriptor(V); +is_AuditReturnParameter_val(observedEventsDescriptor, V) -> + is_ObservedEventsDescriptor(V); +is_AuditReturnParameter_val(statisticsDescriptor, V) -> + is_StatisticsDescriptor(V); +is_AuditReturnParameter_val(packagesDescriptor, V) -> + is_PackagesDescriptor(V); +is_AuditReturnParameter_val(emptyDescriptors, V) -> + is_AuditDescriptor(V). + +chk_AuditReturnParameter(ARP, ARP) -> + chk_type(fun is_AuditReturnParameter/1, 'AuditReturnParameter', ARP); +chk_AuditReturnParameter({Tag, Val1} = ARP1, {Tag, Val2} = ARP2) -> + case (is_AuditReturnParameter_tag(Tag) andalso + is_AuditReturnParameter_val(Tag, Val1) andalso + is_AuditReturnParameter_val(Tag, Val2)) of + true -> + chk_AuditReturnParameter_val(Tag, Val1, Val2); + false -> + wrong_type('AuditReturnParameter', ARP1, ARP2) + end; +chk_AuditReturnParameter({Tag1, Val1} = ARP1, {Tag2, Val2} = ARP2) -> + case ((is_AuditReturnParameter_tag(Tag1) andalso + is_AuditReturnParameter_val(Tag1, Val1)) andalso + (is_AuditReturnParameter_tag(Tag2) andalso + is_AuditReturnParameter_val(Tag2, Val2))) of + true -> + not_equal('AuditReturnParameter', ARP1, ARP2); + false -> + wrong_type('AuditReturnParameter', ARP1, ARP2) + end; +chk_AuditReturnParameter(ARP1, ARP2) -> + wrong_type('AuditReturnParameter', ARP1, ARP2). + +chk_AuditReturnParameter_val(errorDescriptor, V1, V2) -> + validate(fun() -> chk_ErrorDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(mediaDescriptor, V1, V2) -> + validate(fun() -> chk_MediaDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(modemDescriptor, V1, V2) -> + validate(fun() -> chk_ModemDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(muxDescriptor, V1, V2) -> + validate(fun() -> chk_MuxDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(eventsDescriptor, V1, V2) -> + validate(fun() -> chk_EventsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(eventBufferDescriptor, V1, V2) -> + validate(fun() -> chk_EventBufferDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(signalsDescriptor, V1, V2) -> + validate(fun() -> chk_SignalsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(digitMapDescriptor, V1, V2) -> + validate(fun() -> chk_DigitMapDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(observedEventsDescriptor, V1, V2) -> + validate(fun() -> chk_ObservedEventsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(statisticsDescriptor, V1, V2) -> + validate(fun() -> chk_StatisticsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(packagesDescriptor, V1, V2) -> + validate(fun() -> chk_PackagesDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(emptyDescriptors, V1, V2) -> + validate(fun() -> chk_AuditDescriptor(V1, V2) end, + 'AuditReturnParameter'). + + +%% -- AuditDescriptor -- + +is_opt_AuditDescriptor(asn1_NOVALUE) -> + true; +is_opt_AuditDescriptor(V) -> + is_AuditDescriptor(V). + +is_AuditDescriptor(#'AuditDescriptor'{auditToken = AT, + auditPropertyToken = APT}) -> + is_AuditDescriptor_auditToken(AT) andalso + is_AuditDescriptor_auditPropertyToken(APT); +is_AuditDescriptor(_) -> + false. + +is_AuditDescriptor_auditToken(asn1_NOVALUE) -> + true; +is_AuditDescriptor_auditToken([]) -> + true; +is_AuditDescriptor_auditToken([H|T]) -> + is_AuditDescriptor_auditToken_val(H) andalso + is_AuditDescriptor_auditToken(T); +is_AuditDescriptor_auditToken(_) -> + false. + +is_AuditDescriptor_auditToken_val(V) -> + Toks = [muxToken, modemToken, mediaToken, eventsToken, signalsToken, + digitMapToken, statsToken, observedEventsToken, + packagesToken, eventBufferToken], + lists:member(V, Toks). + +is_AuditDescriptor_auditPropertyToken(asn1_NOVALUE) -> + true; +is_AuditDescriptor_auditPropertyToken([]) -> + true; +is_AuditDescriptor_auditPropertyToken([H|T]) -> + is_IndAuditParameter(H) andalso is_AuditDescriptor_auditPropertyToken(T); +is_AuditDescriptor_auditPropertyToken(_) -> + false. + +chk_opt_AuditDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_AuditDescriptor(AD1, AD2) -> + chk_AuditDescriptor(AD1, AD2). + +chk_AuditDescriptor(AD, AD) -> + chk_type(fun is_AuditDescriptor/1, 'AuditDescriptor', AD); +chk_AuditDescriptor(#'AuditDescriptor'{auditToken = AT1, + auditPropertyToken = APT1}, + #'AuditDescriptor'{auditToken = AT2, + auditPropertyToken = APT2}) -> + chk_AuditDescriptor_auditToken(AT1, AT2), + chk_AuditDescriptor_auditPropertyToken(APT1, APT2), + ok; +chk_AuditDescriptor(AD1, AD2) -> + wrong_type('AuditDescriptor', AD1, AD2). + +chk_AuditDescriptor_auditToken(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_AuditDescriptor_auditToken([], []) -> + ok; +chk_AuditDescriptor_auditToken([] = AT1, AT2) -> + not_equal('AuditDescriptor_auditToken', AT1, AT2); +chk_AuditDescriptor_auditToken(AT1, [] = AT2) -> + not_equal('AuditDescriptor_auditToken', AT1, AT2); +chk_AuditDescriptor_auditToken([H|T1], [H|T2]) -> + case is_AuditDescriptor_auditToken_val(H) of + true -> + chk_AuditDescriptor_auditToken(T1, T2); + false -> + wrong_type('AuditDescriptor_auditToken_val', H) + end; +chk_AuditDescriptor_auditToken([H1|_T1], [H2|_T2]) -> + case (is_AuditDescriptor_auditToken_val(H1) andalso + is_AuditDescriptor_auditToken_val(H2)) of + true -> + not_equal('AuditDescriptor_auditToken_val', H1, H2); + false -> + wrong_type('AuditDescriptor_auditToken_val', H1, H2) + end; +chk_AuditDescriptor_auditToken(AT1, AT2) -> + wrong_type('AuditDescriptor_auditToken', AT1, AT2). + +chk_AuditDescriptor_auditPropertyToken(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_AuditDescriptor_auditPropertyToken([], []) -> + ok; +chk_AuditDescriptor_auditPropertyToken([] = AT1, AT2) -> + not_equal('AuditDescriptor_auditPropertyToken', AT1, AT2); +chk_AuditDescriptor_auditPropertyToken(AT1, [] = AT2) -> + not_equal('AuditDescriptor_auditPropertyToken', AT1, AT2); +chk_AuditDescriptor_auditPropertyToken([H|T1], [H|T2]) -> + case is_IndAuditParameter(H) of + true -> + chk_AuditDescriptor_auditPropertyToken(T1, T2); + false -> + wrong_type('AuditDescriptor_auditPropertyToken_val', H) + end; +chk_AuditDescriptor_auditPropertyToken([H1|_], [H2|_]) -> + chk_IndAuditParameter(H1, H2), + not_equal('AuditDescriptor_auditPropertyToken_val', H1, H2); +chk_AuditDescriptor_auditPropertyToken(AT1, AT2) -> + wrong_type('AuditDescriptor_auditPropertyToken', AT1, AT2). + + +%% -- IndAuditParameter -- + +is_IndAuditParameter({Tag, Val}) -> + is_IndAuditParameter_tag(Tag) andalso is_IndAuditParameter_val(Tag, Val); +is_IndAuditParameter(_) -> + false. + +is_IndAuditParameter_tag(Tag) -> + Tags = [indAudMediaDescriptor, + indAudEventsDescriptor, + indAudEventBufferDescriptor, + indAudSignalsDescriptor, + indAudDigitMapDescriptor, + indAudStatisticsDescriptor, + indAudPackagesDescriptor], + lists:member(Tag, Tags). + +is_IndAuditParameter_val(indAudMediaDescriptor, Val) -> + is_IndAudMediaDescriptor(Val); +is_IndAuditParameter_val(indAudEventsDescriptor, Val) -> + is_IndAudEventsDescriptor(Val); +is_IndAuditParameter_val(indAudEventBufferDescriptor, Val) -> + is_IndAudEventBufferDescriptor(Val); +is_IndAuditParameter_val(indAudSignalsDescriptor, Val) -> + is_IndAudSignalsDescriptor(Val); +is_IndAuditParameter_val(indAudDigitMapDescriptor, Val) -> + is_IndAudDigitMapDescriptor(Val); +is_IndAuditParameter_val(indAudStatisticsDescriptor, Val) -> + is_IndAudStatisticsDescriptor(Val); +is_IndAuditParameter_val(indAudPackagesDescriptor, Val) -> + is_IndAudPackagesDescriptor(Val). + +chk_IndAuditParameter(IAP, IAP) -> + chk_type(fun is_IndAuditParameter/1, 'IndAuditParameter', IAP); +chk_IndAuditParameter({Tag, Val1} = IAP1, {Tag, Val2} = IAP2) -> + case (is_IndAuditParameter_tag(Tag) andalso + is_IndAuditParameter_val(Tag, Val1) andalso + is_IndAuditParameter_val(Tag, Val2)) of + true -> + chk_IndAuditParameter_val(Tag, Val1, Val2); + false -> + wrong_type('IndAuditParameter', IAP1, IAP2) + end; +chk_IndAuditParameter({Tag1, Val1} = IAP1, {Tag2, Val2} = IAP2) -> + case ((is_IndAuditParameter_tag(Tag1) andalso + is_IndAuditParameter_val(Tag1, Val1)) andalso + (is_IndAuditParameter_tag(Tag2) andalso + is_IndAuditParameter_val(Tag2, Val2))) of + true -> + not_equal('IndAuditParameter', IAP1, IAP2); + false -> + wrong_type('IndAuditParameter', IAP1, IAP2) + end; +chk_IndAuditParameter(IAP1, IAP2) -> + wrong_type('IndAuditParameter', IAP1, IAP2). + +chk_IndAuditParameter_val(indAudMediaDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudMediaDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudEventsDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudEventsDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudEventBufferDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudEventBufferDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudSignalsDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudSignalsDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudDigitMapDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudDigitMapDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudStatisticsDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudStatisticsDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudPackagesDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudPackagesDescriptor(Val1, Val2) end, + 'IndAuditParameter'). + + +%% -- IndAudMediaDescriptor -- + +is_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = S}) -> + is_opt_IndAudTerminationStateDescriptor(TSD) andalso + is_IndAudMediaDescriptor_streams(S); +is_IndAudMediaDescriptor(_) -> + false. + +is_IndAudMediaDescriptor_streams(asn1_NOVALUE) -> + true; +is_IndAudMediaDescriptor_streams({Tag, Val}) -> + is_IndAudMediaDescriptor_streams_tag(Tag) andalso + is_IndAudMediaDescriptor_streams_val(Tag, Val); +is_IndAudMediaDescriptor_streams(_) -> + false. + +is_IndAudMediaDescriptor_streams_tag(Tag) -> + Tags = [oneStream, multiStream], + lists:member(Tag, Tags). + +is_IndAudMediaDescriptor_streams_val(oneStream, Val) -> + is_IndAudStreamParms(Val); +is_IndAudMediaDescriptor_streams_val(multiStream, Val) -> + is_IndAudMediaDescriptor_multiStream(Val). + +is_IndAudMediaDescriptor_multiStream([]) -> + true; +is_IndAudMediaDescriptor_multiStream([H|T]) -> + is_IndAudStreamDescriptor(H) andalso + is_IndAudMediaDescriptor_multiStream(T); +is_IndAudMediaDescriptor_multiStream(_) -> + false. + +chk_IndAudMediaDescriptor(IAMD, IAMD) -> + chk_type(fun is_IndAudMediaDescriptor/1, 'IndAudMediaDescriptor', IAMD); +chk_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD1, + streams = S1}, + #'IndAudMediaDescriptor'{termStateDescr = TSD2, + streams = S2}) -> + validate(fun() -> chk_opt_IndAudTerminationStateDescriptor(TSD1, TSD2) end, + 'IndAudMediaDescriptor'), + validate(fun() -> chk_IndAudMediaDescriptor_streams(S1, S2) end, + 'IndAudMediaDescriptor'), + ok; +chk_IndAudMediaDescriptor(IAMD1, IAMD2) -> + wrong_type('IndAudMediaDescriptor', IAMD1, IAMD2). + +chk_IndAudMediaDescriptor_streams(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_IndAudMediaDescriptor_streams({Tag, Val1} = S1, + {Tag, Val2} = S2) -> + case (is_IndAudMediaDescriptor_streams_tag(Tag) andalso + is_IndAudMediaDescriptor_streams_val(Tag, Val1) andalso + is_IndAudMediaDescriptor_streams_val(Tag, Val2)) of + true -> + chk_IndAudMediaDescriptor_streams_val(Tag, Val1, Val2); + false -> + wrong_type('IndAudMediaDescriptor_streams', S1, S2) + end; +chk_IndAudMediaDescriptor_streams({Tag1, Val1} = S1, + {Tag2, Val2} = S2) -> + case ((is_IndAudMediaDescriptor_streams_tag(Tag1) andalso + is_IndAudMediaDescriptor_streams_val(Tag1, Val1)) andalso + (is_IndAudMediaDescriptor_streams_tag(Tag2) andalso + is_IndAudMediaDescriptor_streams_val(Tag2, Val2))) of + true -> + not_equal('IndAudMediaDescriptor_streams', S1, S2); + false -> + wrong_type('IndAudMediaDescriptor_streams', S1, S2) + end; +chk_IndAudMediaDescriptor_streams(S1, S2) -> + wrong_type('IndAudMediaDescriptor_streams', S1, S2). + +chk_IndAudMediaDescriptor_streams_val(oneStream, Val1, Val2) -> + validate(fun() -> chk_IndAudStreamParms(Val1, Val2) end, + 'IndAudMediaDescriptor_streams'); +chk_IndAudMediaDescriptor_streams_val(multiStream, Val1, Val2) -> + validate(fun() -> chk_IndAudMediaDescriptor_multiStream(Val1, Val2) end, + 'IndAudMediaDescriptor_streams'). + +chk_IndAudMediaDescriptor_multiStream([], []) -> + ok; +chk_IndAudMediaDescriptor_multiStream([] = MS1, MS2) -> + not_equal('IndAudMediaDescriptor_multiStream', MS1, MS2); +chk_IndAudMediaDescriptor_multiStream(MS1, [] = MS2) -> + not_equal('IndAudMediaDescriptor_multiStream', MS1, MS2); +chk_IndAudMediaDescriptor_multiStream([H|T1], [H|T2]) -> + case is_IndAudStreamDescriptor(H) of + true -> + chk_IndAudMediaDescriptor_multiStream(T1, T2); + false -> + wrong_type('IndAudMediaDescriptor_multiStream_val', H) + end; +chk_IndAudMediaDescriptor_multiStream([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudStreamDescriptor(H1, H2) end, + 'IndAudMediaDescriptor_multiStream_val'), + chk_IndAudMediaDescriptor_multiStream(T1, T2); +chk_IndAudMediaDescriptor_multiStream(MS1, MS2) -> + wrong_type('IndAudMediaDescriptor_multiStream', MS1, MS2). + + +%% -- IndAudStreamDescriptor -- + +is_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID, + streamParms = Parms}) -> + is_StreamID(SID) andalso is_IndAudStreamParms(Parms); +is_IndAudStreamDescriptor(_) -> + false. + +chk_IndAudStreamDescriptor(D, D) -> + chk_type(fun is_IndAudStreamDescriptor/1, 'IndAudStreamDescriptor', D); +chk_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID1, + streamParms = Parms1}, + #'IndAudStreamDescriptor'{streamID = SID2, + streamParms = Parms2}) -> + validate(fun() -> chk_StreamID(SID1, SID2) end, 'IndAudStreamDescriptor'), + validate(fun() -> chk_IndAudStreamParms(Parms1, Parms2) end, + 'IndAudStreamDescriptor'), + ok; +chk_IndAudStreamDescriptor(D1, D2) -> + wrong_type('IndAudStreamDescriptor', D1, D2). + + +%% -- IndAudStreamParms -- + +is_IndAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD}) -> + is_opt_IndAudLocalControlDescriptor(LCD) andalso + is_opt_IndAudLocalRemoteDescriptor(LD) andalso + is_opt_IndAudLocalRemoteDescriptor(RD); +is_IndAudStreamParms(_) -> + false. + +chk_IndAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD1, + localDescriptor = LD1, + remoteDescriptor = RD1}, + #'IndAudStreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2}) -> + validate(fun() -> chk_opt_IndAudLocalControlDescriptor(LCD1, LCD2) end, + 'IndAudStreamParms'), + validate(fun() -> chk_opt_IndAudLocalRemoteDescriptor(LD1, LD2) end, + 'IndAudStreamParms'), + validate(fun() -> chk_opt_IndAudLocalRemoteDescriptor(RD1, RD2) end, + 'IndAudStreamParms'), + ok; +chk_IndAudStreamParms(D1, D2) -> + wrong_type('IndAudStreamParms', D1, D2). + + +%% -- IndAudLocalControlDescriptor -- + +is_opt_IndAudLocalControlDescriptor(asn1_NOVALUE) -> + true; +is_opt_IndAudLocalControlDescriptor(D) -> + is_IndAudLocalControlDescriptor(D). + +is_IndAudLocalControlDescriptor( + #'IndAudLocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PPs}) -> + is_opt_NULL(SM) andalso is_opt_NULL(RV) andalso is_opt_NULL(RG) andalso + is_IndAudLocalControlDescriptor_propertyParms(PPs); +is_IndAudLocalControlDescriptor(_) -> + false. + +is_IndAudLocalControlDescriptor_propertyParms(asn1_NOVALUE) -> + true; +is_IndAudLocalControlDescriptor_propertyParms([]) -> + true; +is_IndAudLocalControlDescriptor_propertyParms([H|T]) -> + is_IndAudPropertyParm(H) andalso + is_IndAudLocalControlDescriptor_propertyParms(T); +is_IndAudLocalControlDescriptor_propertyParms(_) -> + false. + +chk_opt_IndAudLocalControlDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudLocalControlDescriptor( + #'IndAudLocalControlDescriptor'{streamMode = SM1, + reserveValue = RV1, + reserveGroup = RG1, + propertyParms = PPs1}, + #'IndAudLocalControlDescriptor'{streamMode = SM2, + reserveValue = RV2, + reserveGroup = RG2, + propertyParms = PPs2}) -> + chk_opt_NULL(SM1, SM2), + chk_opt_NULL(RV1, RV2), + chk_opt_NULL(RG1, RG2), + chk_IndAudLocalControlDescriptor_propertyParms(PPs1, PPs2), + ok; +chk_opt_IndAudLocalControlDescriptor(D1, D2) -> + wrong_type('IndAudLocalControlDescriptor', D1, D2). + +chk_IndAudLocalControlDescriptor_propertyParms(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_IndAudLocalControlDescriptor_propertyParms([], []) -> + ok; +chk_IndAudLocalControlDescriptor_propertyParms([] = PPs1, PPs2) -> + not_equal('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2); +chk_IndAudLocalControlDescriptor_propertyParms(PPs1, [] = PPs2) -> + not_equal('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2); +chk_IndAudLocalControlDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_IndAudLocalControlDescriptor_propertyParms(T1, T2); + false -> + wrong_type('IndAudLocalControlDescriptor_propertyParms_val', H) + end; +chk_IndAudLocalControlDescriptor_propertyParms([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, + 'IndAudLocalControlDescriptor_propertyParms_val'), + chk_IndAudLocalControlDescriptor_propertyParms(T1, T2); +chk_IndAudLocalControlDescriptor_propertyParms(PPs1, PPs2) -> + wrong_type('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2). + + +%% -- IndAudPropertyParm -- + +is_IndAudPropertyParm(#'IndAudPropertyParm'{name = Name}) -> + d("is_IndAudPropertyParm -> entry"), + is_PkgdName(Name); +is_IndAudPropertyParm(_) -> + false. + +chk_IndAudPropertyParm(#'IndAudPropertyParm'{name = Name1}, + #'IndAudPropertyParm'{name = Name2}) -> + chk_PkgdName(Name1, Name2), + ok; +chk_IndAudPropertyParm(P1, P2) -> + wrong_type('IndAudPropertyParm', P1, P2). + + +%% -- IndAudLocalRemoteDescriptor -- + +is_opt_IndAudLocalRemoteDescriptor(asn1_NOVALUE) -> + true; +is_opt_IndAudLocalRemoteDescriptor(D) -> + is_IndAudLocalRemoteDescriptor(D). + +is_IndAudLocalRemoteDescriptor( + #'IndAudLocalRemoteDescriptor'{propGroupID = ID, + propGrps = Grps}) -> + is_IndAudLocalRemoteDescriptor_propGroupID(ID) andalso + is_IndAudPropertyGroup(Grps); +is_IndAudLocalRemoteDescriptor(_) -> + false. + +is_IndAudLocalRemoteDescriptor_propGroupID(asn1_NOVALUE) -> + true; +is_IndAudLocalRemoteDescriptor_propGroupID(V) -> + is_INTEGER(V, {range, 0, 65535}). + +chk_opt_IndAudLocalRemoteDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudLocalRemoteDescriptor(D1, D2) -> + chk_IndAudLocalRemoteDescriptor(D1, D2). + +chk_IndAudLocalRemoteDescriptor(D, D) -> + chk_type(fun is_IndAudLocalRemoteDescriptor/1, + 'IndAudLocalRemoteDescriptor', D); +chk_IndAudLocalRemoteDescriptor( + #'IndAudLocalRemoteDescriptor'{propGroupID = ID1, + propGrps = Grps1}, + #'IndAudLocalRemoteDescriptor'{propGroupID = ID2, + propGrps = Grps2}) -> + chk_IndAudLocalRemoteDescriptor_propGroupID(ID1, ID2), + chk_IndAudPropertyGroup(Grps1, Grps2), + ok; +chk_IndAudLocalRemoteDescriptor(D1, D2) -> + wrong_type('IndAudLocalRemoteDescriptor', D1, D2). + +chk_IndAudLocalRemoteDescriptor_propGroupID(ID, ID) -> + chk_type(fun is_IndAudLocalRemoteDescriptor_propGroupID/1, + 'IndAudLocalRemoteDescriptor_propGroupID', ID); +chk_IndAudLocalRemoteDescriptor_propGroupID(ID1, ID2) -> + case (is_IndAudLocalRemoteDescriptor_propGroupID(ID1) andalso + is_IndAudLocalRemoteDescriptor_propGroupID(ID2)) of + true -> + not_equal('IndAudLocalRemoteDescriptor_propGroupID', ID1, ID2); + false -> + wrong_type('IndAudLocalRemoteDescriptor_propGroupID', ID1, ID2) + end. + + +%% -- IndAudPropertyGroup -- + +is_IndAudPropertyGroup([]) -> + true; +is_IndAudPropertyGroup([H|T]) -> + is_IndAudPropertyParm(H) andalso is_IndAudPropertyGroup(T); +is_IndAudPropertyGroup(_) -> + false. + +chk_IndAudPropertyGroup([], []) -> + ok; +chk_IndAudPropertyGroup([] = PG1, PG2) -> + not_equal('IndAudPropertyGroup', PG1, PG2); +chk_IndAudPropertyGroup(PG1, [] = PG2) -> + not_equal('IndAudPropertyGroup', PG1, PG2); +chk_IndAudPropertyGroup([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_IndAudPropertyGroup(T1, T2); + false -> + wrong_type('IndAudPropertyGroup_val', H) + end; +chk_IndAudPropertyGroup([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, + 'IndAudPropertyGroup_val'), + chk_IndAudPropertyGroup(T1, T2); +chk_IndAudPropertyGroup(P1, P2) -> + wrong_type('IndAudPropertyGroup', P1, P2). + + +%% -- IndAudTerminationStateDescriptor -- + +is_opt_IndAudTerminationStateDescriptor(asn1_NOVALUE) -> + true; +is_opt_IndAudTerminationStateDescriptor(D) -> + is_IndAudTerminationStateDescriptor(D). + +is_IndAudTerminationStateDescriptor( + #'IndAudTerminationStateDescriptor'{propertyParms = Parms, + eventBufferControl = EBC, + serviceState = SS}) -> + is_IndAudTerminationStateDescriptor_propertyParms(Parms) andalso + is_opt_NULL(EBC) andalso is_opt_NULL(SS); +is_IndAudTerminationStateDescriptor(_) -> + false. + +is_IndAudTerminationStateDescriptor_propertyParms([]) -> + true; +is_IndAudTerminationStateDescriptor_propertyParms([H|T]) -> + is_IndAudPropertyParm(H) andalso + is_IndAudTerminationStateDescriptor_propertyParms(T); +is_IndAudTerminationStateDescriptor_propertyParms(_) -> + false. + +chk_opt_IndAudTerminationStateDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudTerminationStateDescriptor(D1, D2) -> + chk_IndAudTerminationStateDescriptor(D1, D2). + +chk_IndAudTerminationStateDescriptor( + #'IndAudTerminationStateDescriptor'{propertyParms = Parms1, + eventBufferControl = EBC1, + serviceState = SS1}, + #'IndAudTerminationStateDescriptor'{propertyParms = Parms2, + eventBufferControl = EBC2, + serviceState = SS2}) -> + chk_IndAudTerminationStateDescriptor_propertyParms(Parms1, Parms2), + validate(fun() -> chk_opt_NULL(EBC1, EBC2) end, + 'IndAudTerminationStateDescriptor'), + validate(fun() -> chk_opt_NULL(SS1, SS2) end, + 'IndAudTerminationStateDescriptor'), + ok; +chk_IndAudTerminationStateDescriptor(D1, D2) -> + wrong_type('IndAudTerminationStateDescriptor', D1, D2). + +chk_IndAudTerminationStateDescriptor_propertyParms([], []) -> + ok; +chk_IndAudTerminationStateDescriptor_propertyParms([] = PP1, PP2) -> + not_equal('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2); +chk_IndAudTerminationStateDescriptor_propertyParms(PP1, [] = PP2) -> + not_equal('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2); +chk_IndAudTerminationStateDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_IndAudTerminationStateDescriptor_propertyParms(T1, T2); + false -> + wrong_type('IndAudTerminationStateDescriptor_propertyParms', H) + end; +chk_IndAudTerminationStateDescriptor_propertyParms([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, + 'IndAudTerminationStateDescriptor_propertyParms'), + chk_IndAudTerminationStateDescriptor_propertyParms(T1, T2); +chk_IndAudTerminationStateDescriptor_propertyParms(PP1, PP2) -> + wrong_type('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2). + + +%% -- IndAudEventsDescriptor -- + +is_IndAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID, + pkgdName = Name, + streamID = SID}) -> + is_opt_RequestID(RID) andalso + is_PkgdName(Name) andalso + is_opt_StreamID(SID); +is_IndAudEventsDescriptor(_) -> + false. + +chk_IndAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID1, + pkgdName = Name1, + streamID = SID1}, + #'IndAudEventsDescriptor'{requestID = RID2, + pkgdName = Name2, + streamID = SID2}) -> + chk_opt_RequestID(RID1, RID2), + chk_PkgdName(Name1, Name2), + chk_opt_StreamID(SID1, SID2), + ok; +chk_IndAudEventsDescriptor(D1, D2) -> + wrong_type('IndAudEventsDescriptor', D1, D2). + + +%% -- IndAudEventBufferDescriptor -- + +is_IndAudEventBufferDescriptor( + #'IndAudEventBufferDescriptor'{eventName = Name, + streamID = SID}) -> + is_PkgdName(Name) andalso is_opt_StreamID(SID); +is_IndAudEventBufferDescriptor(_) -> + false. + +chk_IndAudEventBufferDescriptor( + #'IndAudEventBufferDescriptor'{eventName = Name1, + streamID = SID1}, + #'IndAudEventBufferDescriptor'{eventName = Name2, + streamID = SID2}) -> + chk_PkgdName(Name1, Name2), + chk_opt_StreamID(SID1, SID2), + ok; +chk_IndAudEventBufferDescriptor(D1, D2) -> + wrong_type('IndAudEventBufferDescriptor', D1, D2). + + +%% -- IndAudSignalsDescriptor -- + +is_IndAudSignalsDescriptor({Tag, Val}) -> + is_IndAudSignalsDescriptor_tag(Tag) andalso + is_IndAudSignalsDescriptor_val(Tag, Val); +is_IndAudSignalsDescriptor(_) -> + false. + +is_IndAudSignalsDescriptor_tag(Tag) -> + Tags = [signal, seqSigList], + lists:member(Tag, Tags). + +is_IndAudSignalsDescriptor_val(signal, Val) -> + is_IndAudSignal(Val); +is_IndAudSignalsDescriptor_val(seqSigList, Val) -> + is_IndAudSeqSigList(Val). + +chk_IndAudSignalsDescriptor(D, D) -> + chk_type(fun is_IndAudSignalsDescriptor/1, 'IndAudSignalsDescriptor', D); +chk_IndAudSignalsDescriptor({Tag, Val1} = D1, {Tag, Val2} = D2) -> + case (is_IndAudSignalsDescriptor_tag(Tag) andalso + is_IndAudSignalsDescriptor_val(Tag, Val1) andalso + is_IndAudSignalsDescriptor_val(Tag, Val2)) of + true -> + chk_IndAudSignalsDescriptor_val(Tag, Val1, Val2); + false -> + wrong_type('IndAudSignalsDescriptor', D1, D2) + end; +chk_IndAudSignalsDescriptor({Tag1, Val1} = D1, {Tag2, Val2} = D2) -> + case ((is_IndAudSignalsDescriptor_tag(Tag1) andalso + is_IndAudSignalsDescriptor_val(Tag1, Val1)) andalso + (is_IndAudSignalsDescriptor_tag(Tag2) andalso + is_IndAudSignalsDescriptor_val(Tag2, Val2))) of + true -> + not_equal('IndAudSignalsDescriptor', D1, D2); + false -> + wrong_type('IndAudSignalsDescriptor', D1, D2) + end; +chk_IndAudSignalsDescriptor(D1, D2) -> + wrong_type('IndAudSignalsDescriptor', D1, D2). + +chk_IndAudSignalsDescriptor_val(signal, Val1, Val2) -> + chk_IndAudSignal(Val1, Val2); +chk_IndAudSignalsDescriptor_val(seqSigList, Val1, Val2) -> + chk_IndAudSeqSigList(Val1, Val2). + + +%% -- IndAudSeqSigList -- + +is_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID, + signalList = SL}) -> + is_IndAudSeqSigList_id(ID) andalso is_opt_IndAudSignal(SL); +is_IndAudSeqSigList(_) -> + false. + +is_IndAudSeqSigList_id(ID) -> is_INTEGER(ID, {range, 0, 65535}). + +chk_IndAudSeqSigList(L, L) -> + chk_type(fun is_IndAudSeqSigList/1, 'IndAudSeqSigList', L); +chk_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID1, + signalList = SL1}, + #'IndAudSeqSigList'{id = ID2, + signalList = SL2}) -> + chk_IndAudSeqSigList_id(ID1, ID2), + chk_opt_IndAudSignal(SL1, SL2), + ok; +chk_IndAudSeqSigList(L1, L2) -> + wrong_type('IndAudSeqSigList', L1, L2). + +chk_IndAudSeqSigList_id(ID, ID) -> + chk_type(fun is_IndAudSeqSigList_id/1, 'IndAudSeqSigList_id', ID); +chk_IndAudSeqSigList_id(ID1, ID2) -> + case (is_IndAudSeqSigList_id(ID1) andalso + is_IndAudSeqSigList_id(ID2)) of + true -> + not_equal('IndAudSeqSigList_id', ID1, ID2); + false -> + wrong_type('IndAudSeqSigList_id', ID1, ID2) + end. + + +%% -- IndAudSignal -- + +is_opt_IndAudSignal(asn1_NOVALUE) -> + true; +is_opt_IndAudSignal(V) -> + is_IndAudSignal(V). + +is_IndAudSignal(#'IndAudSignal'{signalName = Name, + streamID = SID}) -> + is_PkgdName(Name) andalso is_opt_StreamID(SID); +is_IndAudSignal(_) -> + false. + +chk_opt_IndAudSignal(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudSignal(S1, S2) -> + chk_IndAudSignal(S1, S2). + +chk_IndAudSignal(S, S) -> + chk_type(fun is_IndAudSignal/1, 'IndAudSignal', S); +chk_IndAudSignal(#'IndAudSignal'{signalName = Name1, + streamID = SID1}, + #'IndAudSignal'{signalName = Name2, + streamID = SID2}) -> + chk_PkgdName(Name1, Name2), + chk_opt_StreamID(SID1, SID2), + ok; +chk_IndAudSignal(S1, S2) -> + wrong_type('IndAudSignal', S1, S2). + + +%% -- IndAudDigitMapDescriptor -- + +is_IndAudDigitMapDescriptor( + #'IndAudDigitMapDescriptor'{digitMapName = Name}) -> + is_opt_DigitMapName(Name); +is_IndAudDigitMapDescriptor(_) -> + false. + +chk_IndAudDigitMapDescriptor(D, D) -> + chk_type(fun is_IndAudDigitMapDescriptor/1, 'IndAudDigitMapDescriptor', D); +chk_IndAudDigitMapDescriptor( + #'IndAudDigitMapDescriptor'{digitMapName = Name1}, + #'IndAudDigitMapDescriptor'{digitMapName = Name2}) -> + validate(fun() -> chk_opt_DigitMapName(Name1, Name2) end, + 'IndAudDigitMapDescriptor'), + ok; +chk_IndAudDigitMapDescriptor(D1, D2) -> + wrong_type('IndAudDigitMapDescriptor', D1, D2). + + +%% -- IndAudStatisticsDescriptor -- + +is_IndAudStatisticsDescriptor( + #'IndAudStatisticsDescriptor'{statName = Name}) -> + is_PkgdName(Name); +is_IndAudStatisticsDescriptor(_) -> + false. + +chk_IndAudStatisticsDescriptor(D, D) -> + chk_type(fun is_IndAudStatisticsDescriptor/1, + 'IndAudStatisticsDescriptor', D); +chk_IndAudStatisticsDescriptor( + #'IndAudStatisticsDescriptor'{statName = Name1}, + #'IndAudStatisticsDescriptor'{statName = Name2}) -> + validate(fun() -> chk_PkgdName(Name1, Name2) end, + 'IndAudStatisticsDescriptor'), + ok; +chk_IndAudStatisticsDescriptor(D1, D2) -> + wrong_type('IndAudStatisticsDescriptor', D1, D2). + + +%% -- IndAudPackagesDescriptor -- + +is_IndAudPackagesDescriptor( + #'IndAudPackagesDescriptor'{packageName = Name, + packageVersion = Ver}) -> + is_Name(Name) andalso is_IndAudPackagesDescriptor_packageVersion(Ver); +is_IndAudPackagesDescriptor(_) -> + false. + +is_IndAudPackagesDescriptor_packageVersion(V) -> + is_INTEGER(V, {range, 0, 99}). + +chk_IndAudPackagesDescriptor( + #'IndAudPackagesDescriptor'{packageName = Name1, + packageVersion = Ver1}, + #'IndAudPackagesDescriptor'{packageName = Name2, + packageVersion = Ver2}) -> + validate(fun() -> chk_Name(Name1, Name2) end, 'IndAudPackagesDescriptor'), + chk_IndAudPackagesDescriptor_packageVersion(Ver1, Ver2), + ok; +chk_IndAudPackagesDescriptor(D1, D2) -> + wrong_type('IndAudPackagesDescriptor', D1, D2). + +chk_IndAudPackagesDescriptor_packageVersion(V, V) -> + chk_type(fun is_IndAudPackagesDescriptor_packageVersion/1, + 'IndAudPackagesDescriptor_packageVersion', V); +chk_IndAudPackagesDescriptor_packageVersion(V1, V2) -> + case (is_IndAudPackagesDescriptor_packageVersion(V1) andalso + is_IndAudPackagesDescriptor_packageVersion(V2)) of + true -> + not_equal('IndAudPackagesDescriptor_packageVersion', V1, V2); + false -> + wrong_type('IndAudPackagesDescriptor_packageVersion', V1, V2) + end. + + +%% -- NotifyRequest -- + +is_NotifyRequest(#'NotifyRequest'{terminationID = Tids, + observedEventsDescriptor = OED, + errorDescriptor = ED}) -> + is_TerminationIDList(Tids) andalso + is_ObservedEventsDescriptor(OED) andalso + is_opt_ErrorDescriptor(ED); +is_NotifyRequest(_) -> + false. + +chk_NotifyRequest(#'NotifyRequest'{terminationID = Tids1, + observedEventsDescriptor = OED1, + errorDescriptor = ED1}, + #'NotifyRequest'{terminationID = Tids2, + observedEventsDescriptor = OED2, + errorDescriptor = ED2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'NotifyRequest'), + validate(fun() -> chk_ObservedEventsDescriptor(OED1, OED2) end, + 'NotifyRequest'), + validate(fun() -> chk_opt_ErrorDescriptor(ED1, ED2) end, + 'NotifyRequest'), + ok; +chk_NotifyRequest(NR1, NR2) -> + wrong_type('NotifyRequest', NR1, NR2). + + +%% -- NotifyReply -- + +is_NotifyReply(#'NotifyReply'{terminationID = Tids, + errorDescriptor = ED}) -> + is_TerminationIDList(Tids) andalso is_opt_ErrorDescriptor(ED); +is_NotifyReply(_) -> + false. + +chk_NotifyReply(#'NotifyReply'{terminationID = Tids1, + errorDescriptor = ED1}, + #'NotifyReply'{terminationID = Tids2, + errorDescriptor = ED2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, 'NotifyReply'), + validate(fun() -> chk_opt_ErrorDescriptor(ED1, ED2) end, 'NotifyReply'), + ok; +chk_NotifyReply(NR1, NR2) -> + wrong_type('NotifyReply', NR1, NR2). + + +%% -- ObservedEventsDescriptor -- + +is_ObservedEventsDescriptor( + #'ObservedEventsDescriptor'{requestId = RID, + observedEventLst = OEL}) -> + is_RequestID(RID) andalso + is_ObservedEventsDescriptor_observedEventLst(OEL); +is_ObservedEventsDescriptor(_) -> + false. + +is_ObservedEventsDescriptor_observedEventLst([]) -> + true; +is_ObservedEventsDescriptor_observedEventLst([H|T]) -> + is_ObservedEvent(H) andalso + is_ObservedEventsDescriptor_observedEventLst(T); +is_ObservedEventsDescriptor_observedEventLst(_) -> + false. + +chk_ObservedEventsDescriptor( + #'ObservedEventsDescriptor'{requestId = RID1, + observedEventLst = OEL1}, + #'ObservedEventsDescriptor'{requestId = RID2, + observedEventLst = OEL2}) -> + validate(fun() -> chk_RequestID(RID1, RID2) end, + 'ObservedEventsDescriptor'), + validate( + fun() -> + chk_ObservedEventsDescriptor_observedEventLst(OEL1, OEL2) + end, + 'ObservedEventsDescriptor'), + ok; +chk_ObservedEventsDescriptor(D1, D2) -> + wrong_type('ObservedEventsDescriptor', D1, D2). + +chk_ObservedEventsDescriptor_observedEventLst([], []) -> + ok; +chk_ObservedEventsDescriptor_observedEventLst([] = L1, L2) -> + not_equal('ObservedEventsDescriptor_observedEventLst', L1, L2); +chk_ObservedEventsDescriptor_observedEventLst(L1, [] = L2) -> + not_equal('ObservedEventsDescriptor_observedEventLst', L1, L2); +chk_ObservedEventsDescriptor_observedEventLst([H|T1], [H|T2]) -> + case is_ObservedEvent(H) of + true -> + chk_ObservedEventsDescriptor_observedEventLst(T1, T2); + false -> + wrong_type('ObservedEventsDescriptor_observedEventLst_val', H) + end; +chk_ObservedEventsDescriptor_observedEventLst([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ObservedEvent(H1, H2) end, + 'ObservedEventsDescriptor_observedEventLst_val'), + chk_ObservedEventsDescriptor_observedEventLst(T1, T2); +chk_ObservedEventsDescriptor_observedEventLst(L1, L2) -> + wrong_type('ObservedEventsDescriptor_observedEventLst', L1, L2). + + +%% -- ObservedEvent -- + +is_ObservedEvent(#'ObservedEvent'{eventName = Name, + streamID = SID, + eventParList = EPL, + timeNotation = TN}) -> + is_EventName(Name) andalso + is_opt_StreamID(SID) andalso + is_ObservedEvent_eventParList(EPL) andalso + is_opt_TimeNotation(TN); +is_ObservedEvent(_) -> + false. + +is_ObservedEvent_eventParList([]) -> + true; +is_ObservedEvent_eventParList([H|T]) -> + is_EventParameter(H) andalso is_ObservedEvent_eventParList(T); +is_ObservedEvent_eventParList(_) -> + false. + +chk_ObservedEvent(E, E) -> + chk_type(fun is_ObservedEvent/1, 'ObservedEvent', E); +chk_ObservedEvent(#'ObservedEvent'{eventName = Name1, + streamID = SID1, + eventParList = EPL1, + timeNotation = TN1}, + #'ObservedEvent'{eventName = Name2, + streamID = SID2, + eventParList = EPL2, + timeNotation = TN2}) -> + validate(fun() -> chk_EventName(Name1, Name2) end, 'ObservedEvent'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'ObservedEvent'), + chk_ObservedEvent_eventParList(EPL1, EPL2), + validate(fun() -> chk_opt_TimeNotation(TN1, TN2) end, 'ObservedEvent'), + ok; +chk_ObservedEvent(E1, E2) -> + wrong_type('ObservedEvent', E1, E2). + +chk_ObservedEvent_eventParList([], []) -> + ok; +chk_ObservedEvent_eventParList([] = EPL1, EPL2) -> + not_equal('ObservedEvent_eventParList', EPL1, EPL2); +chk_ObservedEvent_eventParList(EPL1, [] = EPL2) -> + not_equal('ObservedEvent_eventParList', EPL1, EPL2); +chk_ObservedEvent_eventParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_ObservedEvent_eventParList(T1, T2); + false -> + wrong_type('ObservedEvent_eventParList_val', H) + end; +chk_ObservedEvent_eventParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'ObservedEvent_eventParList'), + chk_ObservedEvent_eventParList(T1, T2); +chk_ObservedEvent_eventParList(L1, L2) -> + wrong_type('ObservedEvent_eventParList', L1, L2). + + +%% -- EventName -- + +is_EventName(N) -> is_PkgdName(N). + +chk_EventName(N, N) -> + chk_type(fun is_EventName/1, 'EventName', N); +chk_EventName(N1, N2) -> + case (is_EventName(N1) andalso is_EventName(N2)) of + true -> + not_equal('EventName', N1, N2); + false -> + wrong_type('EventName', N1, N2) + end. + + +%% -- EventParameter -- + +is_EventParameter(#'EventParameter'{eventParameterName = Name, + value = Val, + extraInfo = EI}) -> + d("is_EventParameter -> entery with" + "~n Name: ~p" + "~n Val: ~p" + "~n EI: ~p", [Name, Val, EI]), + is_Name(Name) andalso + is_Value(Val) andalso + is_EventParameter_extraInfo(EI); +is_EventParameter(_) -> + false. + +is_EventParameter_extraInfo(asn1_NOVALUE) -> + true; +is_EventParameter_extraInfo({Tag, Val}) -> + is_EventParameter_extraInfo_tag(Tag) andalso + is_EventParameter_extraInfo_val(Tag, Val); +is_EventParameter_extraInfo(_) -> + false. + +is_EventParameter_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_EventParameter_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_EventParameter_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_EventParameter_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + +chk_EventParameter(#'EventParameter'{eventParameterName = Name1, + value = Val1, + extraInfo = EI1}, + #'EventParameter'{eventParameterName = Name2, + value = Val2, + extraInfo = EI2}) -> + validate(fun() -> chk_Name(Name1, Name2) end, 'EventParameter'), + validate(fun() -> chk_Value(Val1, Val2) end, 'EventParameter'), + chk_EventParameter_extraInfo(EI1, EI2), + ok; +chk_EventParameter(P1, P2) -> + wrong_type('EventParameter', P1, P2). + +chk_EventParameter_extraInfo(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_EventParameter_extraInfo(EI, EI) -> + chk_type(fun is_EventParameter_extraInfo/1, + 'EventParameter_extraInfo', EI); +chk_EventParameter_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> + case (is_EventParameter_extraInfo_tag(Tag) andalso + is_EventParameter_extraInfo_val(Tag, Val1) andalso + is_EventParameter_extraInfo_val(Tag, Val2)) of + true -> + chk_EventParameter_extraInfo_val(Tag, Val1, Val2); + false -> + wrong_type('EventParameter_extraInfo', EI1, EI2) + end; +chk_EventParameter_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> + case ((is_EventParameter_extraInfo_tag(Tag1) andalso + is_EventParameter_extraInfo_val(Tag1, Val1)) andalso + (is_EventParameter_extraInfo_tag(Tag2) andalso + is_EventParameter_extraInfo_val(Tag2, Val2))) of + true -> + not_equal('EventParameter_extraInfo', EI1, EI2); + false -> + wrong_type('EventParameter_extraInfo', EI1, EI2) + end; +chk_EventParameter_extraInfo(EI1, EI2) -> + wrong_type('EventParameter_extraInfo', EI1, EI2). + +chk_EventParameter_extraInfo_val(relation, Val1, Val2) -> + validate(fun() -> chk_Relation(Val1, Val2) end, + 'EventParameter_extraInfo_val'); +chk_EventParameter_extraInfo_val(range, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, + 'EventParameter_extraInfo_val'); +chk_EventParameter_extraInfo_val(sublist, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, + 'EventParameter_extraInfo_val'). + + +%% -- ServiceChangeRequest -- + +is_ServiceChangeRequest(#'ServiceChangeRequest'{terminationID = Tids, + serviceChangeParms = Parms}) -> + is_TerminationIDList(Tids) andalso is_ServiceChangeParm(Parms); +is_ServiceChangeRequest(_) -> + false. + +chk_ServiceChangeRequest(R, R) -> + chk_type(fun is_ServiceChangeRequest/1, 'ServiceChangeRequest', R); +chk_ServiceChangeRequest( + #'ServiceChangeRequest'{terminationID = Tids1, + serviceChangeParms = Parms1}, + #'ServiceChangeRequest'{terminationID = Tids2, + serviceChangeParms = Parms2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'ServiceChangeRequest'), + validate(fun() -> chk_ServiceChangeParm(Parms1, Parms2) end, + 'ServiceChangeRequest'), + ok; +chk_ServiceChangeRequest(R1, R2) -> + wrong_type('ServiceChangeRequest', R1, R2). + + +%% -- ServiceChangeReply -- + +is_ServiceChangeReply(#'ServiceChangeReply'{terminationID = Tids, + serviceChangeResult = Res}) -> + is_TerminationIDList(Tids) andalso is_ServiceChangeResult(Res); +is_ServiceChangeReply(_) -> + false. + +chk_ServiceChangeReply(R, R) -> + chk_type(fun is_ServiceChangeReply/1, 'ServiceChangeReply', R); +chk_ServiceChangeReply( + #'ServiceChangeReply'{terminationID = Tids1, + serviceChangeResult = Res1}, + #'ServiceChangeReply'{terminationID = Tids2, + serviceChangeResult = Res2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'ServiceChangeReply'), + validate(fun() -> chk_ServiceChangeResult(Res1, Res2) end, + 'ServiceChangeReply'), + ok; +chk_ServiceChangeReply(R1, R2) -> + wrong_type('ServiceChangeReply', R1, R2). + + +%% -- ServiceChangeResult -- + +is_ServiceChangeResult({Tag, Val}) -> + is_ServiceChangeResult_tag(Tag) andalso + is_ServiceChangeResult_val(Tag, Val); +is_ServiceChangeResult(_) -> + false. + +is_ServiceChangeResult_tag(Tag) -> + Tags = [errorDescriptor, serviceChangeResParms], + lists:member(Tag, Tags). + +is_ServiceChangeResult_val(errorDescriptor, Val) -> + is_ErrorDescriptor(Val); +is_ServiceChangeResult_val(serviceChangeResParms, Val) -> + is_ServiceChangeResParm(Val). + +chk_ServiceChangeResult(Res, Res) -> + chk_type(fun is_ServiceChangeResult/1, 'ServiceChangeResult', Res); +chk_ServiceChangeResult({Tag, Val1} = Res1, {Tag, Val2} = Res2) -> + case (is_ServiceChangeResult_tag(Tag) andalso + is_ServiceChangeResult_val(Tag, Val1) andalso + is_ServiceChangeResult_val(Tag, Val2)) of + true -> + chk_ServiceChangeResult_val(Tag, Val1, Val2); + false -> + wrong_type('ServiceChangeResult', Res1, Res2) + end; +chk_ServiceChangeResult({Tag1, Val1} = Res1, {Tag2, Val2} = Res2) -> + case ((is_ServiceChangeResult_tag(Tag1) andalso + is_ServiceChangeResult_val(Tag1, Val1)) andalso + (is_ServiceChangeResult_tag(Tag2) andalso + is_ServiceChangeResult_val(Tag2, Val2))) of + true -> + not_equal('ServiceChangeResult', Res1, Res2); + false -> + wrong_type('ServiceChangeResult', Res1, Res2) + end; +chk_ServiceChangeResult(Res1, Res2) -> + wrong_type('ServiceChangeResult', Res1, Res2). + +chk_ServiceChangeResult_val(errorDescriptor, Val1, Val2) -> + validate(fun() -> chk_ErrorDescriptor(Val1, Val2) end, + 'ServiceChangeResult'); +chk_ServiceChangeResult_val(serviceChangeResParms, Val1, Val2) -> + validate(fun() -> chk_ServiceChangeResParm(Val1, Val2) end, + 'ServiceChangeResult'). + + +%% -- WildcardField -- + +is_WildcardField(WF) -> is_OCTET_STRING(WF, {exact, 1}). + +chk_WildcardField(WF, WF) -> + case is_WildcardField(WF) of + true -> + ok; + false -> + wrong_type('WildcardField', WF) + end; +chk_WildcardField(WF1, WF2) -> + case (is_WildcardField(WF1) andalso is_WildcardField(WF2)) of + true -> + not_equal('WildcardField', WF1, WF2); + false -> + wrong_type('WildcardField', WF1, WF2) + end. + + +%% -- TerminationID -- + +is_TerminationID(#'TerminationID'{wildcard = W, + id = ID}) -> + is_TerminationID_wildcard(W) andalso is_TerminationID_id(ID); +is_TerminationID(#megaco_term_id{contains_wildcards = _W, + id = _ID}) -> + true; % What are the types? +is_TerminationID(_) -> + false. + +is_TerminationID_wildcard([]) -> + true; +is_TerminationID_wildcard([H|T]) -> + is_WildcardField(H) andalso is_TerminationID_wildcard(T); +is_TerminationID_wildcard(_) -> + false. + +is_TerminationID_id(ID) -> is_OCTET_STRING(ID, {range, 1, 8}). + +chk_TerminationID(Id,Id) -> + chk_type(fun is_TerminationID/1, 'TerminationID', Id); +chk_TerminationID(#'TerminationID'{wildcard = W1, + id = I1}, + #'TerminationID'{wildcard = W2, + id = I2}) -> + chk_TerminationID_wildcard(W1, W2), + chk_TerminationID_id(I1, I2), + ok; +chk_TerminationID(#megaco_term_id{contains_wildcards = W1, + id = I1}, + #megaco_term_id{contains_wildcards = W2, + id = I2}) -> + chk_TerminationID_wildcard(W1, W2), + chk_TerminationID_id(I1, I2), + ok; +chk_TerminationID(Tid1, Tid2) -> + wrong_type('TerminationID', Tid1, Tid2). + +chk_TerminationID_wildcard([], []) -> + ok; +chk_TerminationID_wildcard([] = WF1, WF2) -> + not_equal('TerminationID_wildcard', WF1, WF2); +chk_TerminationID_wildcard(WF1, [] = WF2) -> + not_equal('TerminationID_wildcard', WF1, WF2); +chk_TerminationID_wildcard([H|T1], [H|T2]) -> + case is_WildcardField(H) of + true -> + chk_TerminationID_wildcard(T1, T2); + false -> + wrong_type('TerminationID_wildcard_val', H) + end; +chk_TerminationID_wildcard([H1|T1], [H2|T2]) -> + validate(fun() -> chk_WildcardField(H1, H2) end, + 'TerminationID_wildcard_val'), + chk_TerminationID_wildcard(T1, T2); +chk_TerminationID_wildcard(WF1,WF2) -> + not_equal('TerminationId_wildcard', WF1, WF2). + +chk_TerminationID_id(Id, Id) -> + case is_OCTET_STRING(Id, {range, 1, 8}) of + true -> + ok; + false -> + wrong_type('TerminationID_id', Id, Id) + end; +chk_TerminationID_id(Id1, Id2) -> + not_equal(terminationId_id, Id1, Id2). + + +%% -- TerminationIDList -- + +is_TerminationIDList([]) -> + true; +is_TerminationIDList([H|T]) -> + is_TerminationID(H) andalso is_TerminationIDList(T); +is_TerminationIDList(_) -> + false. + +chk_TerminationIDList([], []) -> + ok; +chk_TerminationIDList([] = L1, L2) -> + not_equal('TerminationIDList', L1, L2); +chk_TerminationIDList(L1, [] = L2) -> + not_equal('TerminationIDList', L1, L2); +chk_TerminationIDList([H|T1], [H|T2]) -> + case is_TerminationID(H) of + true -> + chk_TerminationIDList(T1, T2); + false -> + wrong_type('TerminationIDList', H) + end; +chk_TerminationIDList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TerminationID(H1, H2) end, 'TerminationIDList'), + chk_TerminationIDList(T1, T2); +chk_TerminationIDList(L1, L2) -> + wrong_type('TerminationIDList', L1, L2). + + +%% -- MediaDescriptor -- + +is_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TSD, + streams = S}) -> + d("is_MediaDescriptor -> entry with" + "~n TSD: ~p" + "~n S: ~p", [TSD, S]), + is_opt_TerminationStateDescriptor(TSD) andalso + is_MediaDescriptor_streams(S); +is_MediaDescriptor(_) -> + false. + +is_MediaDescriptor_streams(asn1_NOVALUE) -> + true; +is_MediaDescriptor_streams({Tag, Val}) -> + is_MediaDescriptor_streams_tag(Tag) andalso + is_MediaDescriptor_streams_val(Tag, Val); +is_MediaDescriptor_streams(_) -> + false. + +is_MediaDescriptor_streams_tag(Tag) -> + Tags = [oneStream, multiStream], + lists:member(Tag, Tags). + +is_MediaDescriptor_streams_val(oneStream, SP) -> + is_StreamParms(SP); +is_MediaDescriptor_streams_val(multiStream, SDL) -> + is_MediaDescriptor_multiStream(SDL). + +is_MediaDescriptor_multiStream([]) -> + true; +is_MediaDescriptor_multiStream([H|T]) -> + is_StreamDescriptor(H) andalso is_MediaDescriptor_multiStream(T); +is_MediaDescriptor_multiStream(_) -> + false. + +chk_MediaDescriptor(D, D) -> + chk_type(fun is_MediaDescriptor/1, 'MediaDescriptor', D); +chk_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TSD1, + streams = S1}, + #'MediaDescriptor'{termStateDescr = TSD2, + streams = S2}) -> + validate( + fun() -> + chk_opt_TerminationStateDescriptor(TSD1, TSD2) + end, + 'MediaDescriptor'), + validate( + fun() -> + chk_MediaDescriptor_streams(S1, S2) + end, + 'MediaDescriptor'), + ok; +chk_MediaDescriptor(D1, D2) -> + wrong_type('MediaDescriptor', D1, D2). + + +chk_MediaDescriptor_streams(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_MediaDescriptor_streams({oneStream, SP1}, {oneStream, SP2}) -> + validate(fun() -> + chk_StreamParms(SP1, SP2) + end, + 'MediaDescriptor_streams'); +chk_MediaDescriptor_streams({multiStream, SDs1}, {multiStream, SDs2}) -> + validate(fun() -> + chk_MediaDescriptor_multiStream(SDs1, SDs2) + end, + 'MediaDescriptor_streams'); +chk_MediaDescriptor_streams(S1, S2) -> + wrong_type('MediaDescriptor_streams', S1, S2). + +chk_MediaDescriptor_multiStream([], []) -> + ok; +chk_MediaDescriptor_multiStream([] = MS1, MS2) -> + not_equal('MediaDescriptor_multiStream', MS1, MS2); +chk_MediaDescriptor_multiStream(MS1, [] = MS2) -> + not_equal('MediaDescriptor_multiStream', MS1, MS2); +chk_MediaDescriptor_multiStream([H|T1], [H|T2]) -> + case is_StreamDescriptor(H) of + true -> + chk_MediaDescriptor_multiStream(T1, T2); + false -> + wrong_type('MediaDescriptor_multiStream_val', H) + end; +chk_MediaDescriptor_multiStream([H1|T1], [H2|T2]) -> + validate(fun() -> chk_StreamDescriptor(H1, H2) end, + 'MediaDescriptor_multiStream_val'), + chk_MediaDescriptor_multiStream(T1, T2); +chk_MediaDescriptor_multiStream(MS1, MS2) -> + wrong_type('MediaDescriptor_multiStream_val', MS1, MS2). + + +%% -- StreamDescriptor -- + +is_StreamDescriptor(#'StreamDescriptor'{streamID = SID, + streamParms = Parms}) -> + d("is_StreamDescriptor -> entry with" + "~n SID: ~p" + "~n Parms: ~p", [SID, Parms]), + is_StreamID(SID) andalso is_StreamParms(Parms); +is_StreamDescriptor(X) -> + d("is_StreamDescriptor -> entry when ERROR with" + "~n X: ~p", [X]), + false. + +chk_StreamDescriptor(D, D) -> + chk_type(fun is_StreamDescriptor/1, 'StreamDescriptor', D); +chk_StreamDescriptor(#'StreamDescriptor'{streamID = SID1, + streamParms = Parms1}, + #'StreamDescriptor'{streamID = SID2, + streamParms = Parms2}) -> + validate(fun() -> chk_StreamID(SID1, SID2) end, 'StreamDescriptor'), + validate(fun() -> chk_StreamParms(Parms1, Parms2) end, 'StreamDescriptor'), + ok; +chk_StreamDescriptor(D1, D2) -> + wrong_type('StreamDescriptor', D1, D2). + + +%% -- StreamParms -- + +is_StreamParms(#'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}) -> + d("is_StreamParms -> entry with" + "~n LCD: ~p" + "~n LD: ~p" + "~n RD: ~p" + "~n SD: ~p", [LCD, LD, RD, SD]), + is_opt_LocalControlDescriptor(LCD) andalso + is_opt_LocalRemoteDescriptor(LD) andalso + is_opt_LocalRemoteDescriptor(RD) andalso + is_opt_StatisticsDescriptor(SD); +is_StreamParms(X) -> + d("is_StreamParms -> entry when ERROR with" + "~n X: ~p", [X]), + false. + +chk_StreamParms(SP, SP) -> + chk_type(fun is_StreamParms/1, 'StreamParms', SP); +chk_StreamParms(#'StreamParms'{localControlDescriptor = LCD1, + localDescriptor = LD1, + remoteDescriptor = RD1, + statisticsDescriptor = SD1}, + #'StreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2, + statisticsDescriptor = SD2}) -> + validate(fun() -> chk_opt_LocalControlDescriptor(LCD1, LCD2) end, + 'StreamParms_localControlDescriptor'), + validate(fun() -> chk_opt_LocalRemoteDescriptor(LD1, LD2) end, + 'StreamParms_localDescriptor'), + validate(fun() -> chk_opt_LocalRemoteDescriptor(RD1, RD2) end, + 'StreamParms_remoteDescriptor'), + validate(fun() -> chk_opt_StatisticsDescriptor(SD1, SD2) end, + 'StreamParms_statisticsDescriptor'), + ok; +chk_StreamParms(P1, P2) -> + wrong_type('StreamParms', P1, P2). + + +%% -- LocalControlDescriptor -- + +is_opt_LocalControlDescriptor(D) -> + d("is_opt_LocalControlDescriptor -> entry"), + is_OPTIONAL(fun is_LocalControlDescriptor/1, D). + +is_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP}) -> + d("is_LocalControlDescriptor -> entry with" + "~n SM: ~p" + "~n RV: ~p" + "~n RG: ~p" + "~n PP: ~p", [SM, RV, RG, PP]), + is_opt_StreamMode(SM) andalso + is_opt_BOOLEAN(RV) andalso + is_opt_BOOLEAN(RG) andalso + is_LocalControlDescriptor_propertyParms(PP); +is_LocalControlDescriptor(_) -> + false. + +is_LocalControlDescriptor_propertyParms([]) -> + d("is_LocalControlDescriptor_propertyParms -> entry when done"), + true; +is_LocalControlDescriptor_propertyParms([H|T]) -> + d("is_LocalControlDescriptor_propertyParms -> entry with" + "~n H: ~p" + "~n T: ~p", [H, T]), + is_PropertyParm(H) andalso is_LocalControlDescriptor_propertyParms(T); +is_LocalControlDescriptor_propertyParms(_) -> + false. + +chk_opt_LocalControlDescriptor(LCD1, LCD2) -> + chk_OPTIONAL('LocalControlDescriptor', LCD1, LCD2, + fun is_LocalControlDescriptor/1, + fun chk_LocalControlDescriptor/2). + +chk_LocalControlDescriptor(LCD, LCD) -> + chk_type(fun is_LocalControlDescriptor/1, 'LocalControlDescriptor', LCD); +chk_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = SM1, + reserveValue = RV1, + reserveGroup = RG1, + propertyParms = PP1}, + #'LocalControlDescriptor'{streamMode = SM2, + reserveValue = RV2, + reserveGroup = RG2, + propertyParms = PP2}) -> + validate( + fun() -> chk_opt_StreamMode(SM1, SM2) end, + 'LocalControlDescriptor'), + validate( + fun() -> chk_opt_BOOLEAN(RV1, RV2) end, + 'LocalControlDescriptor_reserveValue'), + validate( + fun() -> chk_opt_BOOLEAN(RG1, RG2) end, + 'LocalControlDescriptor_reserveGroup'), + chk_LocalControlDescriptor_propertyParms(PP1, PP2), + ok; +chk_LocalControlDescriptor(LCD1, LCD2) -> + wrong_type('LocalControlDescriptor', LCD1, LCD2). + + +chk_LocalControlDescriptor_propertyParms([], []) -> + ok; +chk_LocalControlDescriptor_propertyParms([] = PP1, PP2) -> + not_equal('LocalControlDescriptor_propertyParms', PP1, PP2); +chk_LocalControlDescriptor_propertyParms(PP1, [] = PP2) -> + not_equal('LocalControlDescriptor_propertyParms', PP1, PP2); +chk_LocalControlDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_LocalControlDescriptor_propertyParms(T1, T2); + false -> + wrong_type('LocalControlDescriptor_propertyParms_val', H) + end; +chk_LocalControlDescriptor_propertyParms([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, + 'LocalControlDescriptor_propertyParms_val'), + chk_LocalControlDescriptor_propertyParms(T1, T2); +chk_LocalControlDescriptor_propertyParms(PP1, PP2) -> + wrong_type('LocalControlDescriptor_propertyParms', PP1, PP2). + + +%% -- StreamMode -- + +is_opt_StreamMode(asn1_NOVALUE) -> + true; +is_opt_StreamMode(SM) -> + is_StreamMode(SM). + +is_StreamMode(SM) -> + lists:member(SM, [sendOnly, recvOnly, sendRecv, inactive, loopBack]). + +chk_opt_StreamMode(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_StreamMode(SM1, SM2) -> + chk_StreamMode(SM1, SM2). + +chk_StreamMode(SM, SM) -> + chk_type(fun is_StreamMode/1, 'StreamMode', SM); +chk_StreamMode(SM1, SM2) -> + case (is_StreamMode(SM1) andalso is_StreamMode(SM2)) of + true -> + not_equal('StreamMode', SM1, SM2); + false -> + wrong_type('StreamMode', SM1, SM2) + end. + + +%% -- PropertyParm -- + +is_PropertyParm(#'PropertyParm'{name = N, + value = V, + extraInfo = I}) -> + d("is_PropertyParm -> entry with" + "~n N: ~p" + "~n V: ~p" + "~n I: ~p", [N, V, I]), + is_PkgdName(N) andalso + is_PropertyParm_value(V) andalso + is_PropertyParm_extraInfo(I); +is_PropertyParm(_) -> + false. + +is_PropertyParm_value([]) -> + d("is_PropertyParm_value -> entry when done"), + true; +is_PropertyParm_value([H|T]) -> + d("is_PropertyParm_value -> entry with" + "~n H: ~p", [H]), + is_OCTET_STRING(H) andalso is_PropertyParm_value(T); +is_PropertyParm_value(_) -> + false. + +is_PropertyParm_extraInfo(asn1_NOVALUE) -> + true; +is_PropertyParm_extraInfo({Tag, Val}) -> + d("is_PropertyParm_extraInfo -> entry with" + "~n Tag: ~p" + "~n Val: ~p", [Tag, Val]), + is_PropertyParm_extraInfo_tag(Tag) andalso + is_PropertyParm_extraInfo_val(Tag, Val); +is_PropertyParm_extraInfo(_) -> + false. + +is_PropertyParm_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_PropertyParm_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_PropertyParm_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_PropertyParm_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + +chk_PropertyParm(P, P) -> + chk_type(fun is_PropertyParm/1, 'PropertyParm', P); +chk_PropertyParm(#'PropertyParm'{name = N1, + value = V1, + extraInfo = I1}, + #'PropertyParm'{name = N2, + value = V2, + extraInfo = I2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'PropertyParm'), + chk_PropertyParm_value(V1, V2), + chk_PropertyParm_extraInfo(I1, I2), + ok; +chk_PropertyParm(P1, P2) -> + wrong_type('PropertyParm', P1, P2). + +chk_PropertyParm_value([], []) -> + ok; +chk_PropertyParm_value([] = V1, V2) -> + not_equal('PropertyParm_value', V1, V2); +chk_PropertyParm_value(V1, [] = V2) -> + not_equal('PropertyParm_value', V1, V2); +chk_PropertyParm_value([H|T1], [H|T2]) -> + case is_OCTET_STRING(H) of + true -> + chk_PropertyParm_value(T1, T2); + false -> + wrong_type('PropertyParm_value_val', H) + end; +chk_PropertyParm_value([H1|_], [H2|_]) -> + case (is_OCTET_STRING(H1) andalso is_OCTET_STRING(H2)) of + true -> + not_equal('PropertyParm_value_val', H1, H2); + false -> + wrong_type('PropertyParm_value_val', H1, H2) + end; +chk_PropertyParm_value(V1, V2) -> + wrong_type('PropertyParm_value', V1, V2). + +chk_PropertyParm_extraInfo(EI, EI) -> + chk_type(fun is_PropertyParm_extraInfo/1, 'PropertyParm_extraInfo', EI); +chk_PropertyParm_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> + case (is_PropertyParm_extraInfo_tag(Tag) and + is_PropertyParm_extraInfo_val(Tag, Val1) and + is_PropertyParm_extraInfo_val(Tag, Val2)) of + true -> + chk_PropertyParm_extraInfo_val(Tag, Val1, Val2); + false -> + wrong_type('PropertyParm_extraInfo', EI1, EI2) + end; +chk_PropertyParm_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> + case ((is_PropertyParm_extraInfo_tag(Tag1) and + is_PropertyParm_extraInfo_val(Tag1, Val1)) and + (is_PropertyParm_extraInfo_tag(Tag2) and + is_PropertyParm_extraInfo_val(Tag2, Val2))) of + true -> + not_equal('PropertyParm_extraInfo', EI1, EI2); + false -> + wrong_type('PropertyParm_extraInfo', EI1, EI2) + end; +chk_PropertyParm_extraInfo(EI1, EI2) -> + wrong_type('PropertyParm_extraInfo', EI1, EI2). + +chk_PropertyParm_extraInfo_val(relation, Val1, Val2) -> + validate(fun() -> chk_Relation(Val1, Val2) end, 'PropertyParm_extraInfo'); +chk_PropertyParm_extraInfo_val(range, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'PropertyParm_extraInfo'); +chk_PropertyParm_extraInfo_val(sublist, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'PropertyParm_extraInfo'). + + +%% -- Name -- + +is_Name(N) -> + %% Binary: is_OCTET_STRING(N, {exact, 2}). + case is_OCTET_STRING(N, {range, 1, 64}) of + true -> + is_NAME(N); + false -> + false + end. + +is_NAME([H|T]) when H =< $z, $a =< H -> + is_NAME2(T); +is_NAME([H|T]) when H =< $Z, $A =< H -> + is_NAME2(T); +is_NAME(_) -> + false. + +is_NAME2([]) -> + true; +is_NAME2([$_|T]) -> + is_NAME2(T); +is_NAME2([H|T]) when H =< $z, $a =< H -> + is_NAME2(T); +is_NAME2([H|T]) when H =< $Z, $A =< H -> + is_NAME2(T); +is_NAME2([H|T]) when H =< $9, $0 =< H -> + is_NAME2(T); +is_NAME2(_) -> + false. + + + +chk_Name(N, N) -> + chk_type(fun is_Name/1, 'Name', N); +chk_Name(N1, N2) -> + case (is_Name(N1) andalso is_Name(N2)) of + true -> + not_equal('Name', N1, N2); + false -> + wrong_type('Name', N1, N2) + end. + + +%% -- PkgdName -- + +%% PkgdName is either "AB/CD" or just plain "ABCD" +%% Note that in ASN.1 the parts is exactly 2 char +%% each, unless you don't use the native config +%% option. In text and in binary without the native +%% option, it is 63 + 1 chars for each. +is_PkgdName(N) -> + d("is_PkgdName -> entry with" + "~n N: ~p", [N]), + case string:tokens(N, "/") of + ["*" = PackageName, "*" = ItemID] -> + d("is_PkgdName -> tokenized (0): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + true; + [PackageName, "*" = ItemID] -> + d("is_PkgdName -> tokenized (1): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + is_Name(PackageName); + [PackageName, ItemID] -> + d("is_PkgdName -> tokenized (2): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + is_Name(PackageName) andalso is_Name(ItemID); + _ -> + is_Name(N) + end. + +chk_PkgdName(N, N) -> + case is_PkgdName(N) of + true -> + ok; + false -> + wrong_type('PkgdName', N, N) + end; +chk_PkgdName(N1, N2) -> + case (is_PkgdName(N1) andalso is_PkgdName(N2)) of + true -> + not_equal('PkgdName', N1, N2); + false -> + wrong_type('PkgdName', N1, N2) + end. + + +%% -- Relation -- + +is_Relation(R) -> + lists:member(R, [greaterThan, smallerThan, unequalTo]). + +chk_Relation(R, R) -> + chk_type(fun is_Relation/1, 'Relation', R); +chk_Relation(R1, R2) -> + case (is_Relation(R1) andalso is_Relation(R2)) of + true -> + not_equal('Relation', R1, R2); + false -> + wrong_type('Relation', R1, R2) + end. + + +%% -- LocalRemoteDescriptor -- + +is_opt_LocalRemoteDescriptor(D) -> + d("is_LocalRemoteDescriptor -> entry"), + is_OPTIONAL(fun is_LocalRemoteDescriptor/1, D). + +is_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = PGs}) -> + d("is_LocalRemoteDescriptor -> entry with" + "~n PGs: ~p", [PGs]), + is_LocalRemoteDescriptor_propGrps(PGs); +is_LocalRemoteDescriptor(_) -> + false. + +is_LocalRemoteDescriptor_propGrps([]) -> + true; +is_LocalRemoteDescriptor_propGrps([H|T]) -> + is_PropertyGroup(H) andalso is_LocalRemoteDescriptor_propGrps(T); +is_LocalRemoteDescriptor_propGrps(_) -> + false. + +chk_opt_LocalRemoteDescriptor(D1, D2) -> + chk_OPTIONAL('LocalRemoteDescriptor', D1, D2, + fun is_LocalRemoteDescriptor/1, + fun chk_LocalRemoteDescriptor/2). + +chk_LocalRemoteDescriptor(LRD, LRD) -> + chk_type(fun is_LocalRemoteDescriptor/1, 'LocalRemoteDescriptor', LRD); +chk_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = PG1}, + #'LocalRemoteDescriptor'{propGrps = PG2}) -> + chk_LocalRemoteDescriptor_propGrps(PG1, PG2), + ok; +chk_LocalRemoteDescriptor(LRD1, LRD2) -> + wrong_type('LocalRemoteDescriptor', LRD1, LRD2). + +chk_LocalRemoteDescriptor_propGrps([], []) -> + ok; +chk_LocalRemoteDescriptor_propGrps([] = PG1, PG2) -> + not_equal('LocalRemoteDescriptor_propGrps', PG1, PG2); +chk_LocalRemoteDescriptor_propGrps(PG1, [] = PG2) -> + not_equal('LocalRemoteDescriptor_propGrps', PG1, PG2); +chk_LocalRemoteDescriptor_propGrps([H|T1], [H|T2]) -> + case is_PropertyGroup(H) of + true -> + chk_LocalRemoteDescriptor_propGrps(T1, T2); + false -> + wrong_type('LocalRemoteDescriptor_propGrps_val', H) + end; +chk_LocalRemoteDescriptor_propGrps([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyGroup(H1, H2) end, + 'LocalRemoteDescriptor_propGrps_val'), + chk_LocalRemoteDescriptor_propGrps(T1, T2); +chk_LocalRemoteDescriptor_propGrps(PG1, PG2) -> + wrong_type('LocalRemoteDescriptor_propGrps', PG1, PG2). + + +%% -- PropertyGroup -- + +is_PropertyGroup([]) -> + true; +is_PropertyGroup([H|T]) -> + is_PropertyParm(H) andalso is_PropertyGroup(T); +is_PropertyGroup(_) -> + false. + +chk_PropertyGroup([], []) -> + ok; +chk_PropertyGroup([] = PG1, PG2) -> + not_equal('PropertyGroup', PG1, PG2); +chk_PropertyGroup(PG1, [] = PG2) -> + not_equal('PropertyGroup', PG1, PG2); +chk_PropertyGroup([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_PropertyGroup(T1, T2); + false -> + wrong_type('PropertyGroup_val', H) + end; +chk_PropertyGroup([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, 'PropertyGroup_val'), + chk_PropertyGroup(T1, T2); +chk_PropertyGroup(PG1, PG2) -> + wrong_type('PropertyGroup', PG1, PG2). + + +%% -- TerminationStateDescriptor -- + +is_opt_TerminationStateDescriptor(D) -> + is_OPTIONAL(fun is_TerminationStateDescriptor/1, D). + +is_TerminationStateDescriptor( + #'TerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS}) -> + is_TerminationStateDescriptor_propertyParms(PP) andalso + is_opt_EventBufferControl(EBC) andalso + is_opt_ServiceState(SS); +is_TerminationStateDescriptor(_) -> + false. + +is_TerminationStateDescriptor_propertyParms([]) -> + true; +is_TerminationStateDescriptor_propertyParms([H|T]) -> + is_PropertyParm(H) andalso is_TerminationStateDescriptor_propertyParms(T); +is_TerminationStateDescriptor_propertyParms(_) -> + false. + +chk_opt_TerminationStateDescriptor(D1, D2) -> + chk_OPTIONAL('TerminationStateDescriptor', D1, D2, + fun is_TerminationStateDescriptor/1, + fun chk_TerminationStateDescriptor/2). + +chk_TerminationStateDescriptor(D, D) -> + chk_type(fun is_TerminationStateDescriptor/1, + 'TerminationStateDescriptor', D); +chk_TerminationStateDescriptor( + #'TerminationStateDescriptor'{propertyParms = PP1, + eventBufferControl = EBC1, + serviceState = SS1}, + #'TerminationStateDescriptor'{propertyParms = PP2, + eventBufferControl = EBC2, + serviceState = SS2}) -> + chk_TerminationStateDescriptor_propertyParms(PP1, PP2), + validate( + fun() -> + chk_opt_EventBufferControl(EBC1, EBC2) + end, + 'TerminationStateDescriptor'), + validate( + fun() -> + chk_opt_ServiceState(SS1, SS2) + end, + 'TerminationStateDescriptor'), + ok; +chk_TerminationStateDescriptor(D1, D2) -> + wrong_type('TerminationStateDescriptor', D1, D2). + + +chk_TerminationStateDescriptor_propertyParms([], []) -> + ok; +chk_TerminationStateDescriptor_propertyParms([] = P1, P2) -> + not_equal('TerminationStateDescriptor_propertyParms', P1, P2); +chk_TerminationStateDescriptor_propertyParms(P1, [] = P2) -> + not_equal('TerminationStateDescriptor_propertyParms', P1, P2); +chk_TerminationStateDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_TerminationStateDescriptor_propertyParms(T1, T2); + false -> + wrong_type('TerminationStateDescriptor_propertyParms_val', H) + end; +chk_TerminationStateDescriptor_propertyParms([H1|_], [H2|_]) -> + case (is_PropertyParm(H1) andalso is_PropertyParm(H2)) of + true -> + not_equal('TerminationStateDescriptor_propertyParms_val', H1, H2); + false -> + wrong_type('TerminationStateDescriptor_propertyParms_val', H1, H2) + end; +chk_TerminationStateDescriptor_propertyParms(P1, P2) -> + wrong_type('TerminationStateDescriptor_propertyParms', P1, P2). + + +%% -- EventBufferControl -- + +is_opt_EventBufferControl(asn1_NOVALUE) -> + true; +is_opt_EventBufferControl(EBC) -> + is_EventBufferControl(EBC). + +is_EventBufferControl(EBC) -> + lists:member(EBC, [off, lockStep]). + +chk_opt_EventBufferControl(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_EventBufferControl(EBC1, EBC2) -> + chk_EventBufferControl(EBC1, EBC2). + +chk_EventBufferControl(EBC, EBC) -> + chk_type(fun is_EventBufferControl/1, 'EventBufferControl', EBC); +chk_EventBufferControl(EBC1, EBC2) -> + case (is_EventBufferControl(EBC1) andalso is_EventBufferControl(EBC2)) of + true -> + not_equal('EventBufferControl', EBC1, EBC2); + false -> + wrong_type('EventBufferControl', EBC1, EBC2) + end. + + +%% -- ServiceState -- + +is_opt_ServiceState(asn1_NOVALUE) -> + true; +is_opt_ServiceState(SS) -> + is_ServiceState(SS). + +is_ServiceState(SS) -> + lists:member(SS, [test, outOfSvc, inSvc]). + +chk_opt_ServiceState(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_ServiceState(SS1, SS2) -> + chk_ServiceState(SS1, SS2). + +chk_ServiceState(SS, SS) -> + chk_type(fun is_ServiceState/1, 'ServiceState', SS); +chk_ServiceState(SS1, SS2) -> + case (is_ServiceState(SS1) andalso is_ServiceState(SS2)) of + true -> + not_equal('ServiceState', SS1, SS2); + false -> + wrong_type('ServiceState', SS1, SS2) + end. + + +%% -- MuxDescriptor -- + +is_MuxDescriptor(#'MuxDescriptor'{muxType = MT, + termList = TL, + nonStandardData = NSD}) -> + is_MuxType(MT) andalso + is_MuxDescriptor_termList(TL) andalso + is_NonStandardData(NSD); +is_MuxDescriptor(_) -> + false. + +is_MuxDescriptor_termList([]) -> + true; +is_MuxDescriptor_termList([H|T]) -> + is_TerminationID(H) andalso is_MuxDescriptor_termList(T); +is_MuxDescriptor_termList(_) -> + false. + +chk_MuxDescriptor(D, D) -> + chk_type(fun is_MuxDescriptor/1, 'MuxDescriptor', D); +chk_MuxDescriptor(#'MuxDescriptor'{muxType = MT1, + termList = TL1, + nonStandardData = NSD1}, + #'MuxDescriptor'{muxType = MT2, + termList = TL2, + nonStandardData = NSD2}) -> + validate(fun() -> chk_MuxType(MT1, MT2) end, 'MuxDescriptor'), + chk_MuxDescriptor_termList(TL1, TL2), + validate(fun() -> chk_NonStandardData(NSD1, NSD2) end, 'MuxDescriptor'), + ok; +chk_MuxDescriptor(D1, D2) -> + wrong_type('MuxDescriptor', D1, D2). + +chk_MuxDescriptor_termList([], []) -> + ok; +chk_MuxDescriptor_termList([] = TL1, TL2) -> + not_equal('MuxDescriptor_termList', TL1, TL2); +chk_MuxDescriptor_termList(TL1, [] = TL2) -> + not_equal('MuxDescriptor_termList', TL1, TL2); +chk_MuxDescriptor_termList([H|T1], [H|T2]) -> + case is_TerminationID(H) of + true -> + chk_MuxDescriptor_termList(T1, T2); + false -> + wrong_type('MuxDescriptor_termList_val', H) + end; +chk_MuxDescriptor_termList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TerminationID(H1, H2) end, + 'MuxDescriptor_termList_val'), + chk_MuxDescriptor_termList(T1, T2); +chk_MuxDescriptor_termList(TL1, TL2) -> + wrong_type('MuxDescriptor_termList', TL1, TL2). + + +%% -- MuxType -- + +is_MuxType(MT) -> + lists:member(MT, [h221, h223, h226, v76, nx64k]). + +chk_MuxType(MT, MT) -> + chk_type(fun is_MuxType/1, 'MuxType', MT); +chk_MuxType(MT1, MT2) -> + case (is_MuxType(MT1) andalso is_MuxType(MT2)) of + true -> + not_equal('MuxType', MT1, MT2); + false -> + wrong_type('MuxType', MT1, MT2) + end. + + +%% -- StreamID -- + +is_opt_StreamID(V) -> + is_OPTIONAL(fun is_StreamID/1, V). + +is_StreamID(V) -> + d("is_StreamID -> entry with" + "~n V: ~p", [V]), + is_INTEGER(V, {range, 0, 65535}). + +chk_opt_StreamID(V1, V2) -> + chk_OPTIONAL('StreamID', V1, V2, fun is_StreamID/1, fun chk_StreamID/2). + +chk_StreamID(ID, ID) -> + chk_type(fun is_StreamID/1, 'StreamID', ID); +chk_StreamID(ID1, ID2) -> + case (is_StreamID(ID1) andalso is_StreamID(ID2)) of + true -> + not_equal('StreamID', ID1, ID2); + false -> + wrong_type('StreamID', ID1, ID2) + end. + + +%% -- EventsDescriptor -- + +is_EventsDescriptor(#'EventsDescriptor'{requestID = RID, + eventList = EVL}) -> + d("is_EventsDescriptor -> entry with" + "~n RID: ~p" + "~n EVL: ~p", [RID, EVL]), + is_opt_RequestID(RID) andalso is_EventsDescriptor_eventList(EVL); +is_EventsDescriptor(_) -> + false. + +is_EventsDescriptor_eventList([]) -> + true; +is_EventsDescriptor_eventList([H|T]) -> + is_RequestedEvent(H) andalso is_EventsDescriptor_eventList(T); +is_EventsDescriptor_eventList(_) -> + false. + +chk_EventsDescriptor(D, D) -> + chk_type(fun is_EventsDescriptor/1, 'EventsDescriptor', D); +chk_EventsDescriptor(#'EventsDescriptor'{requestID = RID1, + eventList = EVL1}, + #'EventsDescriptor'{requestID = RID2, + eventList = EVL2}) -> + validate(fun() -> chk_opt_RequestID(RID1, RID2) end, 'EventsDescriptor'), + chk_EventsDescriptor_eventList(EVL1, EVL2), + ok; +chk_EventsDescriptor(D1, D2) -> + wrong_type('EventsDescriptor', D1, D2). + +chk_EventsDescriptor_eventList([], []) -> + ok; +chk_EventsDescriptor_eventList([] = EVL1, EVL2) -> + not_equal('EventsDescriptor_eventList', EVL1, EVL2); +chk_EventsDescriptor_eventList(EVL1, [] = EVL2) -> + not_equal('EventsDescriptor_eventList', EVL1, EVL2); +chk_EventsDescriptor_eventList([H|T1], [H|T2]) -> + case is_RequestedEvent(H) of + true -> + chk_EventsDescriptor_eventList(T1, T2); + false -> + wrong_type('EventsDescriptor_eventList_val', H) + end; +chk_EventsDescriptor_eventList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_RequestedEvent(H1, H2) end, + 'EventsDescriptor_eventList_val'), + chk_EventsDescriptor_eventList(T1, T2); +chk_EventsDescriptor_eventList(EVL1, EVL2) -> + wrong_type('EventsDescriptor_eventList', EVL1, EVL2). + + +%% -- RequestedEvent -- + +is_RequestedEvent(#'RequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}) -> + d("is_RequestedEvent -> entry with" + "~n N: ~p" + "~n SID: ~p" + "~n EA: ~p" + "~n EPL: ~p", [N, SID, EA, EPL]), + is_PkgdName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_RequestedActions(EA) andalso + is_RequestedEvent_evParList(EPL); +is_RequestedEvent(_) -> + false. + +is_RequestedEvent_evParList([]) -> + true; +is_RequestedEvent_evParList([H|T]) -> + is_EventParameter(H) andalso is_RequestedEvent_evParList(T); +is_RequestedEvent_evParList(_) -> + false. + +chk_RequestedEvent(RE, RE) -> + chk_type(fun is_RequestedEvent/1, 'RequestedEvent', RE); +chk_RequestedEvent(#'RequestedEvent'{pkgdName = N1, + streamID = SID1, + eventAction = EA1, + evParList = EPL1}, + #'RequestedEvent'{pkgdName = N2, + streamID = SID2, + eventAction = EA2, + evParList = EPL2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'RequestedEvent'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'RequestedEvent'), + validate(fun() -> chk_opt_RequestedActions(EA1, EA2) end, + 'RequestedEvent'), + chk_RequestedEvent_evParList(EPL1, EPL2), + ok; +chk_RequestedEvent(RE1, RE2) -> + wrong_type('RequestedEvent', RE1, RE2). + +chk_RequestedEvent_evParList([], []) -> + ok; +chk_RequestedEvent_evParList([] = EPL1, EPL2) -> + not_equal('RequestedEvent_evParList', EPL1, EPL2); +chk_RequestedEvent_evParList(EPL1, [] = EPL2) -> + not_equal('RequestedEvent_evParList', EPL1, EPL2); +chk_RequestedEvent_evParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_RequestedEvent_evParList(T1, T2); + false -> + wrong_type('RequestedEvent_evParList_val', H) + end; +chk_RequestedEvent_evParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'RequestedEvent_evParList_val'), + chk_RequestedEvent_evParList(T1, T2); +chk_RequestedEvent_evParList(EPL1, EPL2) -> + wrong_type('RequestedEvent_evParList', EPL1, EPL2). + + +%% -- RequestedActions -- + +is_opt_RequestedActions(asn1_NOVALUE) -> + true; +is_opt_RequestedActions(RA) -> + is_RequestedActions(RA). + +is_RequestedActions(#'RequestedActions'{keepActive = KA, + eventDM = EDM, + secondEvent = SE, + signalsDescriptor = SD}) -> + d("is_RequestedActions -> entry with" + "~n KA: ~p" + "~n EDM: ~p" + "~n SE: ~p" + "~n SD: ~p", [KA, EDM, SE, SD]), + is_opt_BOOLEAN(KA) andalso + is_opt_EventDM(EDM) andalso + is_opt_SecondEventsDescriptor(SE) andalso + is_opt_SignalsDescriptor(SD); +is_RequestedActions(_) -> + false. + +chk_opt_RequestedActions(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_RequestedActions(RA1, RA2) -> + chk_RequestedActions(RA1, RA2). + +chk_RequestedActions(RA, RA) -> + chk_type(fun is_RequestedActions/1, 'RequestedActions', RA); +chk_RequestedActions(#'RequestedActions'{keepActive = KA1, + eventDM = EDM1, + secondEvent = SA1, + signalsDescriptor = SD1}, + #'RequestedActions'{keepActive = KA2, + eventDM = EDM2, + secondEvent = SA2, + signalsDescriptor = SD2}) -> + validate(fun() -> chk_opt_BOOLEAN(KA1, KA2) end, 'RequestedActions'), + validate(fun() -> chk_opt_EventDM(EDM1, EDM2) end, 'RequestedActions'), + validate(fun() -> chk_opt_SecondEventsDescriptor(SA1, SA2) end, + 'RequestedActions'), + validate(fun() -> chk_opt_SignalsDescriptor(SD1, SD2) end, + 'RequestedActions'), + ok; +chk_RequestedActions(RA1, RA2) -> + wrong_type('RequestedActions', RA1, RA2). + + +%% -- EventDM -- + +is_opt_EventDM(EDM) -> + is_OPTIONAL(fun is_EventDM/1, EDM). + +is_EventDM({Tag, Val}) -> + is_EventDM_tag(Tag) andalso is_EventDM_val(Tag, Val); +is_EventDM(_) -> + false. + +is_EventDM_tag(Tag) -> + Tags = [digitMapName, digitMapValue], + lists:member(Tag, Tags). + +is_EventDM_val(digitMapName, Val) -> + is_DigitMapName(Val); +is_EventDM_val(digitMapValue, Val) -> + is_DigitMapValue(Val). + +chk_opt_EventDM(EDM1, EDM2) -> + chk_OPTIONAL('EventDM', EDM1, EDM2, fun is_EventDM/1, fun chk_EventDM/2). + +chk_EventDM(EDM, EDM) -> + chk_type(fun is_EventDM/1, 'EventDM', EDM); +chk_EventDM({Tag, Val1} = EDM1, {Tag, Val2} = EDM2) -> + case (is_EventDM_tag(Tag) andalso + is_EventDM_val(Tag, Val1) andalso + is_EventDM_val(Tag, Val2)) of + true -> + chk_EventDM_val(Tag, Val1, Val2); + false -> + wrong_type('EventDM', EDM1, EDM2) + end; +chk_EventDM({Tag1, Val1} = EDM1, {Tag2, Val2} = EDM2) -> + case ((is_EventDM_tag(Tag1) andalso + is_EventDM_val(Tag1, Val1)) andalso + (is_EventDM_tag(Tag2) andalso + is_EventDM_val(Tag2, Val2))) of + true -> + not_equal('EventDM', EDM1, EDM2); + false -> + wrong_type('EventDM', EDM1, EDM2) + end; +chk_EventDM(EDM1, EDM2) -> + wrong_type('EventDM', EDM1, EDM2). + +chk_EventDM_val(digitMapName, Val1, Val2) -> + validate(fun() -> chk_DigitMapName(Val1, Val2) end, 'EventDM'); +chk_EventDM_val(digitMapValue, Val1, Val2) -> + validate(fun() -> chk_DigitMapValue(Val1, Val2) end, 'EventDM'). + + +%% -- SecondEventsDescriptor -- + +is_opt_SecondEventsDescriptor(asn1_NOVALUE) -> + true; +is_opt_SecondEventsDescriptor(D) -> + is_SecondEventsDescriptor(D). + +is_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = RID, + eventList = EL}) -> + is_opt_RequestID(RID) andalso is_SecondEventsDescriptor_eventList(EL); +is_SecondEventsDescriptor(_) -> + false. + +is_SecondEventsDescriptor_eventList([]) -> + true; +is_SecondEventsDescriptor_eventList([H|T]) -> + is_SecondRequestedEvent(H) andalso is_SecondEventsDescriptor_eventList(T); +is_SecondEventsDescriptor_eventList(_) -> + false. + +chk_opt_SecondEventsDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SecondEventsDescriptor(D1, D2) -> + chk_SecondEventsDescriptor(D1, D2). + +chk_SecondEventsDescriptor(D, D) -> + chk_type(fun is_SecondEventsDescriptor/1, 'SecondEventsDescriptor', D); +chk_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = RID1, + eventList = EL1}, + #'SecondEventsDescriptor'{requestID = RID2, + eventList = EL2}) -> + validate(fun() -> chk_opt_RequestID(RID1, RID2) end, + 'SecondEventsDescriptor'), + chk_SecondEventsDescriptor_eventList(EL1, EL2), + ok; +chk_SecondEventsDescriptor(D1, D2) -> + wrong_type('SecondEventsDescriptor', D1, D2). + +chk_SecondEventsDescriptor_eventList([], []) -> + ok; +chk_SecondEventsDescriptor_eventList([] = EL1, EL2) -> + not_equal('SecondEventsDescriptor_eventList', EL1, EL2); +chk_SecondEventsDescriptor_eventList(EL1, [] = EL2) -> + not_equal('SecondEventsDescriptor_eventList', EL1, EL2); +chk_SecondEventsDescriptor_eventList([H|T1], [H|T2]) -> + case is_SecondRequestedEvent(H) of + true -> + chk_SecondEventsDescriptor_eventList(T1, T2); + false -> + wrong_type('SecondEventsDescriptor_eventList_val', H) + end; +chk_SecondEventsDescriptor_eventList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_SecondRequestedEvent(H1, H2) end, + 'SecondEventsDescriptor_eventList_val'), + chk_SecondEventsDescriptor_eventList(T1, T2); +chk_SecondEventsDescriptor_eventList(L1, L2) -> + wrong_type('SecondEventsDescriptor_eventList_val', L1, L2). + + +%% -- SecondRequestedEvent -- + +is_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}) -> + is_PkgdName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_SecondRequestedActions(EA) andalso + is_SecondRequestedEvent_evParList(EPL); +is_SecondRequestedEvent(_) -> + false. + +is_SecondRequestedEvent_evParList([]) -> + true; +is_SecondRequestedEvent_evParList([H|T]) -> + is_EventParameter(H) andalso is_SecondRequestedEvent_evParList(T); +is_SecondRequestedEvent_evParList(_) -> + false. + +chk_SecondRequestedEvent(RE, RE) -> + chk_type(fun is_SecondRequestedEvent/1, 'SecondRequestedEvent', RE); +chk_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N1, + streamID = SID1, + eventAction = EA1, + evParList = EPL1}, + #'SecondRequestedEvent'{pkgdName = N2, + streamID = SID2, + eventAction = EA2, + evParList = EPL2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'SecondRequestedEvent'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, + 'SecondRequestedEvent'), + validate(fun() -> chk_opt_SecondRequestedActions(EA1, EA2) end, + 'SecondRequestedEvent'), + chk_SecondRequestedEvent_evParList(EPL1, EPL2), + ok; +chk_SecondRequestedEvent(RE1, RE2) -> + wrong_type('SecondRequestedEvent', RE1, RE2). + +chk_SecondRequestedEvent_evParList([], []) -> + ok; +chk_SecondRequestedEvent_evParList([] = EPL1, EPL2) -> + not_equal('SecondRequestedEvent_evParList', EPL1, EPL2); +chk_SecondRequestedEvent_evParList(EPL1, [] = EPL2) -> + not_equal('SecondRequestedEvent_evParList', EPL1, EPL2); +chk_SecondRequestedEvent_evParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_SecondRequestedEvent_evParList(T1, T2); + false -> + wrong_type('SecondRequestedEvent_evParList_val', H) + end; +chk_SecondRequestedEvent_evParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'SecondRequestedEvent_evParList_val'), + chk_SecondRequestedEvent_evParList(T1, T2); +chk_SecondRequestedEvent_evParList(EPL1, EPL2) -> + wrong_type('SecondRequestedEvent_evParList', EPL1, EPL2). + + +%% -- SecondRequestedActions -- + +is_opt_SecondRequestedActions(asn1_NOVALUE) -> + true; +is_opt_SecondRequestedActions(SRA) -> + is_SecondRequestedActions(SRA). + +is_SecondRequestedActions(#'SecondRequestedActions'{keepActive = KA, + eventDM = EDM, + signalsDescriptor = SD}) -> + is_opt_BOOLEAN(KA) andalso + is_opt_EventDM(EDM) andalso + is_opt_SignalsDescriptor(SD); +is_SecondRequestedActions(_) -> + false. + +chk_opt_SecondRequestedActions(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SecondRequestedActions(SRA1, SRA2) -> + chk_SecondRequestedActions(SRA1, SRA2). + +chk_SecondRequestedActions(SRA, SRA) -> + chk_type(fun is_SecondRequestedActions/1, 'SecondRequestedActions', SRA); +chk_SecondRequestedActions( + #'SecondRequestedActions'{keepActive = KA1, + eventDM = EDM1, + signalsDescriptor = SD1}, + #'SecondRequestedActions'{keepActive = KA2, + eventDM = EDM2, + signalsDescriptor = SD2}) -> + validate(fun() -> chk_opt_BOOLEAN(KA1, KA2) end, + 'SecondRequestedActions'), + validate(fun() -> chk_opt_EventDM(EDM1, EDM2) end, + 'SecondRequestedActions'), + validate(fun() -> chk_opt_SignalsDescriptor(SD1, SD2) end, + 'SecondRequestedActions'), + ok; +chk_SecondRequestedActions(SRA1, SRA2) -> + wrong_type('SecondRequestedActions', SRA1, SRA2). + + +%% -- EventBufferDescriptor -- + +is_EventBufferDescriptor([]) -> + true; +is_EventBufferDescriptor([H|T]) -> + is_EventSpec(H) andalso is_EventBufferDescriptor(T); +is_EventBufferDescriptor(_) -> + false. + +chk_EventBufferDescriptor([], []) -> + ok; +chk_EventBufferDescriptor([] = D1, D2) -> + not_equal('EventBufferDescriptor', D1, D2); +chk_EventBufferDescriptor(D1, [] = D2) -> + not_equal('EventBufferDescriptor', D1, D2); +chk_EventBufferDescriptor([H|T1], [H|T2]) -> + case is_EventSpec(H) of + true -> + chk_EventBufferDescriptor(T1, T2); + false -> + wrong_type('EventBufferDescriptor_val', H) + end; +chk_EventBufferDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventSpec(H1, H2) end, + 'EventBufferDescriptor_val'), + chk_EventBufferDescriptor(T1, T2); +chk_EventBufferDescriptor(D1, D2) -> + wrong_type('EventBufferDescriptor_val', D1, D2). + + +%% -- EventSpec -- + +is_EventSpec(#'EventSpec'{eventName = N, + streamID = SID, + eventParList = EPL}) -> + is_EventName(N) andalso + is_opt_StreamID(SID) andalso + is_EventSpec_eventParList(EPL); +is_EventSpec(_) -> + false. + +is_EventSpec_eventParList([]) -> + true; +is_EventSpec_eventParList([H|T]) -> + is_EventParameter(H) andalso is_EventSpec_eventParList(T); +is_EventSpec_eventParList(_) -> + false. + +chk_EventSpec(ES, ES) -> + chk_type(fun is_EventSpec/1, 'EventSpec', ES); +chk_EventSpec(#'EventSpec'{eventName = N1, + streamID = SID1, + eventParList = EPL1}, + #'EventSpec'{eventName = N2, + streamID = SID2, + eventParList = EPL2}) -> + validate(fun() -> chk_EventName(N1, N2) end, 'EventSpec'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'EventSpec'), + chk_EventSpec_eventParList(EPL1, EPL2), + ok; +chk_EventSpec(ES1, ES2) -> + wrong_type('EventSpec', ES1, ES2). + +chk_EventSpec_eventParList([], []) -> + ok; +chk_EventSpec_eventParList([] = EPL1, EPL2) -> + not_equal('EventSpec_eventParList', EPL1, EPL2); +chk_EventSpec_eventParList(EPL1, [] = EPL2) -> + not_equal('EventSpec_eventParList', EPL1, EPL2); +chk_EventSpec_eventParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_EventSpec_eventParList(T1, T2); + false -> + wrong_type('EventSpec_eventParList_val', H) + end; +chk_EventSpec_eventParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'EventSpec_eventParList_val'), + chk_EventSpec_eventParList(T1, T2); +chk_EventSpec_eventParList(EPL1, EPL2) -> + wrong_type('EventSpec_eventParList', EPL1, EPL2). + + +%% -- SignalsDescriptor -- + +is_opt_SignalsDescriptor(asn1_NOVALUE) -> + true; +is_opt_SignalsDescriptor(D) -> + is_SignalsDescriptor(D). + +is_SignalsDescriptor([]) -> + true; +is_SignalsDescriptor([H|T]) -> + is_SignalRequest(H) andalso is_SignalsDescriptor(T); +is_SignalsDescriptor(_) -> + false. + +chk_opt_SignalsDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SignalsDescriptor(D1, D2) -> + chk_SignalsDescriptor(D1, D2). + +chk_SignalsDescriptor([], []) -> + ok; +chk_SignalsDescriptor([] = D1, D2) -> + not_equal('SignalsDescriptor', D1, D2); +chk_SignalsDescriptor(D1, [] = D2) -> + not_equal('SignalsDescriptor', D1, D2); +chk_SignalsDescriptor([H|T1], [H|T2]) -> + case is_SignalRequest(H) of + true -> + chk_SignalsDescriptor(T1, T2); + false -> + wrong_type('SignalsDescriptor_val', H) + end; +chk_SignalsDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_SignalRequest(H1, H2) end, 'SignalsDescriptor_val'), + chk_SignalsDescriptor(T1, T2); +chk_SignalsDescriptor(D1, D2) -> + wrong_type('SignalsDescriptor', D1, D2). + + +%% -- SignalRequest -- + +is_SignalRequest({Tag, Val}) -> + is_SignalRequest_tag(Tag) andalso is_SignalRequest_val(Tag, Val); +is_SignalRequest(_) -> + false. + +is_SignalRequest_tag(Tag) -> + Tags = [signal, seqSigList], + lists:member(Tag, Tags). + +is_SignalRequest_val(signal, Val) -> + is_Signal(Val); +is_SignalRequest_val(seqSigList, Val) -> + is_SeqSigList(Val). + +chk_SignalRequest(R, R) -> + chk_type(fun is_SignalRequest/1, 'SignalRequest', R); +chk_SignalRequest({Tag, Val1} = R1, {Tag, Val2} = R2) -> + case (is_SignalRequest_tag(Tag) andalso + is_SignalRequest_val(Tag, Val1) andalso + is_SignalRequest_val(Tag, Val2)) of + true -> + chk_SignalRequest_val(Tag, Val1, Val2); + false -> + wrong_type('SignalRequest', R1, R2) + end; +chk_SignalRequest({Tag1, Val1} = R1, {Tag2, Val2} = R2) -> + case ((is_SignalRequest_tag(Tag1) andalso + is_SignalRequest_val(Tag1, Val1)) andalso + (is_SignalRequest_tag(Tag2) andalso + is_SignalRequest_val(Tag2, Val2))) of + true -> + not_equal('SignalRequest', R1, R2); + false -> + wrong_type('SignalRequest', R1, R2) + end; +chk_SignalRequest(R1, R2) -> + wrong_type('SignalRequest', R1, R2). + +chk_SignalRequest_val(signal, Val1, Val2) -> + validate(fun() -> chk_Signal(Val1, Val2) end, 'SignalRequest'); +chk_SignalRequest_val(seqSigList, Val1, Val2) -> + validate(fun() -> chk_SeqSigList(Val1, Val2) end, 'SignalRequest'). + + +%% -- SeqSigList -- + +is_SeqSigList(#'SeqSigList'{id = ID, + signalList = SL}) -> + is_INTEGER(ID, {range, 0, 65535}) andalso + is_SeqSigList_signalList(SL); +is_SeqSigList(_) -> + false. + +is_SeqSigList_signalList([]) -> + true; +is_SeqSigList_signalList([H|T]) -> + is_Signal(H) andalso is_SeqSigList_signalList(T); +is_SeqSigList_signalList(_) -> + false. + +chk_SeqSigList(L, L) -> + chk_type(fun is_SeqSigList/1, 'SeqSigList', L); +chk_SeqSigList(#'SeqSigList'{id = ID1, + signalList = SL1}, + #'SeqSigList'{id = ID2, + signalList = SL2}) -> + validate(fun() -> chk_INTEGER(ID1, ID2, {range, 0, 65535}) end, + 'SeqSigList'), + chk_SeqSigList_signalList(SL1, SL2), + ok; +chk_SeqSigList(L1, L2) -> + wrong_type('SeqSigList', L1, L2). + +chk_SeqSigList_signalList([], []) -> + ok; +chk_SeqSigList_signalList([] = L1, L2) -> + not_equal('SeqSigList_signalList', L1, L2); +chk_SeqSigList_signalList(L1, [] = L2) -> + not_equal('SeqSigList_signalList', L1, L2); +chk_SeqSigList_signalList([H|T1], [H|T2]) -> + case is_Signal(H) of + true -> + chk_SeqSigList_signalList(T1, T2); + false -> + wrong_type('SeqSigList_signalList_val', H) + end; +chk_SeqSigList_signalList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_Signal(H1, H2) end, + 'SeqSigList_signalList_val'), + chk_SeqSigList_signalList(T1, T2); +chk_SeqSigList_signalList(L1, L2) -> + wrong_type('SeqSigList_signalList', L1, L2). + + +%% -- Signal -- + +is_Signal(#'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL, + direction = Dir, + requestID = RID}) -> + is_SignalName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_SignalType(ST) andalso + is_opt_INTEGER(Dur, {range, 0, 65535}) andalso + is_opt_NotifyCompletion(NC) andalso + is_opt_BOOLEAN(KA) andalso + is_Signal_sigParList(SPL) andalso + is_opt_SignalDirection(Dir) andalso + is_opt_RequestID(RID). + +is_Signal_sigParList([]) -> + true; +is_Signal_sigParList([H|T]) -> + is_SigParameter(H) andalso is_Signal_sigParList(T); +is_Signal_sigParList(_) -> + false. + +chk_Signal(S, S) -> + chk_type(fun is_Signal/1, 'Signal', S); +chk_Signal(#'Signal'{signalName = N1, + streamID = SID1, + sigType = ST1, + duration = Dur1, + notifyCompletion = NC1, + keepActive = KA1, + sigParList = SPL1, + direction = Dir1, + requestID = RID1}, + #'Signal'{signalName = N2, + streamID = SID2, + sigType = ST2, + duration = Dur2, + notifyCompletion = NC2, + keepActive = KA2, + sigParList = SPL2, + direction = Dir2, + requestID = RID2}) -> + validate(fun() -> chk_SignalName(N1, N2) end, 'Signal'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'Signal'), + validate(fun() -> chk_opt_SignalType(ST1, ST2) end, 'Signal'), + validate(fun() -> chk_opt_INTEGER(Dur1, Dur2, {range, 0, 65535}) end, + 'Signal'), + validate(fun() -> chk_opt_NotifyCompletion(NC1, NC2) end, 'Signal'), + validate(fun() -> chk_opt_BOOLEAN(KA1, KA2) end, 'Signal'), + chk_Signal_sigParList(SPL1, SPL2), + validate(fun() -> chk_opt_SignalDirection(Dir1, Dir2) end, 'Signal'), + validate(fun() -> chk_opt_RequestID(RID1, RID2) end, 'Signal'), + ok; +chk_Signal(S1, S2) -> + wrong_type('Signal', S1, S2). + +chk_Signal_sigParList([], []) -> + ok; +chk_Signal_sigParList([] = L1, L2) -> + not_equal('Signal_sigParList', L1, L2); +chk_Signal_sigParList(L1, [] = L2) -> + not_equal('Signal_sigParList', L1, L2); +chk_Signal_sigParList([H|T1], [H|T2]) -> + case is_SigParameter(H) of + true -> + chk_Signal_sigParList(T1, T2); + false -> + wrong_type('Signal_sigParList_val', H) + end; +chk_Signal_sigParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_SigParameter(H1, H2) end, + 'Signal_sigParList_val'), + chk_Signal_sigParList(T1, T2); +chk_Signal_sigParList(L1, L2) -> + wrong_type('Signal_sigParList', L1, L2). + + +%% -- SignalType -- + +is_opt_SignalType(T) -> + is_OPTIONAL(fun is_SignalType/1, T). + +is_SignalType(T) -> + Types = [brief, onOff, timeOut], + lists:member(T, Types). + +chk_opt_SignalType(T1, T2) -> + chk_OPTIONAL('SignalType', T1, T2, + fun is_SignalType/1, fun chk_SignalType/2). + +chk_SignalType(T, T) -> + chk_type(fun is_SignalType/1, 'SignalType', T); +chk_SignalType(T1, T2) -> + case (is_SignalType(T1) andalso is_SignalType(T2)) of + true -> + not_equal('SignalType', T1, T2); + false -> + wrong_type('SignalType', T1, T2) + end. + + +%% -- SignalDirection -- + +is_opt_SignalDirection(T) -> + is_OPTIONAL(fun is_SignalDirection/1, T). + +is_SignalDirection(Dir) -> + Dirs = [internal, external, both], + lists:member(Dir, Dirs). + +chk_opt_SignalDirection(T1, T2) -> + chk_OPTIONAL('SignalDirection', T1, T2, + fun is_SignalDirection/1, fun chk_SignalDirection/2). + +chk_SignalDirection(Dir, Dir) -> + chk_type(fun is_SignalDirection/1, 'SignalDirection', Dir); +chk_SignalDirection(Dir1, Dir2) -> + case (is_SignalDirection(Dir1) andalso is_SignalDirection(Dir2)) of + true -> + not_equal('SignalDirection', Dir1, Dir2); + false -> + wrong_type('SignalDirection', Dir1, Dir2) + end. + + +%% -- SignalName -- + +is_SignalName(N) -> is_PkgdName(N). + +chk_SignalName(N1, N2) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'SignalName'). + + +%% -- NotifyCompletion -- + +is_opt_NotifyCompletion(NC) -> + is_OPTIONAL(fun is_NotifyCompletion/1, NC). + +is_NotifyCompletion(NC) -> + Valids = [onTimeOut, + onInterruptByEvent, + onInterruptByNewSignalDescr, + otherReason], + lists:all(fun(X) -> lists:member(X, Valids) end, NC). + +chk_opt_NotifyCompletion(NC1, NC2) -> + chk_OPTIONAL('NotifyCompletion', NC1, NC2, + fun is_NotifyCompletion/1, + fun chk_NotifyCompletion/2). + +chk_NotifyCompletion(NC, NC) -> + chk_type(fun is_NotifyCompletion/1, 'NotifyCompletion', NC); +chk_NotifyCompletion(NC1, NC2) -> + case (is_NotifyCompletion(NC1) andalso is_NotifyCompletion(NC2)) of + true -> + not_equal('NotifyCompletion', NC1, NC2); + false -> + wrong_type('NotifyCompletion', NC1, NC2) + end. + + +%% -- SigParameter -- + +is_SigParameter(#'SigParameter'{sigParameterName = N, + value = V, + extraInfo = I}) -> + is_Name(N) andalso + is_Value(V) andalso + is_SigParameter_extraInfo(I); +is_SigParameter(_) -> + false. + +is_SigParameter_extraInfo({Tag, Val}) -> + is_SigParameter_extraInfo_tag(Tag) andalso + is_SigParameter_extraInfo_val(Tag, Val); +is_SigParameter_extraInfo(_) -> + false. + +is_SigParameter_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_SigParameter_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_SigParameter_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_SigParameter_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + +chk_SigParameter(P, P) -> + chk_type(fun is_SigParameter/1, 'SigParameter', P); +chk_SigParameter(#'SigParameter'{sigParameterName = N1, + value = V1, + extraInfo = I1}, + #'SigParameter'{sigParameterName = N2, + value = V2, + extraInfo = I2}) -> + validate(fun() -> chk_Name(N1, N2) end, 'SigParameter'), + validate(fun() -> chk_Value(V1, V2) end, 'SigParameter'), + chk_SigParameter_extraInfo(I1, I2), + ok; +chk_SigParameter(P1, P2) -> + wrong_type('SigParameter', P1, P2). + +chk_SigParameter_extraInfo(EI, EI) -> + chk_type(fun is_SigParameter_extraInfo/1, 'SigParameter_extraInfo', EI); +chk_SigParameter_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> + case (is_SigParameter_extraInfo_tag(Tag) and + is_SigParameter_extraInfo_val(Tag, Val1) and + is_SigParameter_extraInfo_val(Tag, Val2)) of + true -> + chk_SigParameter_extraInfo_val(Tag, Val1, Val2); + false -> + wrong_type('SigParameter_extraInfo', EI1, EI2) + end; +chk_SigParameter_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> + case ((is_SigParameter_extraInfo_tag(Tag1) and + is_SigParameter_extraInfo_val(Tag1, Val1)) and + (is_SigParameter_extraInfo_tag(Tag2) and + is_SigParameter_extraInfo_val(Tag2, Val2))) of + true -> + not_equal('SigParameter_extraInfo', EI1, EI2); + false -> + wrong_type('SigParameter_extraInfo', EI1, EI2) + end; +chk_SigParameter_extraInfo(EI1, EI2) -> + wrong_type('SigParameter_extraInfo', EI1, EI2). + +chk_SigParameter_extraInfo_val(relation, Val1, Val2) -> + validate(fun() -> chk_Relation(Val1, Val2) end, 'SigParameter_extraInfo'); +chk_SigParameter_extraInfo_val(range, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'SigParameter_extraInfo'); +chk_SigParameter_extraInfo_val(sublist, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'SigParameter_extraInfo'). + + +%% -- RequestID -- + +is_opt_RequestID(asn1_NOVALUE) -> + true; +is_opt_RequestID(V) -> + is_RequestID(V). + +is_RequestID(V) -> is_INTEGER(V, {range, 0, 4294967295}). + +chk_opt_RequestID(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_RequestID(V1, V2) -> + chk_RequestID(V1, V2). + +chk_RequestID(ID, ID) -> + chk_type(fun is_RequestID/1, 'RequestID', ID); +chk_RequestID(ID1, ID2) -> + case (is_RequestID(ID1) andalso is_RequestID(ID2)) of + true -> + not_equal('RequestID', ID1, ID2); + false -> + wrong_type('RequestID', ID1, ID2) + end. + + +%% -- ModemDescriptor -- + +is_ModemDescriptor(D) when is_record(D, 'ModemDescriptor') -> + true; +is_ModemDescriptor(_) -> + false. + +chk_ModemDescriptor(D, D) when is_record(D, 'ModemDescriptor') -> + ok; +chk_ModemDescriptor(#'ModemDescriptor'{mtl = MTL1, + mpl = MPL1, + nonStandardData = NSD1}, + #'ModemDescriptor'{mtl = MTL2, + mpl = MPL2, + nonStandardData = NSD2}) -> + chk_ModemDescriptor_mtl(MTL1, MTL2), + chk_ModemDescriptor_mpl(MPL1, MPL2), + chk_opt_NonStandardData(NSD1, NSD2), + ok; +chk_ModemDescriptor(D1, D2) -> + wrong_type('ModemDescriptor', D1, D2). + +chk_ModemDescriptor_mtl([], []) -> + ok; +chk_ModemDescriptor_mtl([] = MTL1, MTL2) -> + not_equal('ModemDescriptor_mtl', MTL1, MTL2); +chk_ModemDescriptor_mtl(MTL1, [] = MTL2) -> + not_equal('ModemDescriptor_mtl', MTL1, MTL2); +chk_ModemDescriptor_mtl([H|T1], [H|T2]) -> + case is_ModemType(H) of + true -> + chk_ModemDescriptor_mtl(T1, T2); + false -> + wrong_type('ModemDescriptor_mtl_val', H) + end; +chk_ModemDescriptor_mtl([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ModemType(H1, H2) end, 'ModemDescriptor_mtl_val'), + chk_ModemDescriptor_mtl(T1, T2); +chk_ModemDescriptor_mtl(MTL1, MTL2) -> + wrong_type('ModemDescriptor_mtl', MTL1, MTL2). + + +chk_ModemDescriptor_mpl([], []) -> + ok; +chk_ModemDescriptor_mpl([] = MPL1, MPL2) -> + not_equal('ModemDescriptor_mpl', MPL1, MPL2); +chk_ModemDescriptor_mpl(MPL1, [] = MPL2) -> + not_equal('ModemDescriptor_mpl', MPL1, MPL2); +chk_ModemDescriptor_mpl([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_ModemDescriptor_mpl(T1, T2); + false -> + wrong_type('ModemDescriptor_mpl_val', H) + end; +chk_ModemDescriptor_mpl([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, 'ModemDescriptor_mpl_val'), + chk_ModemDescriptor_mpl(T1, T2); +chk_ModemDescriptor_mpl(MPL1, MPL2) -> + wrong_type('ModemDescriptor_mpl', MPL1, MPL2). + + +%% -- ModemType -- + +chk_ModemType(MT, MT) -> + case is_ModemType(MT) of + true -> + ok; + false -> + wrong_type('ModemType', MT, MT) + end; +chk_ModemType(MT1, MT2) -> + case (is_ModemType(MT1) andalso is_ModemType(MT2)) of + true -> + not_equal('ModemType', MT1, MT2); + false -> + wrong_type('ModemType', MT1, MT2) + end. + +is_ModemType(MT) -> + lists:member(MT, + [v18, v22, v22bis, v32, v32bis, v34, v90, v91, synchISDN]). + + +%% -- DigitMapDescriptor -- + +is_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Val}) -> + is_opt_DigitMapName(Name) andalso is_opt_DigitMapValue(Val); +is_DigitMapDescriptor(_) -> + false. + +chk_DigitMapDescriptor(D, D) -> + chk_type(fun is_DigitMapDescriptor/1, 'DigitMapDescriptor', D); +chk_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name1, + digitMapValue = Val1}, + #'DigitMapDescriptor'{digitMapName = Name2, + digitMapValue = Val2}) -> + d("chk_DigitMapDescriptor -> entry with" + "~n Name1: ~p" + "~n Name2: ~p" + "~n Val1: ~p" + "~n Val2: ~p", [Name1, Name2, Val1, Val2]), + validate(fun() -> chk_opt_DigitMapName(Name1, Name2) end, + 'DigitMapDescriptor'), + validate(fun() -> chk_opt_DigitMapValue(Val1, Val2) end, + 'DigitMapDescriptor'), + ok; +chk_DigitMapDescriptor(D1, D2) -> + wrong_type('DigitMapDescriptor', D1, D2). + + +%% -- DigitMapName -- + +is_opt_DigitMapName(asn1_NOVALUE) -> + true; +is_opt_DigitMapName(N) -> + is_DigitMapName(N). + +is_DigitMapName(N) -> is_Name(N). + +chk_opt_DigitMapName(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_DigitMapName(N1, N2) -> + chk_DigitMapName(N1, N2). + +chk_DigitMapName(N, N) -> + chk_type(fun is_DigitMapName/1, 'DigitMapName', N); +chk_DigitMapName(N1, N2) -> + case (is_DigitMapName(N1) andalso is_DigitMapName(N2)) of + true -> + not_equal('DigitMapName', N1, N2); + false -> + wrong_type('DigitMapName', N1, N2) + end. + + +%% -- DigitMapValue -- + +is_opt_DigitMapValue(V) -> + is_OPTIONAL(fun is_DigitMapValue/1, V). + +is_DigitMapValue(#'DigitMapValue'{startTimer = Start, + shortTimer = Short, + longTimer = Long, + digitMapBody = Body, + durationTimer = Dur}) -> + is_DigitMapValue_startTimer(Start) andalso + is_DigitMapValue_shortTimer(Short) andalso + is_DigitMapValue_longTimer(Long) andalso + is_IA5String(Body) andalso + is_DigitMapValue_durationTimer(Dur); +is_DigitMapValue(_) -> + false. + +is_DigitMapValue_startTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_startTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +is_DigitMapValue_shortTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_shortTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +is_DigitMapValue_longTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_longTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +is_DigitMapValue_durationTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_durationTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +chk_opt_DigitMapValue(V1, V2) -> + chk_OPTIONAL('DigitMapValue', V1, V2, + fun is_DigitMapValue/1, fun chk_DigitMapValue/2). + +chk_DigitMapValue(#'DigitMapValue'{startTimer = Start1, + shortTimer = Short1, + longTimer = Long1, + digitMapBody = Body1, + durationTimer = Dur1}, + #'DigitMapValue'{startTimer = Start2, + shortTimer = Short2, + longTimer = Long2, + digitMapBody = Body2, + durationTimer = Dur2}) -> + d("chk_DigitMapValue -> entry with" + "~n Start1: ~p" + "~n Start2: ~p" + "~n Short1: ~p" + "~n Short2: ~p" + "~n Long1: ~p" + "~n Long2: ~p" + "~n Body1: ~p" + "~n Body2: ~p" + "~n Dur1: ~p" + "~n Dur2: ~p", [Start1, Start2, + Short1, Short2, + Long1, Long2, + Body1, Body2, + Dur1, Dur2]), + chk_DigitMapValue_startTimer(Start1, Start2), + chk_DigitMapValue_shortTimer(Short1, Short2), + chk_DigitMapValue_longTimer(Long1, Long2), + chk_DigitMapValue_digitMapBody(Body1, Body2), + chk_DigitMapValue_durationTimer(Dur1, Dur2), + ok; +chk_DigitMapValue(V1, V2) -> + wrong_type('DigitMapValue', V1, V2). + +chk_DigitMapValue_startTimer(T, T) -> + chk_type(fun is_DigitMapValue_startTimer/1, 'DigitMapValue_startTimer', T); +chk_DigitMapValue_startTimer(T1, T2) -> + case (is_DigitMapValue_startTimer(T1) andalso + is_DigitMapValue_startTimer(T2)) of + true -> + not_equal('DigitMapValue_startTimer', T1, T2); + false -> + wrong_type('DigitMapValue_startTimer', T1, T2) + end. + +chk_DigitMapValue_shortTimer(T, T) -> + chk_type(fun is_DigitMapValue_shortTimer/1, 'DigitMapValue_shortTimer', T); +chk_DigitMapValue_shortTimer(T1, T2) -> + case (is_DigitMapValue_shortTimer(T1) andalso + is_DigitMapValue_shortTimer(T2)) of + true -> + not_equal('DigitMapValue_shortTimer', T1, T2); + false -> + wrong_type('DigitMapValue_shortTimer', T1, T2) + end. + +chk_DigitMapValue_longTimer(T, T) -> + chk_type(fun is_DigitMapValue_longTimer/1, 'DigitMapValue_longTimer', T); +chk_DigitMapValue_longTimer(T1, T2) -> + case (is_DigitMapValue_longTimer(T1) andalso + is_DigitMapValue_longTimer(T2)) of + true -> + not_equal('DigitMapValue_longTimer', T1, T2); + false -> + wrong_type('DigitMapValue_longTimer', T1, T2) + end. + +chk_DigitMapValue_durationTimer(T, T) -> + chk_type(fun is_DigitMapValue_durationTimer/1, + 'DigitMapValue_durationTimer', T); +chk_DigitMapValue_durationTimer(T1, T2) -> + case (is_DigitMapValue_durationTimer(T1) andalso + is_DigitMapValue_durationTimer(T2)) of + true -> + not_equal('DigitMapValue_durationTimer', T1, T2); + false -> + wrong_type('DigitMapValue_durationTimer', T1, T2) + end. + +chk_DigitMapValue_digitMapBody(B, B) -> + d("chk_DigitMapValue_digitMapBody -> entry with" + "~n B: ~p", [B]), + chk_type(fun is_IA5String/1, 'DigitMapValue_digitMapBody', B); +chk_DigitMapValue_digitMapBody(B1, B2) -> + d("chk_DigitMapValue_digitMapBody -> entry with" + "~n B1: ~p" + "~n B2: ~p", [B1, B2]), + case (is_IA5String(B1) andalso is_IA5String(B2)) of + true -> + %% If they are different it could be because + %% of trailing tab's and newline's. + case compare_strings(B1, B2) of + {[], []} -> + ok; + {Str1, []} -> + case strip_tab_and_newline(Str1) of + [] -> + ok; + _ -> + not_equal('DigitMapValue_digitMapBody', B1, B2) + end; + {[], Str2} -> + case strip_tab_and_newline(Str2) of + [] -> + ok; + _ -> + not_equal('DigitMapValue_digitMapBody', B1, B2) + end; + _ -> + not_equal('DigitMapValue_digitMapBody', B1, B2) + end; + false -> + wrong_type('DigitMapValue_digitMapBody', B1, B2) + end. + +%% -- ServiceChangeParm -- + +is_ServiceChangeParm(#'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeAddress = A, + serviceChangeVersion = V, + serviceChangeProfile = P, + serviceChangeReason = R, + serviceChangeDelay = D, + serviceChangeMgcId = Id, + timeStamp = TS, + nonStandardData = NSD, + serviceChangeInfo = I}) -> + is_ServiceChangeMethod(M) andalso + is_opt_ServiceChangeAddress(A) andalso + is_opt_INTEGER(V, {range, 0, 99}) andalso + is_opt_ServiceChangeProfile(P) andalso + is_Value(R) andalso + is_opt_INTEGER(D, {range, 0, 4294967295}) andalso + is_opt_MId(Id) andalso + is_opt_TimeNotation(TS) andalso + is_opt_NonStandardData(NSD) andalso + is_opt_AuditDescriptor(I); +is_ServiceChangeParm(_) -> + false. + +chk_ServiceChangeParm(P, P) -> + chk_type(fun is_ServiceChangeParm/1, 'ServiceChangeParm', P); +chk_ServiceChangeParm(#'ServiceChangeParm'{serviceChangeMethod = M1, + serviceChangeAddress = A1, + serviceChangeVersion = V1, + serviceChangeProfile = P1, + serviceChangeReason = R1, + serviceChangeDelay = D1, + serviceChangeMgcId = Id1, + timeStamp = TS1, + nonStandardData = NSD1, + serviceChangeInfo = I1}, + #'ServiceChangeParm'{serviceChangeMethod = M2, + serviceChangeAddress = A2, + serviceChangeVersion = V2, + serviceChangeProfile = P2, + serviceChangeReason = R2, + serviceChangeDelay = D2, + serviceChangeMgcId = Id2, + timeStamp = TS2, + nonStandardData = NSD2, + serviceChangeInfo = I2}) -> + validate(fun() -> chk_ServiceChangeMethod(M1, M2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_ServiceChangeAddress(A1, A2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_INTEGER(V1, V2, {range, 0, 99}) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_ServiceChangeProfile(P1, P2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_Value(R1, R2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_INTEGER(D1, D2, {range, 0, 4294967295}) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_MId(Id1, Id2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_TimeNotation(TS1, TS2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_NonStandardData(NSD1, NSD2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_AuditDescriptor(I1, I2) end, + 'ServiceChangeParm'), + ok; +chk_ServiceChangeParm(P1, P2) -> + wrong_type('ServiceChangeParm', P1, P2). + + +%% -- ServiceChangeAddress -- + +is_opt_ServiceChangeAddress(A) -> + is_OPTIONAL(fun is_ServiceChangeAddress/1, A). + +is_ServiceChangeAddress({Tag, Val}) -> + is_ServiceChangeAddress_tag(Tag) andalso + is_ServiceChangeAddress_val(Tag, Val); +is_ServiceChangeAddress(_) -> + false. + +is_ServiceChangeAddress_tag(Tag) -> + Tags = [portNumber, ip4Address, ip6Address, domainName, deviceName, + mtpAddress], + lists:member(Tag, Tags). + +is_ServiceChangeAddress_val(portNumber, Val) -> + is_INTEGER(Val, {range, 0, 65535}); +is_ServiceChangeAddress_val(ip4Address, Val) -> + is_IP4Address(Val); +is_ServiceChangeAddress_val(ip6Address, Val) -> + is_IP6Address(Val); +is_ServiceChangeAddress_val(domainName, Val) -> + is_DomainName(Val); +is_ServiceChangeAddress_val(deviceName, Val) -> + is_PathName(Val); +is_ServiceChangeAddress_val(mtpAddress, Val) -> + is_OCTET_STRING(Val, {range, 2, 4}). + + +chk_opt_ServiceChangeAddress(A1, A2) -> + chk_OPTIONAL('ServiceChangeAddress', A1, A2, + fun is_ServiceChangeAddress/1, + fun chk_ServiceChangeAddress/2). + +chk_ServiceChangeAddress(A, A) -> + chk_type(fun is_ServiceChangeAddress/1, 'ServiceChangeAddress', A); +chk_ServiceChangeAddress({Tag, Val1} = A1, {Tag, Val2} = A2) -> + case (is_ServiceChangeAddress_tag(Tag) andalso + is_ServiceChangeAddress_val(Tag, Val1) andalso + is_ServiceChangeAddress_val(Tag, Val2)) of + true -> + chk_ServiceChangeAddress_val(Tag, Val1, Val2); + false -> + wrong_type('ServiceChangeAddress', A1, A2) + end; +chk_ServiceChangeAddress({Tag1, Val1} = A1, {Tag2, Val2} = A2) -> + case ((is_ServiceChangeAddress_tag(Tag1) andalso + is_ServiceChangeAddress_val(Tag1, Val1)) andalso + (is_ServiceChangeAddress_tag(Tag2) andalso + is_ServiceChangeAddress_val(Tag2, Val2))) of + true -> + not_equal('ServiceChangeAddress', A1, A2); + false -> + wrong_type('ServiceChangeAddress', A1, A2) + end; +chk_ServiceChangeAddress(A1, A2) -> + wrong_type('ServiceChangeAddress', A1, A2). + +chk_ServiceChangeAddress_val(portNumber, Val1, Val2) -> + validate(fun() -> chk_INTEGER(Val1, Val2, {range, 0, 99}) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(ip4Address, Val1, Val2) -> + validate(fun() -> chk_IP4Address(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(ip6Address, Val1, Val2) -> + validate(fun() -> chk_IP6Address(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(domainName, Val1, Val2) -> + validate(fun() -> chk_DomainName(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(deviceName, Val1, Val2) -> + validate(fun() -> chk_PathName(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(mtpAddress, Val1, Val2) -> + validate(fun() -> chk_OCTET_STRING(Val1, Val2, {range, 2, 4}) end, + 'ServiceChangeAddress'). + + +%% -- ServiceChangeResParm -- + +is_ServiceChangeResParm(#'ServiceChangeResParm'{serviceChangeMgcId = Id, + serviceChangeAddress = A, + serviceChangeVersion = V, + serviceChangeProfile = P, + timeStamp = TS}) -> + is_opt_MId(Id) andalso + is_opt_ServiceChangeAddress(A) andalso + is_opt_INTEGER(V, {range, 0, 99}) andalso + is_opt_ServiceChangeProfile(P) andalso + is_opt_TimeNotation(TS); +is_ServiceChangeResParm(_) -> + false. + +chk_ServiceChangeResParm(P, P) -> + chk_type(fun is_ServiceChangeResParm/1, 'ServiceChangeResParm', P); +chk_ServiceChangeResParm( + #'ServiceChangeResParm'{serviceChangeMgcId = Id1, + serviceChangeAddress = A1, + serviceChangeVersion = V1, + serviceChangeProfile = P1, + timeStamp = TS1}, + #'ServiceChangeResParm'{serviceChangeMgcId = Id2, + serviceChangeAddress = A2, + serviceChangeVersion = V2, + serviceChangeProfile = P2, + timeStamp = TS2}) -> + validate(fun() -> chk_opt_MId(Id1, Id2) end, 'ServiceChangeResParm'), + validate(fun() -> chk_opt_ServiceChangeAddress(A1, A2) end, + 'ServiceChangeResParm'), + validate(fun() -> chk_opt_INTEGER(V1, V2, {range, 0, 99}) end, + 'ServiceChangeResParm'), + validate(fun() -> chk_opt_ServiceChangeProfile(P1, P2) end, + 'ServiceChangeResParm'), + validate(fun() -> chk_opt_TimeNotation(TS1, TS2) end, + 'ServiceChangeResParm'), + ok; +chk_ServiceChangeResParm(P1, P2) -> + wrong_type('ServiceChangeResParm', P1, P2). + + +%% -- ServiceChangeMethod -- + +is_ServiceChangeMethod(M) -> + Methods = [failover, forced, graceful, restart, disconnected, handOff], + lists:member(M, Methods). + +chk_ServiceChangeMethod(M, M) -> + chk_type(fun is_ServiceChangeMethod/1, 'ServiceChangeMethod', M); +chk_ServiceChangeMethod(M1, M2) -> + case (is_ServiceChangeMethod(M1) andalso is_ServiceChangeMethod(M2)) of + true -> + not_equal('ServiceChangeMethod', M1, M2); + false -> + wrong_type('ServiceChangeMethod', M1, M2) + end. + + +%% -- ServiceChangeProfile -- + +is_opt_ServiceChangeProfile(P) -> + is_OPTIONAL(fun is_ServiceChangeProfile/1, P). + +is_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = N}) -> + is_IA5String(N, {range, 1, 67}); +is_ServiceChangeProfile(_) -> + false. + +chk_opt_ServiceChangeProfile(P1, P2) -> + chk_OPTIONAL('ServiceChangeProfile', P1, P2, + fun is_ServiceChangeProfile/1, + fun chk_ServiceChangeProfile/2). + +chk_ServiceChangeProfile(P, P) -> + chk_type(fun is_ServiceChangeProfile/1, 'ServiceChangeProfile', P); +chk_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = N1}, + #'ServiceChangeProfile'{profileName = N2}) -> + validate(fun() -> chk_IA5String(N1, N2, {range, 1, 67}) end, + 'ServiceChangeProfile'), + ok; +chk_ServiceChangeProfile(P1, P2) -> + wrong_type('ServiceChangeProfile', P1, P2). + + +%% -- PackagesDescriptor -- + +is_PackagesDescriptor([]) -> + true; +is_PackagesDescriptor([H|T]) -> + is_PackagesItem(H) andalso is_PackagesDescriptor(T); +is_PackagesDescriptor(_) -> + false. + +chk_PackagesDescriptor([], []) -> + ok; +chk_PackagesDescriptor([] = D1, D2) -> + not_equal('PackagesDescriptor', D1, D2); +chk_PackagesDescriptor(D1, [] = D2) -> + not_equal('PackagesDescriptor', D1, D2); +chk_PackagesDescriptor([H|T1], [H|T2]) -> + case is_PackagesItem(H) of + true -> + chk_PackagesDescriptor(T1, T2); + false -> + wrong_type('PackagesDescriptor_val', H) + end; +chk_PackagesDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PackagesItem(H1, H2) end, + 'PackagesDescriptor_val'), + chk_PackagesDescriptor(T1, T2); +chk_PackagesDescriptor(D1, D2) -> + wrong_type('PackagesDescriptor_val', D1, D2). + + +%% -- PackagesItem -- + +is_PackagesItem(#'PackagesItem'{packageName = N, + packageVersion = V}) -> + is_Name(N) andalso is_INTEGER(V, {range, 0, 99}); +is_PackagesItem(_) -> + false. + +chk_PackagesItem(I, I) -> + chk_type(fun is_PackagesItem/1, 'PackagesItem', I); +chk_PackagesItem(#'PackagesItem'{packageName = N1, + packageVersion = V1}, + #'PackagesItem'{packageName = N2, + packageVersion = V2}) -> + validate(fun() -> chk_Name(N1, N2) end, 'PackagesItem'), + validate(fun() -> chk_INTEGER(V1, V2, {range, 0, 99}) end, 'PackagesItem'), + ok; +chk_PackagesItem(I1, I2) -> + wrong_type('PackagesItem', I1, I2). + + +%% -- StatisticsDescriptor -- + +is_opt_StatisticsDescriptor(D) -> + is_OPTIONAL(fun is_StatisticsDescriptor/1, D). + +is_StatisticsDescriptor([]) -> + true; +is_StatisticsDescriptor([H|T]) -> + is_StatisticsParameter(H) andalso is_StatisticsDescriptor(T); +is_StatisticsDescriptor(_) -> + false. + +chk_opt_StatisticsDescriptor(D1, D2) -> + chk_OPTIONAL('StatisticsDescriptor', D1, D2, + fun is_StatisticsDescriptor/1, + fun chk_StatisticsDescriptor/2). + +chk_StatisticsDescriptor([], []) -> + ok; +chk_StatisticsDescriptor([] = D1, D2) -> + not_equal('StatisticsDescriptor', D1, D2); +chk_StatisticsDescriptor(D1, [] = D2) -> + not_equal('StatisticsDescriptor', D1, D2); +chk_StatisticsDescriptor([H|T1], [H|T2]) -> + case is_StatisticsParameter(H) of + true -> + chk_StatisticsDescriptor(T1, T2); + false -> + wrong_type('StatisticsDescriptor_val', H) + end; +chk_StatisticsDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_StatisticsParameter(H1, H2) end, + 'StatisticsDescriptor_val'), + chk_StatisticsDescriptor(T1, T2); +chk_StatisticsDescriptor(D1, D2) -> + wrong_type('StatisticsDescriptor_val', D1, D2). + + +%% -- StatisticsParameter -- + +is_StatisticsParameter(#'StatisticsParameter'{statName = N, + statValue = V}) -> + is_PkgdName(N) andalso is_opt_Value(V); +is_StatisticsParameter(_) -> + false. + +chk_StatisticsParameter(P, P) -> + chk_type(fun is_StatisticsParameter/1, 'StatisticsParameter', P); +chk_StatisticsParameter(#'StatisticsParameter'{statName = N1, + statValue = V1}, + #'StatisticsParameter'{statName = N2, + statValue = V2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'StatisticsParameter'), + validate(fun() -> chk_opt_Value(V1, V2) end, 'StatisticsParameter'), + ok; +chk_StatisticsParameter(P1, P2) -> + wrong_type('StatisticsParameter', P1, P2). + + +%% -- NonStandardData -- + +is_opt_NonStandardData(asn1_NOVALUE) -> + true; +is_opt_NonStandardData(NSD) -> + is_NonStandardData(NSD). + +%% is_NonStandardData(#'NonStandardData'{nonStandardIdentifier = Id, +%% data = D}) -> +%% is_NonStandardIdentifier(Id) andalso is_OCTET_STRING(D); +%% is_NonStandardData(_) -> +%% false. + +is_NonStandardData(_) -> + true. + +chk_opt_NonStandardData(asn1_NOVALUE, asn1_NOVALUE) -> + true; +chk_opt_NonStandardData(NSD1, NSD2) -> + chk_NonStandardData(NSD1, NSD2). + +chk_NonStandardData(NSD, NSD) -> + chk_type(fun is_NonStandardData/1, 'NonStandardData', NSD); +%% chk_NonStandardData(#'NonStandardData'{nonStandardIdentifier = Id1, +%% data = D1}, +%% #'NonStandardData'{nonStandardIdentifier = Id2, +%% data = D2}) -> +%% validate(fun() -> chk_NonStandardIdentifier(Id1, Id2) end, +%% 'NonStandardData'), +%% validate(fun() -> chk_OCTET_STRING(D1, D2) end, 'NonStandardData'), +%% ok; +%% chk_NonStandardData(NSD1, NSD2) -> +%% wrong_type('NonStandardData', NSD1, NSD2). +chk_NonStandardData(NSD1, NSD2) -> + not_equal('NonStandardData', NSD1, NSD2). + + +%% -- NonStandardIdentifier -- + +%% is_NonStandardIdentifier({Tag, Val}) -> +%% is_NonStandardIdentifier_tag(Tag) andalso +%% is_NonStandardIdentifier_val(Tag, Val); +%% is_NonStandardIdentifier(_) -> +%% false. + +%% is_NonStandardIdentifier_tag(Tag) -> +%% Tags = [object, h221NonStandard, experimental], +%% lists:member(Tag, Tags). + +%% is_NonStandardIdentifier_val(object, Val) -> +%% is_OBJECT_IDENTIFIER(Val); +%% is_NonStandardIdentifier_val(h221NonStandard, Val) -> +%% is_H221NonStandard(Val); +%% is_NonStandardIdentifier_val(experimental, Val) -> +%% is_IA5String(Val, {exact, 8}). + +%% chk_NonStandardIdentifier(Id, Id) -> +%% chk_type(fun is_NonStandardIdentifier/1, 'NonStandardIdentifier', Id); +%% chk_NonStandardIdentifier({Tag, Val1} = Id1, {Tag, Val2} = Id2) -> +%% case (is_NonStandardIdentifier_tag(Tag) andalso +%% is_NonStandardIdentifier_val(Tag, Val1) andalso +%% is_NonStandardIdentifier_val(Tag, Val1)) of +%% true -> +%% chk_NonStandardIdentifier_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('NonStandardIdentifier', Id1, Id2) +%% end; +%% chk_NonStandardIdentifier({Tag1, Val1} = Id1, {Tag2, Val2} = Id2) -> +%% case ((is_NonStandardIdentifier_tag(Tag1) andalso +%% is_NonStandardIdentifier_val(Tag1, Val1)) andalso +%% (is_NonStandardIdentifier_tag(Tag2) andalso +%% is_NonStandardIdentifier_val(Tag2, Val1))) of +%% true -> +%% not_equal('NonStandardIdentifier', Id1, Id2); +%% false -> +%% wrong_type('NonStandardIdentifier', Id1, Id2) +%% end; +%% chk_NonStandardIdentifier(Id1, Id2) -> +%% wrong_type('NonStandardIdentifier', Id1, Id2). + +%% chk_NonStandardIdentifier_val(object, Val1, Val2) -> +%% chk_OBJECT_IDENTIFIER(Val1, Val2); +%% chk_NonStandardIdentifier_val(h221NonStandard, Val1, Val2) -> +%% chk_H221NonStandard(Val1, Val2); +%% chk_NonStandardIdentifier_val(experimental, Val1, Val2) -> +%% chk_IA5String(Val1, Val2, {exact, 8}). + + +%% -- H221NonStandard -- + +%% is_H221NonStandard(#'H221NonStandard'{t35CountryCode1 = CC1, +%% t35CountryCode2 = CC2, +%% t35Extension = Ext, +%% manufacturerCode = MC}) -> +%% is_INTEGER(CC1, {range, 0, 255}) andalso +%% is_INTEGER(CC2, {range, 0, 255}) andalso +%% is_INTEGER(Ext, {range, 0, 255}) andalso +%% is_INTEGER(Ext, {range, 0, 65535}); +%% is_H221NonStandard(_) -> +%% false. + +%% chk_H221NonStandard(NS, NS) -> +%% chk_type(fun is_H221NonStandard/1, 'H221NonStandard', NS); +%% chk_H221NonStandard(#'H221NonStandard'{t35CountryCode1 = CC11, +%% t35CountryCode2 = CC21, +%% t35Extension = Ext1, +%% manufacturerCode = MC1}, +%% #'H221NonStandard'{t35CountryCode1 = CC12, +%% t35CountryCode2 = CC22, +%% t35Extension = Ext2, +%% manufacturerCode = MC2}) -> +%% validate(fun() -> chk_INTEGER(CC11, CC12, {range, 0, 255}) end, +%% 'H221NonStandard'), +%% validate(fun() -> chk_INTEGER(CC21, CC22, {range, 0, 255}) end, +%% 'H221NonStandard'), +%% validate(fun() -> chk_INTEGER(Ext1, Ext2, {range, 0, 255}) end, +%% 'H221NonStandard'), +%% validate(fun() -> chk_INTEGER(MC1, MC2, {range, 0, 65535}) end, +%% 'H221NonStandard'), +%% ok; +%% chk_H221NonStandard(NS1, NS2) -> +%% wrong_type('H221NonStandard', NS1, NS2). + + +%% -- TimeNotation -- + +is_opt_TimeNotation(asn1_NOVALUE) -> + true; +is_opt_TimeNotation(TN) -> + is_TimeNotation(TN). + +is_TimeNotation(#'TimeNotation'{date = D, time = T}) -> + is_IA5String(D, {exact, 8}) andalso is_IA5String(T, {exact, 8}); +is_TimeNotation(_) -> + false. + +chk_opt_TimeNotation(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_TimeNotation(TN1, TN2) -> + chk_TimeNotation(TN1, TN2). + +chk_TimeNotation(TN, TN) -> + chk_type(fun is_TimeNotation/1, 'TimeNotation', TN); +chk_TimeNotation(#'TimeNotation'{date = D1, time = T1}, + #'TimeNotation'{date = D2, time = T2}) -> + validate(fun() -> chk_IA5String(D1, D2, {exact, 8}) end, 'TimeNotation'), + validate(fun() -> chk_IA5String(T1, T2, {exact, 8}) end, 'TimeNotation'), + ok; +chk_TimeNotation(TN1, TN2) -> + wrong_type('TimeNotation', TN1, TN2). + + +%% -- Value -- + +is_opt_Value(V) -> + is_OPTIONAL(fun is_Value/1, V). + +is_Value([]) -> + true; +is_Value([H|T]) -> + is_OCTET_STRING(H) andalso is_Value(T); +is_Value(_) -> + false. + +chk_opt_Value(V1, V2) -> + chk_OPTIONAL('Value', V1, V2, fun is_Value/1, fun chk_Value/2). + +chk_Value(V, V) -> + case is_Value(V) of + true -> + ok; + false -> + wrong_type('Value', V, V) + end; +chk_Value(V1, V2) -> + case (is_Value(V1) andalso is_Value(V2)) of + true -> + not_equal('Value', V1, V2); + false -> + wrong_type('Value', V1, V2) + end. + + +%% ---------------------------------------------------------------------- +%% Basic type check functions +%% ---------------------------------------------------------------------- + + +is_opt_BOOLEAN(B) -> + is_OPTIONAL(fun is_BOOLEAN/1, B). + +is_BOOLEAN(B) -> + lists:member(B, [true, false]). + +chk_opt_BOOLEAN(B1, B2) -> + chk_OPTIONAL('BOOLEAN', B1, B2, fun is_BOOLEAN/1, fun chk_BOOLEAN/2). + +chk_BOOLEAN(B, B) -> + chk_type(fun is_BOOLEAN/1, 'BOOLEAN', B); +chk_BOOLEAN(B1, B2) -> + case (is_BOOLEAN(B1) andalso is_BOOLEAN(B2)) of + true -> + not_equal('BOOLEAN', B1, B2); + false -> + wrong_type('BOOLEAN', B1, B2) + end. + + +is_IA5String(S) when is_list(S) -> + true; +is_IA5String(_) -> + false. + +% chk_IA5String(S, S) -> +% chk_type(fun is_IA5String/1, 'IA5String', S); +% chk_IA5String(S1, S2) -> +% case (is_IA5String(S1) andalso is_IA5String(S2)) of +% true -> +% not_equal('IA5String', S1, S2); +% false -> +% wrong_type('IA5String', S1, S2) +% end. + +is_IA5String(S, _) when is_list(S) -> + true; +is_IA5String(_, _) -> + false. + +chk_IA5String(S, S, R) -> + chk_type(fun is_IA5String/2, 'IA5String', S, R); +chk_IA5String(S1, S2, R) -> + case (is_IA5String(S1, R) andalso is_IA5String(S2, R)) of + true -> + not_equal('IA5String', S1, S2); + false -> + wrong_type('IA5String', S1, S2) + end. + + +is_OCTET_STRING(L) -> is_OCTET_STRING(L, any). + +is_OCTET_STRING(L, any) when is_list(L) -> + true; +is_OCTET_STRING(L, {exact, Len}) when is_list(L) andalso (length(L) =:= Len) -> + true; +is_OCTET_STRING(L, {atleast, Len}) when is_list(L) andalso (Len =< length(L)) -> + true; +is_OCTET_STRING(L, {atmost, Len}) when is_list(L) andalso (length(L) =< Len) -> + true; +is_OCTET_STRING(L, {range, Min, Max}) + when is_list(L) andalso (Min =< length(L)) andalso (length(L) =< Max) -> + true; +is_OCTET_STRING(_, _) -> + false. + +%% chk_OCTET_STRING(L1, L2) -> +%% chk_OCTET_STRING(L1, L2, any). + +chk_OCTET_STRING(L, L, R) -> + chk_type(fun is_OCTET_STRING/2, 'OCTET STRING', L, R); +chk_OCTET_STRING(L1, L2, R) -> + case (is_OCTET_STRING(L1, R) andalso is_OCTET_STRING(L2, R)) of + true -> + not_equal('OCTET STRING', L1, L2); + false -> + wrong_type('OCTET STRING', L1, L2) + end. + + +%% is_OBJECT_IDENTIFIER(_) -> +%% true. + +%% chk_OBJECT_IDENTIFIER(X, X) -> +%% ok; +%% chk_OBJECT_IDENTIFIER(X1, X2) -> +%% not_equal('OBJECT IDENTIFIER', X1, X2). + + +is_opt_NULL(N) -> + is_OPTIONAL(fun is_NULL/1, N). + +is_NULL('NULL') -> + true; +is_NULL(_) -> + false. + +chk_opt_NULL(N1, N2) -> + chk_OPTIONAL('NULL', N1, N2, fun is_NULL/1, fun chk_NULL/2). + +chk_NULL(N, N) -> + chk_type(fun is_NULL/1, 'NULL', N); +chk_NULL(N1, N2) -> + case (is_NULL(N1) andalso is_NULL(N2)) of + true -> + not_equal('NULL', N1, N2); + false -> + wrong_type('NULL', N1, N2) + end. + + +is_opt_INTEGER(I, R) -> + is_OPTIONAL(fun(X) -> is_INTEGER(X, R) end, I). + +is_INTEGER(I, any) when is_integer(I) -> + true; +is_INTEGER(I, {exact, I}) when is_integer(I) -> + true; +is_INTEGER(I, {atleast, Min}) when is_integer(I) andalso is_integer(Min) andalso (Min =< I) -> + true; +is_INTEGER(I, {atmost, Max}) when is_integer(I) andalso is_integer(Max) andalso (I =< Max) -> + true; +is_INTEGER(I, {range, Min, Max}) + when is_integer(I) andalso + is_integer(Min) andalso + is_integer(Max) andalso + (Min =< I) andalso (I =< Max) -> + true; +is_INTEGER(_, _) -> + false. + +chk_opt_INTEGER(I1, I2, R) -> + chk_OPTIONAL('INTEGER', I1, I2, + fun(X) -> is_INTEGER(X, R) end, + fun(Y1, Y2) -> chk_INTEGER(Y1, Y2, R) end). + +chk_INTEGER(I, I, R) -> + chk_type(fun is_INTEGER/2, 'INTEGER', I, R); +chk_INTEGER(I1, I2, R) -> + case (is_INTEGER(I1, R) andalso is_INTEGER(I2, R)) of + true -> + not_equal('INTEGER', I1, I2); + false -> + wrong_type('INTEGER', I1, I2) + end. + + +%% ---------------------------------------------------------------------- +%% Various utility functions +%% ---------------------------------------------------------------------- + + +to_lower([C|Cs]) when (C >= $A) andalso (C =< $Z) -> + [C+($a-$A)|to_lower(Cs)]; +to_lower([C|Cs]) -> + [C|to_lower(Cs)]; +to_lower([]) -> + []. + + +validate(F, Type) when is_function(F) -> + case (catch F()) of + {error, Reason} -> + error({Type, Reason}); + ok -> + ok + end. + + +chk_type(F, T, V) when is_function(F) andalso is_atom(T) -> + case F(V) of + true -> + ok; + false -> + wrong_type(T, V) + end. + +chk_type(F, T, V1, V2) when is_function(F) andalso is_atom(T) -> + case F(V1, V2) of + true -> + ok; + false -> + wrong_type(T, V1) + end. + + +is_OPTIONAL(_, asn1_NOVALUE) -> + true; +is_OPTIONAL(F, Val) when is_function(F) -> + F(Val). + +chk_OPTIONAL(_, asn1_NOVALUE, asn1_NOVALUE, _, _) -> + ok; +chk_OPTIONAL(Type, asn1_NOVALUE = V1, V2, IS, _CHK) when is_function(IS) -> + case IS(V2) of + true -> + not_equal(Type, V1, V2); + false -> + wrong_type(Type, V1, V2) + end; +chk_OPTIONAL(Type, V1, asn1_NOVALUE = V2, IS, _CHK) when is_function(IS) -> + case IS(V1) of + true -> + not_equal(Type, V1, V2); + false -> + wrong_type(Type, V1, V2) + end; +chk_OPTIONAL(_Type, V1, V2, _IS, CHK) when is_function(CHK) -> + CHK(V1, V2). + + +%% ---------------------------------------------------------------------- + +compare_strings([] = L1, L2) -> + {L1, L2}; +compare_strings(L1, [] = L2) -> + {L1, L2}; +compare_strings([H|T1], [H|T2]) -> + compare_strings(T1, T2); +compare_strings(L1, L2) -> + {L1, L2}. + +strip_tab_and_newline([]) -> + []; +strip_tab_and_newline([$\n|T]) -> + strip_tab_and_newline(T); +strip_tab_and_newline([$\t|T]) -> + strip_tab_and_newline(T); +strip_tab_and_newline([H|T]) -> + [H|strip_tab_and_newline(T)]. + + +%% ---------------------------------------------------------------------- + +atmost_once(Type, Val) -> + error({atmost_once, {Type, Val}}). + +wrong_type(Type, Val) -> + error({wrong_type, {Type, Val}}). + +wrong_type(Type, Val1, Val2) -> + error({wrong_type, {Type, Val1, Val2}}). + +not_equal(What, Val1, Val2) -> + error({not_equal, {What, Val1, Val2}}). + +error(Reason) -> + throw({error, Reason}). + + +%% ---------------------------------------------------------------------- + +d(F) -> + d(F, []). + +d(F, A) -> + d(get(dbg), F, A). + +d(true, F, A) -> + io:format("DBG:" ++ F ++ "~n", A); +d(_, _, _) -> + ok. + diff --git a/lib/megaco/test/megaco_test_msg_prev3c_lib.erl b/lib/megaco/test/megaco_test_msg_prev3c_lib.erl new file mode 100644 index 0000000000..74a05060d0 --- /dev/null +++ b/lib/megaco/test/megaco_test_msg_prev3c_lib.erl @@ -0,0 +1,8643 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Utility functions for creating the megaco types +%%---------------------------------------------------------------------- + +-module(megaco_test_msg_prev3c_lib). + +%% ---- + +-include_lib("megaco/include/megaco_message_prev3c.hrl"). +-include_lib("megaco/include/megaco.hrl"). + +%% ---- + +-export([chk_MegacoMessage/2, + + cre_MegacoMessage/1, + cre_MegacoMessage/2, + + cre_ActionReply/2, + cre_ActionReply/3, + cre_ActionReply/4, + cre_ActionRequest/2, + cre_ActionRequest/3, + cre_ActionRequest/4, + cre_AmmDescriptor/1, + cre_AmmRequest/2, + cre_AmmsReply/1, + cre_AmmsReply/2, + cre_AuditDescriptor/0, + cre_AuditDescriptor/1, + cre_AuditDescriptor/2, + cre_AuditReply/1, + cre_AuditRequest/2, + cre_AuditRequest/3, + cre_AuditResult/2, + cre_AuditReturnParameter/1, + cre_AuthenticationHeader/3, + cre_BOOLEAN/1, + cre_Command/2, + cre_CommandReply/2, + cre_CommandRequest/1, + cre_CommandRequest/2, + cre_CommandRequest/3, + cre_ContextAttrAuditRequest/0, + cre_ContextAttrAuditRequest/3, + cre_ContextAttrAuditRequest/4, + cre_ContextAttrAuditRequest/5, + cre_ContextAttrAuditRequest/6, + cre_ContextAttrAuditRequest/7, + cre_ContextAttrAuditRequest/8, + cre_ContextAttrAuditRequest/9, + cre_ContextID/1, + cre_ContextRequest/0, + cre_ContextRequest/1, + cre_ContextRequest/2, + cre_ContextRequest/3, + cre_ContextRequest/4, + cre_ContextRequest/5, + cre_ContextRequest/6, + cre_DigitMapDescriptor/0, + cre_DigitMapDescriptor/1, + cre_DigitMapDescriptor/2, + cre_DigitMapName/1, + cre_DigitMapValue/1, + cre_DigitMapValue/4, + cre_DigitMapValue/5, + cre_ErrorCode/1, + cre_ErrorDescriptor/1, + cre_ErrorDescriptor/2, + cre_ErrorText/1, + cre_EventBufferControl/1, + cre_EventBufferDescriptor/1, + cre_EventDM/1, + cre_EventName/1, + cre_EventParameter/2, + cre_EventParameter/4, + cre_EventsDescriptor/0, + cre_EventsDescriptor/2, + cre_EventSpec/2, + cre_EventSpec/3, + %% cre_H221NonStandard/4, + cre_IndAuditParameter/1, + cre_IndAudLocalControlDescriptor/0, + cre_IndAudLocalControlDescriptor/4, + cre_IndAudLocalControlDescriptor/5, + cre_IndAudLocalRemoteDescriptor/1, + cre_IndAudLocalRemoteDescriptor/2, + cre_IndAudMediaDescriptor/0, + cre_IndAudMediaDescriptor/1, + cre_IndAudMediaDescriptor/2, + cre_IndAudPropertyGroup/1, + cre_IndAudPropertyParm/1, + cre_IndAudPropertyParm/2, + cre_IndAudDigitMapDescriptor/0, + cre_IndAudDigitMapDescriptor/1, + cre_IndAudEventBufferDescriptor/1, + cre_IndAudEventBufferDescriptor/2, + cre_IndAudEventsDescriptor/1, + cre_IndAudEventsDescriptor/2, + cre_IndAudEventsDescriptor/3, + cre_IndAudPackagesDescriptor/2, + cre_IndAudSeqSigList/1, + cre_IndAudSeqSigList/2, + cre_IndAudSignal/1, + cre_IndAudSignal/2, + cre_IndAudSignalsDescriptor/1, + cre_IndAudStatisticsDescriptor/1, + cre_IndAudStreamDescriptor/2, + cre_IndAudStreamParms/0, + cre_IndAudStreamParms/1, + cre_IndAudStreamParms/3, + cre_IndAudStreamParms/4, + cre_IndAudTerminationStateDescriptor/1, + cre_IndAudTerminationStateDescriptor/3, + cre_IndAudTerminationStateDescriptor/4, + cre_LocalControlDescriptor/1, + cre_LocalControlDescriptor/2, + cre_LocalControlDescriptor/4, + cre_LocalRemoteDescriptor/1, + cre_MediaDescriptor/0, + cre_MediaDescriptor/1, + cre_MediaDescriptor/2, + cre_Message/3, + cre_ModemDescriptor/2, + %% cre_ModemDescriptor/3, + cre_ModemType/1, + cre_MuxDescriptor/2, + %% cre_MuxDescriptor/3, + cre_MuxType/1, + cre_Name/1, + %% cre_NonStandardData/2, + %% cre_NonStandardIdentifier/1, + cre_NotifyBehaviour/2, + cre_NotifyCompletion/1, + cre_NotifyReply/1, + cre_NotifyReply/2, + cre_NotifyRequest/2, + cre_NotifyRequest/3, + cre_ObservedEvent/2, + cre_ObservedEvent/3, + cre_ObservedEvent/4, + cre_ObservedEventsDescriptor/2, + cre_PackagesDescriptor/1, + cre_PackagesItem/2, + cre_PkgdName/1, + cre_PkgdName/2, + cre_PropertyGroup/1, + cre_PropertyParm/2, + cre_PropertyParm/4, + cre_RegulatedEmbeddedDescriptor/0, + cre_RegulatedEmbeddedDescriptor/1, + cre_RegulatedEmbeddedDescriptor/2, + cre_Relation/1, + cre_RequestedActions/0, + cre_RequestedActions/1, + cre_RequestedActions/4, + cre_RequestedActions/6, + cre_RequestedEvent/1, + cre_RequestedEvent/2, + cre_RequestedEvent/3, + cre_RequestedEvent/4, + cre_RequestID/1, + cre_SecondEventsDescriptor/1, + cre_SecondEventsDescriptor/2, + cre_SecondRequestedActions/0, + cre_SecondRequestedActions/1, + cre_SecondRequestedActions/2, + cre_SecondRequestedActions/3, + cre_SecondRequestedActions/5, + cre_SecondRequestedEvent/2, + cre_SecondRequestedEvent/3, + cre_SecondRequestedEvent/4, + cre_SelectLogic/1, + cre_SeqSigList/2, + cre_ServiceChangeAddress/2, + cre_ServiceChangeRequest/2, + cre_ServiceChangeMethod/1, + cre_ServiceChangeParm/2, + cre_ServiceChangeParm/4, + cre_ServiceChangeParm/9, + cre_ServiceChangeParm/10, + cre_ServiceChangeProfile/1, + cre_ServiceChangeProfile/2, + cre_ServiceChangeReply/2, + cre_ServiceChangeResParm/0, + cre_ServiceChangeResParm/2, + cre_ServiceChangeResParm/5, + cre_ServiceChangeResult/1, + cre_ServiceState/1, + cre_Signal/1, + cre_Signal/2, + cre_Signal/7, + cre_Signal/9, + cre_Signal/10, + cre_SignalDirection/1, + cre_SignalName/1, + cre_SignalRequest/1, + cre_SignalsDescriptor/1, + cre_SignalType/1, + cre_SigParameter/2, + cre_SigParameter/4, + cre_StatisticsDescriptor/1, + cre_StatisticsParameter/1, + cre_StatisticsParameter/2, + cre_StreamDescriptor/2, + cre_StreamID/1, + cre_StreamMode/1, + cre_StreamParms/0, + cre_StreamParms/1, + cre_StreamParms/2, + cre_StreamParms/3, + cre_StreamParms/4, + cre_SubtractRequest/1, + cre_SubtractRequest/2, + cre_TopologyRequest/3, + cre_TopologyRequest/4, + cre_TerminationAudit/1, + cre_TerminationID/2, + cre_TerminationIDList/1, + cre_TerminationStateDescriptor/1, + cre_TerminationStateDescriptor/2, + cre_TerminationStateDescriptor/3, + cre_TermListAuditResult/2, + cre_TimeNotation/2, + cre_Transaction/1, + cre_TransactionAck/1, + cre_TransactionAck/2, + cre_TransactionId/1, + cre_TransactionPending/1, + cre_TransactionReply/2, + cre_TransactionReply/3, + cre_TransactionRequest/2, + cre_Value/1 + %% cre_WildcardField/1, + ]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +cre_MegacoMessage(M) when is_record(M, 'Message') -> + #'MegacoMessage'{mess = M}. + +cre_MegacoMessage(AH, M) + when is_record(AH, 'AuthenticationHeader') andalso is_record(M, 'Message') -> + #'MegacoMessage'{authHeader = AH, + mess = M}. + +cre_AuthenticationHeader(SPI, SN, AD) -> + #'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AD}. + +cre_Message(V, Mid, ED) when is_record(ED, 'ErrorDescriptor') -> + Body = {errorDescriptor, ED}, + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, Transactions) when is_list(Transactions) -> + Body = {transactions, Transactions}, + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, {transactions, T} = Body) when is_list(T) -> + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, {errorDescriptor, ED} = Body) + when is_record(ED, 'ErrorDescriptor') -> + #'Message'{version = V, + mId = Mid, + messageBody = Body}. + + +cre_ErrorDescriptor(EC) when is_integer(EC) -> + #'ErrorDescriptor'{errorCode = EC}. + +cre_ErrorDescriptor(EC, ET) when is_integer(EC) andalso is_list(ET) -> + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + +cre_ErrorCode(C) when is_integer(C) andalso (0 =< C) andalso (C =< 65535) -> + C; +cre_ErrorCode(C) -> + exit({invalid_ErrorCode, C}). + +cre_ErrorText(T) when is_list(T) -> + T. + +cre_ContextID(Val) when 0 =< Val, Val =< 4294967295 -> + Val; +cre_ContextID(Val) -> + exit({invalid_ContextID, Val}). + +cre_Transaction(TR) when is_record(TR, 'TransactionRequest') -> + {transactionRequest, TR}; +cre_Transaction(TP) when is_record(TP, 'TransactionPending') -> + {transactionPending, TP}; +cre_Transaction(TR) when is_record(TR, 'TransactionReply') -> + {transactionReply, TR}; +cre_Transaction(TRA) when is_list(TRA) -> + {transactionResponseAck, TRA}. + +cre_TransactionId(Val) when 0 =< Val, Val =< 4294967295 -> + Val; +cre_TransactionId(Val) -> + exit({invalid_TransactionId, Val}). + +cre_TransactionRequest(TransID, ARs) when is_integer(TransID) andalso is_list(ARs) -> + #'TransactionRequest'{transactionId = TransID, + actions = ARs}. + +cre_TransactionPending(TransID) when is_integer(TransID) -> + #'TransactionPending'{transactionId = TransID}. + +cre_TransactionReply(TransID, ED) + when is_integer(TransID) andalso is_record(ED, 'ErrorDescriptor') -> + Res = {transactionError, ED}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}; +cre_TransactionReply(TransID, ARs) + when is_integer(TransID) andalso is_list(ARs) -> + Res = {actionReplies, ARs}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}. + +cre_TransactionReply(TransID, IAR, ED) + when is_integer(TransID) andalso + ((IAR =:= 'NULL') orelse (IAR =:= asn1_NOVALUE)) andalso + is_record(ED, 'ErrorDescriptor') -> + Res = {transactionError, ED}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}; +cre_TransactionReply(TransID, IAR, ARs) + when is_integer(TransID) andalso + ((IAR =:= 'NULL') orelse (IAR =:= asn1_NOVALUE)) andalso + is_list(ARs) -> + Res = {actionReplies, ARs}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}. + +cre_TransactionAck(FirstAck) -> + #'TransactionAck'{firstAck = FirstAck}. + +cre_TransactionAck(FirstAck, FirstAck) -> + #'TransactionAck'{firstAck = FirstAck}; +cre_TransactionAck(FirstAck, LastAck) -> + #'TransactionAck'{firstAck = FirstAck, + lastAck = LastAck}. + +cre_ActionRequest(CtxID, CmdReqs) + when is_integer(CtxID) andalso is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + commandRequests = CmdReqs}. + +cre_ActionRequest(CtxID, CtxReq, CmdReqs) + when is_integer(CtxID) andalso + is_record(CtxReq, 'ContextRequest') andalso + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextRequest = CtxReq, + commandRequests = CmdReqs}; +cre_ActionRequest(CtxID, CAAR, CmdReqs) + when is_integer(CtxID) and + is_record(CAAR, 'ContextAttrAuditRequest') and + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextAttrAuditReq = CAAR, + commandRequests = CmdReqs}. + +cre_ActionRequest(CtxID, CtxReq, CAAR, CmdReqs) + when is_integer(CtxID) and + (is_record(CtxReq, 'ContextRequest') or + (CtxReq == asn1_NOVALUE)) and + (is_record(CAAR, 'ContextAttrAuditRequest') or + (CAAR == asn1_NOVALUE)) and + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextRequest = CtxReq, + contextAttrAuditReq = CAAR, + commandRequests = CmdReqs}. + +cre_ActionReply(CtxID, CmdReps) + when is_integer(CtxID) andalso is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + commandReply = CmdReps}. + +cre_ActionReply(CtxID, ED, CmdReps) + when is_integer(CtxID) andalso is_record(ED, 'ErrorDescriptor') andalso is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + errorDescriptor = ED, + commandReply = CmdReps}; +cre_ActionReply(CtxID, CtxReq, CmdReps) + when is_integer(CtxID) andalso + is_record(CtxReq, 'ContextRequest') andalso + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + contextReply = CtxReq, + commandReply = CmdReps}. + +cre_ActionReply(CtxID, ED, CtxReq, CmdReps) + when is_integer(CtxID) andalso + (is_record(ED, 'ErrorDescriptor') orelse (ED =:= asn1_NOVALUE)) andalso + (is_record(CtxReq, 'ContextRequest') orelse (CtxReq =:= asn1_NOVALUE)) andalso + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + errorDescriptor = ED, + contextReply = CtxReq, + commandReply = CmdReps}. + +cre_ContextRequest() -> + strip_ContextRequest(#'ContextRequest'{}). + +cre_ContextRequest(Prio) when is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15) -> + strip_ContextRequest(#'ContextRequest'{priority = Prio}); +cre_ContextRequest(Em) when (Em =:= true) orelse (Em =:= false) orelse (Em =:= asn1_NOVALUE) -> + strip_ContextRequest(#'ContextRequest'{emergency = Em}); +cre_ContextRequest(Top) when is_list(Top) -> + strip_ContextRequest(#'ContextRequest'{topologyReq = Top}). + +cre_ContextRequest(Prio, Em) + when (is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em}, + strip_ContextRequest(CR); +cre_ContextRequest(Prio, Top) + when is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15) andalso is_list(Top) -> + CR = #'ContextRequest'{priority = Prio, + topologyReq = Top}, + strip_ContextRequest(CR). + +cre_ContextRequest(Prio, Em, Top) + when (is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) and + (is_list(Top) or (Top == asn1_NOVALUE)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top}, + strip_ContextRequest(CR). + +cre_ContextRequest(Prio, Em, Top, Ieps) + when (is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) and + (is_list(Top) or (Top == asn1_NOVALUE)) and + ((Ieps == true) or (Ieps == false)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + iepscallind = Ieps}, + strip_ContextRequest(CR); +cre_ContextRequest(Prio, Em, Top, Ctx) + when ((is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) or + (Prio == asn1_NOVALUE)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) and + (is_list(Top) or (Top == asn1_NOVALUE)) and + (is_list(Ctx)) -> + CR = + case context_list_or_prop(Ctx) of + contextProp -> + #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + contextProp = Ctx}; + contextList -> + #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + contextList = Ctx} + end, + strip_ContextRequest(CR). + +cre_ContextRequest(Prio, Em, Top, Ieps, Ctx) + when ((is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) or + (Prio == asn1_NOVALUE)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) and + (is_list(Top) or (Top == asn1_NOVALUE)) and + ((Ieps == true) or (Ieps == false) or (Ieps == asn1_NOVALUE)) and + (is_list(Ctx)) -> + CR = + case context_list_or_prop(Ctx) of + contextProp -> + #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + iepscallind = Ieps, + contextProp = Ctx}; + contextList -> + #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + iepscallind = Ieps, + contextList = Ctx} + end, + strip_ContextRequest(CR). + +cre_ContextRequest(Prio, Em, Top, Ieps, CtxProp, CtxList) + when ((is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) or + (Prio == asn1_NOVALUE)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) and + (is_list(Top) or (Top == asn1_NOVALUE)) and + ((Ieps == true) or (Ieps == false) or (Ieps == asn1_NOVALUE)) and + (is_list(CtxProp) or (CtxProp == asn1_NOVALUE)) and + (is_list(CtxList) or (CtxList == asn1_NOVALUE)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + iepscallind = Ieps, + contextProp = CtxProp, + contextList = CtxList}, + strip_ContextRequest(CR). + +context_list_or_prop(asn1_NOVALUE) -> + contextProp; +context_list_or_prop([]) -> + contextProp; +context_list_or_prop([H|T]) -> + case is_ContextID(H) of + true -> + context_list_or_prop(T, contextList); + false -> + context_list_or_prop(T, contextProp) + end. + +context_list_or_prop([], What) -> + What; +context_list_or_prop([H|T], What) -> + case is_ContextID(H) of + true when What == contextList -> + context_list_or_prop(T, What); + false when What == contextProp -> + context_list_or_prop(T, What); + _ -> + error({invalid_contextListOrProp, H, What}) + end. + +strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE, + emergency = asn1_NOVALUE, + topologyReq = asn1_NOVALUE, + iepscallind = asn1_NOVALUE, + contextProp = asn1_NOVALUE}) -> + asn1_NOVALUE; +strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE, + emergency = asn1_NOVALUE, + topologyReq = Top, + iepscallind = Ieps, + contextProp = Prop} = CR) -> + case (((Top == []) or (Top == asn1_NOVALUE)) and + ((Ieps == false) or (Ieps == asn1_NOVALUE)) and + ((Prop == []) or (Prop == asn1_NOVALUE))) of + true -> + asn1_NOVALUE; + false -> + CR + end; +strip_ContextRequest(CR) -> + CR. + +cre_ContextAttrAuditRequest() -> + strip_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{}). + +cre_ContextAttrAuditRequest(Top, Em, Prio) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio}, + strip_ContextAttrAuditRequest(CAAR). + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) and + ((Ieps == 'NULL') or (Ieps == asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ieps}, + strip_ContextAttrAuditRequest(CAAR). + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) and + ((Ieps == 'NULL') or (Ieps == asn1_NOVALUE)) and + (is_list(Ctx) or (Ctx == asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ieps, + contextPropAud = Ctx}, + strip_ContextAttrAuditRequest(CAAR). + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx, SelPrio) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) and + ((Ieps == 'NULL') or (Ieps == asn1_NOVALUE)) and + (is_list(Ctx) or (Ctx == asn1_NOVALUE)) and + ((is_integer(SelPrio) and ((0 =< SelPrio) and (SelPrio =< 15))) or + (SelPrio == asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ieps, + contextPropAud = Ctx, + selectpriority = SelPrio}, + strip_ContextAttrAuditRequest(CAAR). + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx, SelPrio, SelLog) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) and + ((Ieps == 'NULL') or (Ieps == asn1_NOVALUE)) and + (is_list(Ctx) or (Ctx == asn1_NOVALUE)) and + ((is_integer(SelPrio) and ((0 =< SelPrio) and (SelPrio =< 15))) or + (SelPrio == asn1_NOVALUE)) -> + case ((SelLog == asn1_NOVALUE) orelse is_SelectLogic(SelLog)) of + true -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ieps, + contextPropAud = Ctx, + selectpriority = SelPrio, + selectLogic = SelLog}, + strip_ContextAttrAuditRequest(CAAR); + false -> + error({invalid_SelectLogic, SelLog, + ['ContextAttrAuditRequest', + Top, Em, Prio, Ieps, Ctx, SelPrio]}) + end. + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx, + SelPrio, SelEm, SelIeps) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) and + ((Ieps == 'NULL') or (Ieps == asn1_NOVALUE)) and + (is_list(Ctx) or (Ctx == asn1_NOVALUE)) and + ((is_integer(SelPrio) and ((0 =< SelPrio) and (SelPrio =< 15))) or + (SelPrio == asn1_NOVALUE)) and + ((SelEm == true) or + (SelEm == false) or + (SelEm == asn1_NOVALUE)) and + ((SelIeps == true) or + (SelIeps == false) or + (SelIeps == asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ieps, + contextPropAud = Ctx, + selectpriority = SelPrio, + selectemergency = SelEm, + selectiepscallind = SelIeps}, + strip_ContextAttrAuditRequest(CAAR). + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx, + SelPrio, SelEm, SelIeps, SelLog) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) and + ((Ieps == 'NULL') or (Ieps == asn1_NOVALUE)) and + (is_list(Ctx) or (Ctx == asn1_NOVALUE)) and + ((is_integer(SelPrio) and ((0 =< SelPrio) and (SelPrio =< 15))) or + (SelPrio == asn1_NOVALUE)) and + ((SelEm == true) or + (SelEm == false) or + (SelEm == asn1_NOVALUE)) and + ((SelIeps == true) or + (SelIeps == false) or + (SelIeps == asn1_NOVALUE)) -> + case ((SelLog == asn1_NOVALUE) orelse is_SelectLogic(SelLog)) of + true -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ieps, + contextPropAud = Ctx, + selectpriority = SelPrio, + selectemergency = SelEm, + selectiepscallind = SelIeps, + selectLogic = SelLog}, + strip_ContextAttrAuditRequest(CAAR); + false -> + error({invalid_SelectLogic, SelLog}) + end. + +strip_ContextAttrAuditRequest( + #'ContextAttrAuditRequest'{topology = asn1_NOVALUE, + emergency = asn1_NOVALUE, + priority = asn1_NOVALUE, + iepscallind = asn1_NOVALUE, + contextPropAud = asn1_NOVALUE}) -> + asn1_NOVALUE; +strip_ContextAttrAuditRequest( + #'ContextAttrAuditRequest'{topology = asn1_NOVALUE, + emergency = asn1_NOVALUE, + priority = asn1_NOVALUE, + iepscallind = asn1_NOVALUE, + contextPropAud = []}) -> + asn1_NOVALUE; +strip_ContextAttrAuditRequest(CAAR) -> + CAAR. + + +cre_SelectLogic(andAUDITSelect = SL) -> + {SL, 'NULL'}; +cre_SelectLogic(orAUDITSelect = SL) -> + {SL, 'NULL'}; +cre_SelectLogic(asn1_NOVALUE) -> + asn1_NOVALUE. + + +cre_CommandRequest(Cmd) -> + #'CommandRequest'{command = Cmd}. + +cre_CommandRequest(Cmd, Opt) + when ((Opt == 'NULL') or (Opt == asn1_NOVALUE)) -> + #'CommandRequest'{command = Cmd, + optional = Opt}. + +cre_CommandRequest(Cmd, Opt, WR) + when ((Opt == 'NULL') or (Opt == asn1_NOVALUE)) and + ((WR == 'NULL') or (WR == asn1_NOVALUE)) -> + #'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = WR}. + +cre_Command(addReq = Tag, Req) + when is_record(Req, 'AmmRequest') -> + {Tag, Req}; +cre_Command(moveReq = Tag, Req) + when is_record(Req, 'AmmRequest') -> + {Tag, Req}; +cre_Command(modReq = Tag, Req) + when is_record(Req, 'AmmRequest') -> + {Tag, Req}; +cre_Command(subtractReq = Tag, Req) + when is_record(Req, 'SubtractRequest') -> + {Tag, Req}; +cre_Command(auditCapRequest = Tag, Req) + when is_record(Req, 'AuditRequest') -> + {Tag, Req}; +cre_Command(auditValueRequest = Tag, Req) + when is_record(Req, 'AuditRequest') -> + {Tag, Req}; +cre_Command(notifyReq = Tag, Req) + when is_record(Req, 'NotifyRequest') -> + {Tag, Req}; +cre_Command(serviceChangeReq = Tag, Req) + when is_record(Req, 'ServiceChangeRequest') -> + {Tag, Req}. + +cre_CommandReply(addReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(moveReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(modReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(subtractReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(auditCapReply = Tag, Rep) + when is_tuple(Rep) -> + {Tag, Rep}; +cre_CommandReply(auditValueReply = Tag, Rep) + when is_tuple(Rep) -> + {Tag, Rep}; +cre_CommandReply(notifyReply = Tag, Rep) + when is_record(Rep, 'NotifyReply') -> + {Tag, Rep}; +cre_CommandReply(serviceChangeReply = Tag, Rep) + when is_record(Rep, 'ServiceChangeReply') -> + {Tag, Rep}. + + +%% -- TopologyRequest -- + +cre_TopologyRequest(From, To, TD) + when (is_record(From, 'TerminationID') or + is_record(From, megaco_term_id)) and + (is_record(To, 'TerminationID') or + is_record(To, megaco_term_id)) and + ((TD == bothway) or (TD == isolate) or (TD == oneway)) -> + #'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = TD}; +cre_TopologyRequest(From, To, TDE) + when (is_record(From, 'TerminationID') or + is_record(From, megaco_term_id)) and + (is_record(To, 'TerminationID') or + is_record(To, megaco_term_id)) and + ((TDE == onewayexternal) or (TDE == onewayboth)) -> + #'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = oneway, + topologyDirectionExtension = TDE}. + +cre_TopologyRequest(From, To, TD, SID) + when (is_record(From, 'TerminationID') or + is_record(From, megaco_term_id)) and + (is_record(To, 'TerminationID') or + is_record(To, megaco_term_id)) and + ((TD == bothway) or (TD == isolate) or (TD == oneway)) and + (is_integer(SID)) -> + #'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = TD, + streamID = SID}; +cre_TopologyRequest(From, To, SID, TDE) + when (is_record(From, 'TerminationID') or + is_record(From, megaco_term_id)) and + (is_record(To, 'TerminationID') or + is_record(To, megaco_term_id)) and + (is_integer(SID)) and + ((TDE == onewayexternal) or (TDE == onewayboth)) -> + #'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = oneway, + streamID = SID, + topologyDirectionExtension = TDE}. + +cre_AmmRequest(TermIDs, Descs) -> + d("cre_AmmRequest -> entry with" + "~n TermIDs: ~p" + "~n Descs: ~p", [TermIDs, Descs]), + case is_TerminationIDList(TermIDs) andalso + is_AmmRequest_descriptors(Descs) of + true -> + #'AmmRequest'{terminationID = TermIDs, + descriptors = Descs}; + false -> + error({invalid_AmmRequest, {TermIDs, Descs}}) + end. + +cre_AmmDescriptor(D) when is_record(D, 'MediaDescriptor') -> + {mediaDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'ModemDescriptor') -> + {modemDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'MuxDescriptor') -> + {muxDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'EventsDescriptor') -> + {eventsDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'DigitMapDescriptor') -> + {digitMapDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'AuditDescriptor') -> + {auditDescriptor, D}; +cre_AmmDescriptor(D) when is_list(D) -> + case is_EventBufferDescriptor(D) of + true -> + {eventBufferDescriptor, D}; + false -> + case is_SignalsDescriptor(D) of + true -> + {signalsDescriptor, D}; + false -> + case is_StatisticsDescriptor(D) of + true -> + {statisticsDescriptor, D}; + false -> + error({invalid_AmmDescriptor, D}) + end + end + end. + +cre_AmmsReply(TermIDs) when is_list(TermIDs) -> + #'AmmsReply'{terminationID = TermIDs}. + +cre_AmmsReply(TermIDs, TAs) when is_list(TermIDs) andalso is_list(TAs) -> + #'AmmsReply'{terminationID = TermIDs, + terminationAudit = TAs}. + +cre_SubtractRequest(TermIDs) when is_list(TermIDs) -> + #'SubtractRequest'{terminationID = TermIDs}. + +cre_SubtractRequest(TermIDs, Audit) + when is_list(TermIDs) andalso is_record(Audit, 'AuditDescriptor') -> + #'SubtractRequest'{terminationID = TermIDs, + auditDescriptor = Audit}. + +cre_AuditRequest(TermID, Audit) + when is_record(TermID, megaco_term_id) andalso + is_record(Audit, 'AuditDescriptor') -> + #'AuditRequest'{terminationID = TermID, + auditDescriptor = Audit}. + +cre_AuditRequest(TID, Audit, [TID|_] = TIDs) + when is_record(TID, megaco_term_id) and + is_record(Audit, 'AuditDescriptor') -> + #'AuditRequest'{terminationID = TID, + auditDescriptor = Audit, + terminationIDList = TIDs}. + +cre_AuditReply(TermIDs) when is_list(TermIDs) -> + {contextAuditResult, TermIDs}; +cre_AuditReply(ED) when is_record(ED, 'ErrorDescriptor') -> + {error, ED}; +cre_AuditReply(Audit) when is_record(Audit, 'AuditResult') -> + {auditResult, Audit}; +cre_AuditReply(ARTL) when is_record(ARTL, 'TermListAuditResult') -> + {auditResultTermList, ARTL}. + +cre_AuditResult(TID, TAs) + when is_record(TID, megaco_term_id) andalso is_list(TAs) -> + #'AuditResult'{terminationID = TID, + terminationAuditResult = TAs}. + +cre_TermListAuditResult(TIDs, TA) + when is_list(TIDs) andalso is_list(TA) -> + #'TermListAuditResult'{terminationIDList = TIDs, + terminationAuditResult = TA}. + +cre_TerminationAudit(D) -> + true = is_TerminationAudit(D), + D. + +cre_AuditReturnParameter(D) when is_record(D, 'ErrorDescriptor') -> + {errorDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'MediaDescriptor') -> + {mediaDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'ModemDescriptor') -> + {modemDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'MuxDescriptor') -> + {muxDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'EventsDescriptor') -> + {eventsDescriptor, D}; +cre_AuditReturnParameter([H|_] = D) when is_record(H, 'EventSpec') -> + {eventBufferDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'DigitMapDescriptor') -> + {digitMapDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'ObservedEventsDescriptor') -> + {observedEventsDescriptor, D}; +cre_AuditReturnParameter([H|_] = D) when is_record(H, 'StatisticsParameter') -> + {statisticsDescriptor, D}; +cre_AuditReturnParameter([H|_] = D) when is_record(H, 'PackagesItem') -> + {packagesDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'AuditDescriptor') -> + {emptyDescriptors, D}; +cre_AuditReturnParameter([H|_] = D) when is_tuple(H) -> + {signalsDescriptor, D}. + +cre_AuditDescriptor() -> + #'AuditDescriptor'{}. + +cre_AuditDescriptor([H|_] = AT) when is_atom(H) -> + #'AuditDescriptor'{auditToken = AT}; +cre_AuditDescriptor(APT) -> + #'AuditDescriptor'{auditPropertyToken = APT}. + +cre_AuditDescriptor(AT, APT) -> + #'AuditDescriptor'{auditToken = AT, + auditPropertyToken = APT}. + +cre_IndAuditParameter(D) when is_record(D, 'IndAudMediaDescriptor') -> + {indAudMediaDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudEventsDescriptor') -> + {indAudEventsDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudEventBufferDescriptor') -> + {indAudEventBufferDescriptor, D}; +cre_IndAuditParameter({signal, _} = D) -> + {indAudSignalsDescriptor, D}; +cre_IndAuditParameter({seqSigList, _} = D) -> + {indAudSignalsDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudDigitMapDescriptor') -> + {indAudDigitMapDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudStatisticsDescriptor') -> + {indAudStatisticsDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudPackagesDescriptor') -> + {indAudPackagesDescriptor, D}. + +cre_IndAudMediaDescriptor() -> + #'IndAudMediaDescriptor'{}. + +cre_IndAudMediaDescriptor(TSD) + when is_record(TSD, 'IndAudTerminationStateDescriptor') -> + #'IndAudMediaDescriptor'{termStateDescr = TSD}; +cre_IndAudMediaDescriptor(Parms) when is_record(Parms, 'IndAudStreamParms') -> + Streams = {oneStream, Parms}, + #'IndAudMediaDescriptor'{streams = Streams}; +cre_IndAudMediaDescriptor(Descs) when is_list(Descs) -> + Streams = {multiStream, Descs}, + #'IndAudMediaDescriptor'{streams = Streams}. + +cre_IndAudMediaDescriptor(TSD, Parms) + when is_record(TSD, 'IndAudTerminationStateDescriptor') andalso + is_record(Parms, 'IndAudStreamParms') -> + Streams = {oneStream, Parms}, + #'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = Streams}; +cre_IndAudMediaDescriptor(TSD, Descs) + when is_record(TSD, 'IndAudTerminationStateDescriptor') andalso is_list(Descs) -> + Streams = {multiStream, Descs}, + #'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = Streams}. + +cre_IndAudStreamDescriptor(SID, Parms) + when is_integer(SID) andalso is_record(Parms, 'IndAudStreamParms') -> + #'IndAudStreamDescriptor'{streamID = SID, + streamParms = Parms}; +cre_IndAudStreamDescriptor(SID, Parms) -> + error({invalid_IndAudStreamDescriptor, [SID, Parms]}). + +cre_IndAudStreamParms() -> + #'IndAudStreamParms'{}. + +cre_IndAudStreamParms(LCD) when is_record(LCD, 'IndAudLocalControlDescriptor') -> + #'IndAudStreamParms'{localControlDescriptor = LCD}; +cre_IndAudStreamParms(SD) when is_record(SD, 'IndAudStatisticsDescriptor') -> + #'IndAudStreamParms'{statisticsDescriptor = SD}. + +cre_IndAudStreamParms(LC, L, R) + when is_record(LC, 'IndAudLocalControlDescriptor') andalso + is_record(L, 'IndAudLocalRemoteDescriptor') andalso + is_record(R, 'IndAudLocalRemoteDescriptor') -> + #'IndAudStreamParms'{localControlDescriptor = LC, + localDescriptor = L, + remoteDescriptor = R}. + +cre_IndAudStreamParms(LC, L, R, S) + when is_record(LC, 'IndAudLocalControlDescriptor') andalso + is_record(L, 'IndAudLocalRemoteDescriptor') andalso + is_record(R, 'IndAudLocalRemoteDescriptor') andalso + is_record(S, 'IndAudStatisticsDescriptor') -> + #'IndAudStreamParms'{localControlDescriptor = LC, + localDescriptor = L, + remoteDescriptor = R, + statisticsDescriptor = S}. + +cre_IndAudLocalControlDescriptor() -> + #'IndAudLocalControlDescriptor'{}. + +cre_IndAudLocalControlDescriptor(SM, RV, RG, PP) + when ((SM == 'NULL') or (SM == asn1_NOVALUE)) and + ((RV == 'NULL') or (RV == asn1_NOVALUE)) and + ((RG == 'NULL') or (RG == asn1_NOVALUE)) and + (is_list(PP) or (PP == asn1_NOVALUE)) -> + #'IndAudLocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP}; +cre_IndAudLocalControlDescriptor(RV, RG, PP, SMS) + when ((RV == 'NULL') or (RV == asn1_NOVALUE)) and + ((RG == 'NULL') or (RG == asn1_NOVALUE)) and + (is_list(PP) or (PP == asn1_NOVALUE)) and + is_atom(SMS) -> + #'IndAudLocalControlDescriptor'{reserveValue = RV, + reserveGroup = RG, + propertyParms = PP, + streamModeSel = SMS}. + +cre_IndAudLocalControlDescriptor(SM, RV, RG, PP, SMS) + when (SM == 'NULL') and + (is_atom(SMS) and (SMS =/= asn1_NOVALUE)) -> + error({invalid_IndAudLocalControlDescriptor, [SM, RV, RG, PP, SMS]}); +cre_IndAudLocalControlDescriptor(SM, RV, RG, PP, SMS) + when ((SM == 'NULL') or (SM == asn1_NOVALUE)) and + ((RV == 'NULL') or (RV == asn1_NOVALUE)) and + ((RG == 'NULL') or (RG == asn1_NOVALUE)) and + (is_list(PP) or (PP == asn1_NOVALUE)) and + is_atom(SMS) -> + case is_StreamMode(SMS) of + true -> + #'IndAudLocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP, + streamModeSel = SMS}; + false -> + error({invalid_IndAudLocalControlDescriptor, SMS}) + end. + +cre_IndAudPropertyParm(PkgdName) when is_list(PkgdName) -> + #'IndAudPropertyParm'{name = PkgdName}. + +cre_IndAudPropertyParm(PkgdName, PP) + when is_list(PkgdName) andalso is_record(PP, 'PropertyParm') -> + #'IndAudPropertyParm'{name = PkgdName, propertyParms = PP}. + +cre_IndAudLocalRemoteDescriptor(Grps) + when is_list(Grps) -> + #'IndAudLocalRemoteDescriptor'{propGrps = Grps}. + +cre_IndAudLocalRemoteDescriptor(GID, Grps) + when is_integer(GID) andalso (0 =< GID) andalso (GID =< 65535) andalso is_list(Grps) -> + #'IndAudLocalRemoteDescriptor'{propGroupID = GID, + propGrps = Grps}. + +cre_IndAudPropertyGroup([]) -> + []; +cre_IndAudPropertyGroup([H|_] = PG) + when is_record(H, 'IndAudPropertyParm') -> + PG. + +cre_IndAudTerminationStateDescriptor([] = PP) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP}; +cre_IndAudTerminationStateDescriptor([H|_] = PP) + when is_record(H, 'IndAudPropertyParm') -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP}. + +cre_IndAudTerminationStateDescriptor([] = PP, EBC, SS) + when ((EBC == 'NULL') or (EBC == asn1_NOVALUE)) and + ((SS == 'NULL') or (SS == asn1_NOVALUE)) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS}; +cre_IndAudTerminationStateDescriptor([H|_] = PP, EBC, SS) + when is_record(H, 'IndAudPropertyParm') andalso + ((EBC =:= 'NULL') orelse (EBC =:= asn1_NOVALUE)) andalso + ((SS =:= 'NULL') orelse (SS =:= asn1_NOVALUE)) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS}. + +cre_IndAudTerminationStateDescriptor(PP, EBC, SS, SSS) + when (SS =:= 'NULL') andalso + ((is_atom(SSS) andalso (SSS =/= asn1_NOVALUE))) -> + error({invalid_IndAudTerminationStateDescriptor, [PP, EBC, SS, SSS]}); +cre_IndAudTerminationStateDescriptor([] = PP, EBC, SS, SSS) + when ((EBC =:= 'NULL') orelse (EBC =:= asn1_NOVALUE)) andalso + ((SS =:= 'NULL') orelse (SS =:= asn1_NOVALUE)) andalso + is_atom(SSS) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS, + serviceStateSel = SSS}; +cre_IndAudTerminationStateDescriptor([H|_] = PP, EBC, SS, SSS) + when is_record(H, 'IndAudPropertyParm') and + ((EBC =:= 'NULL') orelse (EBC =:= asn1_NOVALUE)) andalso + ((SS =:= 'NULL') orelse (SS =:= asn1_NOVALUE)) andalso + is_atom(SSS) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS, + serviceStateSel = SSS}. + +cre_IndAudEventsDescriptor(PkgdName) + when is_list(PkgdName) -> + #'IndAudEventsDescriptor'{pkgdName = PkgdName}. + +cre_IndAudEventsDescriptor(RID, PkgdName) + when is_integer(RID) andalso is_list(PkgdName) -> + #'IndAudEventsDescriptor'{requestID = RID, pkgdName = PkgdName}; +cre_IndAudEventsDescriptor(PkgdName, SID) + when is_list(PkgdName) andalso is_integer(SID) -> + #'IndAudEventsDescriptor'{pkgdName = PkgdName, streamID = SID}. + +cre_IndAudEventsDescriptor(RID, PkgdName, SID) + when is_integer(RID) andalso is_list(PkgdName) andalso is_integer(SID) -> + #'IndAudEventsDescriptor'{requestID = RID, + pkgdName = PkgdName, + streamID = SID}. + +cre_IndAudEventBufferDescriptor(EventName) when is_list(EventName) -> + #'IndAudEventBufferDescriptor'{eventName = EventName}. + +cre_IndAudEventBufferDescriptor(EventName, SID) + when is_list(EventName) andalso is_integer(SID) -> + #'IndAudEventBufferDescriptor'{eventName = EventName, streamID = SID}. + +cre_IndAudSignalsDescriptor(S) when is_record(S, 'IndAudSignal') -> + {signal, S}; +cre_IndAudSignalsDescriptor(S) when is_record(S, 'IndAudSeqSigList') -> + {seqSigList, S}. + +cre_IndAudSeqSigList(ID) when is_integer(ID) andalso (0=< ID) andalso (ID =< 65535) -> + #'IndAudSeqSigList'{id = ID}. + +cre_IndAudSeqSigList(ID, S) + when is_integer(ID) andalso (0=< ID) andalso (ID =< 65535) andalso is_record(S, 'IndAudSignal') -> + #'IndAudSeqSigList'{id = ID, signalList = S}. + +cre_IndAudSignal(SigName) when is_list(SigName) -> + #'IndAudSignal'{signalName = SigName}. + +cre_IndAudSignal(SigName, RID) + when is_list(SigName) andalso is_integer(RID) -> + #'IndAudSignal'{signalName = SigName, + signalRequestID = RID}. + +cre_IndAudDigitMapDescriptor() -> + #'IndAudDigitMapDescriptor'{}. + +cre_IndAudDigitMapDescriptor(DMN) when is_list(DMN) -> + #'IndAudDigitMapDescriptor'{digitMapName = DMN}. + +cre_IndAudStatisticsDescriptor(StatName) when is_list(StatName) -> + #'IndAudStatisticsDescriptor'{statName = StatName}. + +cre_IndAudPackagesDescriptor(N, V) + when is_list(N) andalso is_integer(V) andalso (0 =< V) andalso (V =< 99) -> + #'IndAudPackagesDescriptor'{packageName = N, + packageVersion = V}. + +cre_NotifyRequest(TermIDs, D) + when is_list(TermIDs) andalso is_record(D, 'ObservedEventsDescriptor') -> + #'NotifyRequest'{terminationID = TermIDs, + observedEventsDescriptor = D}. + +cre_NotifyRequest(TermIDs, D, ED) + when is_list(TermIDs) andalso is_record(D, 'ObservedEventsDescriptor') andalso is_record(ED, 'ErrorDescriptor') -> + #'NotifyRequest'{terminationID = TermIDs, + observedEventsDescriptor = D, + errorDescriptor = ED}. + +cre_NotifyReply(TermIDs) when is_list(TermIDs) -> + #'NotifyReply'{terminationID = TermIDs}. + +cre_NotifyReply(TermIDs, ED) + when is_list(TermIDs) andalso is_record(ED, 'ErrorDescriptor') -> + #'NotifyReply'{terminationID = TermIDs, + errorDescriptor = ED}. + +cre_ObservedEventsDescriptor(RID, [H|_] = L) + when is_integer(RID) andalso is_record(H, 'ObservedEvent') -> + #'ObservedEventsDescriptor'{requestId = RID, + observedEventLst = L}. + +cre_ObservedEvent(EN, EPL) when is_list(EN) andalso is_list(EPL) -> + #'ObservedEvent'{eventName = EN, + eventParList = EPL}; +cre_ObservedEvent(EN, TN) when is_list(EN) andalso is_record(TN, 'TimeNotation') -> + #'ObservedEvent'{eventName = EN, + timeNotation = TN}. + +cre_ObservedEvent(EN, SID, EPL) when is_list(EN) andalso is_integer(SID) andalso is_list(EPL) -> + #'ObservedEvent'{eventName = EN, + streamID = SID, + eventParList = EPL}; +cre_ObservedEvent(EN, EPL, TN) + when is_list(EN) andalso is_list(EPL) andalso is_record(TN, 'TimeNotation') -> + #'ObservedEvent'{eventName = EN, + eventParList = EPL, + timeNotation = TN}. + +cre_ObservedEvent(EN, SID, EPL, TN) + when is_list(EN) andalso is_integer(SID) andalso is_list(EPL) andalso is_record(TN, 'TimeNotation') -> + #'ObservedEvent'{eventName = EN, + streamID = SID, + eventParList = EPL, + timeNotation = TN}. + +cre_EventName(N) when is_list(N) -> + N. + +cre_EventParameter(N, V) when is_list(N) andalso is_list(V) -> + #'EventParameter'{eventParameterName = N, + value = V}. + +cre_EventParameter(N, V, relation = Tag, R) + when is_list(N) andalso is_list(V) andalso is_atom(R) -> + EI = {Tag, R}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}; +cre_EventParameter(N, V, range = Tag, B) + when is_list(N) andalso is_list(V) andalso is_atom(B) -> + EI = {Tag, B}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}; +cre_EventParameter(N, V, sublist = Tag, B) + when is_list(N) andalso is_list(V) andalso is_atom(B) -> + EI = {Tag, B}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}. + +cre_ServiceChangeRequest(TermIDs, SCP) + when is_list(TermIDs) andalso is_record(SCP, 'ServiceChangeParm') -> + #'ServiceChangeRequest'{terminationID = TermIDs, + serviceChangeParms = SCP}. + +cre_ServiceChangeReply(TermIDs, {Tag, R} = SCR) + when is_list(TermIDs) andalso is_atom(Tag) andalso is_tuple(R) -> + #'ServiceChangeReply'{terminationID = TermIDs, + serviceChangeResult = SCR}. + +cre_ServiceChangeResult(ED) when is_record(ED, 'ErrorDescriptor') -> + {errorDescriptor, ED}; +cre_ServiceChangeResult(SCRP) when is_record(SCRP, 'ServiceChangeResParm') -> + {serviceChangeResParms, SCRP}. + +%% cre_WildcardField(L) when list(L), length(L) == 1 -> L. + +cre_TerminationID(W, ID) + when is_list(W) andalso is_list(ID) andalso (1 =< length(ID)) andalso (length(ID) =< 8) -> + #'TerminationID'{wildcard = W, + id = ID}. + +cre_TerminationIDList(L) when is_list(L) -> + L. + +cre_MediaDescriptor() -> + #'MediaDescriptor'{}. + +cre_MediaDescriptor(TSD) when is_record(TSD, 'TerminationStateDescriptor') -> + #'MediaDescriptor'{termStateDescr = TSD}; +cre_MediaDescriptor(SP) when is_record(SP, 'StreamParms') -> + Streams = {oneStream, SP}, + #'MediaDescriptor'{streams = Streams}; +cre_MediaDescriptor([H|_] = SDs) when is_record(H, 'StreamDescriptor') -> + Streams = {multiStream, SDs}, + #'MediaDescriptor'{streams = Streams}. + +cre_MediaDescriptor(TSD, SP) + when is_record(TSD, 'TerminationStateDescriptor') andalso + is_record(SP, 'StreamParms') -> + Streams = {oneStream, SP}, + #'MediaDescriptor'{termStateDescr = TSD, + streams = Streams}; +cre_MediaDescriptor(TSD, [H|_] = SDs) + when is_record(TSD, 'TerminationStateDescriptor') andalso + is_record(H, 'StreamDescriptor') -> + Streams = {multiStream, SDs}, + #'MediaDescriptor'{termStateDescr = TSD, + streams = Streams}. + +cre_StreamDescriptor(SID, SP) when is_integer(SID) andalso is_record(SP, 'StreamParms') -> + #'StreamDescriptor'{streamID = SID, + streamParms = SP}. + +cre_StreamParms() -> + #'StreamParms'{}. + +cre_StreamParms(LCD) when is_record(LCD, 'LocalControlDescriptor') -> + #'StreamParms'{localControlDescriptor = LCD}; +cre_StreamParms(LD) when is_record(LD, 'LocalRemoteDescriptor') -> + #'StreamParms'{localDescriptor = LD}; +cre_StreamParms(SD) when is_list(SD) -> + #'StreamParms'{statisticsDescriptor = SD}. + +cre_StreamParms(LCD, LD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD}. + +cre_StreamParms(LCD, LD, RD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) and + (is_record(RD, 'LocalRemoteDescriptor') or (RD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD}; +cre_StreamParms(LCD, LD, SD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + statisticsDescriptor = SD}. + +cre_StreamParms(LCD, LD, RD, SD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) and + (is_record(RD, 'LocalRemoteDescriptor') or (RD == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}. + +cre_LocalControlDescriptor(SM) when is_atom(SM) -> + #'LocalControlDescriptor'{streamMode = SM, propertyParms = []}; +cre_LocalControlDescriptor([H|_] = PP) when is_record(H, 'PropertyParm') -> + #'LocalControlDescriptor'{propertyParms = PP}. + +cre_LocalControlDescriptor(SM, [H|_] = PP) + when is_atom(SM) andalso is_record(H, 'PropertyParm') -> + #'LocalControlDescriptor'{streamMode = SM, + propertyParms = PP}. + +cre_LocalControlDescriptor(SM, RV, RG, [H|_] = PP) + when is_atom(SM) andalso + ((RV =:= true) orelse (RV =:= false) orelse (RV =:= asn1_NOVALUE)) andalso + ((RG =:= true) orelse (RG =:= false) orelse (RG =:= asn1_NOVALUE)) andalso + is_record(H, 'PropertyParm') -> + #'LocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP}. + +cre_StreamMode(sendOnly = M) -> + M; +cre_StreamMode(recvOnly = M) -> + M; +cre_StreamMode(sendRecv = M) -> + M; +cre_StreamMode(inactive = M) -> + M; +cre_StreamMode(loopBack = M) -> + M. + +cre_PropertyParm(N, [H|_] = V) when is_list(N) andalso is_list(H) -> + #'PropertyParm'{name = N, value = V}. + +cre_PropertyParm(N, [H|_] = V, relation = Tag, R) + when is_list(N) andalso is_list(H) andalso is_atom(R) -> + EI = {Tag, R}, + #'PropertyParm'{name = N, value = V, extraInfo = EI}; +cre_PropertyParm(N, [H|_] = V, range = Tag, B) + when is_list(N) andalso is_list(H) andalso is_atom(B) -> + EI = {Tag, B}, + #'PropertyParm'{name = N, value = V, extraInfo = EI}; +cre_PropertyParm(N, [H|_] = V, sublist = Tag, B) + when is_list(N) andalso is_list(H) andalso is_atom(B) -> + EI = {Tag, B}, + #'PropertyParm'{name = N, value = V, extraInfo = EI}. + + +cre_Name(N) when is_list(N) andalso (length(N) == 2) -> + N. + +cre_PkgdName(N) when is_list(N) -> + case string:tokens(N, [$\\]) of + [_PkgName, _ItemID] -> + N; + _ -> + error({invalid_PkgdName, N}) + end. +cre_PkgdName(root, root) -> + "*/*"; +cre_PkgdName(PackageName, root) + when is_list(PackageName) andalso (length(PackageName) =< 64) -> + PackageName ++ "/*"; +cre_PkgdName(PackageName, ItemID) + when ((is_list(PackageName) andalso (length(PackageName) =< 64)) andalso + (is_list(ItemID) andalso (length(ItemID) =< 64))) -> + PackageName ++ "/" ++ ItemID; +cre_PkgdName(PackageName, ItemID) -> + error({invalid_PkgdName, {PackageName, ItemID}}). + +cre_Relation(greaterThan = R) -> + R; +cre_Relation(smallerThan = R) -> + R; +cre_Relation(unequalTo = R) -> + R. + +cre_LocalRemoteDescriptor([H|_] = PGs) when is_list(H) -> + #'LocalRemoteDescriptor'{propGrps = PGs}. + +cre_PropertyGroup([H|_] = PG) when is_record(H, 'PropertyParm') -> + PG. + +cre_TerminationStateDescriptor([H|_] = PPs) when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs}. + +cre_TerminationStateDescriptor([H|_] = PPs, off = EBC) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + eventBufferControl = EBC}; +cre_TerminationStateDescriptor([H|_] = PPs, lockStep = EBC) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + eventBufferControl = EBC}; +cre_TerminationStateDescriptor([H|_] = PPs, test = SS) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + serviceState = SS}; +cre_TerminationStateDescriptor([H|_] = PPs, outOfSvc = SS) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + serviceState = SS}; +cre_TerminationStateDescriptor([H|_] = PPs, inSvc = SS) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + serviceState = SS}. + +cre_TerminationStateDescriptor([H|_] = PPs, EMC, SS) + when is_record(H, 'PropertyParm') andalso + ((EMC =:= off) orelse (EMC =:= lockStep)) andalso + ((SS =:= test) orelse (SS =:= outOfSvc) orelse (SS =:= inSvc)) -> + #'TerminationStateDescriptor'{propertyParms = PPs, + eventBufferControl = EMC, + serviceState = SS}. + +cre_EventBufferControl(off = EBC) -> + EBC; +cre_EventBufferControl(lockStep = EBC) -> + EBC. + +cre_ServiceState(test = SS) -> + SS; +cre_ServiceState(outOfSvc = SS) -> + SS; +cre_ServiceState(inSvc = SS) -> + SS. + +cre_MuxDescriptor(MT, [H|_] = TL) + when is_atom(MT) andalso is_record(H, 'TerminationID') -> + #'MuxDescriptor'{muxType = MT, termList = TL}. + +%% cre_MuxDescriptor(MT, [H|_] = TL, NSD) +%% when atom(MT), record(H, 'TerminationID'), record(NSD, 'NonStandardData') -> +%% #'MuxDescriptor'{muxType = MT, termList = TL, nonStandardData = NSD}. + +cre_MuxType(h221 = MT) -> + MT; +cre_MuxType(h223 = MT) -> + MT; +cre_MuxType(h226 = MT) -> + MT; +cre_MuxType(v76 = MT) -> + MT; +cre_MuxType(nx64k = MT) -> + MT. + +cre_StreamID(Val) when 0 =< Val, Val =< 65535 -> + Val; +cre_StreamID(Val) -> + exit({invalid_ContextID, Val}). + +%% RequestID must be present if eventList is non empty +cre_EventsDescriptor() -> + #'EventsDescriptor'{eventList = []}. + +cre_EventsDescriptor(RID, [H|_] = EL) + when is_integer(RID) andalso is_record(H, 'RequestedEvent') -> + #'EventsDescriptor'{requestID = RID, eventList = EL}. + +cre_RequestedEvent(N) -> + #'RequestedEvent'{pkgdName = N}. + +cre_RequestedEvent(N, EPL) + when is_list(N) andalso is_list(EPL) -> + #'RequestedEvent'{pkgdName = N, + evParList = EPL}; +cre_RequestedEvent(N, EA) + when is_list(N) andalso is_record(EA, 'RequestedActions')-> + #'RequestedEvent'{pkgdName = N, + eventAction = EA}. + + +cre_RequestedEvent(N, SID, EPL) + when is_list(N) and is_integer(SID) and is_list(EPL) -> + #'RequestedEvent'{pkgdName = N, + streamID = SID, + evParList = EPL}; +cre_RequestedEvent(N, EA, EPL) + when is_list(N) and is_record(EA, 'RequestedActions') and is_list(EPL) -> + #'RequestedEvent'{pkgdName = N, + eventAction = EA, + evParList = EPL}. + +cre_RequestedEvent(N, SID, EA, EPL) + when is_list(N) and + is_integer(SID) and + is_record(EA, 'RequestedActions') and + is_list(EPL) -> + #'RequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}. + +cre_RegulatedEmbeddedDescriptor() -> + #'RegulatedEmbeddedDescriptor'{}. + +cre_RegulatedEmbeddedDescriptor(D) -> + case is_SecondEventsDescriptor(D) of + true -> + #'RegulatedEmbeddedDescriptor'{secondEvent = D}; + false -> + case is_SignalsDescriptor(D) of + true -> + #'RegulatedEmbeddedDescriptor'{signalsDescriptor = D}; + false -> + error({invalid_RegulatedEmbeddedDescriptor, D}) + end + end. + +cre_RegulatedEmbeddedDescriptor(SED, SD) + when ((SED == asn1_NOVALUE) or is_record(SED, 'SecondEventsDescriptor')) and + ((SD == asn1_NOVALUE) or is_list(SD)) -> + #'RegulatedEmbeddedDescriptor'{secondEvent = SED, + signalsDescriptor = SD}. + +cre_NotifyBehaviour(notifyImmediate = Tag, 'NULL' = Val) -> + {Tag, Val}; +cre_NotifyBehaviour(notifyRegulated = Tag, Val) + when is_record(Val, 'RegulatedEmbeddedDescriptor') -> + {Tag, Val}; +cre_NotifyBehaviour(neverNotify = Tag, 'NULL' = Val) -> + {Tag, Val}; +cre_NotifyBehaviour(Tag, Val) -> + error({invalid_NotifyBehaviour, [Tag, Val]}). + +cre_RequestedActions() -> + #'RequestedActions'{}. + +cre_RequestedActions(KA) + when (KA == true) or (KA == true) -> + #'RequestedActions'{keepActive = KA}; +cre_RequestedActions(SE) + when is_record(SE, 'SecondEventsDescriptor') -> + #'RequestedActions'{secondEvent = SE}; +cre_RequestedActions(SD) + when is_list(SD) -> + #'RequestedActions'{signalsDescriptor = SD}; +cre_RequestedActions({Tag, _} = EDM) + when is_atom(Tag) -> + #'RequestedActions'{eventDM = EDM}. + +cre_RequestedActions(KA, {Tag, _} = EDM, SE, SD) + when ((KA == true) or (KA == true) or (KA == asn1_NOVALUE)) and + (is_atom(Tag) or (EDM == asn1_NOVALUE)) and + (is_record(SE, 'SecondEventsDescriptor') or (SE == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) -> + #'RequestedActions'{keepActive = KA, + eventDM = EDM, + secondEvent = SE, + signalsDescriptor = SD}. + +cre_RequestedActions(KA, {EDMTag, _} = EDM, SE, SD, {NBTag, _} = NB, RED) + when ((KA == true) or (KA == true) or (KA == asn1_NOVALUE)) and + (is_atom(EDMTag) or (EDM == asn1_NOVALUE)) and + (is_record(SE, 'SecondEventsDescriptor') or (SE == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) and + (is_atom(NBTag) or (NB == asn1_NOVALUE)) and + ((RED == 'NULL') or (RED == asn1_NOVALUE)) -> + #'RequestedActions'{keepActive = KA, + eventDM = EDM, + secondEvent = SE, + signalsDescriptor = SD, + notifyBehaviour = NB, + resetEventsDescriptor = RED}. + +cre_EventDM(N) when is_list(N) -> + {digitMapName, N}; +cre_EventDM(V) when is_record(V, 'DigitMapValue') -> + {digitMapValue, V}. + +cre_SecondEventsDescriptor([H|_] = EL) + when is_record(H, 'SecondRequestedEvent') -> + #'SecondEventsDescriptor'{eventList = EL}. + +cre_SecondEventsDescriptor(RID, [H|_] = EL) + when is_integer(RID) andalso is_record(H, 'SecondRequestedEvent') -> + #'SecondEventsDescriptor'{requestID = RID, eventList = EL}. + +cre_SecondRequestedEvent(N, EPL) + when is_list(N) andalso is_list(EPL) -> + #'SecondRequestedEvent'{pkgdName = N, + evParList = EPL}; +cre_SecondRequestedEvent(N, EPL) -> + error({invalid_SecondRequestedEvent, [N, EPL]}). + +cre_SecondRequestedEvent(N, SID, EPL) + when is_list(N) andalso is_integer(SID) andalso is_list(EPL) -> + #'SecondRequestedEvent'{pkgdName = N, + streamID = SID, + evParList = EPL}; +cre_SecondRequestedEvent(N, EA, EPL) + when is_list(N) andalso + is_record(EA, 'SecondRequestedActions') andalso + is_list(EPL) -> + #'SecondRequestedEvent'{pkgdName = N, + eventAction = EA, + evParList = EPL}. + +cre_SecondRequestedEvent(N, SID, EA, EPL) + when is_list(N) andalso + is_integer(SID) andalso + is_record(EA, 'SecondRequestedActions') andalso + is_list(EPL) -> + #'SecondRequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}. + +cre_SecondRequestedActions() -> + #'SecondRequestedActions'{}. + +cre_SecondRequestedActions(KA) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) -> + #'SecondRequestedActions'{keepActive = KA}; +cre_SecondRequestedActions(SD) when is_list(SD) -> + #'SecondRequestedActions'{signalsDescriptor = SD}; +cre_SecondRequestedActions({Tag, _} = Val) when is_atom(Tag) -> + case is_EventDM(Val) of + true -> + #'SecondRequestedActions'{eventDM = Val}; + false -> + case is_NotifyBehaviour(Val) of + true -> + #'SecondRequestedActions'{notifyBehaviour = Val}; + false -> + error({invalid_SecondRequestedActions, Val}) + end + end; +cre_SecondRequestedActions('NULL' = RED) -> + #'SecondRequestedActions'{resetEventsDescriptor = RED}. + +cre_SecondRequestedActions(KA, SD) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SD) -> + #'SecondRequestedActions'{keepActive = KA, signalsDescriptor = SD}; +cre_SecondRequestedActions(KA, {Tag, _} = Val) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_atom(Tag) -> + case is_EventDM(Val) of + true -> + #'SecondRequestedActions'{keepActive = KA, + eventDM = Val}; + false -> + case is_NotifyBehaviour(Val) of + true -> + #'SecondRequestedActions'{keepActive = KA, + notifyBehaviour = Val}; + false -> + error({invalid_SecondRequestedActions, Val}) + end + end; +cre_SecondRequestedActions(KA, 'NULL' = RED) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) -> + #'SecondRequestedActions'{keepActive = KA, + resetEventsDescriptor = RED}. + +cre_SecondRequestedActions(KA, {Tag, _} = EDM, SD) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_atom(Tag) and + is_list(SD) -> + #'SecondRequestedActions'{keepActive = KA, + eventDM = EDM, + signalsDescriptor = SD}; +cre_SecondRequestedActions(KA, SD, {Tag, _} = NB) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SD) and + is_atom(Tag) -> + #'SecondRequestedActions'{keepActive = KA, + signalsDescriptor = SD, + notifyBehaviour = NB}; +cre_SecondRequestedActions(KA, SD, 'NULL' = RED) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SD) -> + #'SecondRequestedActions'{keepActive = KA, + signalsDescriptor = SD, + resetEventsDescriptor = RED}. + +cre_SecondRequestedActions(KA, {EDMTag, _} = EDM, SD, + {NBTag, _} = NB, RED) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + (is_atom(EDMTag) or (EDM == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) and + (is_atom(NBTag) or (NB == asn1_NOVALUE)) and + ((RED == 'NULL') or (RED == asn1_NOVALUE)) -> + #'SecondRequestedActions'{keepActive = KA, + eventDM = EDM, + signalsDescriptor = SD, + notifyBehaviour = NB, + resetEventsDescriptor = RED}. + +cre_EventBufferDescriptor([H|_] = D) when is_record(H, 'EventSpec') -> + D. + +cre_EventSpec(N, [H|_] = EPL) when is_list(N) andalso is_record(H, 'EventParameter') -> + #'EventSpec'{eventName = N, eventParList = EPL}. + +cre_EventSpec(N, SID, [H|_] = EPL) + when is_list(N) andalso is_integer(SID) andalso is_record(H, 'EventParameter') -> + #'EventSpec'{eventName = N, streamID = SID, eventParList = EPL}. + +cre_SignalsDescriptor(D) -> + case is_SignalsDescriptor(D) of + true -> + D; + false -> + error({invalid_SignalsDescriptor, D}) + end. + +cre_SignalRequest(S) when is_record(S, 'Signal') -> + {signal, S}; +cre_SignalRequest(S) when is_record(S, 'SeqSigList') -> + {seqSigList, S}. + +cre_SeqSigList(ID, [H|_] = SL) + when is_integer(ID) andalso (0 =< ID) andalso (ID =< 65535) andalso is_record(H, 'Signal') -> + #'SeqSigList'{id = ID, signalList = SL}. + +cre_Signal(N) when is_list(N) -> + #'Signal'{signalName = N}. + +cre_Signal(N, SPL) when is_list(N) andalso is_list(SPL) -> + #'Signal'{signalName = N, + sigParList = SPL}. + +cre_Signal(N, SID, ST, Dur, NC, KA, SPL) + when is_list(N) and + (is_integer(SID) or (SID == asn1_NOVALUE)) and + ((ST == brief) or (ST == onOff) or (ST == timeOut) or + (ST == asn1_NOVALUE)) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 65535)) or + (Dur == asn1_NOVALUE)) and + (is_list(NC) or (NC == asn1_NOVALUE)) and + ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SPL) -> + #'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL}. + +cre_Signal(N, SID, ST, Dur, NC, KA, SPL, Dir, RID) + when is_list(N) and + (is_integer(SID) or (SID == asn1_NOVALUE)) and + ((ST == brief) or (ST == onOff) or (ST == timeOut) or + (ST == asn1_NOVALUE)) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 65535)) or + (Dur == asn1_NOVALUE)) and + (is_list(NC) or (NC == asn1_NOVALUE)) and + ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SPL) and + ((Dir == internal) or (Dir == external) or (Dir == both) or + (Dir == asn1_NOVALUE)) and + (is_integer(RID) or (RID == asn1_NOVALUE)) -> + #'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL, + direction = Dir, + requestID = RID}. + +cre_Signal(N, SID, ST, Dur, NC, KA, SPL, Dir, RID, ISIG) + when is_list(N) and + (is_integer(SID) or (SID == asn1_NOVALUE)) and + ((ST == brief) or (ST == onOff) or (ST == timeOut) or + (ST == asn1_NOVALUE)) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 65535)) or + (Dur == asn1_NOVALUE)) and + (is_list(NC) or (NC == asn1_NOVALUE)) and + ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SPL) and + ((Dir == internal) or (Dir == external) or (Dir == both) or + (Dir == asn1_NOVALUE)) and + (is_integer(RID) or (RID == asn1_NOVALUE)) and + (is_integer(ISIG) or (ISIG == asn1_NOVALUE)) -> + #'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL, + direction = Dir, + requestID = RID, + intersigDelay = ISIG}. + +cre_SignalType(brief = ST) -> + ST; +cre_SignalType(onOff = ST) -> + ST; +cre_SignalType(timeOut = ST) -> + ST. + +cre_SignalDirection(internal = SD) -> + SD; +cre_SignalDirection(external = SD) -> + SD; +cre_SignalDirection(both = SD) -> + SD. + +cre_SignalName(N) -> + cre_PkgdName(N). + +cre_NotifyCompletion(L) when is_list(L) -> + Vals = [onTimeOut, onInterruptByEvent, + onInterruptByNewSignalDescr, otherReason], + F = fun(E) -> case lists:member(E, Vals) of + true -> + ok; + false -> + exit({invalid_NotifyCompletion, E}) + end + end, + lists:foreach(F, L), + L. + +cre_SigParameter(N, V) when is_list(N) andalso is_list(V) -> + #'SigParameter'{sigParameterName = N, value = V}. + +cre_SigParameter(N, V, relation = Tag, R) + when is_list(N) and is_list(V) and is_atom(R) -> + EI = {Tag, R}, + #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}; +cre_SigParameter(N, V, range = Tag, B) + when is_list(N) and is_list(V) and is_atom(B) -> + EI = {Tag, B}, + #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}; +cre_SigParameter(N, V, sublist = Tag, B) + when is_list(N) and is_list(V) and is_atom(B) -> + EI = {Tag, B}, + #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}. + +cre_RequestID(Val) when 0 =< Val, Val =< 4294967295 -> + Val; +cre_RequestID(Val) -> + exit({invalid_RequestID, Val}). + +cre_ModemDescriptor(MTL, MPL) when is_list(MTL) andalso is_list(MPL) -> + #'ModemDescriptor'{mtl = MTL, mpl = MPL}. + +%% cre_ModemDescriptor(MTL, MPL, NSD) +%% when list(MTL), list(MPL), record(NSD, 'NonStandardData') -> +%% #'ModemDescriptor'{mtl = MTL, mpl = MPL}. + +cre_ModemType(v18 = MT) -> + MT; +cre_ModemType(v22 = MT) -> + MT; +cre_ModemType(v22bis = MT) -> + MT; +cre_ModemType(v32 = MT) -> + MT; +cre_ModemType(v32bis = MT) -> + MT; +cre_ModemType(v34 = MT) -> + MT; +cre_ModemType(v90 = MT) -> + MT; +cre_ModemType(v91 = MT) -> + MT; +cre_ModemType(synchISDN = MT) -> + MT. + +cre_DigitMapDescriptor() -> + #'DigitMapDescriptor'{}. + +cre_DigitMapDescriptor(N) when is_list(N) -> + #'DigitMapDescriptor'{digitMapName = N}; +cre_DigitMapDescriptor(V) when is_record(V, 'DigitMapValue') -> + #'DigitMapDescriptor'{digitMapValue = V}. + +cre_DigitMapDescriptor(N, V) when is_list(N) andalso is_record(V, 'DigitMapValue') -> + #'DigitMapDescriptor'{digitMapName = N, digitMapValue = V}. + +cre_DigitMapName(N) -> + cre_Name(N). + +cre_DigitMapValue(DMB) when is_list(DMB) -> + #'DigitMapValue'{digitMapBody = DMB}. + +cre_DigitMapValue(Start, Short, Long, DMB) -> + cre_DigitMapValue(Start, Short, Long, DMB, asn1_NOVALUE). + +cre_DigitMapValue(Start, Short, Long, DMB, Dur) + when ((is_integer(Start) and (0 =< Start) and (Start =< 99)) or + (Start == asn1_NOVALUE)) and + ((is_integer(Short) and (0 =< Short) and (Short =< 99)) or + (Short == asn1_NOVALUE)) and + ((is_integer(Long) and (0 =< Long) and (Long =< 99)) or + (Long == asn1_NOVALUE)) and + is_list(DMB) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 99)) or + (Dur == asn1_NOVALUE)) -> + #'DigitMapValue'{startTimer = Start, + shortTimer = Short, + longTimer = Long, + digitMapBody = DMB, + durationTimer = Dur}. + +cre_ServiceChangeParm(M, R) when is_atom(M) andalso is_list(R) -> + #'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeReason = R}. + +cre_ServiceChangeParm(M, Addr, Prof, Reason) -> + cre_ServiceChangeParm(M, Addr, asn1_NOVALUE, Prof, Reason, asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE). + +%% Addr = asn1_NOVALUE | {AddrTag, AddrVal} +cre_ServiceChangeParm(M, Addr, Ver, Prof, R, D, Mid, TS, I) -> + cre_ServiceChangeParm(M, Addr, Ver, Prof, R, D, Mid, TS, I, asn1_NOVALUE). + +cre_ServiceChangeParm(M, Addr, Ver, Prof, R, D, Mid, TS, I, IF) + when is_atom(M) and + ((is_integer(Ver) and (0 =< Ver) and (Ver =< 99)) or + (Ver == asn1_NOVALUE)) and + (is_record(Prof, 'ServiceChangeProfile') or (Prof == asn1_NOVALUE)) and + is_list(R) and + ((is_integer(D) and (0 =< D) and (D =< 4294967295)) or + (D == asn1_NOVALUE)) and + (is_record(TS, 'TimeNotation') or (TS == asn1_NOVALUE)) and + (is_record(I, 'AuditDescriptor') or (I == asn1_NOVALUE)) and + ((IF == 'NULL') or (IF == asn1_NOVALUE)) -> + F = fun(A) -> + (A == asn1_NOVALUE) orelse + (is_tuple(A) + andalso is_atom(element(1, A))) + end, + case (F(Addr) andalso F(Mid)) of + true -> + #'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeAddress = Addr, + serviceChangeVersion = Ver, + serviceChangeProfile = Prof, + serviceChangeReason = R, + serviceChangeDelay = D, + serviceChangeMgcId = Mid, + timeStamp = TS, + serviceChangeInfo = I, + serviceChangeIncompleteFlag = IF}; + _ -> + exit({invalid_ServiceChangeParm_args, {Addr, Mid}}) + end. + +cre_ServiceChangeAddress(portNumber = Tag, P) + when is_integer(P) andalso (0 =< P) andalso (P =< 65535) -> + {Tag, P}; +cre_ServiceChangeAddress(ip4Address = Tag, A) when is_record(A, 'IP4Address') -> + {Tag, A}; +cre_ServiceChangeAddress(ip6Address = Tag, A) when is_record(A, 'IP6Address') -> + {Tag, A}; +cre_ServiceChangeAddress(domainName = Tag, N) when is_record(N, 'DomainName') -> + {Tag, N}; +cre_ServiceChangeAddress(deviceName = Tag, N) when is_list(N) -> + {Tag, N}; +cre_ServiceChangeAddress(mtpAddress = Tag, A) when is_list(A) -> + {Tag, A}. + +cre_ServiceChangeResParm() -> + #'ServiceChangeResParm'{}. +cre_ServiceChangeResParm(Addr, Prof) -> + cre_ServiceChangeResParm(asn1_NOVALUE, Addr, asn1_NOVALUE, + Prof, asn1_NOVALUE). +cre_ServiceChangeResParm(Mid, Addr, Ver, Prof, TS) + when ((is_integer(Ver) andalso (0 =< Ver) andalso (Ver =< 99)) orelse + (Ver =:= asn1_NOVALUE)) andalso + (is_record(Prof, 'ServiceChangeProfile') orelse (Prof =:= asn1_NOVALUE)) andalso + (is_record(TS, 'TimeNotation') orelse (TS =:= asn1_NOVALUE)) -> + F = fun(A) -> + (A == asn1_NOVALUE) orelse + (is_tuple(A) + andalso is_atom(element(1, A))) + end, + case (F(Addr) andalso F(Mid)) of + true -> + #'ServiceChangeResParm'{serviceChangeMgcId = Mid, + serviceChangeAddress = Addr, + serviceChangeVersion = Ver, + serviceChangeProfile = Prof, + timeStamp = TS}; + _ -> + exit({invalid_ServiceChangeResParm_args, {Addr, Mid}}) + end. + +cre_ServiceChangeMethod(failover = M) -> + M; +cre_ServiceChangeMethod(forced = M) -> + M; +cre_ServiceChangeMethod(graceful = M) -> + M; +cre_ServiceChangeMethod(restart = M) -> + M; +cre_ServiceChangeMethod(disconnected = M) -> + M; +cre_ServiceChangeMethod(handOff = M) -> + M. + +%% The version field is added to make it look more like ABNF +cre_ServiceChangeProfile(N) -> + cre_ServiceChangeProfile(N, 1). + +cre_ServiceChangeProfile(N, V) + when is_list(N) andalso is_integer(V) andalso (0 =< V) andalso (V =< 99) -> + #'ServiceChangeProfile'{profileName = N, version = V}. + +cre_PackagesDescriptor([H|_] = D) when is_record(H, 'PackagesItem') -> + D. + +cre_PackagesItem(N, Ver) when is_list(N) andalso is_integer(Ver) andalso (0 =< Ver) andalso (Ver =< 99) -> + #'PackagesItem'{packageName = N, + packageVersion = Ver}. + +cre_StatisticsDescriptor(D) -> + true = is_StatisticsDescriptor(D), + D. + +cre_StatisticsParameter(N) when is_list(N) -> + #'StatisticsParameter'{statName = N}. + +cre_StatisticsParameter(N, V) when is_list(N) andalso is_list(V) -> + #'StatisticsParameter'{statName = N, statValue = V}. + +%% cre_NonStandardData({Tag, _} = Id, Data) when atom(Tag), list(Data) -> +%% #'NonStandardData'{nonStandardIdentifier = Id, data = Data}. + +%% cre_NonStandardIdentifier(H221) when record(H221, 'H221NonStandard') -> +%% {h221NonStandard, H221}; +%% cre_NonStandardIdentifier(Obj) when tuple(Obj) -> +%% {object, Obj}; +%% cre_NonStandardIdentifier(Exp) when list(Exp), length(Exp) == 8 -> +%% {experimental, Exp}. + +%% cre_H221NonStandard(CC1, CC2, Ext, MC) +%% when (is_integer(CC1) and (0 =< CC1) and (CC1 =< 255)) and +%% (is_integer(CC2) and (0 =< CC2) and (CC2 =< 255)) and +%% (is_integer(Ext) and (0 =< Ext) and (Ext =< 255)) and +%% (is_integer(MC) and (0 =< MC) and (MC =< 255)) -> +%% #'H221NonStandard'{t35CountryCode1 = CC1, +%% t35CountryCode2 = CC2, +%% t35Extension = Ext, +%% manufacturerCode = MC}. + +cre_TimeNotation(D, T) + when is_list(D) andalso (length(D) =:= 8) andalso is_list(T) andalso (length(T) =:= 8) -> + #'TimeNotation'{date = D, time = T}. + +cre_Value([H|_] = V) when is_list(H) -> + V. + +cre_BOOLEAN(true = B) -> + B; +cre_BOOLEAN(false = B) -> + B. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% -- MegacoMessage -- + +is_MegacoMessage(#'MegacoMessage'{authHeader = Auth, + mess = Mess}) -> + d("is_MegacoMessage -> entry"), + is_opt_AuthenticationHeader(Auth) andalso is_Message(Mess); +is_MegacoMessage(_) -> + false. + + +chk_MegacoMessage(M, M) -> + d("chk_MegacoMessage -> entry (1)"), + chk_type(fun is_MegacoMessage/1, 'MegacoMessage', M); +chk_MegacoMessage(#'MegacoMessage'{authHeader = Auth1, + mess = Mess1}, + #'MegacoMessage'{authHeader = Auth2, + mess = Mess2}) -> + d("chk_MegacoMessage -> entry (2)"), + chk_opt_AuthenticationHeader(Auth1,Auth2), + chk_Message(Mess1,Mess2), + ok; +chk_MegacoMessage(M1, M2) -> + wrong_type('MegacoMessage', M1, M2). + + +%% -- AuthenticationHeader -- + +is_opt_AuthenticationHeader(AH) -> + is_OPTIONAL(fun is_AuthenticationHeader/1, AH). + +is_AuthenticationHeader(#'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AD}) -> + is_SecurityParmIndex(SPI) andalso + is_SequenceNum(SN) andalso + is_AuthData(AD); +is_AuthenticationHeader(_) -> + false. + +%% This stuff is not really used, so make it simple... +chk_opt_AuthenticationHeader(A1, A2) -> + chk_OPTIONAL('AuthenticationHeader', A1, A2, + fun is_AuthenticationHeader/1, + fun chk_AuthenticationHeader/2). + +chk_AuthenticationHeader(A, A) -> + chk_type(fun is_AuthenticationHeader/1, 'AuthenticationHeader', A); +chk_AuthenticationHeader(A1, A2) -> + case (is_AuthenticationHeader(A1) andalso is_AuthenticationHeader(A2)) of + true -> + not_equal('AuthenticationHeader', A1, A2); + false -> + wrong_type('AuthenticationHeader', A1, A2) + end. + + +%% -- SecurityParmIndex -- + +is_SecurityParmIndex(V) -> is_OCTET_STRING(V, {exact, 4}). + + +%% -- SequenceNum -- + +is_SequenceNum(V) -> is_OCTET_STRING(V, {exact, 4}). + + +%% -- AuthData -- + +is_AuthData(V) -> is_OCTET_STRING(V, {range, 12, 32}). + + +%% -- Message -- + +is_Message(#'Message'{version = V, + mId = MID, + messageBody = Body}) -> + d("is_Message -> entry"), + is_INTEGER(V, {range, 0, 99}) andalso + is_MId(MID) andalso + is_Message_messageBody(Body); +is_Message(_) -> + false. + +chk_Message(M, M) -> + d("chk_Message -> entry (1)"), + chk_type(fun is_Message/1, 'Message', M); +chk_Message(#'Message'{version = V1, + mId = MID1, + messageBody = Body1}, + #'Message'{version = V2, + mId = MID2, + messageBody = Body2}) -> + d("chk_Message -> entry with" + "~n V1: ~p" + "~n V2: ~p" + "~n MID1: ~p" + "~n MID2: ~p" + "~n Body1: ~p" + "~n Body2: ~p", + [V1, V2, MID1, MID2, Body1, Body2]), + validate(fun() -> chk_INTEGER(V1, V2, {range, 0, 99}) end, + 'Message_version'), + validate(fun() -> chk_MId(MID1, MID2) end, 'Message_mId'), + chk_Message_messageBody(Body1, Body2), + ok; +chk_Message(M1, M2) -> + wrong_type('Message', M1, M2). + + +is_Message_messageBody({Tag, Val}) -> + d("is_Message_messageBody -> entry"), + is_Message_messageBody_tag(Tag) andalso + is_Message_messageBody_val(Tag, Val); +is_Message_messageBody(_) -> + false. + +is_Message_messageBody_tag(Tag) -> + Tags = [messageError, transactions], + lists:member(Tag, Tags). + +is_Message_messageBody_val(messageError, Val) -> + is_ErrorDescriptor(Val); +is_Message_messageBody_val(transactions, Val) -> + is_Message_messageBody_transactions(Val). + +is_Message_messageBody_transactions([]) -> + d("is_Message_messageBody_transactions -> entry when done"), + true; +is_Message_messageBody_transactions([H|T]) -> + d("is_Message_messageBody_transactions -> entry"), + is_Transaction(H) andalso is_Message_messageBody_transactions(T); +is_Message_messageBody_transactions(_) -> + false. + +chk_Message_messageBody(B, B) -> + d("chk_Message_messageBody -> entry (1)"), + chk_type(fun is_Message_messageBody/1, 'Message_messageBody', B); +chk_Message_messageBody({Tag, Val1} = B1, {Tag, Val2} = B2) -> + d("chk_Message_messageBody -> entry (2)"), + case (is_Message_messageBody_tag(Tag) andalso + is_Message_messageBody_val(Tag, Val1) andalso + is_Message_messageBody_val(Tag, Val2)) of + true -> + chk_Message_messageBody_val(Tag, Val1, Val2); + false -> + wrong_type('Message_messageBody', B1, B2) + end; +chk_Message_messageBody({Tag1, Val1} = B1, {Tag2, Val2} = B2) -> + d("chk_Message_messageBody -> entry (3)"), + case ((is_Message_messageBody_tag(Tag1) andalso + is_Message_messageBody_val(Tag1, Val1)) andalso + (is_Message_messageBody_tag(Tag2) andalso + is_Message_messageBody_val(Tag2, Val2))) of + true -> + not_equal('Message_messageBody', B1, B2); + false -> + wrong_type('Message_messageBody', B1, B2) + end; +chk_Message_messageBody(B1, B2) -> + wrong_type('Message_messageBody', B1, B2). + +chk_Message_messageBody_val(messageError, Val1, Val2) -> + validate(fun() -> chk_ErrorDescriptor(Val1, Val2) end, + 'Message_messageBody'); +chk_Message_messageBody_val(transactions, Val1, Val2) -> + chk_Message_messageBody_transactions(lists:sort(Val1), + lists:sort(Val2)). + +chk_Message_messageBody_transactions([], []) -> + d("chk_Message_messageBody_transactions -> entry - ok (1)"), + ok; +chk_Message_messageBody_transactions([] = T1, T2) -> + d("chk_Message_messageBody_transactions -> entry - not-equal (2)"), + not_equal('Message_messageBody_transactions', T1, T2); +chk_Message_messageBody_transactions(T1, [] = T2) -> + d("chk_Message_messageBody_transactions -> entry - not-equal (3)"), + not_equal('Message_messageBody_transactions', T1, T2); +chk_Message_messageBody_transactions([H|T1], [H|T2]) -> + d("chk_Message_messageBody_transactions -> entry (4)"), + case is_Transaction(H) of + true -> + chk_Message_messageBody_transactions(T1, T2); + false -> + wrong_type('Message_messageBody_transactions_val', H) + end; +chk_Message_messageBody_transactions([H1|T1], [H2|T2]) -> + d("chk_Message_messageBody_transactions -> entry (5)"), + validate(fun() -> chk_Transaction(H1, H2) end, + 'Message_messageBody_transactions_val'), + chk_Message_messageBody_transactions(T1, T2); +chk_Message_messageBody_transactions(T1, T2) -> + d("chk_Message_messageBody_transactions -> entry - wrong-type (6)"), + wrong_type('Message_messageBody_transactions', T1, T2). + + +%% -- MId -- + +is_opt_MId(M) -> + is_OPTIONAL(fun is_MId/1, M). + +is_MId({Tag, Val}) -> + is_MId_tag(Tag) andalso is_MId_val(Tag, Val); +is_MId(_) -> + false. + +is_MId_tag(Tag) -> + Tags = [ip4Address, ip6Address, domainName, deviceName, mtpAddress], + lists:member(Tag, Tags). + +is_MId_val(ip4Address, Val) -> is_IP4Address(Val); +is_MId_val(ip6Address, Val) -> is_IP6Address(Val); +is_MId_val(domainName, Val) -> is_DomainName(Val); +is_MId_val(deviceName, Val) -> is_PathName(Val); +is_MId_val(mtpAddress, Val) -> is_OCTET_STRING(Val, {range, 2, 4}). + +chk_opt_MId(M1, M2) -> + chk_OPTIONAL('MId', M1, M2, fun is_MId/1, fun chk_MId/2). + +chk_MId(M, M) -> + chk_type(fun is_MId/1, 'MId', M); +chk_MId({Tag, Val1} = M1, {Tag, Val2} = M2) -> + case (is_MId_tag(Tag) andalso + is_MId_val(Tag, Val1) andalso + is_MId_val(Tag, Val2)) of + true -> + chk_MId_val(Tag, Val1, Val2); + false -> + wrong_type('MId', M1, M2) + end; +chk_MId({Tag1, Val1} = M1, {Tag2, Val2} = M2) -> + case ((is_MId_tag(Tag1) andalso + is_MId_val(Tag1, Val1)) andalso + (is_MId_tag(Tag2) andalso + is_MId_val(Tag2, Val2))) of + true -> + not_equal('MId', M1, M2); + false -> + wrong_type('MId', M1, M2) + end; +chk_MId(M1, M2) -> + wrong_type('MId', M1, M2). + +chk_MId_val(ip4Address, M1, M2) -> chk_IP4Address(M1, M2); +chk_MId_val(ip6Address, M1, M2) -> chk_IP6Address(M1, M2); +chk_MId_val(domainName, M1, M2) -> chk_DomainName(M1, M2); +chk_MId_val(deviceName, M1, M2) -> chk_PathName(M1, M2); +chk_MId_val(mtpAddress, M1, M2) -> chk_OCTET_STRING(M1, M2, {range, 2, 4}). + + +%% -- DomainName -- + +is_DomainName(#'DomainName'{name = N, portNumber = PN}) -> + is_IA5String(N) andalso is_opt_INTEGER(PN, {range, 0, 65535}); +is_DomainName(_) -> + false. + +chk_DomainName(N, N) -> + ok; +chk_DomainName(N1, N2) -> + not_equal('DomainName', N1, N2). + + +%% -- IP4Address -- + +is_IP4Address(#'IP4Address'{address = A, portNumber = PN}) -> + is_OCTET_STRING(A, {exact, 4}) andalso + is_opt_INTEGER(PN, {range, 0, 65535}); +is_IP4Address(_) -> + false. + +chk_IP4Address(A, A) -> + ok; +chk_IP4Address(A1, A2) -> + not_equal('IP4Address', A1, A2). + + +%% -- IP6Address -- + +is_IP6Address(#'IP6Address'{address = A, portNumber = PN}) -> + is_OCTET_STRING(A, {exact, 16}) andalso + is_opt_INTEGER(PN, {range, 0, 65535}); +is_IP6Address(_) -> + false. + +chk_IP6Address(A, A) -> + ok; +chk_IP6Address(A1, A2) -> + not_equal('IP6Address', A1, A2). + + +%% -- PathName -- + +is_PathName(N) -> is_IA5String(N, {range, 1, 64}). + +chk_PathName(N, N) -> + ok; +chk_PathName(N1, N2) -> + not_equal('PathName', N1, N2). + + +%% -- Transaction -- + +is_Transaction({Tag, Val}) -> + d("is_Transaction -> entry"), + is_Transaction_tag(Tag) andalso is_Transaction_val(Tag, Val); +is_Transaction(_) -> + false. + +is_Transaction_tag(Tag) -> + Tags = [transactionRequest, + transactionPending, + transactionReply, + transactionResponseAck], + lists:member(Tag, Tags). + +is_Transaction_val(transactionRequest, V) -> is_TransactionRequest(V); +is_Transaction_val(transactionPending, V) -> is_TransactionPending(V); +is_Transaction_val(transactionReply, V) -> is_TransactionReply(V); +is_Transaction_val(transactionResponseAck, V) -> is_TransactionResponseAck(V). + + +chk_Transaction({Tag, Val} = Trans, Trans) -> + d("chk_Transaction -> entry (1)"), + case (is_Transaction_tag(Tag) andalso is_Transaction_val(Tag, Val)) of + true -> + ok; + false -> + wrong_type('Transaction', Trans, Trans) + end; +chk_Transaction({Tag, Val1} = Trans1, {Tag, Val2} = Trans2) -> + d("chk_Transaction -> entry (2)"), + case (is_Transaction_tag(Tag) and + is_Transaction_val(Tag, Val1) and + is_Transaction_val(Tag, Val2)) of + true -> + chk_Transaction_val(Tag, Val1, Val2); + false -> + wrong_type('Transaction', Trans1, Trans2) + end; +chk_Transaction({Tag1, Val1} = Trans1, {Tag2, Val2} = Trans2) -> + d("chk_Transaction -> entry (3)"), + case ((is_Transaction_tag(Tag1) andalso + is_Transaction_val(Tag1, Val1)) andalso + (is_Transaction_tag(Tag2) andalso + is_Transaction_val(Tag2, Val2))) of + true -> + not_equal('Transaction', Trans1, Trans2); + false -> + wrong_type('Transaction', Trans1, Trans2) + end; +chk_Transaction(Trans1, Trans2) -> + d("chk_Transaction -> entry - wrong-type - (4)"), + wrong_type('Transaction', Trans1, Trans2). + +chk_Transaction_val(transactionRequest, T1, T2) -> + chk_TransactionRequest(T1, T2); +chk_Transaction_val(transactionPending, T1, T2) -> + chk_TransactionPending(T1, T2); +chk_Transaction_val(transactionReply, T1, T2) -> + chk_TransactionReply(T1,T2); +chk_Transaction_val(transactionResponseAck, T1, T2) -> + chk_TransactionResponseAck(T1, T2). + + +%% -- TransactionId -- + +is_opt_TransactionId(TID) -> + is_OPTIONAL(fun is_TransactionId/1, TID). + +is_TransactionId(TID) -> + d("is_TransactionId -> entry"), + is_INTEGER(TID, {range, 0, 4294967295}). + +chk_opt_TransactionId(TID1, TID2) -> + chk_OPTIONAL('TransactionId', TID1, TID2, + fun is_TransactionId/1, fun chk_TransactionId/2). + +chk_TransactionId(TID, TID) -> + chk_type(fun is_TransactionId/1, 'TransactionId', TID); +chk_TransactionId(TID1, TID2) -> + case (is_TransactionId(TID1) andalso is_TransactionId(TID2)) of + true -> + not_equal('TransactionId', TID1, TID2); + false -> + wrong_type('TransactionId', TID1, TID2) + end. + + +%% -- TransactionRequest -- + +is_TransactionRequest(#'TransactionRequest'{transactionId = TID, + actions = Acts}) -> + d("is_TransactionRequest -> entry"), + is_TransactionId(TID) andalso is_TransactionRequest_actions(Acts); +is_TransactionRequest(_) -> + false. + +chk_TransactionRequest(T, T) -> + chk_type(fun is_TransactionRequest/1, 'TransactionRequest', T); +chk_TransactionRequest(#'TransactionRequest'{transactionId = TID1, + actions = Acts1}, + #'TransactionRequest'{transactionId = TID2, + actions = Acts2}) -> + validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionRequest'), + chk_TransactionRequest_actions(lists:sort(Acts1), + lists:sort(Acts2)), + ok; +chk_TransactionRequest(T1, T2) -> + wrong_type('TransactionRequest', T1, T2). + +is_TransactionRequest_actions([]) -> + d("is_TransactionRequest_actions -> entry when done"), + true; +is_TransactionRequest_actions([H|T]) -> + d("is_TransactionRequest_actions -> entry"), + is_ActionRequest(H) andalso is_TransactionRequest_actions(T); +is_TransactionRequest_actions(_) -> + false. + +chk_TransactionRequest_actions([], []) -> + ok; +chk_TransactionRequest_actions([] = Acts1, Acts2) -> + not_equal('TransactionRequest_actions', Acts1, Acts2); +chk_TransactionRequest_actions(Acts1, [] = Acts2) -> + not_equal('TransactionRequest_actions', Acts1, Acts2); +chk_TransactionRequest_actions([H|T1], [H|T2]) -> + case is_ActionRequest(H) of + true -> + chk_TransactionRequest_actions(T1, T2); + false -> + wrong_type('TransactionRequest_actions_val', H) + end; +chk_TransactionRequest_actions([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ActionRequest(H1, H2) end, + 'TransactionRequest_actions_val'), + chk_TransactionRequest_actions(T1, T2); +chk_TransactionRequest_actions(Acts1, Acts2) -> + wrong_type('TransactionRequest_actions', Acts1, Acts2). + + +%% -- TransactionPending -- + +is_TransactionPending(#'TransactionPending'{transactionId = TID}) -> + d("is_TransactionPending -> entry"), + is_TransactionId(TID); +is_TransactionPending(_) -> + false. + +chk_TransactionPending(T, T) -> + chk_type(fun is_TransactionPending/1, 'TransactionPending', T); +chk_TransactionPending(#'TransactionPending'{transactionId = TID1}, + #'TransactionPending'{transactionId = TID2}) -> + validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionPending'), + ok; +chk_TransactionPending(T1, T2) -> + wrong_type('TransactionPending', T1, T2). + + +%% -- TransactionReply -- + +is_TransactionReply(#'TransactionReply'{transactionId = TID, + immAckRequired = IAR, + transactionResult = TR}) -> + d("is_TransactionReply -> entry"), + is_TransactionId(TID) andalso + is_opt_NULL(IAR) andalso + is_TransactionReply_transactionResult(TR); +is_TransactionReply(_) -> + false. + +chk_TransactionReply(T, T) -> + d("chk_TransactionReply -> entry (2)"), + chk_type(fun is_TransactionReply/1, 'TransactionReply', T); +chk_TransactionReply(#'TransactionReply'{transactionId = TID1, + immAckRequired = IAR1, + transactionResult = TR1}, + #'TransactionReply'{transactionId = TID2, + immAckRequired = IAR2, + transactionResult = TR2}) -> + d("chk_TransactionReply -> entry (2)"), + validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionReply'), + validate(fun() -> chk_opt_NULL(IAR1, IAR2) end, 'TransactionReply'), + chk_TransactionReply_transactionResult(TR1, TR2), + ok; +chk_TransactionReply(T1, T2) -> + d("chk_TransactionReply -> entry (3)"), + wrong_type('TransactionReply', T1, T2). + +is_TransactionReply_transactionResult({Tag, Val}) -> + d("is_TransactionReply_transactionResult -> entry"), + is_TransactionReply_transactionResult_tag(Tag) andalso + is_TransactionReply_transactionResult_val(Tag, Val); +is_TransactionReply_transactionResult(_) -> + false. + +is_TransactionReply_transactionResult_tag(T) -> + lists:member(T, [transactionError, actionReplies]). + +is_TransactionReply_transactionResult_val(transactionError, V) -> + is_ErrorDescriptor(V); +is_TransactionReply_transactionResult_val(actionReplies, V) -> + is_TransactionReply_actionReplies(V). + +chk_TransactionReply_transactionResult(Res, Res) -> + chk_type(fun is_TransactionReply_transactionResult/1, + 'TransactionReply_transactionResult', Res); +chk_TransactionReply_transactionResult({Tag, Val1} = Res1, + {Tag, Val2} = Res2) -> + case (is_TransactionReply_transactionResult_tag(Tag) and + is_TransactionReply_transactionResult_val(Tag, Val1) and + is_TransactionReply_transactionResult_val(Tag, Val2)) of + true -> + chk_TransactionReply_transactionResult_val(Tag, Val1, Val2); + false -> + wrong_type('TransactionReply_transactionResult', Res1, Res2) + end; +chk_TransactionReply_transactionResult({Tag1, Val1} = Res1, + {Tag2, Val2} = Res2) -> + case ((is_TransactionReply_transactionResult_tag(Tag1) and + is_TransactionReply_transactionResult_val(Tag1, Val1)) and + (is_TransactionReply_transactionResult_tag(Tag2) and + is_TransactionReply_transactionResult_val(Tag2, Val2))) of + true -> + not_equal('TransactionReply_transactionResult', Res1, Res2); + false -> + wrong_type('TransactionReply_transactionResult', Res1, Res2) + end; +chk_TransactionReply_transactionResult(Res1, Res2) -> + wrong_type('TransactionReply_transactionResult', Res1, Res2). + +chk_TransactionReply_transactionResult_val(transactionError, E1, E2) -> + validate(fun() -> chk_ErrorDescriptor(E1, E2) end, + 'TransactionReply_transactionResult'); +chk_TransactionReply_transactionResult_val(actionReplies, R1, R2) -> + validate(fun() -> + chk_TransactionReply_actionReplies(lists:sort(R1), + lists:sort(R2)) + end, + 'TransactionReply_transactionResult'). + +is_TransactionReply_actionReplies([]) -> + d("is_TransactionReply_actionReplies -> entry when done"), + true; +is_TransactionReply_actionReplies([H|T]) -> + d("is_TransactionReply_actionReplies -> entry"), + is_ActionReply(H) andalso is_TransactionReply_actionReplies(T); +is_TransactionReply_actionReplies(_) -> + false. + +chk_TransactionReply_actionReplies([], []) -> + ok; +chk_TransactionReply_actionReplies([] = AR1, AR2) -> + not_equal('TransactionReply_actionReplies', AR1, AR2); +chk_TransactionReply_actionReplies(AR1, [] = AR2) -> + not_equal('TransactionReply_actionReplies', AR1, AR2); +chk_TransactionReply_actionReplies([H|T1], [H|T2]) -> + case is_ActionReply(H) of + true -> + chk_TransactionReply_actionReplies(T1, T2); + false -> + wrong_type('TransactionReply_actionReplies_val', H) + end; +chk_TransactionReply_actionReplies([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ActionReply(H1, H2) end, + 'TransactionReply_actionReplies_val'), + chk_TransactionReply_actionReplies(T1, T2); +chk_TransactionReply_actionReplies(AR1, AR2) -> + wrong_type('TransactionReply_actionReplies', AR1, AR2). + + +%% -- TransactionResponseAck -- + +is_TransactionResponseAck([]) -> + d("is_TransactionResponseAck -> entry when done"), + true; +is_TransactionResponseAck([H|T]) -> + d("is_TransactionResponseAck -> entry"), + is_TransactionAck(H) andalso is_TransactionResponseAck(T); +is_TransactionResponseAck(_) -> + false. + +chk_TransactionResponseAck([], []) -> + ok; +chk_TransactionResponseAck([] = AR1, AR2) -> + not_equal('TransactionResponseAck', AR1, AR2); +chk_TransactionResponseAck(AR1, [] = AR2) -> + not_equal('TransactionResponseAck', AR1, AR2); +chk_TransactionResponseAck([H|T1], [H|T2]) -> + case is_TransactionAck(H) of + true -> + chk_TransactionResponseAck(T1, T2); + false -> + wrong_type('TransactionResponseAck_val', H) + end; +chk_TransactionResponseAck([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TransactionAck(H1, H2) end, + 'TransactionResponseAck'), + chk_TransactionResponseAck(T1, T2); +chk_TransactionResponseAck(AR1, AR2) -> + wrong_type('TransactionResponseAck', AR1, AR2). + + +%% -- TransactionAck -- + +is_TransactionAck(#'TransactionAck'{firstAck = F, + lastAck = L}) -> + d("is_TransactionAck -> entry"), + is_TransactionId(F) andalso is_opt_TransactionId(L); +is_TransactionAck(_) -> + false. + +chk_TransactionAck(T, T) -> + chk_type(fun is_TransactionAck/1, 'TransactionAck', T); +chk_TransactionAck(#'TransactionAck'{firstAck = F1, + lastAck = L1}, + #'TransactionAck'{firstAck = F2, + lastAck = L2}) -> + validate(fun() -> chk_TransactionId(F1, F2) end, 'TransactionAck'), + validate(fun() -> chk_opt_TransactionId(L1, L2) end, 'TransactionAck'), + ok; +chk_TransactionAck(T1, T2) -> + wrong_type('TransactionAck', T1, T2). + + +%% -- ErrorDescriptor -- + +is_opt_ErrorDescriptor(V) -> + is_OPTIONAL(fun is_ErrorDescriptor/1, V). + +is_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code, + errorText = Text}) -> + d("is_ErrorDescriptor -> entry"), + is_ErrorCode(Code) andalso is_opt_ErrorText(Text); +is_ErrorDescriptor(_) -> + false. + +chk_opt_ErrorDescriptor(E1, E2) -> + chk_OPTIONAL('ErrorDescriptor', E1, E2, + fun is_ErrorDescriptor/1, fun chk_ErrorDescriptor/2). + +chk_ErrorDescriptor(E, E) -> + chk_type(fun is_ErrorDescriptor/1, 'ErrorDescriptor', E); +chk_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code1, + errorText = Text1}, + #'ErrorDescriptor'{errorCode = Code2, + errorText = Text2}) -> + chk_ErrorCode(Code1, Code2), + chk_opt_ErrorText(Text1, Text2), + ok; +chk_ErrorDescriptor(E1, E2) -> + wrong_type('ErrorDescriptor', E1, E2). + + +%% -- ErrorCode -- + +is_ErrorCode(C) -> is_INTEGER(C, {range, 0, 65535}). + +chk_ErrorCode(C, C) -> + case is_ErrorCode(C) of + true -> + ok; + false -> + wrong_type(errorCode, C, C) + end; +chk_ErrorCode(C1, C2) -> + case (is_ErrorCode(C1) andalso is_ErrorCode(C2)) of + true -> + not_equal(errorCode, C1, C2); + false -> + wrong_type(errorCode, C1, C2) + end. + + +%% -- ErrorText -- + +is_opt_ErrorText(V) -> + is_OPTIONAL(fun is_ErrorText/1, V). + +is_ErrorText(V) -> is_IA5String(V). + +chk_opt_ErrorText(T1, T2) -> + chk_OPTIONAL('ErrorText', T1, T2, fun is_ErrorText/1, fun chk_ErrorText/2). + +chk_ErrorText(T, T) -> + chk_type(fun is_ErrorText/1, 'ErrorText', T); +chk_ErrorText(T1, T2) -> + case (is_ErrorText(T1) andalso is_ErrorText(T2)) of + true -> + case {to_lower(T1), to_lower(T2)} of + {T, T} -> + ok; + _ -> + not_equal('ErrorText', T1, T2) + end; + false -> + wrong_type('ErrorText', T1, T2) + end. + + +%% -- ContextID -- + +is_ContextID(Id) -> is_INTEGER(Id, {range, 0, 4294967295}). + +chk_ContextID(Id, Id) -> + chk_type(fun is_ContextID/1, 'ContextID', Id); +chk_ContextID(Id1, Id2) -> + case (is_ContextID(Id1) andalso is_ContextID(Id2)) of + true -> + not_equal('ContextID', Id1, Id2); + false -> + wrong_type('ContextID', Id1, Id2) + end. + + +%% -- ActionRequest -- + +is_ActionRequest(#'ActionRequest'{contextId = Id, + contextRequest = CtxReq, + contextAttrAuditReq = AuditReq, + commandRequests = CmdReqs}) -> + d("is_ActionRequest -> entry"), + is_ContextID(Id) andalso + is_opt_ContextRequest(CtxReq) andalso + is_opt_ContextAttrAuditRequest(AuditReq) andalso + is_ActionRequest_commandRequests(CmdReqs); +is_ActionRequest(_) -> + false. + +chk_ActionRequest(A, A) -> + chk_type(fun is_ActionRequest/1, 'ActionRequest', A); +chk_ActionRequest(#'ActionRequest'{contextId = Id1, + contextRequest = Req1, + contextAttrAuditReq = AuditReq1, + commandRequests = CmdReqs1}, + #'ActionRequest'{contextId = Id2, + contextRequest = Req2, + contextAttrAuditReq = AuditReq2, + commandRequests = CmdReqs2}) -> + validate(fun() -> chk_ContextID(Id1, Id2) end, 'ActionRequest'), + validate(fun() -> chk_opt_ContextRequest(Req1, Req2) end, 'ActionRequest'), + validate(fun() -> + chk_opt_ContextAttrAuditRequest(AuditReq1, AuditReq2) + end, + 'ActionRequest'), + chk_ActionRequest_commandRequests(CmdReqs1, CmdReqs2), + ok. + + +is_ActionRequest_commandRequests([]) -> + d("is_ActionRequest_commandRequests -> entry when done"), + true; +is_ActionRequest_commandRequests([H|T]) -> + d("is_ActionRequest_commandRequests -> entry"), + is_CommandRequest(H) andalso is_ActionRequest_commandRequests(T); +is_ActionRequest_commandRequests(_) -> + false. + +chk_ActionRequest_commandRequests([], []) -> + ok; +chk_ActionRequest_commandRequests([] = CmdReqs1, CmdReqs2) -> + not_equal('ActionRequest_commandRequests', CmdReqs1, CmdReqs2); +chk_ActionRequest_commandRequests(CmdReqs1, [] = CmdReqs2) -> + not_equal('ActionRequest_commandRequests', CmdReqs1, CmdReqs2); +chk_ActionRequest_commandRequests([H|T1], [H|T2]) -> + case is_CommandRequest(H) of + true -> + chk_ActionRequest_commandRequests(T1, T2); + false -> + wrong_type('ActionRequest_commandRequest_val', H) + end; +chk_ActionRequest_commandRequests([H1|T1], [H2|T2]) -> + validate(fun() -> chk_CommandRequest(H1, H2) end, + 'ActionRequest_commandRequests_val'), + chk_ActionRequest_commandRequests(T1, T2); +chk_ActionRequest_commandRequests(R1, R2) -> + wrong_type('ActionRequest_commandRequests', R1, R2). + + +%% -- ActionReply -- + +is_ActionReply(#'ActionReply'{contextId = Id, + errorDescriptor = ED, + contextReply = CtxRep, + commandReply = CmdRep}) -> + d("is_ActionReply -> entry"), + is_ContextID(Id) andalso + is_opt_ErrorDescriptor(ED) andalso + is_opt_ContextRequest(CtxRep) andalso + is_ActionReply_commandReply(CmdRep); +is_ActionReply(_) -> + false. + +is_ActionReply_commandReply([]) -> + d("is_ActionReply_commandReply -> entry when done"), + true; +is_ActionReply_commandReply([H|T]) -> + d("is_ActionReply_commandReply -> entry"), + is_CommandReply(H) andalso is_ActionReply_commandReply(T); +is_ActionReply_commandReply(_) -> + false. + +chk_ActionReply(A, A) -> + d("chk_ActionReply -> entry (1)"), + chk_type(fun is_ActionReply/1, 'ActionReply', A); +chk_ActionReply(#'ActionReply'{contextId = Id1, + errorDescriptor = ED1, + contextReply = CtxRep1, + commandReply = CmdRep1}, + #'ActionReply'{contextId = Id2, + errorDescriptor = ED2, + contextReply = CtxRep2, + commandReply = CmdRep2}) -> + d("chk_ActionReply -> entry (2)"), + chk_ContextID(Id1, Id2), + chk_opt_ErrorDescriptor(ED1, ED2), + chk_opt_ContextRequest(CtxRep1, CtxRep2), + chk_ActionReply_commandReply(CmdRep1, CmdRep2). + +chk_ActionReply_commandReply([], []) -> + ok; +chk_ActionReply_commandReply([] = Reps1, Reps2) -> + not_equal('ActionReply_commandReply', Reps1, Reps2); +chk_ActionReply_commandReply(Reps1, [] = Reps2) -> + not_equal('ActionReply_commandReply', Reps1, Reps2); +chk_ActionReply_commandReply([H|T1], [H|T2]) -> + case is_CommandReply(H) of + true -> + chk_ActionReply_commandReply(T1, T2); + false -> + wrong_type('ActionReply_commandReply_val', H) + end; +chk_ActionReply_commandReply([H1|T1], [H2|T2]) -> + validate(fun() -> chk_CommandReply(H1, H2) end, + 'ActionReply_commandReply_val'), + chk_ActionReply_commandReply(T1, T2); +chk_ActionReply_commandReply(R1, R2) -> + wrong_type('ActionReply_commandReply', R1, R2). + + +%% -- ContextRequest -- + +is_opt_ContextRequest(V) -> + is_OPTIONAL(fun is_ContextRequest/1, V). + +is_ContextRequest(#'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = TopReq, + iepscallind = Ieps, + contextProp = CtxProp, + contextList = CtxList}) -> + d("is_ContextRequest -> entry"), + is_ContextRequest_priority(Prio) andalso + is_ContextRequest_emergency(Em) andalso + is_ContextRequest_topologyReq(TopReq) andalso + is_ContextRequest_iepscallind(Ieps) andalso + is_ContextRequest_contextProp(CtxProp) andalso + is_ContextRequest_contextList(CtxList); +is_ContextRequest(_) -> + false. + +is_ContextRequest_priority(asn1_NOVALUE) -> + true; +is_ContextRequest_priority(V) -> + is_INTEGER(V, {range, 1, 15}). + +is_ContextRequest_emergency(asn1_NOVALUE) -> + true; +is_ContextRequest_emergency(V) -> + is_BOOLEAN(V). + +is_ContextRequest_topologyReq(asn1_NOVALUE) -> + true; +is_ContextRequest_topologyReq([]) -> + true; +is_ContextRequest_topologyReq([H|T]) -> + is_TopologyRequest(H) andalso is_ContextRequest_topologyReq(T); +is_ContextRequest_topologyReq(_) -> + false. + +is_ContextRequest_iepscallind(asn1_NOVALUE) -> + true; +is_ContextRequest_iepscallind(V) -> + is_BOOLEAN(V). + +is_ContextRequest_contextProp(asn1_NOVALUE) -> + true; +is_ContextRequest_contextProp([]) -> + true; +is_ContextRequest_contextProp([H|T]) -> + is_PropertyParm(H) andalso is_ContextRequest_contextProp(T); +is_ContextRequest_contextProp(_) -> + false. + +is_ContextRequest_contextList(asn1_NOVALUE) -> + true; +is_ContextRequest_contextList([]) -> + true; +is_ContextRequest_contextList([H|T]) -> + is_ContextID(H) andalso is_ContextRequest_contextList(T); +is_ContextRequest_contextList(_) -> + false. + +chk_opt_ContextRequest(R1, R2) -> + chk_OPTIONAL('ContextRequest', R1, R2, + fun is_ContextRequest/1, fun chk_ContextRequest/2). + +chk_ContextRequest(R, R) -> + chk_type(fun is_ContextRequest/1, 'ContextRequest', R); +chk_ContextRequest(#'ContextRequest'{priority = Prio1, + emergency = Em1, + topologyReq = TopReq1, + iepscallind = Ieps1, + contextProp = CtxProp1, + contextList = CtxList1}, + #'ContextRequest'{priority = Prio2, + emergency = Em2, + topologyReq = TopReq2, + iepscallind = Ieps2, + contextProp = CtxProp2, + contextList = CtxList2}) -> + chk_ContextRequest_priority(Prio1, Prio2), + chk_ContextRequest_emergency(Em1, Em2), + chk_ContextRequest_topologyReq(TopReq1, TopReq2), + chk_ContextRequest_iepscallind(Ieps1, Ieps2), + chk_ContextRequest_contextProp(CtxProp1, CtxProp2), + chk_ContextRequest_contextList(CtxList1, CtxList2), + ok; +chk_ContextRequest(R1, R2) -> + wrong_type('ContextRequest', R1, R2). + + +chk_ContextRequest_priority(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_ContextRequest_priority(P, P) -> + chk_type(fun is_ContextRequest_priority/1, 'ContextRequest_priority', P); +chk_ContextRequest_priority(P1, P2) -> + case (is_ContextRequest_priority(P1) andalso + is_ContextRequest_priority(P2)) of + true -> + not_equal('ContextRequest_priority', P1, P2); + false -> + wrong_type(contextRequest_priority, P1, P2) + end. + + +chk_ContextRequest_emergency(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_emergency(E, E) -> + chk_type(fun is_ContextRequest_emergency/1, 'ContextRequest_emergency', E); +chk_ContextRequest_emergency(E1, E2) -> + case (is_ContextRequest_emergency(E1) andalso + is_ContextRequest_emergency(E2)) of + true -> + not_equal('ContextRequest_emergency', E1, E2); + false -> + wrong_type('ContextRequest_emergency', E1, E2) + end. + +chk_ContextRequest_topologyReq(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_topologyReq([], []) -> + ok; +chk_ContextRequest_topologyReq([] = T1, T2) -> + not_equal('ContextRequest_topologyReq', T1, T2); +chk_ContextRequest_topologyReq(T1, [] = T2) -> + not_equal('ContextRequest_topologyReq', T1, T2); +chk_ContextRequest_topologyReq([H|T1], [H|T2]) -> + case is_TopologyRequest(H) of + true -> + chk_ContextRequest_topologyReq(T1, T2); + false -> + wrong_type('ContextRequest_topologyReq_val', H) + end; +chk_ContextRequest_topologyReq([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TopologyRequest(H1, H2) end, + 'ContextRequest_topologyReq_val'), + chk_ContextRequest_topologyReq(T1, T2); +chk_ContextRequest_topologyReq(T1, T2) -> + wrong_type('ContextRequest_topologyReq', T1, T2). + + +chk_ContextRequest_iepscallind(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_iepscallind(E, E) -> + chk_type(fun is_ContextRequest_iepscallind/1, + 'ContextRequest_iepscallind', E); +chk_ContextRequest_iepscallind(E1, E2) -> + case (is_ContextRequest_iepscallind(E1) andalso + is_ContextRequest_iepscallind(E2)) of + true -> + case (((E1 == false) and (E2 == asn1_NOVALUE)) or + ((E1 == asn1_NOVALUE) and (E2 == false))) of + true -> + ok; + false -> + not_equal('ContextRequest_iepscallind', E1, E2) + end; + + false -> + wrong_type('ContextRequest_iepscallind', E1, E2) + end. + +chk_ContextRequest_contextProp(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_contextProp([], []) -> + ok; +chk_ContextRequest_contextProp([] = T1, T2) -> + not_equal('ContextRequest_contextProp', T1, T2); +chk_ContextRequest_contextProp(T1, [] = T2) -> + not_equal('ContextRequest_contextProp', T1, T2); +chk_ContextRequest_contextProp([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_ContextRequest_contextProp(T1, T2); + false -> + wrong_type('ContextRequest_contextProp_val', H) + end; +chk_ContextRequest_contextProp([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, + 'ContextRequest_contextProp_val'), + chk_ContextRequest_contextProp(T1, T2); +chk_ContextRequest_contextProp(T1, T2) -> + wrong_type('ContextRequest_contextProp', T1, T2). + +chk_ContextRequest_contextList(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_contextList([], []) -> + ok; +chk_ContextRequest_contextList([] = T1, T2) -> + not_equal('ContextRequest_contextList', T1, T2); +chk_ContextRequest_contextList(T1, [] = T2) -> + not_equal('ContextRequest_contextList', T1, T2); +chk_ContextRequest_contextList([H|T1], [H|T2]) -> + case is_ContextID(H) of + true -> + chk_ContextRequest_contextList(T1, T2); + false -> + wrong_type('ContextRequest_contextList_val', H) + end; +chk_ContextRequest_contextList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ContextID(H1, H2) end, + 'ContextRequest_contextList_val'), + chk_ContextRequest_contextList(T1, T2); +chk_ContextRequest_contextList(T1, T2) -> + wrong_type('ContextRequest_contextList', T1, T2). + + +%% -- ContextAttrAuditRequest -- + +is_opt_ContextAttrAuditRequest(asn1_NOVALUE) -> + true; +is_opt_ContextAttrAuditRequest(V) -> + is_ContextAttrAuditRequest(V). + +is_ContextAttrAuditRequest( + #'ContextAttrAuditRequest'{topology = T, + emergency = E, + priority = P, + iepscallind = I, + contextPropAud = A, + selectpriority = SP, + selectemergency = SE, + selectiepscallind = SI, + selectLogic = SL}) -> + d("is_ContextAttrAuditRequest -> entry"), + is_opt_NULL(T) andalso + is_opt_NULL(E) andalso + is_opt_NULL(P) andalso + is_opt_NULL(I) andalso + is_ContextAttrAuditRequest_contextPropAud(A) andalso + is_ContextAttrAuditRequest_selectpriority(SP) andalso + is_ContextAttrAuditRequest_selectemergency(SE) andalso + is_ContextAttrAuditRequest_selectiepscallind(SI) andalso + is_opt_SelectLogic(SL); +is_ContextAttrAuditRequest(_) -> + false. + +is_ContextAttrAuditRequest_contextPropAud(asn1_NOVALUE) -> + true; +is_ContextAttrAuditRequest_contextPropAud([]) -> + true; +is_ContextAttrAuditRequest_contextPropAud([H|T]) -> + d("is_ContextAttrAuditRequest_contextPropAud -> entry"), + is_IndAudPropertyParm(H) andalso + is_ContextAttrAuditRequest_contextPropAud(T). + +is_ContextAttrAuditRequest_selectpriority(asn1_NOVALUE) -> + true; +is_ContextAttrAuditRequest_selectpriority(V) -> + is_INTEGER(V, {range, 1, 15}). + +is_ContextAttrAuditRequest_selectemergency(asn1_NOVALUE) -> + true; +is_ContextAttrAuditRequest_selectemergency(V) -> + is_BOOLEAN(V). + +is_ContextAttrAuditRequest_selectiepscallind(asn1_NOVALUE) -> + true; +is_ContextAttrAuditRequest_selectiepscallind(V) -> + is_BOOLEAN(V). + + +chk_opt_ContextAttrAuditRequest(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_ContextAttrAuditRequest(R1, R2) -> + chk_ContextAttrAuditRequest(R1, R2). + +chk_ContextAttrAuditRequest(R, R) -> + chk_type(fun is_ContextAttrAuditRequest/1, 'ContextAttrAuditRequest', R); +chk_ContextAttrAuditRequest( + #'ContextAttrAuditRequest'{topology = T1, + emergency = E1, + priority = P1, + iepscallind = I1, + contextPropAud = A1, + selectpriority = SP1, + selectemergency = SE1, + selectiepscallind = SI1, + selectLogic = SL1}, + #'ContextAttrAuditRequest'{topology = T2, + emergency = E2, + priority = P2, + iepscallind = I2, + contextPropAud = A2, + selectpriority = SP2, + selectemergency = SE2, + selectiepscallind = SI2, + selectLogic = SL2}) -> + validate(fun() -> chk_opt_NULL(T1, T2) end, + 'ContextAttrAuditRequest_topology'), + validate(fun() -> chk_opt_NULL(E1, E2) end, + 'ContextAttrAuditRequest_emergency'), + validate(fun() -> chk_opt_NULL(P1, P2) end, + 'ContextAttrAuditRequest_priority'), + validate(fun() -> chk_opt_NULL(I1, I2) end, + 'ContextAttrAuditRequest_iepscallind'), + chk_ContextAttrAuditRequest_contextPropAud(lists:sort(A1), + lists:sort(A2)), + chk_ContextAttrAuditRequest_selectpriority(SP1, SP2), + chk_ContextAttrAuditRequest_selectemergency(SE1, SE2), + chk_ContextAttrAuditRequest_selectiepscallind(SI1, SI2), + chk_ContextAttrAuditRequest_selectLogic(SL1, SL2), + ok. + +chk_ContextAttrAuditRequest_contextPropAud(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextAttrAuditRequest_contextPropAud(A, A) -> + chk_type(fun is_ContextAttrAuditRequest_contextPropAud/1, + 'ContextAttrAuditRequest_contextPropAud', A); +chk_ContextAttrAuditRequest_contextPropAud([], []) -> + ok; +chk_ContextAttrAuditRequest_contextPropAud([] = T1, T2) -> + not_equal('ContextAttrAuditRequest_contextPropAud', T1, T2); +chk_ContextAttrAuditRequest_contextPropAud(T1, [] = T2) -> + not_equal('ContextAttrAuditRequest_contextPropAud', T1, T2); +chk_ContextAttrAuditRequest_contextPropAud([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_ContextAttrAuditRequest_contextPropAud(T1, T2); + false -> + wrong_type('ContextAttrAuditRequest_contextPropAud_val', H) + end; +chk_ContextAttrAuditRequest_contextPropAud([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, + 'ContextAttrAuditRequest_contextPropAud_val'), + chk_ContextAttrAuditRequest_contextPropAud(T1, T2); +chk_ContextAttrAuditRequest_contextPropAud(T1, T2) -> + wrong_type('ContextAttrAuditRequest_contextPropAud', T1, T2). + +chk_ContextAttrAuditRequest_selectpriority(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextAttrAuditRequest_selectpriority(A, A) -> + chk_type(fun is_ContextAttrAuditRequest_selectpriority/1, + 'ContextAttrAuditRequest_selectpriority', A); +chk_ContextAttrAuditRequest_selectpriority(SP1, SP2) -> + case (is_ContextAttrAuditRequest_selectpriority(SP1) andalso + is_ContextAttrAuditRequest_selectpriority(SP2)) of + true -> + not_equal('ContextAttrAuditRequest_selectpriority', SP1, SP2); + false -> + wrong_type('ContextAttrAuditRequest_selectpriority', SP1, SP2) + end. + +chk_ContextAttrAuditRequest_selectemergency(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextAttrAuditRequest_selectemergency(A, A) -> + chk_type(fun is_ContextAttrAuditRequest_selectemergency/1, + 'ContextAttrAuditRequest_selectemergency', A); +chk_ContextAttrAuditRequest_selectemergency(SE1, SE2) -> + case (is_ContextAttrAuditRequest_selectemergency(SE1) andalso + is_ContextAttrAuditRequest_selectemergency(SE2)) of + true -> + not_equal('ContextAttrAuditRequest_selectemergency', SE1, SE2); + false -> + wrong_type('ContextAttrAuditRequest_selectemergency', SE1, SE2) + end. + +chk_ContextAttrAuditRequest_selectiepscallind(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextAttrAuditRequest_selectiepscallind(A, A) -> + chk_type(fun is_ContextAttrAuditRequest_selectiepscallind/1, + 'ContextAttrAuditRequest_selectiepscallind', A); +chk_ContextAttrAuditRequest_selectiepscallind(SI1, SI2) -> + case (is_ContextAttrAuditRequest_selectiepscallind(SI1) andalso + is_ContextAttrAuditRequest_selectiepscallind(SI2)) of + true -> + not_equal('ContextAttrAuditRequest_selectiepscallind', SI1, SI2); + false -> + wrong_type('ContextAttrAuditRequest_selectiepscallind', SI1, SI2) + end. + +chk_ContextAttrAuditRequest_selectLogic(SL1, SL2) -> + validate(fun() -> chk_opt_SelectLogic(SL1, SL2) end, + 'ContextAttrAuditRequest_selectLogic'). + + +%% -- SelectLogic -- + +is_opt_SelectLogic(asn1_NOVALUE) -> + true; +is_opt_SelectLogic(SL) -> + is_SelectLogic(SL). + +is_SelectLogic({Tag, Val}) -> + d("is_SelectLogic -> entry"), + is_SelectLogic_tag(Tag) andalso is_SelectLogic_val(Tag, Val); +is_SelectLogic(_) -> + false. + +is_SelectLogic_tag(Tag) -> + Tags = [andAUDITSelect, orAUDITSelect], + lists:member(Tag, Tags). + +is_SelectLogic_val(andAUDITSelect, 'NULL') -> true; +is_SelectLogic_val(orAUDITSelect, 'NULL') -> true; +is_SelectLogic_val(_, _) -> false. + +chk_opt_SelectLogic(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SelectLogic(SL1, SL2) -> + chk_SelectLogic(SL1, SL2). + +chk_SelectLogic(SL, SL) -> + chk_type(fun is_SelectLogic/1, 'SelectLogic', SL); +chk_SelectLogic(asn1_NOVALUE, {andAUDITSelect, 'NULL'}) -> + ok; % AND is default +chk_SelectLogic({andAUDITSelect, 'NULL'}, asn1_NOVALUE) -> + ok; % AND is default +chk_SelectLogic({Tag, Val1} = SL1, {Tag, Val2} = SL2) -> + case (is_SelectLogic_tag(Tag) andalso + is_SelectLogic_val(Tag, Val1) andalso + is_SelectLogic_val(Tag, Val2)) of + true -> + chk_SelectLogic_val(Tag, Val1, Val2); + false -> + wrong_type('SelectLogic', SL1, SL2) + end; +chk_SelectLogic({Tag1, Val1} = SL1, {Tag2, Val2} = SL2) -> + case ((is_SelectLogic_tag(Tag1) andalso + is_SelectLogic_val(Tag1, Val1)) andalso + (is_SelectLogic_tag(Tag2) andalso + is_SelectLogic_val(Tag2, Val2))) of + true -> + not_equal('SelectLogic', SL1, SL2); + false -> + wrong_type('SelectLogic', SL1, SL2) + end; +chk_SelectLogic(SL1, SL2) -> + wrong_type('SelectLogic', SL1, SL2). + +chk_SelectLogic_val(andAUDITSelect, SL1, SL2) -> + validate(fun() -> chk_NULL(SL1, SL2) end, 'SelectLogic_andAUDITSelect'); +chk_SelectLogic_val(orAUDITSelect, SL1, SL2) -> + validate(fun() -> chk_NULL(SL1, SL2) end, 'SelectLogic_orAUDITSelect'). + + +%% -- CommandRequest -- + +is_CommandRequest(#'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = WR}) -> + d("is_CommandRequest -> entry with" + "~n Cmd: ~p" + "~n Opt: ~p" + "~n WR: ~p", [Cmd, Opt, WR]), + is_Command(Cmd) andalso is_opt_NULL(Opt) andalso is_opt_NULL(WR); +is_CommandRequest(_) -> + false. + +chk_CommandRequest(C, C) -> + chk_type(fun is_CommandRequest/1, 'CommandRequest', C); +chk_CommandRequest(#'CommandRequest'{command = Cmd1, + optional = Opt1, + wildcardReturn = WR1}, + #'CommandRequest'{command = Cmd2, + optional = Opt2, + wildcardReturn = WR2}) -> + validate(fun() -> chk_Command(Cmd1, Cmd2) end, 'CommandRequest'), + validate(fun() -> chk_opt_NULL(Opt1, Opt2) end, 'CommandRequest'), + validate(fun() -> chk_opt_NULL(WR1, WR2) end, 'CommandRequest'), + ok; +chk_CommandRequest(R1, R2) -> + wrong_type('CommandRequest', R1, R2). + + +%% -- Command -- + +is_Command({Tag, Val}) -> + d("is_Command -> entry with" + "~n Tag: ~p" + "~n Val: ~p", [Tag, Val]), + is_Command_tag(Tag) andalso is_Command_val(Tag, Val); +is_Command(_) -> + false. + +is_Command_tag(Tag) -> + Tags = [addReq, moveReq, modReq, subtractReq, auditCapRequest, + auditValueRequest, notifyReq, serviceChangeReq], + lists:member(Tag, Tags). + +is_Command_val(addReq, V) -> is_AmmRequest(V); +is_Command_val(moveReq, V) -> is_AmmRequest(V); +is_Command_val(modReq, V) -> is_AmmRequest(V); +is_Command_val(subtractReq, V) -> is_SubtractRequest(V); +is_Command_val(auditCapRequest, V) -> is_AuditRequest(V); +is_Command_val(auditValueRequest, V) -> is_AuditRequest(V); +is_Command_val(notifyReq, V) -> is_NotifyRequest(V); +is_Command_val(serviceChangeReq, V) -> is_ServiceChangeRequest(V). + +chk_Command(Cmd, Cmd) -> + chk_type(fun is_Command/1, 'Command', Cmd); +chk_Command({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> + case (is_Command_tag(Tag) andalso + is_Command_val(Tag, Val1) andalso + is_Command_val(Tag, Val2)) of + true -> + chk_Command_val(Tag, Val1, Val2); + false -> + wrong_type('Command', Cmd1, Cmd2) + end; +chk_Command({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> + case ((is_Command_tag(Tag1) andalso is_Command_val(Tag1, Val1)) andalso + (is_Command_tag(Tag2) andalso is_Command_val(Tag2, Val2))) of + true -> + not_equal('Command', Cmd1, Cmd2); + false -> + wrong_type('Command', Cmd1, Cmd2) + end; +chk_Command(Cmd1, Cmd2) -> + wrong_type('Command', Cmd1, Cmd2). + + +chk_Command_val(addReq, R1, R2) -> + validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_addReq'); +chk_Command_val(moveReq, R1, R2) -> + validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_moveReq'); +chk_Command_val(modReq, R1, R2) -> + validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_modReq'); +chk_Command_val(subtractReq, R1, R2) -> + validate(fun() -> chk_SubtractRequest(R1, R2) end, 'Command_subtractReq'); +chk_Command_val(auditCapRequest, R1, R2) -> + validate(fun() -> chk_AuditRequest(R1, R2) end, 'Command_auditCapRequest'); +chk_Command_val(auditValueRequest, R1, R2) -> + validate(fun() -> chk_AuditRequest(R1, R2) end, + 'Command_auditValueRequest'); +chk_Command_val(notifyReq, R1, R2) -> + validate(fun() -> chk_NotifyRequest(R1, R2) end, 'Command_notifyReq'); +chk_Command_val(serviceChangeReq, R1, R2) -> + validate(fun() -> chk_ServiceChangeRequest(R1, R2) end, + 'Command_serviceChangeReq'). + + +%% -- CommandReply -- + +is_CommandReply({Tag, Val}) -> + d("is_CommandReply -> entry"), + is_CommandReply_tag(Tag) andalso is_CommandReply_val(Tag, Val); +is_CommandReply(_) -> + false. + +is_CommandReply_tag(Tag) -> + Tags = [addReply, moveReply, modReply, subtractReply, + auditCapReply, auditValueReply, notifyReply, serviceChangeReply], + lists:member(Tag, Tags). + +is_CommandReply_val(addReply, V) -> is_AmmsReply(V); +is_CommandReply_val(moveReply, V) -> is_AmmsReply(V); +is_CommandReply_val(modReply, V) -> is_AmmsReply(V); +is_CommandReply_val(subtractReply, V) -> is_AmmsReply(V); +is_CommandReply_val(auditCapReply, V) -> is_AuditReply(V); +is_CommandReply_val(auditValueReply, V) -> is_AuditReply(V); +is_CommandReply_val(notifyReply, V) -> is_NotifyReply(V); +is_CommandReply_val(serviceChangeReply, V) -> is_ServiceChangeReply(V). + +chk_CommandReply({Tag, Val} = Cmd, Cmd) -> + case (is_CommandReply_tag(Tag) andalso is_CommandReply_val(Tag, Val)) of + true -> + ok; + false -> + wrong_type('CommandReply', Cmd) + end; +chk_CommandReply({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> + case (is_CommandReply_tag(Tag) andalso + is_CommandReply_val(Tag, Val1) andalso + is_CommandReply_val(Tag, Val2)) of + true -> + chk_CommandReply_val(Tag, Val1, Val2); + false -> + wrong_type('CommandReply', Cmd1, Cmd2) + end; +chk_CommandReply({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> + case ((is_CommandReply_tag(Tag1) andalso + is_CommandReply_val(Tag1, Val1)) andalso + (is_CommandReply_tag(Tag2) andalso + is_CommandReply_val(Tag2, Val2))) of + true -> + not_equal('CommandReply', Cmd1, Cmd2); + false -> + wrong_type('CommandReply', Cmd1, Cmd2) + end; +chk_CommandReply(Cmd1, Cmd2) -> + wrong_type('CommandReply', Cmd1, Cmd2). + +chk_CommandReply_val(addReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_addReply'); +chk_CommandReply_val(moveReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_moveReply'); +chk_CommandReply_val(modReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_modReply'); +chk_CommandReply_val(subtractReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_subtractReply'); +chk_CommandReply_val(auditCapReply, V1, V2) -> + validate(fun() -> chk_AuditReply(V1, V2) end, + 'CommandReply_auditCapReply'); +chk_CommandReply_val(auditValueReply, V1, V2) -> + validate(fun() -> chk_AuditReply(V1, V2) end, + 'CommandReply_auditValueReply'); +chk_CommandReply_val(notifyReply, V1, V2) -> + validate(fun() -> chk_NotifyReply(V1, V2) end, 'CommandReply_notifyReply'); +chk_CommandReply_val(serviceChangeReply, V1, V2) -> + validate(fun() -> chk_ServiceChangeReply(V1, V2) end, + 'CommandReply_serviceChangeReply'). + + +%% -- TopologyRequest -- + +is_TopologyRequest(#'TopologyRequest'{terminationFrom = F, + terminationTo = T, + topologyDirection = TD, + streamID = S, + topologyDirectionExtension = TDE}) -> + d("is_TopologyRequest -> entry"), + is_TerminationID(F) andalso + is_TerminationID(T) andalso + is_TopologyRequest_topologyDirection(TD) andalso + is_opt_StreamID(S) andalso + is_TopologyRequest_topologyDirectionExtension(TDE); +is_TopologyRequest(_) -> + false. + +is_TopologyRequest_topologyDirection(D) -> + lists:member(D, [bothway, isolate, oneway]). + +is_TopologyRequest_topologyDirectionExtension(asn1_NOVALUE) -> + true; +is_TopologyRequest_topologyDirectionExtension(D) -> + lists:member(D, [onewayexternal, onewayboth]). + + +chk_TopologyRequest(T, T) when is_record(T,'TopologyRequest') -> + ok; +chk_TopologyRequest(#'TopologyRequest'{terminationFrom = F1, + terminationTo = T1, + topologyDirection = TD1, + streamID = S1, + topologyDirectionExtension = TDE1}, + #'TopologyRequest'{terminationFrom = F2, + terminationTo = T2, + topologyDirection = TD2, + streamID = S2, + topologyDirectionExtension = TDE2}) -> + validate(fun() -> chk_TerminationID(F1, F2) end, + 'TopologyRequest_terminationFrom'), + validate(fun() -> chk_TerminationID(T1, T2) end, + 'TopologyRequest_terminationTo'), + chk_TopologyRequest_topologyDirection(TD1, TD2), + validate(fun() -> chk_opt_StreamID(S1, S2) end, + 'TopologyRequest_streamID'), + chk_TopologyRequest_topologyDirectionExtension(TDE1, TDE2), + ok. + +chk_TopologyRequest_topologyDirection(D, D) -> + case is_TopologyRequest_topologyDirection(D) of + true -> + ok; + false -> + wrong_type('TopologyRequest_topologyDirection', D) + end; +chk_TopologyRequest_topologyDirection(D1, D2) -> + case (is_TopologyRequest_topologyDirection(D1) andalso + is_TopologyRequest_topologyDirection(D1)) of + true -> + not_equal('TopologyRequest_topologyDirection', D1, D2); + false -> + wrong_type('TopologyRequest_topologyDirection', D1, D2) + end. + +chk_TopologyRequest_topologyDirectionExtension(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_TopologyRequest_topologyDirectionExtension(D, D) -> + case is_TopologyRequest_topologyDirectionExtension(D) of + true -> + ok; + false -> + wrong_type('TopologyRequest_topologyDirectionExtension', D) + end; +chk_TopologyRequest_topologyDirectionExtension(D1, D2) -> + case (is_TopologyRequest_topologyDirectionExtension(D1) andalso + is_TopologyRequest_topologyDirectionExtension(D1)) of + true -> + not_equal('TopologyRequest_topologyDirectionExtension', D1, D2); + false -> + wrong_type('TopologyRequest_topologyDirectionExtension', D1, D2) + end. + + +%% -- AmmRequest -- + +is_AmmRequest(#'AmmRequest'{terminationID = Tids, + descriptors = Descs}) -> + d("is_AmmRequest -> entry with" + "~n Tids: ~p", [Tids]), + is_TerminationIDList(Tids) andalso is_AmmRequest_descriptors(Descs); +is_AmmRequest(_) -> + false. + +is_AmmRequest_descriptors(Descs) -> + d("is_AmmRequest_descriptors -> entry"), + is_AmmRequest_descriptors(Descs, []). + +is_AmmRequest_descriptors([], _) -> + true; +is_AmmRequest_descriptors([{Tag, _} = Desc|Descs], FoundDescs) -> + d("is_AmmRequest_descriptors -> entry with" + "~n Tag: ~p" + "~n FoundDescs: ~p", [Tag, FoundDescs]), + case lists:member(Tag, FoundDescs) of + true -> + atmost_once('AmmRequest_descriptors', Tag); + false -> + case is_AmmDescriptor(Desc) of + true -> + is_AmmRequest_descriptors(Descs, [Tag|FoundDescs]); + false -> + wrong_type('AmmRequest_descriptors', Desc) + end + end; +is_AmmRequest_descriptors(Descs, _) -> + d("is_AmmRequest_descriptors -> entry with WRONG TYPE" + "~n Descs: ~p", [Descs]), + wrong_type('AmmRequest_descriptors', Descs). + + +chk_AmmRequest(R, R) when is_record(R, 'AmmRequest') -> + d("chk_AmmRequest -> entry when equal"), + chk_type(fun is_AmmRequest/1, 'AmmRequest', R); +chk_AmmRequest(#'AmmRequest'{terminationID = Tids1, + descriptors = Descs1}, + #'AmmRequest'{terminationID = Tids2, + descriptors = Descs2}) -> + d("chk_AmmRequest -> entry with not equal" + "~n Tids1: ~p" + "~n Tids2: ~p", [Tids1, Tids2]), + validate( + fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'AmmRequest'), + validate( + fun() -> chk_AmmRequest_descriptors(Descs1, Descs2) end, + 'AmmRequest'), + ok. + + +chk_AmmRequest_descriptors([], []) -> + d("chk_AmmRequest_descriptors -> done when OK"), + ok; +chk_AmmRequest_descriptors([] = Descs1, Descs2) -> + d("chk_AmmRequest_descriptors -> done when NOT EQUAL:" + "~n Descs1: ~p" + "~n Descs1: ~p", [Descs1, Descs2]), + not_equal('AmmRequest_descriptors', Descs1, Descs2); +chk_AmmRequest_descriptors(Descs1, [] = Descs2) -> + d("chk_AmmRequest_descriptors -> done when NOT EQUAL:" + "~n Descs1: ~p" + "~n Descs1: ~p", [Descs1, Descs2]), + not_equal('AmmRequest_descriptors', Descs1, Descs2); +chk_AmmRequest_descriptors([H|T1], [H|T2]) -> + d("chk_AmmRequest_descriptors -> entry when equal"), + case is_AmmDescriptor(H) of + true -> + chk_AmmRequest_descriptors(T1, T2); + false -> + wrong_type('AmmRequest_descriptors_val', H) + end; +chk_AmmRequest_descriptors([H1|T1], [H2|T2]) -> + d("chk_AmmRequest_descriptors -> entry when not equal"), + validate(fun() -> chk_AmmDescriptor(H1, H2) end, + 'AmmRequest_descriptors_val'), + chk_AmmRequest_descriptors(T1, T2); +chk_AmmRequest_descriptors(Descs1, Descs2) -> + d("chk_AmmRequest_descriptors -> done when WRONG TYPE:" + "~n Descs1: ~p" + "~n Descs1: ~p", [Descs1, Descs2]), + wrong_type('AmmRequest_descriptors', Descs1, Descs2). + + +%% -- AmmDescriptor -- + +is_AmmDescriptor({Tag, Val}) -> + d("is_AmmDescriptor -> entry with" + "~n Tag: ~p" + "~n Val: ~p",[Tag, Val]), + is_AmmDescriptor_tag(Tag) andalso is_AmmDescriptor_val(Tag, Val); +is_AmmDescriptor(_) -> + false. + +is_AmmDescriptor_tag(Tag) -> + Tags = [mediaDescriptor, modemDescriptor, muxDescriptor, eventsDescriptor, + eventBufferDescriptor, signalsDescriptor, digitMapDescriptor, + auditDescriptor, statisticsDescriptor], + lists:member(Tag, Tags). + +is_AmmDescriptor_val(mediaDescriptor, D) -> + is_MediaDescriptor(D); +is_AmmDescriptor_val(modemDescriptor, D) -> + is_ModemDescriptor(D); +is_AmmDescriptor_val(muxDescriptor, D) -> + is_MuxDescriptor(D); +is_AmmDescriptor_val(eventsDescriptor, D) -> + is_EventsDescriptor(D); +is_AmmDescriptor_val(eventBufferDescriptor, D) -> + is_EventBufferDescriptor(D); +is_AmmDescriptor_val(signalsDescriptor, D) -> + is_SignalsDescriptor(D); +is_AmmDescriptor_val(digitMapDescriptor, D) -> + is_DigitMapDescriptor(D); +is_AmmDescriptor_val(auditDescriptor, D) -> + is_AuditDescriptor(D); +is_AmmDescriptor_val(statisticsDescriptor, D) -> + is_StatisticsDescriptor(D). + +chk_AmmDescriptor(D, D) -> + chk_type(fun is_AmmDescriptor_tag/1, 'AmmDescriptor', D); +chk_AmmDescriptor({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> + case (is_AmmDescriptor_tag(Tag) andalso + is_AmmDescriptor_val(Tag, Val1) andalso + is_AmmDescriptor_val(Tag, Val2)) of + true -> + chk_AmmDescriptor_val(Tag, Val1, Val2); + false -> + wrong_type('AmmDescriptor', Cmd1, Cmd2) + end; +chk_AmmDescriptor({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> + case ((is_AmmDescriptor_tag(Tag1) andalso + is_AmmDescriptor_val(Tag1, Val1)) andalso + (is_AmmDescriptor_tag(Tag2) andalso + is_AmmDescriptor_val(Tag2, Val2))) of + true -> + not_equal('AmmDescriptor', Cmd1, Cmd2); + false -> + wrong_type('AmmDescriptor', Cmd1, Cmd2) + end; +chk_AmmDescriptor(Cmd1, Cmd2) -> + wrong_type('AmmDescriptor', Cmd1, Cmd2). + +chk_AmmDescriptor_val(mediaDescriptor, D1, D2) -> + validate(fun() -> chk_MediaDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(modemDescriptor, D1, D2) -> + validate(fun() -> chk_ModemDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(muxDescriptor, D1, D2) -> + validate(fun() -> chk_MuxDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(eventsDescriptor, D1, D2) -> + validate(fun() -> chk_EventsDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(eventBufferDescriptor, D1, D2) -> + validate(fun() -> chk_EventBufferDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(signalsDescriptor, D1, D2) -> + validate(fun() -> chk_SignalsDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(digitMapDescriptor, D1, D2) -> + validate(fun() -> chk_DigitMapDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(auditDescriptor, D1, D2) -> + validate(fun() -> chk_AuditDescriptor(D1, D2) end, 'AmmDescriptor'). + + +%% -- AmmsReply -- + +is_AmmsReply(#'AmmsReply'{terminationID = Tids, + terminationAudit = TA}) -> + is_TerminationIDList(Tids) andalso is_opt_TerminationAudit(TA); +is_AmmsReply(_) -> + false. + +chk_AmmsReply(R, R) -> + is_AmmsReply(R); +chk_AmmsReply(#'AmmsReply'{terminationID = TID1, + terminationAudit = TA1}, + #'AmmsReply'{terminationID = TID2, + terminationAudit = TA2}) -> + validate(fun() -> chk_TerminationIDList(TID1, TID2) end, 'AmmsReply'), + validate(fun() -> chk_opt_TerminationAudit(TA1, TA2) end, 'AmmsReply'), + ok; +chk_AmmsReply(R1, R2) -> + wrong_type('AmmsReply', R1, R2). + + +%% -- SubtractRequest -- + +is_SubtractRequest(#'SubtractRequest'{terminationID = TID, + auditDescriptor = AD}) -> + d("is_SubtractDescriptor -> entry with" + "~n TID: ~p" + "~n AD: ~p",[TID, AD]), + is_TerminationIDList(TID) andalso is_opt_AuditDescriptor(AD); +is_SubtractRequest(_) -> + false. + +chk_SubtractRequest(R, R) -> + chk_type(fun is_SubtractRequest/1, 'SubtractRequest', R); +chk_SubtractRequest(#'SubtractRequest'{terminationID = Tids1, + auditDescriptor = AD1}, + #'SubtractRequest'{terminationID = Tids2, + auditDescriptor = AD2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'SubtractRequest'), + validate(fun() -> chk_opt_AuditDescriptor(AD1, AD2) end, + 'SubtractRequest'), + ok; +chk_SubtractRequest(SR1, SR2) -> + wrong_type('SubtractRequest', SR1, SR2). + + +%% -- AuditRequest -- + +is_AuditRequest(#'AuditRequest'{terminationID = TID, + auditDescriptor = AD, + terminationIDList = asn1_NOVALUE}) -> + d("is_AuditRequest -> entry with" + "~n TID: ~p" + "~n AD: ~p",[TID, AD]), + is_TerminationID(TID) andalso + is_AuditDescriptor(AD); +is_AuditRequest(#'AuditRequest'{terminationID = TID, + auditDescriptor = AD, + terminationIDList = [TID|_] = TIDs}) -> + d("is_AuditRequest -> entry with" + "~n TID: ~p" + "~n AD: ~p" + "~n TIDs: ~p",[TID, AD, TIDs]), + is_TerminationID(TID) andalso + is_AuditDescriptor(AD) andalso + is_TerminationIDList(TIDs); +is_AuditRequest(_) -> + false. + +chk_AuditRequest(R, R) -> + chk_type(fun is_AuditRequest/1, 'AuditRequest', R); +chk_AuditRequest(#'AuditRequest'{terminationID = TID1, + auditDescriptor = AD1, + terminationIDList = [TID1|_] = TIDs1}, + #'AuditRequest'{terminationID = TID2, + auditDescriptor = AD2, + terminationIDList = [TID2|_] = TIDs2}) -> + validate(fun() -> chk_TerminationID(TID1, TID2) end, + 'AuditRequest'), + validate(fun() -> chk_AuditDescriptor(AD1, AD2) end, + 'AuditRequest'), + validate(fun() -> chk_opt_TerminationIDList(TIDs1, TIDs2) end, + 'AuditRequest'), + ok; +chk_AuditRequest(AR1, AR2) -> + wrong_type('AuditRequest', AR1, AR2). + + +%% -- AuditReply -- + +is_AuditReply({Tag, Val}) -> + is_AuditReply_tag(Tag) andalso is_AuditReply_val(Tag, Val); +is_AuditReply(_) -> + false. + +is_AuditReply_tag(Tag) -> + Tags = [contextAuditResult, error, auditResult, auditResultTermList], + lists:member(Tag, Tags). + +is_AuditReply_val(contextAuditResult, Val) -> + is_TerminationIDList(Val); +is_AuditReply_val(error, Val) -> + is_ErrorDescriptor(Val); +is_AuditReply_val(auditResult, Val) -> + is_AuditResult(Val); +is_AuditReply_val(auditResultTermList, Val) -> + is_TermListAuditResult(Val). + +chk_AuditReply(R, R) -> + chk_type(fun is_AuditReply/1, 'AuditReply', R); +chk_AuditReply({Tag, Val1} = R1, {Tag, Val2} = R2) -> + case (is_AuditReply_tag(Tag) andalso + is_AuditReply_val(Tag, Val1)andalso + is_AuditReply_val(Tag, Val2)) of + true -> + chk_AuditReply_val(Tag, Val1, Val2); + false -> + wrong_type('AuditReply', R1, R2) + end; +chk_AuditReply({Tag1, Val1} = R1, {Tag2, Val2} = R2) -> + case ((is_AuditReply_tag(Tag1) andalso + is_AuditReply_val(Tag1, Val1)) andalso + (is_AuditReply_tag(Tag2) andalso + is_AuditReply_val(Tag2, Val2))) of + true -> + not_equal('AuditReply', R1, R2); + false -> + wrong_type('AuditReply', R1, R2) + end; +chk_AuditReply(AR1, AR2) -> + wrong_type('AuditReply', AR1, AR2). + +chk_AuditReply_val(contextAuditResult, Val1, Val2) -> + chk_TerminationIDList(Val1, Val2); +chk_AuditReply_val(error, Val1, Val2) -> + chk_ErrorDescriptor(Val1, Val2); +chk_AuditReply_val(auditResult, Val1, Val2) -> + chk_AuditResult(Val1, Val2); +chk_AuditReply_val(auditResultTermList, Val1, Val2) -> + chk_TermListAuditResult(Val1, Val2). + + +%% -- AuditResult -- + +is_AuditResult(#'AuditResult'{terminationID = TID, + terminationAuditResult = TAR}) -> + is_TerminationID(TID) andalso is_TerminationAudit(TAR); +is_AuditResult(_) -> + false. + +chk_AuditResult(R, R) -> + d("chk_AuditResult -> entry (1)"), + chk_type(fun is_AuditResult/1, 'AuditResult', R); +chk_AuditResult(#'AuditResult'{terminationID = TID1, + terminationAuditResult = TAR1}, + #'AuditResult'{terminationID = TID2, + terminationAuditResult = TAR2}) -> + d("chk_AuditResult -> entry (2)"), + validate(fun() -> chk_TerminationID(TID1, TID2) end, 'AuditResult'), + validate(fun() -> chk_TerminationAudit(TAR1, TAR2) end, 'AuditResult'), + ok; +chk_AuditResult(AR1, AR2) -> + d("chk_AuditResult -> entry (3)"), + wrong_type('AuditResult', AR1, AR2). + + +%% -- TermListAuditResult -- + +is_TermListAuditResult(#'TermListAuditResult'{terminationIDList = TIDs, + terminationAuditResult = TAR}) -> + is_TerminationIDList(TIDs) andalso is_TerminationAudit(TAR); +is_TermListAuditResult(_) -> + false. + +chk_TermListAuditResult(TLAR, TLAR) -> + d("chk_TermListAuditResult(1) -> entry with" + "~n TLAR: ~p", [TLAR]), + chk_type(fun is_TermListAuditResult/1, 'TermListAuditResult', TLAR); +chk_TermListAuditResult( + #'TermListAuditResult'{terminationIDList = TIDs1, + terminationAuditResult = TAR1}, + #'TermListAuditResult'{terminationIDList = TIDs2, + terminationAuditResult = TAR2}) -> + d("chk_TermListAuditResult(2) -> entry with" + "~n TIDs1: ~p" + "~n TAR1: ~p" + "~n TIDs2: ~p" + "~n TAR2: ~p", [TIDs1, TAR1, TIDs2, TAR2]), + validate(fun() -> chk_TerminationIDList(TIDs1, TIDs2) end, + 'TermListAuditResult_terminationIDList'), + validate(fun() -> chk_TerminationAudit(TAR1, TAR2) end, + 'TermListAuditResult_terminationAuditResult'), + ok; +chk_TermListAuditResult(TLAR1, TLAR2) -> + d("chk_TermListAuditResult(3) -> entry with" + "~n TLAR1: ~p" + "~n TLAR2: ~p", [TLAR1, TLAR2]), + wrong_type('TermListAuditResult', TLAR1, TLAR2). + + +%% -- TerminationAudit -- + +is_opt_TerminationAudit(TA) -> + is_OPTIONAL(fun is_TerminationAudit/1, TA). + +is_TerminationAudit([]) -> + true; +is_TerminationAudit([H|T]) -> + is_AuditReturnParameter(H) andalso is_TerminationAudit(T); +is_TerminationAudit(_) -> + false. + +chk_opt_TerminationAudit(TA1, TA2) -> + d("chk_opt_TerminationAudit -> entry with" + "~n TA1: ~p" + "~n TA2: ~p", [TA1, TA2]), + chk_OPTIONAL('TerminationAudit', + strip_TerminationAudit(TA1), + strip_TerminationAudit(TA2), + fun is_TerminationAudit/1, fun chk_TerminationAudit/2). + +strip_TerminationAudit(L) when is_list(L) -> + d("strip_TerminationAudit(1) -> entry with" + "~n L: ~p", [L]), + %% Drop all empty emptyDescriptor's + F = fun({emptyDescriptors, AD}) -> + case AD of + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = asn1_NOVALUE} -> + true; + _ -> + false + end; + (_) -> + false + end, + lists:dropwhile(F, L); +strip_TerminationAudit(asn1_NOVALUE) -> + d("strip_TerminationAudit(2) -> entry"), + []; +strip_TerminationAudit(X) -> + d("strip_TerminationAudit(3) -> entry with" + "~n X: ~p", [X]), + X. + +chk_TerminationAudit(TA1, TA2) -> + d("chk_TerminationAudit -> entry with" + "~n TA1: ~p" + "~n TA2: ~p", [TA1, TA2]), + do_chk_TerminationAudit(strip_TerminationAudit(TA1), + strip_TerminationAudit(TA2)). + +do_chk_TerminationAudit([], []) -> + d("do_chk_TerminationAudit(1) -> entry"), + ok; +do_chk_TerminationAudit([], asn1_NOVALUE) -> + d("do_chk_TerminationAudit(2) -> entry"), + ok; +do_chk_TerminationAudit(asn1_NOVALUE, []) -> + d("do_chk_TerminationAudit(3) -> entry"), + ok; +do_chk_TerminationAudit([] = TA1, TA2) -> + d("do_chk_TerminationAudit(4) -> entry with" + "~n TA2: ~p", [TA2]), + not_equal('TerminationAudit', TA1, TA2); +do_chk_TerminationAudit(TA1, [] = TA2) -> + d("do_chk_TerminationAudit(5) -> entry with" + "~n TA1: ~p", [TA1]), + not_equal('TerminationAudit', TA1, TA2); +do_chk_TerminationAudit([H|T1], [H|T2]) -> + d("do_chk_TerminationAudit(6) -> entry with" + "~n H: ~p", [H]), + case is_AuditReturnParameter(H) of + true -> + do_chk_TerminationAudit(T1, T2); + false -> + wrong_type('TerminationAudit', H) + end; +do_chk_TerminationAudit([H1|T1], [H2|T2]) -> + d("do_chk_TerminationAudit(7) -> entry with" + "~n H1: ~p" + "~n H2: ~p", [H1, H2]), + chk_AuditReturnParameter(H1, H2), + do_chk_TerminationAudit(T1, T2); +do_chk_TerminationAudit(TA1, TA2) -> + d("do_chk_TerminationAudit(8) -> entry with" + "~n TA1: ~p" + "~n TA2: ~p", [TA1, TA2]), + not_equal('TerminationAudit', TA1, TA2). + + +%% -- AuditReturnParameter -- + +is_AuditReturnParameter({Tag, Val}) -> + is_AuditReturnParameter_tag(Tag) andalso + is_AuditReturnParameter_val(Tag, Val); +is_AuditReturnParameter(_) -> + false. + +is_AuditReturnParameter_tag(Tag) -> + Tags = [errorDescriptor, + mediaDescriptor, + modemDescriptor, + muxDescriptor, + eventsDescriptor, + eventBufferDescriptor, + signalsDescriptor, + digitMapDescriptor, + observedEventsDescriptor, + statisticsDescriptor, + packagesDescriptor, + emptyDescriptors], + lists:member(Tag, Tags). + +is_AuditReturnParameter_val(errorDescriptor, V) -> + is_ErrorDescriptor(V); +is_AuditReturnParameter_val(mediaDescriptor, V) -> + is_MediaDescriptor(V); +is_AuditReturnParameter_val(modemDescriptor, V) -> + is_ModemDescriptor(V); +is_AuditReturnParameter_val(muxDescriptor, V) -> + is_MuxDescriptor(V); +is_AuditReturnParameter_val(eventsDescriptor, V) -> + is_EventsDescriptor(V); +is_AuditReturnParameter_val(eventBufferDescriptor, V) -> + is_EventBufferDescriptor(V); +is_AuditReturnParameter_val(signalsDescriptor, V) -> + is_SignalsDescriptor(V); +is_AuditReturnParameter_val(digitMapDescriptor, V) -> + is_DigitMapDescriptor(V); +is_AuditReturnParameter_val(observedEventsDescriptor, V) -> + is_ObservedEventsDescriptor(V); +is_AuditReturnParameter_val(statisticsDescriptor, V) -> + is_StatisticsDescriptor(V); +is_AuditReturnParameter_val(packagesDescriptor, V) -> + is_PackagesDescriptor(V); +is_AuditReturnParameter_val(emptyDescriptors, V) -> + is_AuditDescriptor(V). + +chk_AuditReturnParameter(ARP, ARP) -> + chk_type(fun is_AuditReturnParameter/1, 'AuditReturnParameter', ARP); +chk_AuditReturnParameter({Tag, Val1} = ARP1, {Tag, Val2} = ARP2) -> + case (is_AuditReturnParameter_tag(Tag) andalso + is_AuditReturnParameter_val(Tag, Val1) andalso + is_AuditReturnParameter_val(Tag, Val2)) of + true -> + chk_AuditReturnParameter_val(Tag, Val1, Val2); + false -> + wrong_type('AuditReturnParameter', ARP1, ARP2) + end; +chk_AuditReturnParameter({Tag1, Val1} = ARP1, {Tag2, Val2} = ARP2) -> + case ((is_AuditReturnParameter_tag(Tag1) andalso + is_AuditReturnParameter_val(Tag1, Val1)) andalso + (is_AuditReturnParameter_tag(Tag2) andalso + is_AuditReturnParameter_val(Tag2, Val2))) of + true -> + not_equal('AuditReturnParameter', ARP1, ARP2); + false -> + wrong_type('AuditReturnParameter', ARP1, ARP2) + end; +chk_AuditReturnParameter(ARP1, ARP2) -> + wrong_type('AuditReturnParameter', ARP1, ARP2). + +chk_AuditReturnParameter_val(errorDescriptor, V1, V2) -> + validate(fun() -> chk_ErrorDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(mediaDescriptor, V1, V2) -> + validate(fun() -> chk_MediaDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(modemDescriptor, V1, V2) -> + validate(fun() -> chk_ModemDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(muxDescriptor, V1, V2) -> + validate(fun() -> chk_MuxDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(eventsDescriptor, V1, V2) -> + validate(fun() -> chk_EventsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(eventBufferDescriptor, V1, V2) -> + validate(fun() -> chk_EventBufferDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(signalsDescriptor, V1, V2) -> + validate(fun() -> chk_SignalsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(digitMapDescriptor, V1, V2) -> + validate(fun() -> chk_DigitMapDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(observedEventsDescriptor, V1, V2) -> + validate(fun() -> chk_ObservedEventsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(statisticsDescriptor, V1, V2) -> + validate(fun() -> chk_StatisticsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(packagesDescriptor, V1, V2) -> + validate(fun() -> chk_PackagesDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(emptyDescriptors, V1, V2) -> + validate(fun() -> chk_AuditDescriptor(V1, V2) end, + 'AuditReturnParameter'). + + +%% -- AuditDescriptor -- + +is_opt_AuditDescriptor(asn1_NOVALUE) -> + true; +is_opt_AuditDescriptor(V) -> + is_AuditDescriptor(V). + +is_AuditDescriptor(#'AuditDescriptor'{auditToken = AT, + auditPropertyToken = APT}) -> + d("is_AuditDescriptor -> entry with" + "~n AT: ~p" + "~n APT: ~p", [AT, APT]), + is_AuditDescriptor_auditToken(AT) andalso + is_AuditDescriptor_auditPropertyToken(APT); +is_AuditDescriptor(_) -> + false. + +is_AuditDescriptor_auditToken(asn1_NOVALUE) -> + true; +is_AuditDescriptor_auditToken([]) -> + true; +is_AuditDescriptor_auditToken([H|T]) -> + is_AuditDescriptor_auditToken_val(H) andalso + is_AuditDescriptor_auditToken(T); +is_AuditDescriptor_auditToken(_) -> + false. + +is_AuditDescriptor_auditToken_val(V) -> + Toks = [muxToken, modemToken, mediaToken, eventsToken, signalsToken, + digitMapToken, statsToken, observedEventsToken, + packagesToken, eventBufferToken], + lists:member(V, Toks). + +is_AuditDescriptor_auditPropertyToken(asn1_NOVALUE) -> + true; +is_AuditDescriptor_auditPropertyToken([]) -> + true; +is_AuditDescriptor_auditPropertyToken([H|T]) -> + d("is_AuditDescriptor_auditPropertyToken -> entry with" + "~n H: ~p", [H]), + is_IndAuditParameter(H) andalso is_AuditDescriptor_auditPropertyToken(T); +is_AuditDescriptor_auditPropertyToken(_) -> + false. + +chk_opt_AuditDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_AuditDescriptor(AD1, AD2) -> + chk_AuditDescriptor(AD1, AD2). + +chk_AuditDescriptor(AD, AD) -> + chk_type(fun is_AuditDescriptor/1, 'AuditDescriptor', AD); +chk_AuditDescriptor(#'AuditDescriptor'{auditToken = AT1, + auditPropertyToken = APT1}, + #'AuditDescriptor'{auditToken = AT2, + auditPropertyToken = APT2}) -> + chk_AuditDescriptor_auditToken(maybe_sort(AT1), maybe_sort(AT2)), + chk_AuditDescriptor_auditPropertyToken(APT1, APT2), + ok; +chk_AuditDescriptor(AD1, AD2) -> + wrong_type('AuditDescriptor', AD1, AD2). + +chk_AuditDescriptor_auditToken(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_AuditDescriptor_auditToken([], []) -> + ok; +chk_AuditDescriptor_auditToken([] = AT1, AT2) -> + not_equal('AuditDescriptor_auditToken', AT1, AT2); +chk_AuditDescriptor_auditToken(AT1, [] = AT2) -> + not_equal('AuditDescriptor_auditToken', AT1, AT2); +chk_AuditDescriptor_auditToken([H|T1], [H|T2]) -> + case is_AuditDescriptor_auditToken_val(H) of + true -> + chk_AuditDescriptor_auditToken(T1, T2); + false -> + wrong_type('AuditDescriptor_auditToken_val', H) + end; +chk_AuditDescriptor_auditToken([H1|_T1], [H2|_T2]) -> + case (is_AuditDescriptor_auditToken_val(H1) andalso + is_AuditDescriptor_auditToken_val(H2)) of + true -> + not_equal('AuditDescriptor_auditToken_val', H1, H2); + false -> + wrong_type('AuditDescriptor_auditToken_val', H1, H2) + end; +chk_AuditDescriptor_auditToken(AT1, AT2) -> + wrong_type('AuditDescriptor_auditToken', AT1, AT2). + +chk_AuditDescriptor_auditPropertyToken(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_AuditDescriptor_auditPropertyToken([], []) -> + ok; +chk_AuditDescriptor_auditPropertyToken([] = AT1, AT2) -> + not_equal('AuditDescriptor_auditPropertyToken', AT1, AT2); +chk_AuditDescriptor_auditPropertyToken(AT1, [] = AT2) -> + not_equal('AuditDescriptor_auditPropertyToken', AT1, AT2); +chk_AuditDescriptor_auditPropertyToken([H|T1], [H|T2]) -> + case is_IndAuditParameter(H) of + true -> + chk_AuditDescriptor_auditPropertyToken(T1, T2); + false -> + wrong_type('AuditDescriptor_auditPropertyToken_val', H) + end; +chk_AuditDescriptor_auditPropertyToken([H1|_], [H2|_]) -> + chk_IndAuditParameter(H1, H2), + not_equal('AuditDescriptor_auditPropertyToken_val', H1, H2); +chk_AuditDescriptor_auditPropertyToken(AT1, AT2) -> + wrong_type('AuditDescriptor_auditPropertyToken', AT1, AT2). + + +%% -- IndAuditParameter -- + +is_IndAuditParameter({Tag, Val}) -> + is_IndAuditParameter_tag(Tag) andalso is_IndAuditParameter_val(Tag, Val); +is_IndAuditParameter(_) -> + false. + +is_IndAuditParameter_tag(Tag) -> + Tags = [indAudMediaDescriptor, + indAudEventsDescriptor, + indAudEventBufferDescriptor, + indAudSignalsDescriptor, + indAudDigitMapDescriptor, + indAudStatisticsDescriptor, + indAudPackagesDescriptor], + lists:member(Tag, Tags). + +is_IndAuditParameter_val(indAudMediaDescriptor, Val) -> + is_IndAudMediaDescriptor(Val); +is_IndAuditParameter_val(indAudEventsDescriptor, Val) -> + is_IndAudEventsDescriptor(Val); +is_IndAuditParameter_val(indAudEventBufferDescriptor, Val) -> + is_IndAudEventBufferDescriptor(Val); +is_IndAuditParameter_val(indAudSignalsDescriptor, Val) -> + is_IndAudSignalsDescriptor(Val); +is_IndAuditParameter_val(indAudDigitMapDescriptor, Val) -> + is_IndAudDigitMapDescriptor(Val); +is_IndAuditParameter_val(indAudStatisticsDescriptor, Val) -> + is_IndAudStatisticsDescriptor(Val); +is_IndAuditParameter_val(indAudPackagesDescriptor, Val) -> + is_IndAudPackagesDescriptor(Val). + +chk_IndAuditParameter(IAP, IAP) -> + chk_type(fun is_IndAuditParameter/1, 'IndAuditParameter', IAP); +chk_IndAuditParameter({Tag, Val1} = IAP1, {Tag, Val2} = IAP2) -> + case (is_IndAuditParameter_tag(Tag) andalso + is_IndAuditParameter_val(Tag, Val1) andalso + is_IndAuditParameter_val(Tag, Val2)) of + true -> + chk_IndAuditParameter_val(Tag, Val1, Val2); + false -> + wrong_type('IndAuditParameter', IAP1, IAP2) + end; +chk_IndAuditParameter({Tag1, Val1} = IAP1, {Tag2, Val2} = IAP2) -> + case ((is_IndAuditParameter_tag(Tag1) andalso + is_IndAuditParameter_val(Tag1, Val1)) andalso + (is_IndAuditParameter_tag(Tag2) andalso + is_IndAuditParameter_val(Tag2, Val2))) of + true -> + not_equal('IndAuditParameter', IAP1, IAP2); + false -> + wrong_type('IndAuditParameter', IAP1, IAP2) + end; +chk_IndAuditParameter(IAP1, IAP2) -> + wrong_type('IndAuditParameter', IAP1, IAP2). + +chk_IndAuditParameter_val(indAudMediaDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudMediaDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudEventsDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudEventsDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudEventBufferDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudEventBufferDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudSignalsDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudSignalsDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudDigitMapDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudDigitMapDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudStatisticsDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudStatisticsDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudPackagesDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudPackagesDescriptor(Val1, Val2) end, + 'IndAuditParameter'). + + +%% -- IndAudMediaDescriptor -- + +is_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = S}) -> + d("is_IndAudMediaDescriptor -> entry with" + "~n TSD: ~p" + "~n S: ~p", [TSD, S]), + is_opt_IndAudTerminationStateDescriptor(TSD) andalso + is_IndAudMediaDescriptor_streams(S); +is_IndAudMediaDescriptor(_) -> + false. + +is_IndAudMediaDescriptor_streams(asn1_NOVALUE) -> + true; +is_IndAudMediaDescriptor_streams({Tag, Val}) -> + d("is_IndAudMediaDescriptor_streams -> entry with" + "~n Tag: ~p" + "~n Val: ~p", [Tag, Val]), + is_IndAudMediaDescriptor_streams_tag(Tag) andalso + is_IndAudMediaDescriptor_streams_val(Tag, Val); +is_IndAudMediaDescriptor_streams(_) -> + false. + +is_IndAudMediaDescriptor_streams_tag(Tag) -> + Tags = [oneStream, multiStream], + lists:member(Tag, Tags). + +is_IndAudMediaDescriptor_streams_val(oneStream, Val) -> + d("is_IndAudMediaDescriptor_streams_val(oneStream) -> entry with" + "~n Val: ~p", [Val]), + is_IndAudStreamParms(Val); +is_IndAudMediaDescriptor_streams_val(multiStream, Val) -> + d("is_IndAudMediaDescriptor_streams_val(multiStream) -> entry with" + "~n Val: ~p", [Val]), + is_IndAudMediaDescriptor_multiStream(Val). + +is_IndAudMediaDescriptor_multiStream([]) -> + true; +is_IndAudMediaDescriptor_multiStream([H|T]) -> + d("is_IndAudMediaDescriptor_multiStream -> entry with" + "~n H: ~p", [H]), + is_IndAudStreamDescriptor(H) andalso + is_IndAudMediaDescriptor_multiStream(T); +is_IndAudMediaDescriptor_multiStream(_) -> + false. + +chk_IndAudMediaDescriptor(IAMD, IAMD) -> + chk_type(fun is_IndAudMediaDescriptor/1, 'IndAudMediaDescriptor', IAMD); +chk_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD1, + streams = S1}, + #'IndAudMediaDescriptor'{termStateDescr = TSD2, + streams = S2}) -> + validate(fun() -> chk_opt_IndAudTerminationStateDescriptor(TSD1, TSD2) end, + 'IndAudMediaDescriptor'), + validate(fun() -> chk_IndAudMediaDescriptor_streams(S1, S2) end, + 'IndAudMediaDescriptor'), + ok; +chk_IndAudMediaDescriptor(IAMD1, IAMD2) -> + wrong_type('IndAudMediaDescriptor', IAMD1, IAMD2). + +chk_IndAudMediaDescriptor_streams(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_IndAudMediaDescriptor_streams({Tag, Val1} = S1, + {Tag, Val2} = S2) -> + case (is_IndAudMediaDescriptor_streams_tag(Tag) andalso + is_IndAudMediaDescriptor_streams_val(Tag, Val1) andalso + is_IndAudMediaDescriptor_streams_val(Tag, Val2)) of + true -> + chk_IndAudMediaDescriptor_streams_val(Tag, Val1, Val2); + false -> + wrong_type('IndAudMediaDescriptor_streams', S1, S2) + end; +chk_IndAudMediaDescriptor_streams({Tag1, Val1} = S1, + {Tag2, Val2} = S2) -> + case ((is_IndAudMediaDescriptor_streams_tag(Tag1) andalso + is_IndAudMediaDescriptor_streams_val(Tag1, Val1)) andalso + (is_IndAudMediaDescriptor_streams_tag(Tag2) andalso + is_IndAudMediaDescriptor_streams_val(Tag2, Val2))) of + true -> + not_equal('IndAudMediaDescriptor_streams', S1, S2); + false -> + wrong_type('IndAudMediaDescriptor_streams', S1, S2) + end; +chk_IndAudMediaDescriptor_streams(S1, S2) -> + wrong_type('IndAudMediaDescriptor_streams', S1, S2). + +chk_IndAudMediaDescriptor_streams_val(oneStream, Val1, Val2) -> + validate(fun() -> chk_IndAudStreamParms(Val1, Val2) end, + 'IndAudMediaDescriptor_streams'); +chk_IndAudMediaDescriptor_streams_val(multiStream, Val1, Val2) -> + validate(fun() -> chk_IndAudMediaDescriptor_multiStream(Val1, Val2) end, + 'IndAudMediaDescriptor_streams'). + +chk_IndAudMediaDescriptor_multiStream([], []) -> + ok; +chk_IndAudMediaDescriptor_multiStream([] = MS1, MS2) -> + not_equal('IndAudMediaDescriptor_multiStream', MS1, MS2); +chk_IndAudMediaDescriptor_multiStream(MS1, [] = MS2) -> + not_equal('IndAudMediaDescriptor_multiStream', MS1, MS2); +chk_IndAudMediaDescriptor_multiStream([H|T1], [H|T2]) -> + case is_IndAudStreamDescriptor(H) of + true -> + chk_IndAudMediaDescriptor_multiStream(T1, T2); + false -> + wrong_type('IndAudMediaDescriptor_multiStream_val', H) + end; +chk_IndAudMediaDescriptor_multiStream([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudStreamDescriptor(H1, H2) end, + 'IndAudMediaDescriptor_multiStream_val'), + chk_IndAudMediaDescriptor_multiStream(T1, T2); +chk_IndAudMediaDescriptor_multiStream(MS1, MS2) -> + wrong_type('IndAudMediaDescriptor_multiStream', MS1, MS2). + + +%% -- IndAudStreamDescriptor -- + +is_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID, + streamParms = Parms}) -> + d("is_IndAudStreamDescriptor -> entry with" + "~n SID: ~p" + "~n Parms: ~p", [SID, Parms]), + is_StreamID(SID) andalso is_IndAudStreamParms(Parms); +is_IndAudStreamDescriptor(_) -> + false. + +chk_IndAudStreamDescriptor(D, D) -> + chk_type(fun is_IndAudStreamDescriptor/1, 'IndAudStreamDescriptor', D); +chk_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID1, + streamParms = Parms1}, + #'IndAudStreamDescriptor'{streamID = SID2, + streamParms = Parms2}) -> + validate(fun() -> chk_StreamID(SID1, SID2) end, 'IndAudStreamDescriptor'), + validate(fun() -> chk_IndAudStreamParms(Parms1, Parms2) end, + 'IndAudStreamDescriptor'), + ok; +chk_IndAudStreamDescriptor(D1, D2) -> + wrong_type('IndAudStreamDescriptor', D1, D2). + + +%% -- IndAudStreamParms -- + +is_IndAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD}) -> + d("is_IndAudStreamParms -> entry with" + "~n LCD: ~p" + "~n LD: ~p" + "~n RD: ~p", [LCD, LD, RD]), + is_opt_IndAudLocalControlDescriptor(LCD) andalso + is_opt_IndAudLocalRemoteDescriptor(LD) andalso + is_opt_IndAudLocalRemoteDescriptor(RD); +is_IndAudStreamParms(_) -> + false. + +chk_IndAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD1, + localDescriptor = LD1, + remoteDescriptor = RD1}, + #'IndAudStreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2}) -> + validate(fun() -> chk_opt_IndAudLocalControlDescriptor(LCD1, LCD2) end, + 'IndAudStreamParms'), + validate(fun() -> chk_opt_IndAudLocalRemoteDescriptor(LD1, LD2) end, + 'IndAudStreamParms'), + validate(fun() -> chk_opt_IndAudLocalRemoteDescriptor(RD1, RD2) end, + 'IndAudStreamParms'), + ok; +chk_IndAudStreamParms(D1, D2) -> + wrong_type('IndAudStreamParms', D1, D2). + + +%% -- IndAudLocalControlDescriptor -- + +is_opt_IndAudLocalControlDescriptor(asn1_NOVALUE) -> + true; +is_opt_IndAudLocalControlDescriptor(D) -> + is_IndAudLocalControlDescriptor(D). + +is_IndAudLocalControlDescriptor( + #'IndAudLocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PPs, + streamModeSel = SMS}) -> + d("is_IndAudLocalControlDescriptor -> entry with" + "~n SM: ~p" + "~n RV: ~p" + "~n RG: ~p" + "~n PPs: ~p" + "~n SMS: ~p", [SM, RV, RG, PPs, SMS]), + is_opt_NULL(SM) andalso + is_opt_NULL(RV) andalso + is_opt_NULL(RG) andalso + is_IndAudLocalControlDescriptor_propertyParms(PPs) andalso + is_opt_StreamMode(SMS); +is_IndAudLocalControlDescriptor(_) -> + false. + +is_IndAudLocalControlDescriptor_propertyParms(asn1_NOVALUE) -> + true; +is_IndAudLocalControlDescriptor_propertyParms([]) -> + true; +is_IndAudLocalControlDescriptor_propertyParms([H|T]) -> + is_IndAudPropertyParm(H) andalso + is_IndAudLocalControlDescriptor_propertyParms(T); +is_IndAudLocalControlDescriptor_propertyParms(_) -> + false. + +chk_opt_IndAudLocalControlDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudLocalControlDescriptor( + #'IndAudLocalControlDescriptor'{streamMode = SM1, + reserveValue = RV1, + reserveGroup = RG1, + propertyParms = PPs1, + streamModeSel = SMS1}, + #'IndAudLocalControlDescriptor'{streamMode = SM2, + reserveValue = RV2, + reserveGroup = RG2, + propertyParms = PPs2, + streamModeSel = SMS2}) -> + chk_IndAudLocalControlDescriptor_streamMode(SM1, SM2), + chk_IndAudLocalControlDescriptor_reserveValue(RV1, RV2), + chk_IndAudLocalControlDescriptor_reserveGroup(RG1, RG2), + chk_IndAudLocalControlDescriptor_propertyParms(PPs1, PPs2), + chk_IndAudLocalControlDescriptor_streamModeSel(SMS1, SMS2), + ok; +chk_opt_IndAudLocalControlDescriptor(D1, D2) -> + wrong_type('IndAudLocalControlDescriptor', D1, D2). + +chk_IndAudLocalControlDescriptor_streamMode(SM1, SM2) -> + validate(fun() -> chk_opt_NULL(SM1, SM2) end, + 'IndAudLocalControlDescriptor_streamMode'). + +chk_IndAudLocalControlDescriptor_reserveValue(RV1, RV2) -> + validate(fun() -> chk_opt_NULL(RV1, RV2) end, + 'IndAudLocalControlDescriptor_reserveValue'). + +chk_IndAudLocalControlDescriptor_reserveGroup(RG1, RG2) -> + validate(fun() -> chk_opt_NULL(RG1, RG2) end, + 'IndAudLocalControlDescriptor_reserveGroup'). + +chk_IndAudLocalControlDescriptor_propertyParms(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_IndAudLocalControlDescriptor_propertyParms([], []) -> + ok; +chk_IndAudLocalControlDescriptor_propertyParms([] = PPs1, PPs2) -> + not_equal('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2); +chk_IndAudLocalControlDescriptor_propertyParms(PPs1, [] = PPs2) -> + not_equal('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2); +chk_IndAudLocalControlDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_IndAudLocalControlDescriptor_propertyParms(T1, T2); + false -> + wrong_type('IndAudLocalControlDescriptor_propertyParms_val', H) + end; +chk_IndAudLocalControlDescriptor_propertyParms([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, + 'IndAudLocalControlDescriptor_propertyParms_val'), + chk_IndAudLocalControlDescriptor_propertyParms(T1, T2); +chk_IndAudLocalControlDescriptor_propertyParms(PPs1, PPs2) -> + wrong_type('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2). + +chk_IndAudLocalControlDescriptor_streamModeSel(SMS1, SMS2) -> + validate(fun() -> chk_opt_StreamMode(SMS1, SMS2) end, + 'IndAudLocalControlDescriptor_streamModeSel'). + + +%% -- IndAudPropertyParm -- + +is_IndAudPropertyParm(#'IndAudPropertyParm'{name = Name, + propertyParms = PP}) -> + d("is_IndAudPropertyParm -> entry"), + is_PkgdName(Name) andalso is_opt_PropertyParm(PP); +is_IndAudPropertyParm(_) -> + false. + +chk_IndAudPropertyParm(#'IndAudPropertyParm'{name = Name1, + propertyParms = PP1}, + #'IndAudPropertyParm'{name = Name2, + propertyParms = PP2}) -> + validate(fun() -> chk_PkgdName(Name1, Name2) end, 'IndAudPropertyParm'), + validate(fun() -> chk_opt_PropertyParm(PP1, PP2) end, + 'IndAudPropertyParm'), + ok; +chk_IndAudPropertyParm(P1, P2) -> + wrong_type('IndAudPropertyParm', P1, P2). + + +%% -- IndAudLocalRemoteDescriptor -- + +is_opt_IndAudLocalRemoteDescriptor(asn1_NOVALUE) -> + true; +is_opt_IndAudLocalRemoteDescriptor(D) -> + is_IndAudLocalRemoteDescriptor(D). + +is_IndAudLocalRemoteDescriptor( + #'IndAudLocalRemoteDescriptor'{propGroupID = ID, + propGrps = Grps}) -> + is_IndAudLocalRemoteDescriptor_propGroupID(ID) andalso + is_IndAudPropertyGroup(Grps); +is_IndAudLocalRemoteDescriptor(_) -> + false. + +is_IndAudLocalRemoteDescriptor_propGroupID(asn1_NOVALUE) -> + true; +is_IndAudLocalRemoteDescriptor_propGroupID(V) -> + is_INTEGER(V, {range, 0, 65535}). + +chk_opt_IndAudLocalRemoteDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudLocalRemoteDescriptor(D1, D2) -> + chk_IndAudLocalRemoteDescriptor(D1, D2). + +chk_IndAudLocalRemoteDescriptor(D, D) -> + chk_type(fun is_IndAudLocalRemoteDescriptor/1, + 'IndAudLocalRemoteDescriptor', D); +chk_IndAudLocalRemoteDescriptor( + #'IndAudLocalRemoteDescriptor'{propGroupID = ID1, + propGrps = Grps1}, + #'IndAudLocalRemoteDescriptor'{propGroupID = ID2, + propGrps = Grps2}) -> + chk_IndAudLocalRemoteDescriptor_propGroupID(ID1, ID2), + chk_IndAudPropertyGroup(Grps1, Grps2), + ok; +chk_IndAudLocalRemoteDescriptor(D1, D2) -> + wrong_type('IndAudLocalRemoteDescriptor', D1, D2). + +chk_IndAudLocalRemoteDescriptor_propGroupID(ID, ID) -> + chk_type(fun is_IndAudLocalRemoteDescriptor_propGroupID/1, + 'IndAudLocalRemoteDescriptor_propGroupID', ID); +chk_IndAudLocalRemoteDescriptor_propGroupID(ID1, ID2) -> + case (is_IndAudLocalRemoteDescriptor_propGroupID(ID1) andalso + is_IndAudLocalRemoteDescriptor_propGroupID(ID2)) of + true -> + not_equal('IndAudLocalRemoteDescriptor_propGroupID', ID1, ID2); + false -> + wrong_type('IndAudLocalRemoteDescriptor_propGroupID', ID1, ID2) + end. + + +%% -- IndAudPropertyGroup -- + +is_IndAudPropertyGroup([]) -> + true; +is_IndAudPropertyGroup([H|T]) -> + is_IndAudPropertyParm(H) andalso is_IndAudPropertyGroup(T); +is_IndAudPropertyGroup(_) -> + false. + +chk_IndAudPropertyGroup([], []) -> + ok; +chk_IndAudPropertyGroup([] = PG1, PG2) -> + not_equal('IndAudPropertyGroup', PG1, PG2); +chk_IndAudPropertyGroup(PG1, [] = PG2) -> + not_equal('IndAudPropertyGroup', PG1, PG2); +chk_IndAudPropertyGroup([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_IndAudPropertyGroup(T1, T2); + false -> + wrong_type('IndAudPropertyGroup_val', H) + end; +chk_IndAudPropertyGroup([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, + 'IndAudPropertyGroup_val'), + chk_IndAudPropertyGroup(T1, T2); +chk_IndAudPropertyGroup(P1, P2) -> + wrong_type('IndAudPropertyGroup', P1, P2). + + +%% -- IndAudTerminationStateDescriptor -- + +is_opt_IndAudTerminationStateDescriptor(asn1_NOVALUE) -> + true; +is_opt_IndAudTerminationStateDescriptor(D) -> + is_IndAudTerminationStateDescriptor(D). + +is_IndAudTerminationStateDescriptor( + #'IndAudTerminationStateDescriptor'{propertyParms = Parms, + eventBufferControl = EBC, + serviceState = SS, + serviceStateSel = SSS}) -> + is_IndAudTerminationStateDescriptor_propertyParms(Parms) andalso + is_opt_NULL(EBC) andalso + is_opt_NULL(SS) andalso + is_opt_ServiceState(SSS); +is_IndAudTerminationStateDescriptor(_) -> + false. + +is_IndAudTerminationStateDescriptor_propertyParms([]) -> + true; +is_IndAudTerminationStateDescriptor_propertyParms([H|T]) -> + is_IndAudPropertyParm(H) andalso + is_IndAudTerminationStateDescriptor_propertyParms(T); +is_IndAudTerminationStateDescriptor_propertyParms(_) -> + false. + +chk_opt_IndAudTerminationStateDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudTerminationStateDescriptor(D1, D2) -> + chk_IndAudTerminationStateDescriptor(D1, D2). + +chk_IndAudTerminationStateDescriptor( + #'IndAudTerminationStateDescriptor'{propertyParms = Parms1, + eventBufferControl = EBC1, + serviceState = SS1, + serviceStateSel = SSS1}, + #'IndAudTerminationStateDescriptor'{propertyParms = Parms2, + eventBufferControl = EBC2, + serviceState = SS2, + serviceStateSel = SSS2}) -> + chk_IndAudTerminationStateDescriptor_propertyParms(Parms1, Parms2), + chk_IndAudTerminationStateDescriptor_eventBufferControl(EBC1, EBC2), + chk_IndAudTerminationStateDescriptor_serviceState(SS1, SS2), + chk_IndAudTerminationStateDescriptor_serviceStateSel(SSS1, SSS2), + ok; +chk_IndAudTerminationStateDescriptor(D1, D2) -> + wrong_type('IndAudTerminationStateDescriptor', D1, D2). + +chk_IndAudTerminationStateDescriptor_propertyParms([], []) -> + ok; +chk_IndAudTerminationStateDescriptor_propertyParms([] = PP1, PP2) -> + not_equal('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2); +chk_IndAudTerminationStateDescriptor_propertyParms(PP1, [] = PP2) -> + not_equal('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2); +chk_IndAudTerminationStateDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_IndAudTerminationStateDescriptor_propertyParms(T1, T2); + false -> + wrong_type('IndAudTerminationStateDescriptor_propertyParms', H) + end; +chk_IndAudTerminationStateDescriptor_propertyParms([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, + 'IndAudTerminationStateDescriptor_propertyParms'), + chk_IndAudTerminationStateDescriptor_propertyParms(T1, T2); +chk_IndAudTerminationStateDescriptor_propertyParms(PP1, PP2) -> + wrong_type('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2). + +chk_IndAudTerminationStateDescriptor_eventBufferControl(EBC1, EBC2) -> + validate(fun() -> chk_opt_NULL(EBC1, EBC2) end, + 'IndAudTerminationStateDescriptor_eventBufferControl'). + +chk_IndAudTerminationStateDescriptor_serviceState(SS1, SS2) -> + validate(fun() -> chk_opt_NULL(SS1, SS2) end, + 'IndAudTerminationStateDescriptor_serviceState'). + +chk_IndAudTerminationStateDescriptor_serviceStateSel(SSS1, SSS2) -> + validate(fun() -> chk_opt_ServiceState(SSS1, SSS2) end, + 'IndAudTerminationStateDescriptor_serviceStateSel'). + +%% -- IndAudEventsDescriptor -- + +is_IndAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID, + pkgdName = Name, + streamID = SID}) -> + is_opt_RequestID(RID) andalso + is_PkgdName(Name) andalso + is_opt_StreamID(SID); +is_IndAudEventsDescriptor(_) -> + false. + +chk_IndAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID1, + pkgdName = Name1, + streamID = SID1}, + #'IndAudEventsDescriptor'{requestID = RID2, + pkgdName = Name2, + streamID = SID2}) -> + chk_opt_RequestID(RID1, RID2), + chk_PkgdName(Name1, Name2), + chk_opt_StreamID(SID1, SID2), + ok; +chk_IndAudEventsDescriptor(D1, D2) -> + wrong_type('IndAudEventsDescriptor', D1, D2). + + +%% -- IndAudEventBufferDescriptor -- + +is_IndAudEventBufferDescriptor( + #'IndAudEventBufferDescriptor'{eventName = Name, + streamID = SID}) -> + is_PkgdName(Name) andalso is_opt_StreamID(SID); +is_IndAudEventBufferDescriptor(_) -> + false. + +chk_IndAudEventBufferDescriptor( + #'IndAudEventBufferDescriptor'{eventName = Name1, + streamID = SID1}, + #'IndAudEventBufferDescriptor'{eventName = Name2, + streamID = SID2}) -> + chk_PkgdName(Name1, Name2), + chk_opt_StreamID(SID1, SID2), + ok; +chk_IndAudEventBufferDescriptor(D1, D2) -> + wrong_type('IndAudEventBufferDescriptor', D1, D2). + + +%% -- IndAudSignalsDescriptor -- + +is_IndAudSignalsDescriptor({Tag, Val}) -> + is_IndAudSignalsDescriptor_tag(Tag) andalso + is_IndAudSignalsDescriptor_val(Tag, Val); +is_IndAudSignalsDescriptor(_) -> + false. + +is_IndAudSignalsDescriptor_tag(Tag) -> + Tags = [signal, seqSigList], + lists:member(Tag, Tags). + +is_IndAudSignalsDescriptor_val(signal, Val) -> + is_IndAudSignal(Val); +is_IndAudSignalsDescriptor_val(seqSigList, Val) -> + is_IndAudSeqSigList(Val). + +chk_IndAudSignalsDescriptor(D, D) -> + chk_type(fun is_IndAudSignalsDescriptor/1, 'IndAudSignalsDescriptor', D); +chk_IndAudSignalsDescriptor({Tag, Val1} = D1, {Tag, Val2} = D2) -> + case (is_IndAudSignalsDescriptor_tag(Tag) andalso + is_IndAudSignalsDescriptor_val(Tag, Val1) andalso + is_IndAudSignalsDescriptor_val(Tag, Val2)) of + true -> + chk_IndAudSignalsDescriptor_val(Tag, Val1, Val2); + false -> + wrong_type('IndAudSignalsDescriptor', D1, D2) + end; +chk_IndAudSignalsDescriptor({Tag1, Val1} = D1, {Tag2, Val2} = D2) -> + case ((is_IndAudSignalsDescriptor_tag(Tag1) andalso + is_IndAudSignalsDescriptor_val(Tag1, Val1)) andalso + (is_IndAudSignalsDescriptor_tag(Tag2) andalso + is_IndAudSignalsDescriptor_val(Tag2, Val2))) of + true -> + not_equal('IndAudSignalsDescriptor', D1, D2); + false -> + wrong_type('IndAudSignalsDescriptor', D1, D2) + end; +chk_IndAudSignalsDescriptor(D1, D2) -> + wrong_type('IndAudSignalsDescriptor', D1, D2). + +chk_IndAudSignalsDescriptor_val(signal, Val1, Val2) -> + chk_IndAudSignal(Val1, Val2); +chk_IndAudSignalsDescriptor_val(seqSigList, Val1, Val2) -> + chk_IndAudSeqSigList(Val1, Val2). + + +%% -- IndAudSeqSigList -- + +is_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID, + signalList = SL}) -> + is_IndAudSeqSigList_id(ID) andalso is_opt_IndAudSignal(SL); +is_IndAudSeqSigList(_) -> + false. + +is_IndAudSeqSigList_id(ID) -> is_INTEGER(ID, {range, 0, 65535}). + +chk_IndAudSeqSigList(L, L) -> + chk_type(fun is_IndAudSeqSigList/1, 'IndAudSeqSigList', L); +chk_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID1, + signalList = SL1}, + #'IndAudSeqSigList'{id = ID2, + signalList = SL2}) -> + chk_IndAudSeqSigList_id(ID1, ID2), + chk_opt_IndAudSignal(SL1, SL2), + ok; +chk_IndAudSeqSigList(L1, L2) -> + wrong_type('IndAudSeqSigList', L1, L2). + +chk_IndAudSeqSigList_id(ID, ID) -> + chk_type(fun is_IndAudSeqSigList_id/1, 'IndAudSeqSigList_id', ID); +chk_IndAudSeqSigList_id(ID1, ID2) -> + case (is_IndAudSeqSigList_id(ID1) andalso + is_IndAudSeqSigList_id(ID2)) of + true -> + not_equal('IndAudSeqSigList_id', ID1, ID2); + false -> + wrong_type('IndAudSeqSigList_id', ID1, ID2) + end. + + +%% -- IndAudSignal -- + +is_opt_IndAudSignal(asn1_NOVALUE) -> + true; +is_opt_IndAudSignal(V) -> + is_IndAudSignal(V). + +is_IndAudSignal(#'IndAudSignal'{signalName = Name, + streamID = SID, + signalRequestID = SRID}) -> + is_PkgdName(Name) andalso + is_opt_StreamID(SID) andalso + is_opt_RequestID(SRID); +is_IndAudSignal(_) -> + false. + +chk_opt_IndAudSignal(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudSignal(S1, S2) -> + chk_IndAudSignal(S1, S2). + +chk_IndAudSignal(S, S) -> + chk_type(fun is_IndAudSignal/1, 'IndAudSignal', S); +chk_IndAudSignal(#'IndAudSignal'{signalName = Name1, + streamID = SID1, + signalRequestID = SRID1}, + #'IndAudSignal'{signalName = Name2, + streamID = SID2, + signalRequestID = SRID2}) -> + validate(fun() -> chk_PkgdName(Name1, Name2) end, + 'IndAudSignal_signalName'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, + 'IndAudSignal_streamID'), + validate(fun() -> chk_opt_RequestID(SRID1, SRID2) end, + 'IndAudSignal_signalRequestID'), + ok; +chk_IndAudSignal(S1, S2) -> + wrong_type('IndAudSignal', S1, S2). + + +%% -- IndAudDigitMapDescriptor -- + +is_IndAudDigitMapDescriptor( + #'IndAudDigitMapDescriptor'{digitMapName = Name}) -> + is_opt_DigitMapName(Name); +is_IndAudDigitMapDescriptor(_) -> + false. + +chk_IndAudDigitMapDescriptor(D, D) -> + chk_type(fun is_IndAudDigitMapDescriptor/1, 'IndAudDigitMapDescriptor', D); +chk_IndAudDigitMapDescriptor( + #'IndAudDigitMapDescriptor'{digitMapName = Name1}, + #'IndAudDigitMapDescriptor'{digitMapName = Name2}) -> + validate(fun() -> chk_opt_DigitMapName(Name1, Name2) end, + 'IndAudDigitMapDescriptor'), + ok; +chk_IndAudDigitMapDescriptor(D1, D2) -> + wrong_type('IndAudDigitMapDescriptor', D1, D2). + + +%% -- IndAudStatisticsDescriptor -- + +is_IndAudStatisticsDescriptor( + #'IndAudStatisticsDescriptor'{statName = Name}) -> + is_PkgdName(Name); +is_IndAudStatisticsDescriptor(_) -> + false. + +chk_IndAudStatisticsDescriptor(D, D) -> + chk_type(fun is_IndAudStatisticsDescriptor/1, + 'IndAudStatisticsDescriptor', D); +chk_IndAudStatisticsDescriptor( + #'IndAudStatisticsDescriptor'{statName = Name1}, + #'IndAudStatisticsDescriptor'{statName = Name2}) -> + validate(fun() -> chk_PkgdName(Name1, Name2) end, + 'IndAudStatisticsDescriptor'), + ok; +chk_IndAudStatisticsDescriptor(D1, D2) -> + wrong_type('IndAudStatisticsDescriptor', D1, D2). + + +%% -- IndAudPackagesDescriptor -- + +is_IndAudPackagesDescriptor( + #'IndAudPackagesDescriptor'{packageName = Name, + packageVersion = Ver}) -> + is_Name(Name) andalso is_IndAudPackagesDescriptor_packageVersion(Ver); +is_IndAudPackagesDescriptor(_) -> + false. + +is_IndAudPackagesDescriptor_packageVersion(V) -> + is_INTEGER(V, {range, 0, 99}). + +chk_IndAudPackagesDescriptor( + #'IndAudPackagesDescriptor'{packageName = Name1, + packageVersion = Ver1}, + #'IndAudPackagesDescriptor'{packageName = Name2, + packageVersion = Ver2}) -> + validate(fun() -> chk_Name(Name1, Name2) end, 'IndAudPackagesDescriptor'), + chk_IndAudPackagesDescriptor_packageVersion(Ver1, Ver2), + ok; +chk_IndAudPackagesDescriptor(D1, D2) -> + wrong_type('IndAudPackagesDescriptor', D1, D2). + +chk_IndAudPackagesDescriptor_packageVersion(V, V) -> + chk_type(fun is_IndAudPackagesDescriptor_packageVersion/1, + 'IndAudPackagesDescriptor_packageVersion', V); +chk_IndAudPackagesDescriptor_packageVersion(V1, V2) -> + case (is_IndAudPackagesDescriptor_packageVersion(V1) andalso + is_IndAudPackagesDescriptor_packageVersion(V2)) of + true -> + not_equal('IndAudPackagesDescriptor_packageVersion', V1, V2); + false -> + wrong_type('IndAudPackagesDescriptor_packageVersion', V1, V2) + end. + + +%% -- NotifyRequest -- + +is_NotifyRequest(#'NotifyRequest'{terminationID = Tids, + observedEventsDescriptor = OED, + errorDescriptor = ED}) -> + is_TerminationIDList(Tids) andalso + is_ObservedEventsDescriptor(OED) andalso + is_opt_ErrorDescriptor(ED); +is_NotifyRequest(_) -> + false. + +chk_NotifyRequest(#'NotifyRequest'{terminationID = Tids1, + observedEventsDescriptor = OED1, + errorDescriptor = ED1}, + #'NotifyRequest'{terminationID = Tids2, + observedEventsDescriptor = OED2, + errorDescriptor = ED2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'NotifyRequest'), + validate(fun() -> chk_ObservedEventsDescriptor(OED1, OED2) end, + 'NotifyRequest'), + validate(fun() -> chk_opt_ErrorDescriptor(ED1, ED2) end, + 'NotifyRequest'), + ok; +chk_NotifyRequest(NR1, NR2) -> + wrong_type('NotifyRequest', NR1, NR2). + + +%% -- NotifyReply -- + +is_NotifyReply(#'NotifyReply'{terminationID = Tids, + errorDescriptor = ED}) -> + is_TerminationIDList(Tids) andalso is_opt_ErrorDescriptor(ED); +is_NotifyReply(_) -> + false. + +chk_NotifyReply(#'NotifyReply'{terminationID = Tids1, + errorDescriptor = ED1}, + #'NotifyReply'{terminationID = Tids2, + errorDescriptor = ED2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, 'NotifyReply'), + validate(fun() -> chk_opt_ErrorDescriptor(ED1, ED2) end, 'NotifyReply'), + ok; +chk_NotifyReply(NR1, NR2) -> + wrong_type('NotifyReply', NR1, NR2). + + +%% -- ObservedEventsDescriptor -- + +is_ObservedEventsDescriptor( + #'ObservedEventsDescriptor'{requestId = RID, + observedEventLst = OEL}) -> + is_RequestID(RID) andalso + is_ObservedEventsDescriptor_observedEventLst(OEL); +is_ObservedEventsDescriptor(_) -> + false. + +is_ObservedEventsDescriptor_observedEventLst([]) -> + true; +is_ObservedEventsDescriptor_observedEventLst([H|T]) -> + is_ObservedEvent(H) andalso + is_ObservedEventsDescriptor_observedEventLst(T); +is_ObservedEventsDescriptor_observedEventLst(_) -> + false. + +chk_ObservedEventsDescriptor( + #'ObservedEventsDescriptor'{requestId = RID1, + observedEventLst = OEL1}, + #'ObservedEventsDescriptor'{requestId = RID2, + observedEventLst = OEL2}) -> + validate(fun() -> chk_RequestID(RID1, RID2) end, + 'ObservedEventsDescriptor'), + validate( + fun() -> + chk_ObservedEventsDescriptor_observedEventLst(OEL1, OEL2) + end, + 'ObservedEventsDescriptor'), + ok; +chk_ObservedEventsDescriptor(D1, D2) -> + wrong_type('ObservedEventsDescriptor', D1, D2). + +chk_ObservedEventsDescriptor_observedEventLst([], []) -> + ok; +chk_ObservedEventsDescriptor_observedEventLst([] = L1, L2) -> + not_equal('ObservedEventsDescriptor_observedEventLst', L1, L2); +chk_ObservedEventsDescriptor_observedEventLst(L1, [] = L2) -> + not_equal('ObservedEventsDescriptor_observedEventLst', L1, L2); +chk_ObservedEventsDescriptor_observedEventLst([H|T1], [H|T2]) -> + case is_ObservedEvent(H) of + true -> + chk_ObservedEventsDescriptor_observedEventLst(T1, T2); + false -> + wrong_type('ObservedEventsDescriptor_observedEventLst_val', H) + end; +chk_ObservedEventsDescriptor_observedEventLst([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ObservedEvent(H1, H2) end, + 'ObservedEventsDescriptor_observedEventLst_val'), + chk_ObservedEventsDescriptor_observedEventLst(T1, T2); +chk_ObservedEventsDescriptor_observedEventLst(L1, L2) -> + wrong_type('ObservedEventsDescriptor_observedEventLst', L1, L2). + + +%% -- ObservedEvent -- + +is_ObservedEvent(#'ObservedEvent'{eventName = Name, + streamID = SID, + eventParList = EPL, + timeNotation = TN}) -> + is_EventName(Name) andalso + is_opt_StreamID(SID) andalso + is_ObservedEvent_eventParList(EPL) andalso + is_opt_TimeNotation(TN); +is_ObservedEvent(_) -> + false. + +is_ObservedEvent_eventParList([]) -> + true; +is_ObservedEvent_eventParList([H|T]) -> + is_EventParameter(H) andalso is_ObservedEvent_eventParList(T); +is_ObservedEvent_eventParList(_) -> + false. + +chk_ObservedEvent(E, E) -> + chk_type(fun is_ObservedEvent/1, 'ObservedEvent', E); +chk_ObservedEvent(#'ObservedEvent'{eventName = Name1, + streamID = SID1, + eventParList = EPL1, + timeNotation = TN1}, + #'ObservedEvent'{eventName = Name2, + streamID = SID2, + eventParList = EPL2, + timeNotation = TN2}) -> + validate(fun() -> chk_EventName(Name1, Name2) end, 'ObservedEvent'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'ObservedEvent'), + chk_ObservedEvent_eventParList(EPL1, EPL2), + validate(fun() -> chk_opt_TimeNotation(TN1, TN2) end, 'ObservedEvent'), + ok; +chk_ObservedEvent(E1, E2) -> + wrong_type('ObservedEvent', E1, E2). + +chk_ObservedEvent_eventParList([], []) -> + ok; +chk_ObservedEvent_eventParList([] = EPL1, EPL2) -> + not_equal('ObservedEvent_eventParList', EPL1, EPL2); +chk_ObservedEvent_eventParList(EPL1, [] = EPL2) -> + not_equal('ObservedEvent_eventParList', EPL1, EPL2); +chk_ObservedEvent_eventParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_ObservedEvent_eventParList(T1, T2); + false -> + wrong_type('ObservedEvent_eventParList_val', H) + end; +chk_ObservedEvent_eventParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'ObservedEvent_eventParList'), + chk_ObservedEvent_eventParList(T1, T2); +chk_ObservedEvent_eventParList(L1, L2) -> + wrong_type('ObservedEvent_eventParList', L1, L2). + + +%% -- EventName -- + +is_EventName(N) -> is_PkgdName(N). + +chk_EventName(N, N) -> + chk_type(fun is_EventName/1, 'EventName', N); +chk_EventName(N1, N2) -> + case (is_EventName(N1) andalso is_EventName(N2)) of + true -> + not_equal('EventName', N1, N2); + false -> + wrong_type('EventName', N1, N2) + end. + + +%% -- EventParameter -- + +is_EventParameter(#'EventParameter'{eventParameterName = Name, + value = Val, + extraInfo = EI}) -> + d("is_EventParameter -> entery with" + "~n Name: ~p" + "~n Val: ~p" + "~n EI: ~p", [Name, Val, EI]), + is_Name(Name) andalso + is_Value(Val) andalso + is_EventParameter_extraInfo(EI); +is_EventParameter(_) -> + false. + +is_EventParameter_extraInfo(asn1_NOVALUE) -> + true; +is_EventParameter_extraInfo({Tag, Val}) -> + is_EventParameter_extraInfo_tag(Tag) andalso + is_EventParameter_extraInfo_val(Tag, Val); +is_EventParameter_extraInfo(_) -> + false. + +is_EventParameter_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_EventParameter_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_EventParameter_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_EventParameter_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + +chk_EventParameter(#'EventParameter'{eventParameterName = Name1, + value = Val1, + extraInfo = EI1}, + #'EventParameter'{eventParameterName = Name2, + value = Val2, + extraInfo = EI2}) -> + validate(fun() -> chk_Name(Name1, Name2) end, 'EventParameter'), + validate(fun() -> chk_Value(Val1, Val2) end, 'EventParameter'), + chk_EventParameter_extraInfo(EI1, EI2), + ok; +chk_EventParameter(P1, P2) -> + wrong_type('EventParameter', P1, P2). + +chk_EventParameter_extraInfo(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_EventParameter_extraInfo(EI, EI) -> + chk_type(fun is_EventParameter_extraInfo/1, + 'EventParameter_extraInfo', EI); +chk_EventParameter_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> + case (is_EventParameter_extraInfo_tag(Tag) andalso + is_EventParameter_extraInfo_val(Tag, Val1) andalso + is_EventParameter_extraInfo_val(Tag, Val2)) of + true -> + chk_EventParameter_extraInfo_val(Tag, Val1, Val2); + false -> + wrong_type('EventParameter_extraInfo', EI1, EI2) + end; +chk_EventParameter_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> + case ((is_EventParameter_extraInfo_tag(Tag1) andalso + is_EventParameter_extraInfo_val(Tag1, Val1)) andalso + (is_EventParameter_extraInfo_tag(Tag2) andalso + is_EventParameter_extraInfo_val(Tag2, Val2))) of + true -> + not_equal('EventParameter_extraInfo', EI1, EI2); + false -> + wrong_type('EventParameter_extraInfo', EI1, EI2) + end; +chk_EventParameter_extraInfo(EI1, EI2) -> + wrong_type('EventParameter_extraInfo', EI1, EI2). + +chk_EventParameter_extraInfo_val(relation, Val1, Val2) -> + validate(fun() -> chk_Relation(Val1, Val2) end, + 'EventParameter_extraInfo_val'); +chk_EventParameter_extraInfo_val(range, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, + 'EventParameter_extraInfo_val'); +chk_EventParameter_extraInfo_val(sublist, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, + 'EventParameter_extraInfo_val'). + + +%% -- ServiceChangeRequest -- + +is_ServiceChangeRequest(#'ServiceChangeRequest'{terminationID = Tids, + serviceChangeParms = Parms}) -> + is_TerminationIDList(Tids) andalso is_ServiceChangeParm(Parms); +is_ServiceChangeRequest(_) -> + false. + +chk_ServiceChangeRequest(R, R) -> + chk_type(fun is_ServiceChangeRequest/1, 'ServiceChangeRequest', R); +chk_ServiceChangeRequest( + #'ServiceChangeRequest'{terminationID = Tids1, + serviceChangeParms = Parms1}, + #'ServiceChangeRequest'{terminationID = Tids2, + serviceChangeParms = Parms2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'ServiceChangeRequest'), + validate(fun() -> chk_ServiceChangeParm(Parms1, Parms2) end, + 'ServiceChangeRequest'), + ok; +chk_ServiceChangeRequest(R1, R2) -> + wrong_type('ServiceChangeRequest', R1, R2). + + +%% -- ServiceChangeReply -- + +is_ServiceChangeReply(#'ServiceChangeReply'{terminationID = Tids, + serviceChangeResult = Res}) -> + is_TerminationIDList(Tids) andalso is_ServiceChangeResult(Res); +is_ServiceChangeReply(_) -> + false. + +chk_ServiceChangeReply(R, R) -> + chk_type(fun is_ServiceChangeReply/1, 'ServiceChangeReply', R); +chk_ServiceChangeReply( + #'ServiceChangeReply'{terminationID = Tids1, + serviceChangeResult = Res1}, + #'ServiceChangeReply'{terminationID = Tids2, + serviceChangeResult = Res2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'ServiceChangeReply'), + validate(fun() -> chk_ServiceChangeResult(Res1, Res2) end, + 'ServiceChangeReply'), + ok; +chk_ServiceChangeReply(R1, R2) -> + wrong_type('ServiceChangeReply', R1, R2). + + +%% -- ServiceChangeResult -- + +is_ServiceChangeResult({Tag, Val}) -> + is_ServiceChangeResult_tag(Tag) andalso + is_ServiceChangeResult_val(Tag, Val); +is_ServiceChangeResult(_) -> + false. + +is_ServiceChangeResult_tag(Tag) -> + Tags = [errorDescriptor, serviceChangeResParms], + lists:member(Tag, Tags). + +is_ServiceChangeResult_val(errorDescriptor, Val) -> + is_ErrorDescriptor(Val); +is_ServiceChangeResult_val(serviceChangeResParms, Val) -> + is_ServiceChangeResParm(Val). + +chk_ServiceChangeResult(Res, Res) -> + chk_type(fun is_ServiceChangeResult/1, 'ServiceChangeResult', Res); +chk_ServiceChangeResult({Tag, Val1} = Res1, {Tag, Val2} = Res2) -> + case (is_ServiceChangeResult_tag(Tag) andalso + is_ServiceChangeResult_val(Tag, Val1) andalso + is_ServiceChangeResult_val(Tag, Val2)) of + true -> + chk_ServiceChangeResult_val(Tag, Val1, Val2); + false -> + wrong_type('ServiceChangeResult', Res1, Res2) + end; +chk_ServiceChangeResult({Tag1, Val1} = Res1, {Tag2, Val2} = Res2) -> + case ((is_ServiceChangeResult_tag(Tag1) andalso + is_ServiceChangeResult_val(Tag1, Val1)) andalso + (is_ServiceChangeResult_tag(Tag2) andalso + is_ServiceChangeResult_val(Tag2, Val2))) of + true -> + not_equal('ServiceChangeResult', Res1, Res2); + false -> + wrong_type('ServiceChangeResult', Res1, Res2) + end; +chk_ServiceChangeResult(Res1, Res2) -> + wrong_type('ServiceChangeResult', Res1, Res2). + +chk_ServiceChangeResult_val(errorDescriptor, Val1, Val2) -> + validate(fun() -> chk_ErrorDescriptor(Val1, Val2) end, + 'ServiceChangeResult'); +chk_ServiceChangeResult_val(serviceChangeResParms, Val1, Val2) -> + validate(fun() -> chk_ServiceChangeResParm(Val1, Val2) end, + 'ServiceChangeResult'). + + +%% -- WildcardField -- + +is_WildcardField(WF) -> is_OCTET_STRING(WF, {exact, 1}). + +chk_WildcardField(WF, WF) -> + case is_WildcardField(WF) of + true -> + ok; + false -> + wrong_type('WildcardField', WF) + end; +chk_WildcardField(WF1, WF2) -> + case (is_WildcardField(WF1) andalso is_WildcardField(WF2)) of + true -> + not_equal('WildcardField', WF1, WF2); + false -> + wrong_type('WildcardField', WF1, WF2) + end. + + +%% -- TerminationID -- + +is_TerminationID(#'TerminationID'{wildcard = W, + id = ID}) -> + is_TerminationID_wildcard(W) andalso is_TerminationID_id(ID); +is_TerminationID(#megaco_term_id{contains_wildcards = _W, + id = _ID}) -> + true; % What are the types? +is_TerminationID(_) -> + false. + +is_TerminationID_wildcard([]) -> + true; +is_TerminationID_wildcard([H|T]) -> + is_WildcardField(H) andalso is_TerminationID_wildcard(T); +is_TerminationID_wildcard(_) -> + false. + +is_TerminationID_id(ID) -> is_OCTET_STRING(ID, {range, 1, 8}). + +chk_TerminationID(Id,Id) -> + d("chk_TerminationID(1) -> entry with" + "~n Id: ~p", [Id]), + chk_type(fun is_TerminationID/1, 'TerminationID', Id); +chk_TerminationID(#'TerminationID'{wildcard = W1, + id = I1}, + #'TerminationID'{wildcard = W2, + id = I2}) -> + d("chk_TerminationID(2) -> entry with" + "~n W1: ~p" + "~n W2: ~p" + "~n I1: ~p" + "~n I2: ~p", [W1, W2, I1, I2]), + chk_TerminationID_wildcard(W1, W2), + chk_TerminationID_id(I1, I2), + ok; +chk_TerminationID(#megaco_term_id{contains_wildcards = W1, + id = I1}, + #megaco_term_id{contains_wildcards = W2, + id = I2}) -> + d("chk_TerminationID(3) -> entry with" + "~n W1: ~p" + "~n W2: ~p" + "~n I1: ~p" + "~n I2: ~p", [W1, W2, I1, I2]), + validate(fun() -> chk_BOOLEAN(W1, W2) end, 'TerminationID_wildcard'), + chk_TerminationID_id(I1, I2), + ok; +chk_TerminationID(Tid1, Tid2) -> + d("chk_TerminationID(4) -> entry with" + "~n Tid1: ~p" + "~n Tid2: ~p", [Tid1, Tid2]), + wrong_type('TerminationID', Tid1, Tid2). + +chk_TerminationID_wildcard([], []) -> + ok; +chk_TerminationID_wildcard([] = WF1, WF2) -> + not_equal('TerminationID_wildcard', WF1, WF2); +chk_TerminationID_wildcard(WF1, [] = WF2) -> + not_equal('TerminationID_wildcard', WF1, WF2); +chk_TerminationID_wildcard([H|T1], [H|T2]) -> + case is_WildcardField(H) of + true -> + chk_TerminationID_wildcard(T1, T2); + false -> + wrong_type('TerminationID_wildcard_val', H) + end; +chk_TerminationID_wildcard([H1|T1], [H2|T2]) -> + validate(fun() -> chk_WildcardField(H1, H2) end, + 'TerminationID_wildcard_val'), + chk_TerminationID_wildcard(T1, T2); +chk_TerminationID_wildcard(WF1,WF2) -> + not_equal('TerminationId_wildcard', WF1, WF2). + +chk_TerminationID_id(Id, Id) -> + case is_OCTET_STRING(Id, {range, 1, 8}) of + true -> + ok; + false -> + wrong_type('TerminationID_id', Id, Id) + end; +chk_TerminationID_id(Id1, Id2) -> + Id12 = flatten_TerminationID_id(Id1, []), + Id22 = flatten_TerminationID_id(Id2, []), + case Id12 == Id22 of + true -> + ok; + false -> + not_equal(terminationId_id, Id1, Id2) + end. + +flatten_TerminationID_id([], Acc) -> + lists:flatten(lists:reverse(Acc)); +flatten_TerminationID_id([H|T], Acc) -> + flatten_TerminationID_id(T, [string:tokens(H, [$/])|Acc]). + +%% -- TerminationIDList -- + +%% is_opt_TerminationIDList(asn1_NOVALUE) -> +%% true; +%% is_opt_TerminationIDList(TIDs) -> +%% is_TerminationIDList(TIDs). + +is_TerminationIDList([]) -> + true; +is_TerminationIDList([H|T]) -> + is_TerminationID(H) andalso is_TerminationIDList(T); +is_TerminationIDList(_) -> + false. + +chk_opt_TerminationIDList(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_TerminationIDList(TIDs1, TIDs2) -> + chk_TerminationIDList(TIDs1, TIDs2). + +chk_TerminationIDList([], []) -> + ok; +chk_TerminationIDList([] = L1, L2) -> + not_equal('TerminationIDList', L1, L2); +chk_TerminationIDList(L1, [] = L2) -> + not_equal('TerminationIDList', L1, L2); +chk_TerminationIDList([H|T1], [H|T2]) -> + case is_TerminationID(H) of + true -> + chk_TerminationIDList(T1, T2); + false -> + wrong_type('TerminationIDList', H) + end; +chk_TerminationIDList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TerminationID(H1, H2) end, 'TerminationIDList'), + chk_TerminationIDList(T1, T2); +chk_TerminationIDList(L1, L2) -> + wrong_type('TerminationIDList', L1, L2). + + +%% -- MediaDescriptor -- + +is_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TSD, + streams = S}) -> + d("is_MediaDescriptor -> entry with" + "~n TSD: ~p" + "~n S: ~p", [TSD, S]), + is_opt_TerminationStateDescriptor(TSD) andalso + is_MediaDescriptor_streams(S); +is_MediaDescriptor(_) -> + false. + +is_MediaDescriptor_streams(asn1_NOVALUE) -> + true; +is_MediaDescriptor_streams({Tag, Val}) -> + is_MediaDescriptor_streams_tag(Tag) andalso + is_MediaDescriptor_streams_val(Tag, Val); +is_MediaDescriptor_streams(_) -> + false. + +is_MediaDescriptor_streams_tag(Tag) -> + Tags = [oneStream, multiStream], + lists:member(Tag, Tags). + +is_MediaDescriptor_streams_val(oneStream, SP) -> + is_StreamParms(SP); +is_MediaDescriptor_streams_val(multiStream, SDL) -> + is_MediaDescriptor_multiStream(SDL). + +is_MediaDescriptor_multiStream([]) -> + true; +is_MediaDescriptor_multiStream([H|T]) -> + is_StreamDescriptor(H) andalso is_MediaDescriptor_multiStream(T); +is_MediaDescriptor_multiStream(_) -> + false. + +chk_MediaDescriptor(D, D) -> + chk_type(fun is_MediaDescriptor/1, 'MediaDescriptor', D); +chk_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TSD1, + streams = S1}, + #'MediaDescriptor'{termStateDescr = TSD2, + streams = S2}) -> + validate( + fun() -> + chk_opt_TerminationStateDescriptor(TSD1, TSD2) + end, + 'MediaDescriptor'), + validate( + fun() -> + chk_MediaDescriptor_streams(S1, S2) + end, + 'MediaDescriptor'), + ok; +chk_MediaDescriptor(D1, D2) -> + wrong_type('MediaDescriptor', D1, D2). + + +chk_MediaDescriptor_streams(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_MediaDescriptor_streams({oneStream, SP1}, {oneStream, SP2}) -> + validate(fun() -> + chk_StreamParms(SP1, SP2) + end, + 'MediaDescriptor_streams'); +chk_MediaDescriptor_streams({multiStream, SDs1}, {multiStream, SDs2}) -> + validate(fun() -> + chk_MediaDescriptor_multiStream(SDs1, SDs2) + end, + 'MediaDescriptor_streams'); +chk_MediaDescriptor_streams(S1, S2) -> + wrong_type('MediaDescriptor_streams', S1, S2). + +chk_MediaDescriptor_multiStream([], []) -> + ok; +chk_MediaDescriptor_multiStream([] = MS1, MS2) -> + not_equal('MediaDescriptor_multiStream', MS1, MS2); +chk_MediaDescriptor_multiStream(MS1, [] = MS2) -> + not_equal('MediaDescriptor_multiStream', MS1, MS2); +chk_MediaDescriptor_multiStream([H|T1], [H|T2]) -> + case is_StreamDescriptor(H) of + true -> + chk_MediaDescriptor_multiStream(T1, T2); + false -> + wrong_type('MediaDescriptor_multiStream_val', H) + end; +chk_MediaDescriptor_multiStream([H1|T1], [H2|T2]) -> + validate(fun() -> chk_StreamDescriptor(H1, H2) end, + 'MediaDescriptor_multiStream_val'), + chk_MediaDescriptor_multiStream(T1, T2); +chk_MediaDescriptor_multiStream(MS1, MS2) -> + wrong_type('MediaDescriptor_multiStream_val', MS1, MS2). + + +%% -- StreamDescriptor -- + +is_StreamDescriptor(#'StreamDescriptor'{streamID = SID, + streamParms = Parms}) -> + d("is_StreamDescriptor -> entry with" + "~n SID: ~p" + "~n Parms: ~p", [SID, Parms]), + is_StreamID(SID) andalso is_StreamParms(Parms); +is_StreamDescriptor(X) -> + d("is_StreamDescriptor -> entry when ERROR with" + "~n X: ~p", [X]), + false. + +chk_StreamDescriptor(D, D) -> + chk_type(fun is_StreamDescriptor/1, 'StreamDescriptor', D); +chk_StreamDescriptor(#'StreamDescriptor'{streamID = SID1, + streamParms = Parms1}, + #'StreamDescriptor'{streamID = SID2, + streamParms = Parms2}) -> + validate(fun() -> chk_StreamID(SID1, SID2) end, 'StreamDescriptor'), + validate(fun() -> chk_StreamParms(Parms1, Parms2) end, 'StreamDescriptor'), + ok; +chk_StreamDescriptor(D1, D2) -> + wrong_type('StreamDescriptor', D1, D2). + + +%% -- StreamParms -- + +is_StreamParms(#'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}) -> + d("is_StreamParms -> entry with" + "~n LCD: ~p" + "~n LD: ~p" + "~n RD: ~p" + "~n SD: ~p", [LCD, LD, RD, SD]), + is_opt_LocalControlDescriptor(LCD) andalso + is_opt_LocalRemoteDescriptor(LD) andalso + is_opt_LocalRemoteDescriptor(RD) andalso + is_opt_StatisticsDescriptor(SD); +is_StreamParms(X) -> + d("is_StreamParms -> entry when ERROR with" + "~n X: ~p", [X]), + false. + +chk_StreamParms(SP, SP) -> + chk_type(fun is_StreamParms/1, 'StreamParms', SP); +chk_StreamParms(#'StreamParms'{localControlDescriptor = LCD1, + localDescriptor = LD1, + remoteDescriptor = RD1, + statisticsDescriptor = SD1}, + #'StreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2, + statisticsDescriptor = SD2}) -> + validate(fun() -> chk_opt_LocalControlDescriptor(LCD1, LCD2) end, + 'StreamParms_localControlDescriptor'), + validate(fun() -> chk_opt_LocalRemoteDescriptor(LD1, LD2) end, + 'StreamParms_localDescriptor'), + validate(fun() -> chk_opt_LocalRemoteDescriptor(RD1, RD2) end, + 'StreamParms_remoteDescriptor'), + validate(fun() -> chk_opt_StatisticsDescriptor(SD1, SD2) end, + 'StreamParms_statisticsDescriptor'), + ok; +chk_StreamParms(P1, P2) -> + wrong_type('StreamParms', P1, P2). + + +%% -- LocalControlDescriptor -- + +is_opt_LocalControlDescriptor(D) -> + d("is_opt_LocalControlDescriptor -> entry"), + is_OPTIONAL(fun is_LocalControlDescriptor/1, D). + +is_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP}) -> + d("is_LocalControlDescriptor -> entry with" + "~n SM: ~p" + "~n RV: ~p" + "~n RG: ~p" + "~n PP: ~p", [SM, RV, RG, PP]), + is_opt_StreamMode(SM) andalso + is_opt_BOOLEAN(RV) andalso + is_opt_BOOLEAN(RG) andalso + is_LocalControlDescriptor_propertyParms(PP); +is_LocalControlDescriptor(_) -> + false. + +is_LocalControlDescriptor_propertyParms([]) -> + d("is_LocalControlDescriptor_propertyParms -> entry when done"), + true; +is_LocalControlDescriptor_propertyParms([H|T]) -> + d("is_LocalControlDescriptor_propertyParms -> entry with" + "~n H: ~p" + "~n T: ~p", [H, T]), + is_PropertyParm(H) andalso is_LocalControlDescriptor_propertyParms(T); +is_LocalControlDescriptor_propertyParms(_) -> + false. + +chk_opt_LocalControlDescriptor(LCD1, LCD2) -> + chk_OPTIONAL('LocalControlDescriptor', LCD1, LCD2, + fun is_LocalControlDescriptor/1, + fun chk_LocalControlDescriptor/2). + +chk_LocalControlDescriptor(LCD, LCD) -> + chk_type(fun is_LocalControlDescriptor/1, 'LocalControlDescriptor', LCD); +chk_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = SM1, + reserveValue = RV1, + reserveGroup = RG1, + propertyParms = PP1}, + #'LocalControlDescriptor'{streamMode = SM2, + reserveValue = RV2, + reserveGroup = RG2, + propertyParms = PP2}) -> + validate( + fun() -> chk_opt_StreamMode(SM1, SM2) end, + 'LocalControlDescriptor'), + validate( + fun() -> chk_opt_BOOLEAN(RV1, RV2) end, + 'LocalControlDescriptor_reserveValue'), + validate( + fun() -> chk_opt_BOOLEAN(RG1, RG2) end, + 'LocalControlDescriptor_reserveGroup'), + chk_LocalControlDescriptor_propertyParms(PP1, PP2), + ok; +chk_LocalControlDescriptor(LCD1, LCD2) -> + wrong_type('LocalControlDescriptor', LCD1, LCD2). + + +chk_LocalControlDescriptor_propertyParms([], []) -> + ok; +chk_LocalControlDescriptor_propertyParms([] = PP1, PP2) -> + not_equal('LocalControlDescriptor_propertyParms', PP1, PP2); +chk_LocalControlDescriptor_propertyParms(PP1, [] = PP2) -> + not_equal('LocalControlDescriptor_propertyParms', PP1, PP2); +chk_LocalControlDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_LocalControlDescriptor_propertyParms(T1, T2); + false -> + wrong_type('LocalControlDescriptor_propertyParms_val', H) + end; +chk_LocalControlDescriptor_propertyParms([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, + 'LocalControlDescriptor_propertyParms_val'), + chk_LocalControlDescriptor_propertyParms(T1, T2); +chk_LocalControlDescriptor_propertyParms(PP1, PP2) -> + wrong_type('LocalControlDescriptor_propertyParms', PP1, PP2). + + +%% -- StreamMode -- + +is_opt_StreamMode(asn1_NOVALUE) -> + true; +is_opt_StreamMode(SM) -> + is_StreamMode(SM). + +is_StreamMode(SM) -> + lists:member(SM, [sendOnly, recvOnly, sendRecv, inactive, loopBack]). + +chk_opt_StreamMode(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_StreamMode(SM1, SM2) -> + chk_StreamMode(SM1, SM2). + +chk_StreamMode(SM, SM) -> + chk_type(fun is_StreamMode/1, 'StreamMode', SM); +chk_StreamMode(SM1, SM2) -> + case (is_StreamMode(SM1) andalso is_StreamMode(SM2)) of + true -> + not_equal('StreamMode', SM1, SM2); + false -> + wrong_type('StreamMode', SM1, SM2) + end. + + +%% -- PropertyParm -- + +is_opt_PropertyParm(asn1_NOVALUE) -> + true; +is_opt_PropertyParm(PP) -> + is_PropertyParm(PP). + +is_PropertyParm(#'PropertyParm'{name = N, + value = V, + extraInfo = I}) -> + d("is_PropertyParm -> entry with" + "~n N: ~p" + "~n V: ~p" + "~n I: ~p", [N, V, I]), + is_PkgdName(N) andalso + is_PropertyParm_value(V) andalso + is_PropertyParm_extraInfo(I); +is_PropertyParm(_) -> + false. + +is_PropertyParm_value([]) -> + d("is_PropertyParm_value -> entry when done"), + true; +is_PropertyParm_value([H|T]) -> + d("is_PropertyParm_value -> entry with" + "~n H: ~p", [H]), + is_OCTET_STRING(H) andalso is_PropertyParm_value(T); +is_PropertyParm_value(_) -> + false. + +is_PropertyParm_extraInfo(asn1_NOVALUE) -> + true; +is_PropertyParm_extraInfo({Tag, Val}) -> + d("is_PropertyParm_extraInfo -> entry with" + "~n Tag: ~p" + "~n Val: ~p", [Tag, Val]), + is_PropertyParm_extraInfo_tag(Tag) andalso + is_PropertyParm_extraInfo_val(Tag, Val); +is_PropertyParm_extraInfo(_) -> + false. + +is_PropertyParm_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_PropertyParm_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_PropertyParm_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_PropertyParm_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + + +chk_opt_PropertyParm(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_PropertyParm(P1, P2) -> + chk_PropertyParm(P1, P2). + +chk_PropertyParm(P, P) -> + chk_type(fun is_PropertyParm/1, 'PropertyParm', P); +chk_PropertyParm(#'PropertyParm'{name = N1, + value = V1, + extraInfo = I1}, + #'PropertyParm'{name = N2, + value = V2, + extraInfo = I2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'PropertyParm'), + chk_PropertyParm_value(V1, V2), + chk_PropertyParm_extraInfo(I1, I2), + ok; +chk_PropertyParm(P1, P2) -> + wrong_type('PropertyParm', P1, P2). + +chk_PropertyParm_value([], []) -> + ok; +chk_PropertyParm_value([] = V1, V2) -> + not_equal('PropertyParm_value', V1, V2); +chk_PropertyParm_value(V1, [] = V2) -> + not_equal('PropertyParm_value', V1, V2); +chk_PropertyParm_value([H|T1], [H|T2]) -> + case is_OCTET_STRING(H) of + true -> + chk_PropertyParm_value(T1, T2); + false -> + wrong_type('PropertyParm_value_val', H) + end; +chk_PropertyParm_value([H1|_], [H2|_]) -> + case (is_OCTET_STRING(H1) andalso is_OCTET_STRING(H2)) of + true -> + not_equal('PropertyParm_value_val', H1, H2); + false -> + wrong_type('PropertyParm_value_val', H1, H2) + end; +chk_PropertyParm_value(V1, V2) -> + wrong_type('PropertyParm_value', V1, V2). + +chk_PropertyParm_extraInfo(EI, EI) -> + chk_type(fun is_PropertyParm_extraInfo/1, 'PropertyParm_extraInfo', EI); +chk_PropertyParm_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> + case (is_PropertyParm_extraInfo_tag(Tag) and + is_PropertyParm_extraInfo_val(Tag, Val1) and + is_PropertyParm_extraInfo_val(Tag, Val2)) of + true -> + chk_PropertyParm_extraInfo_val(Tag, Val1, Val2); + false -> + wrong_type('PropertyParm_extraInfo', EI1, EI2) + end; +chk_PropertyParm_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> + case ((is_PropertyParm_extraInfo_tag(Tag1) and + is_PropertyParm_extraInfo_val(Tag1, Val1)) and + (is_PropertyParm_extraInfo_tag(Tag2) and + is_PropertyParm_extraInfo_val(Tag2, Val2))) of + true -> + not_equal('PropertyParm_extraInfo', EI1, EI2); + false -> + wrong_type('PropertyParm_extraInfo', EI1, EI2) + end; +chk_PropertyParm_extraInfo(EI1, EI2) -> + wrong_type('PropertyParm_extraInfo', EI1, EI2). + +chk_PropertyParm_extraInfo_val(relation, Val1, Val2) -> + validate(fun() -> chk_Relation(Val1, Val2) end, 'PropertyParm_extraInfo'); +chk_PropertyParm_extraInfo_val(range, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'PropertyParm_extraInfo'); +chk_PropertyParm_extraInfo_val(sublist, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'PropertyParm_extraInfo'). + + +%% -- Name -- + +is_Name(N) -> + %% Binary: is_OCTET_STRING(N, {exact, 2}). + case is_OCTET_STRING(N, {range, 1, 64}) of + true -> + is_NAME(N); + false -> + false + end. + +is_NAME([H|T]) when H =< $z, $a =< H -> + is_NAME2(T); +is_NAME([H|T]) when H =< $Z, $A =< H -> + is_NAME2(T); +is_NAME(_) -> + false. + +is_NAME2([]) -> + true; +is_NAME2([$_|T]) -> + is_NAME2(T); +is_NAME2([H|T]) when H =< $z, $a =< H -> + is_NAME2(T); +is_NAME2([H|T]) when H =< $Z, $A =< H -> + is_NAME2(T); +is_NAME2([H|T]) when H =< $9, $0 =< H -> + is_NAME2(T); +is_NAME2(_) -> + false. + + + +chk_Name(N, N) -> + chk_type(fun is_Name/1, 'Name', N); +chk_Name(N1, N2) -> + case (is_Name(N1) andalso is_Name(N2)) of + true -> + not_equal('Name', N1, N2); + false -> + wrong_type('Name', N1, N2) + end. + + +%% -- PkgdName -- + +%% PkgdName is either "AB/CD" or just plain "ABCD" +%% Note that in ASN.1 the parts is exactly 2 char +%% each, unless you don't use the native config +%% option. In text and in binary without the native +%% option, it is 63 + 1 chars for each. +is_PkgdName(N) -> + d("is_PkgdName -> entry with" + "~n N: ~p", [N]), + case string:tokens(N, "/") of + ["*" = PackageName, "*" = ItemID] -> + d("is_PkgdName -> tokenized (0): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + true; + [PackageName, "*" = ItemID] -> + d("is_PkgdName -> tokenized (1): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + is_Name(PackageName); + [PackageName, ItemID] -> + d("is_PkgdName -> tokenized (2): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + is_Name(PackageName) andalso is_Name(ItemID); + _ -> + is_Name(N) + end. + +chk_PkgdName(N, N) -> + case is_PkgdName(N) of + true -> + ok; + false -> + wrong_type('PkgdName', N, N) + end; +chk_PkgdName(N1, N2) -> + case (is_PkgdName(N1) andalso is_PkgdName(N2)) of + true -> + not_equal('PkgdName', N1, N2); + false -> + wrong_type('PkgdName', N1, N2) + end. + + +%% -- Relation -- + +is_Relation(R) -> + lists:member(R, [greaterThan, smallerThan, unequalTo]). + +chk_Relation(R, R) -> + chk_type(fun is_Relation/1, 'Relation', R); +chk_Relation(R1, R2) -> + case (is_Relation(R1) andalso is_Relation(R2)) of + true -> + not_equal('Relation', R1, R2); + false -> + wrong_type('Relation', R1, R2) + end. + + +%% -- LocalRemoteDescriptor -- + +is_opt_LocalRemoteDescriptor(D) -> + d("is_LocalRemoteDescriptor -> entry"), + is_OPTIONAL(fun is_LocalRemoteDescriptor/1, D). + +is_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = PGs}) -> + d("is_LocalRemoteDescriptor -> entry with" + "~n PGs: ~p", [PGs]), + is_LocalRemoteDescriptor_propGrps(PGs); +is_LocalRemoteDescriptor(_) -> + false. + +is_LocalRemoteDescriptor_propGrps([]) -> + true; +is_LocalRemoteDescriptor_propGrps([H|T]) -> + is_PropertyGroup(H) andalso is_LocalRemoteDescriptor_propGrps(T); +is_LocalRemoteDescriptor_propGrps(_) -> + false. + +chk_opt_LocalRemoteDescriptor(D1, D2) -> + chk_OPTIONAL('LocalRemoteDescriptor', D1, D2, + fun is_LocalRemoteDescriptor/1, + fun chk_LocalRemoteDescriptor/2). + +chk_LocalRemoteDescriptor(LRD, LRD) -> + chk_type(fun is_LocalRemoteDescriptor/1, 'LocalRemoteDescriptor', LRD); +chk_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = PG1}, + #'LocalRemoteDescriptor'{propGrps = PG2}) -> + chk_LocalRemoteDescriptor_propGrps(PG1, PG2), + ok; +chk_LocalRemoteDescriptor(LRD1, LRD2) -> + wrong_type('LocalRemoteDescriptor', LRD1, LRD2). + +chk_LocalRemoteDescriptor_propGrps([], []) -> + ok; +chk_LocalRemoteDescriptor_propGrps([] = PG1, PG2) -> + not_equal('LocalRemoteDescriptor_propGrps', PG1, PG2); +chk_LocalRemoteDescriptor_propGrps(PG1, [] = PG2) -> + not_equal('LocalRemoteDescriptor_propGrps', PG1, PG2); +chk_LocalRemoteDescriptor_propGrps([H|T1], [H|T2]) -> + case is_PropertyGroup(H) of + true -> + chk_LocalRemoteDescriptor_propGrps(T1, T2); + false -> + wrong_type('LocalRemoteDescriptor_propGrps_val', H) + end; +chk_LocalRemoteDescriptor_propGrps([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyGroup(H1, H2) end, + 'LocalRemoteDescriptor_propGrps_val'), + chk_LocalRemoteDescriptor_propGrps(T1, T2); +chk_LocalRemoteDescriptor_propGrps(PG1, PG2) -> + wrong_type('LocalRemoteDescriptor_propGrps', PG1, PG2). + + +%% -- PropertyGroup -- + +is_PropertyGroup([]) -> + true; +is_PropertyGroup([H|T]) -> + is_PropertyParm(H) andalso is_PropertyGroup(T); +is_PropertyGroup(_) -> + false. + +chk_PropertyGroup([], []) -> + ok; +chk_PropertyGroup([] = PG1, PG2) -> + not_equal('PropertyGroup', PG1, PG2); +chk_PropertyGroup(PG1, [] = PG2) -> + not_equal('PropertyGroup', PG1, PG2); +chk_PropertyGroup([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_PropertyGroup(T1, T2); + false -> + wrong_type('PropertyGroup_val', H) + end; +chk_PropertyGroup([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, 'PropertyGroup_val'), + chk_PropertyGroup(T1, T2); +chk_PropertyGroup(PG1, PG2) -> + wrong_type('PropertyGroup', PG1, PG2). + + +%% -- TerminationStateDescriptor -- + +is_opt_TerminationStateDescriptor(D) -> + is_OPTIONAL(fun is_TerminationStateDescriptor/1, D). + +is_TerminationStateDescriptor( + #'TerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS}) -> + is_TerminationStateDescriptor_propertyParms(PP) andalso + is_opt_EventBufferControl(EBC) andalso + is_opt_ServiceState(SS); +is_TerminationStateDescriptor(_) -> + false. + +is_TerminationStateDescriptor_propertyParms([]) -> + true; +is_TerminationStateDescriptor_propertyParms([H|T]) -> + is_PropertyParm(H) andalso is_TerminationStateDescriptor_propertyParms(T); +is_TerminationStateDescriptor_propertyParms(_) -> + false. + +chk_opt_TerminationStateDescriptor(D1, D2) -> + chk_OPTIONAL('TerminationStateDescriptor', D1, D2, + fun is_TerminationStateDescriptor/1, + fun chk_TerminationStateDescriptor/2). + +chk_TerminationStateDescriptor(D, D) -> + chk_type(fun is_TerminationStateDescriptor/1, + 'TerminationStateDescriptor', D); +chk_TerminationStateDescriptor( + #'TerminationStateDescriptor'{propertyParms = PP1, + eventBufferControl = EBC1, + serviceState = SS1}, + #'TerminationStateDescriptor'{propertyParms = PP2, + eventBufferControl = EBC2, + serviceState = SS2}) -> + chk_TerminationStateDescriptor_propertyParms(PP1, PP2), + validate( + fun() -> + chk_opt_EventBufferControl(EBC1, EBC2) + end, + 'TerminationStateDescriptor'), + validate( + fun() -> + chk_opt_ServiceState(SS1, SS2) + end, + 'TerminationStateDescriptor'), + ok; +chk_TerminationStateDescriptor(D1, D2) -> + wrong_type('TerminationStateDescriptor', D1, D2). + + +chk_TerminationStateDescriptor_propertyParms([], []) -> + ok; +chk_TerminationStateDescriptor_propertyParms([] = P1, P2) -> + not_equal('TerminationStateDescriptor_propertyParms', P1, P2); +chk_TerminationStateDescriptor_propertyParms(P1, [] = P2) -> + not_equal('TerminationStateDescriptor_propertyParms', P1, P2); +chk_TerminationStateDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_TerminationStateDescriptor_propertyParms(T1, T2); + false -> + wrong_type('TerminationStateDescriptor_propertyParms_val', H) + end; +chk_TerminationStateDescriptor_propertyParms([H1|_], [H2|_]) -> + case (is_PropertyParm(H1) andalso is_PropertyParm(H2)) of + true -> + not_equal('TerminationStateDescriptor_propertyParms_val', H1, H2); + false -> + wrong_type('TerminationStateDescriptor_propertyParms_val', H1, H2) + end; +chk_TerminationStateDescriptor_propertyParms(P1, P2) -> + wrong_type('TerminationStateDescriptor_propertyParms', P1, P2). + + +%% -- EventBufferControl -- + +is_opt_EventBufferControl(asn1_NOVALUE) -> + true; +is_opt_EventBufferControl(EBC) -> + is_EventBufferControl(EBC). + +is_EventBufferControl(EBC) -> + lists:member(EBC, [off, lockStep]). + +chk_opt_EventBufferControl(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_EventBufferControl(EBC1, EBC2) -> + chk_EventBufferControl(EBC1, EBC2). + +chk_EventBufferControl(EBC, EBC) -> + chk_type(fun is_EventBufferControl/1, 'EventBufferControl', EBC); +chk_EventBufferControl(EBC1, EBC2) -> + case (is_EventBufferControl(EBC1) andalso is_EventBufferControl(EBC2)) of + true -> + not_equal('EventBufferControl', EBC1, EBC2); + false -> + wrong_type('EventBufferControl', EBC1, EBC2) + end. + + +%% -- ServiceState -- + +is_opt_ServiceState(asn1_NOVALUE) -> + true; +is_opt_ServiceState(SS) -> + is_ServiceState(SS). + +is_ServiceState(SS) -> + lists:member(SS, [test, outOfSvc, inSvc]). + +chk_opt_ServiceState(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_ServiceState(SS1, SS2) -> + chk_ServiceState(SS1, SS2). + +chk_ServiceState(SS, SS) -> + chk_type(fun is_ServiceState/1, 'ServiceState', SS); +chk_ServiceState(SS1, SS2) -> + case (is_ServiceState(SS1) andalso is_ServiceState(SS2)) of + true -> + not_equal('ServiceState', SS1, SS2); + false -> + wrong_type('ServiceState', SS1, SS2) + end. + + +%% -- MuxDescriptor -- + +is_MuxDescriptor(#'MuxDescriptor'{muxType = MT, + termList = TL, + nonStandardData = NSD}) -> + is_MuxType(MT) andalso + is_MuxDescriptor_termList(TL) andalso + is_NonStandardData(NSD); +is_MuxDescriptor(_) -> + false. + +is_MuxDescriptor_termList([]) -> + true; +is_MuxDescriptor_termList([H|T]) -> + is_TerminationID(H) andalso is_MuxDescriptor_termList(T); +is_MuxDescriptor_termList(_) -> + false. + +chk_MuxDescriptor(D, D) -> + chk_type(fun is_MuxDescriptor/1, 'MuxDescriptor', D); +chk_MuxDescriptor(#'MuxDescriptor'{muxType = MT1, + termList = TL1, + nonStandardData = NSD1}, + #'MuxDescriptor'{muxType = MT2, + termList = TL2, + nonStandardData = NSD2}) -> + validate(fun() -> chk_MuxType(MT1, MT2) end, 'MuxDescriptor'), + chk_MuxDescriptor_termList(TL1, TL2), + validate(fun() -> chk_NonStandardData(NSD1, NSD2) end, 'MuxDescriptor'), + ok; +chk_MuxDescriptor(D1, D2) -> + wrong_type('MuxDescriptor', D1, D2). + +chk_MuxDescriptor_termList([], []) -> + ok; +chk_MuxDescriptor_termList([] = TL1, TL2) -> + not_equal('MuxDescriptor_termList', TL1, TL2); +chk_MuxDescriptor_termList(TL1, [] = TL2) -> + not_equal('MuxDescriptor_termList', TL1, TL2); +chk_MuxDescriptor_termList([H|T1], [H|T2]) -> + case is_TerminationID(H) of + true -> + chk_MuxDescriptor_termList(T1, T2); + false -> + wrong_type('MuxDescriptor_termList_val', H) + end; +chk_MuxDescriptor_termList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TerminationID(H1, H2) end, + 'MuxDescriptor_termList_val'), + chk_MuxDescriptor_termList(T1, T2); +chk_MuxDescriptor_termList(TL1, TL2) -> + wrong_type('MuxDescriptor_termList', TL1, TL2). + + +%% -- MuxType -- + +is_MuxType(MT) -> + lists:member(MT, [h221, h223, h226, v76, nx64k]). + +chk_MuxType(MT, MT) -> + chk_type(fun is_MuxType/1, 'MuxType', MT); +chk_MuxType(MT1, MT2) -> + case (is_MuxType(MT1) andalso is_MuxType(MT2)) of + true -> + not_equal('MuxType', MT1, MT2); + false -> + wrong_type('MuxType', MT1, MT2) + end. + + +%% -- StreamID -- + +is_opt_StreamID(V) -> + is_OPTIONAL(fun is_StreamID/1, V). + +is_StreamID(V) -> + d("is_StreamID -> entry with" + "~n V: ~p", [V]), + is_INTEGER(V, {range, 0, 65535}). + +chk_opt_StreamID(V1, V2) -> + chk_OPTIONAL('StreamID', V1, V2, fun is_StreamID/1, fun chk_StreamID/2). + +chk_StreamID(ID, ID) -> + chk_type(fun is_StreamID/1, 'StreamID', ID); +chk_StreamID(ID1, ID2) -> + case (is_StreamID(ID1) andalso is_StreamID(ID2)) of + true -> + not_equal('StreamID', ID1, ID2); + false -> + wrong_type('StreamID', ID1, ID2) + end. + + +%% -- EventsDescriptor -- + +is_EventsDescriptor(#'EventsDescriptor'{requestID = RID, + eventList = EVL}) -> + d("is_EventsDescriptor -> entry with" + "~n RID: ~p" + "~n EVL: ~p", [RID, EVL]), + is_opt_RequestID(RID) andalso is_EventsDescriptor_eventList(EVL); +is_EventsDescriptor(_) -> + false. + +is_EventsDescriptor_eventList([]) -> + true; +is_EventsDescriptor_eventList([H|T]) -> + is_RequestedEvent(H) andalso is_EventsDescriptor_eventList(T); +is_EventsDescriptor_eventList(_) -> + false. + +chk_EventsDescriptor(D, D) -> + chk_type(fun is_EventsDescriptor/1, 'EventsDescriptor', D); +chk_EventsDescriptor(#'EventsDescriptor'{requestID = RID1, + eventList = EVL1}, + #'EventsDescriptor'{requestID = RID2, + eventList = EVL2}) -> + validate(fun() -> chk_opt_RequestID(RID1, RID2) end, 'EventsDescriptor'), + chk_EventsDescriptor_eventList(EVL1, EVL2), + ok; +chk_EventsDescriptor(D1, D2) -> + wrong_type('EventsDescriptor', D1, D2). + +chk_EventsDescriptor_eventList([], []) -> + ok; +chk_EventsDescriptor_eventList([] = EVL1, EVL2) -> + not_equal('EventsDescriptor_eventList', EVL1, EVL2); +chk_EventsDescriptor_eventList(EVL1, [] = EVL2) -> + not_equal('EventsDescriptor_eventList', EVL1, EVL2); +chk_EventsDescriptor_eventList([H|T1], [H|T2]) -> + case is_RequestedEvent(H) of + true -> + chk_EventsDescriptor_eventList(T1, T2); + false -> + wrong_type('EventsDescriptor_eventList_val', H) + end; +chk_EventsDescriptor_eventList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_RequestedEvent(H1, H2) end, + 'EventsDescriptor_eventList_val'), + chk_EventsDescriptor_eventList(T1, T2); +chk_EventsDescriptor_eventList(EVL1, EVL2) -> + wrong_type('EventsDescriptor_eventList', EVL1, EVL2). + + +%% -- RequestedEvent -- + +is_RequestedEvent(#'RequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}) -> + d("is_RequestedEvent -> entry with" + "~n N: ~p" + "~n SID: ~p" + "~n EA: ~p" + "~n EPL: ~p", [N, SID, EA, EPL]), + is_PkgdName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_RequestedActions(EA) andalso + is_RequestedEvent_evParList(EPL); +is_RequestedEvent(_) -> + false. + +is_RequestedEvent_evParList([]) -> + true; +is_RequestedEvent_evParList([H|T]) -> + is_EventParameter(H) andalso is_RequestedEvent_evParList(T); +is_RequestedEvent_evParList(_) -> + false. + +chk_RequestedEvent(RE, RE) -> + chk_type(fun is_RequestedEvent/1, 'RequestedEvent', RE); +chk_RequestedEvent(#'RequestedEvent'{pkgdName = N1, + streamID = SID1, + eventAction = EA1, + evParList = EPL1}, + #'RequestedEvent'{pkgdName = N2, + streamID = SID2, + eventAction = EA2, + evParList = EPL2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'RequestedEvent'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'RequestedEvent'), + validate(fun() -> chk_opt_RequestedActions(EA1, EA2) end, + 'RequestedEvent'), + chk_RequestedEvent_evParList(EPL1, EPL2), + ok; +chk_RequestedEvent(RE1, RE2) -> + wrong_type('RequestedEvent', RE1, RE2). + +chk_RequestedEvent_evParList([], []) -> + ok; +chk_RequestedEvent_evParList([] = EPL1, EPL2) -> + not_equal('RequestedEvent_evParList', EPL1, EPL2); +chk_RequestedEvent_evParList(EPL1, [] = EPL2) -> + not_equal('RequestedEvent_evParList', EPL1, EPL2); +chk_RequestedEvent_evParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_RequestedEvent_evParList(T1, T2); + false -> + wrong_type('RequestedEvent_evParList_val', H) + end; +chk_RequestedEvent_evParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'RequestedEvent_evParList_val'), + chk_RequestedEvent_evParList(T1, T2); +chk_RequestedEvent_evParList(EPL1, EPL2) -> + wrong_type('RequestedEvent_evParList', EPL1, EPL2). + + +%% -- RegulatedEmbeddedDescriptor -- + +is_RegulatedEmbeddedDescriptor( + #'RegulatedEmbeddedDescriptor'{secondEvent = SE, + signalsDescriptor = SD}) -> + is_opt_SecondEventsDescriptor(SE) andalso + is_opt_SignalsDescriptor(SD); +is_RegulatedEmbeddedDescriptor(_) -> + false. + + +chk_RegulatedEmbeddedDescriptor( + #'RegulatedEmbeddedDescriptor'{secondEvent = SE1, + signalsDescriptor = SD1}, + #'RegulatedEmbeddedDescriptor'{secondEvent = SE2, + signalsDescriptor = SD2}) -> + chk_RegulatedEmbeddedDescriptor_secondEvent(SE1, SE2), + chk_RegulatedEmbeddedDescriptor_signalsDescriptor(SD1, SD2), + ok; +chk_RegulatedEmbeddedDescriptor(RED1, RED2) -> + wrong_type('RegulatedEmbeddedDescriptor', RED1, RED2). + +chk_RegulatedEmbeddedDescriptor_secondEvent(SE1, SE2) -> + validate(fun() -> chk_opt_SecondEventsDescriptor(SE1, SE2) end, + 'RegulatedEmbeddedDescriptor_secondEvent'). + +chk_RegulatedEmbeddedDescriptor_signalsDescriptor(SD1, SD2) -> + validate(fun() -> chk_opt_SignalsDescriptor(SD1, SD2) end, + 'RegulatedEmbeddedDescriptor_signalsDescriptor'). + + +%% -- NotifyBehaviour -- + +tags_NotifyBehaviour() -> + [ + {notifyImmediate, + fun is_NULL/1, + fun chk_NULL/2}, + + {notifyRegulated, + fun is_RegulatedEmbeddedDescriptor/1, + fun chk_RegulatedEmbeddedDescriptor/2}, + + {neverNotify, + fun is_NULL/1, + fun chk_NULL/2} + ]. + +is_opt_NotifyBehaviour(asn1_NOVALUE) -> + true; +is_opt_NotifyBehaviour(NB) -> + is_NotifyBehaviour(NB). + +is_NotifyBehaviour(NB) -> + is_CHOICE(NB, tags_NotifyBehaviour()). + +chk_opt_NotifyBehaviour(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_NotifyBehaviour(NB1, NB2) -> + chk_NotifyBehaviour(NB1, NB2). + +chk_NotifyBehaviour(NB1, NB2) -> + chk_CHOICE(NB1, NB2, 'NotifyBehaviour', tags_NotifyBehaviour()). + + +%% -- RequestedActions -- + +is_opt_RequestedActions(asn1_NOVALUE) -> + true; +is_opt_RequestedActions(RA) -> + is_RequestedActions(RA). + +is_RequestedActions(#'RequestedActions'{keepActive = KA, + eventDM = EDM, + secondEvent = SE, + signalsDescriptor = SD, + notifyBehaviour = NB, + resetEventsDescriptor = RED}) -> + d("is_RequestedActions -> entry with" + "~n KA: ~p" + "~n EDM: ~p" + "~n SE: ~p" + "~n SD: ~p" + "~n NB: ~p" + "~n RED: ~p", [KA, EDM, SE, SD, NB, RED]), + is_opt_BOOLEAN(KA) andalso + is_opt_EventDM(EDM) andalso + is_opt_SecondEventsDescriptor(SE) andalso + is_opt_SignalsDescriptor(SD) andalso + is_opt_NotifyBehaviour(SD) andalso + is_opt_NULL(SD); +is_RequestedActions(_) -> + false. + +chk_opt_RequestedActions(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_RequestedActions(RA1, RA2) -> + chk_RequestedActions(RA1, RA2). + +chk_RequestedActions(RA, RA) -> + chk_type(fun is_RequestedActions/1, 'RequestedActions', RA); +chk_RequestedActions(#'RequestedActions'{keepActive = KA1, + eventDM = EDM1, + secondEvent = SE1, + signalsDescriptor = SD1, + notifyBehaviour = NB1, + resetEventsDescriptor = RED1}, + #'RequestedActions'{keepActive = KA2, + eventDM = EDM2, + secondEvent = SE2, + signalsDescriptor = SD2, + notifyBehaviour = NB2, + resetEventsDescriptor = RED2}) -> + chk_RequestedActions_keepActive(KA1, KA2), + chk_RequestedActions_eventDM(EDM1, EDM2), + chk_RequestedActions_secondEvent(SE1, SE2), + chk_RequestedActions_signalsDescriptor(SD1, SD2), + chk_RequestedActions_notifyBehaviour(NB1, NB2), + chk_RequestedActions_resetEventsDescriptor(RED1, RED2), + ok; +chk_RequestedActions(RA1, RA2) -> + wrong_type('RequestedActions', RA1, RA2). + +chk_RequestedActions_keepActive(V1, V2) -> + validate(fun() -> chk_opt_BOOLEAN(V1, V2) end, + 'RequestedActions_keepActive'). + +chk_RequestedActions_eventDM(V1, V2) -> + validate(fun() -> chk_opt_EventDM(V1, V2) end, + 'RequestedActions_eventDM'). + +chk_RequestedActions_secondEvent(V1, V2) -> + validate(fun() -> chk_opt_SecondEventsDescriptor(V1, V2) end, + 'RequestedActions_secondEvent'). + +chk_RequestedActions_signalsDescriptor(V1, V2) -> + validate(fun() -> chk_opt_SignalsDescriptor(V1, V2) end, + 'RequestedActions_signalsDescriptor'). + +chk_RequestedActions_notifyBehaviour(V1, V2) -> + validate(fun() -> chk_opt_NotifyBehaviour(V1, V2) end, + 'RequestedActions_notifyBehaviour'). + +chk_RequestedActions_resetEventsDescriptor(V1, V2) -> + validate(fun() -> chk_opt_NULL(V1, V2) end, + 'RequestedActions_resetEventsDescriptor'). + + +%% -- EventDM -- + +is_opt_EventDM(EDM) -> + is_OPTIONAL(fun is_EventDM/1, EDM). + +is_EventDM({Tag, Val}) -> + is_EventDM_tag(Tag) andalso is_EventDM_val(Tag, Val); +is_EventDM(_) -> + false. + +is_EventDM_tag(Tag) -> + Tags = [digitMapName, digitMapValue], + lists:member(Tag, Tags). + +is_EventDM_val(digitMapName, Val) -> + is_DigitMapName(Val); +is_EventDM_val(digitMapValue, Val) -> + is_DigitMapValue(Val). + +chk_opt_EventDM(EDM1, EDM2) -> + chk_OPTIONAL('EventDM', EDM1, EDM2, fun is_EventDM/1, fun chk_EventDM/2). + +chk_EventDM(EDM, EDM) -> + chk_type(fun is_EventDM/1, 'EventDM', EDM); +chk_EventDM({Tag, Val1} = EDM1, {Tag, Val2} = EDM2) -> + case (is_EventDM_tag(Tag) andalso + is_EventDM_val(Tag, Val1) andalso + is_EventDM_val(Tag, Val2)) of + true -> + chk_EventDM_val(Tag, Val1, Val2); + false -> + wrong_type('EventDM', EDM1, EDM2) + end; +chk_EventDM({Tag1, Val1} = EDM1, {Tag2, Val2} = EDM2) -> + case ((is_EventDM_tag(Tag1) andalso + is_EventDM_val(Tag1, Val1)) andalso + (is_EventDM_tag(Tag2) andalso + is_EventDM_val(Tag2, Val2))) of + true -> + not_equal('EventDM', EDM1, EDM2); + false -> + wrong_type('EventDM', EDM1, EDM2) + end; +chk_EventDM(EDM1, EDM2) -> + wrong_type('EventDM', EDM1, EDM2). + +chk_EventDM_val(digitMapName, Val1, Val2) -> + validate(fun() -> chk_DigitMapName(Val1, Val2) end, 'EventDM'); +chk_EventDM_val(digitMapValue, Val1, Val2) -> + validate(fun() -> chk_DigitMapValue(Val1, Val2) end, 'EventDM'). + + +%% -- SecondEventsDescriptor -- + +is_opt_SecondEventsDescriptor(asn1_NOVALUE) -> + true; +is_opt_SecondEventsDescriptor(D) -> + is_SecondEventsDescriptor(D). + +is_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = RID, + eventList = EL}) -> + is_opt_RequestID(RID) andalso is_SecondEventsDescriptor_eventList(EL); +is_SecondEventsDescriptor(_) -> + false. + +is_SecondEventsDescriptor_eventList([]) -> + true; +is_SecondEventsDescriptor_eventList([H|T]) -> + is_SecondRequestedEvent(H) andalso is_SecondEventsDescriptor_eventList(T); +is_SecondEventsDescriptor_eventList(_) -> + false. + +chk_opt_SecondEventsDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SecondEventsDescriptor(D1, D2) -> + chk_SecondEventsDescriptor(D1, D2). + +chk_SecondEventsDescriptor(D, D) -> + chk_type(fun is_SecondEventsDescriptor/1, 'SecondEventsDescriptor', D); +chk_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = RID1, + eventList = EL1}, + #'SecondEventsDescriptor'{requestID = RID2, + eventList = EL2}) -> + validate(fun() -> chk_opt_RequestID(RID1, RID2) end, + 'SecondEventsDescriptor'), + chk_SecondEventsDescriptor_eventList(EL1, EL2), + ok; +chk_SecondEventsDescriptor(D1, D2) -> + wrong_type('SecondEventsDescriptor', D1, D2). + +chk_SecondEventsDescriptor_eventList([], []) -> + ok; +chk_SecondEventsDescriptor_eventList([] = EL1, EL2) -> + not_equal('SecondEventsDescriptor_eventList', EL1, EL2); +chk_SecondEventsDescriptor_eventList(EL1, [] = EL2) -> + not_equal('SecondEventsDescriptor_eventList', EL1, EL2); +chk_SecondEventsDescriptor_eventList([H|T1], [H|T2]) -> + case is_SecondRequestedEvent(H) of + true -> + chk_SecondEventsDescriptor_eventList(T1, T2); + false -> + wrong_type('SecondEventsDescriptor_eventList_val', H) + end; +chk_SecondEventsDescriptor_eventList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_SecondRequestedEvent(H1, H2) end, + 'SecondEventsDescriptor_eventList_val'), + chk_SecondEventsDescriptor_eventList(T1, T2); +chk_SecondEventsDescriptor_eventList(L1, L2) -> + wrong_type('SecondEventsDescriptor_eventList_val', L1, L2). + + +%% -- SecondRequestedEvent -- + +is_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}) -> + is_PkgdName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_SecondRequestedActions(EA) andalso + is_SecondRequestedEvent_evParList(EPL); +is_SecondRequestedEvent(_) -> + false. + +is_SecondRequestedEvent_evParList([]) -> + true; +is_SecondRequestedEvent_evParList([H|T]) -> + is_EventParameter(H) andalso is_SecondRequestedEvent_evParList(T); +is_SecondRequestedEvent_evParList(_) -> + false. + +chk_SecondRequestedEvent(RE, RE) -> + chk_type(fun is_SecondRequestedEvent/1, 'SecondRequestedEvent', RE); +chk_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N1, + streamID = SID1, + eventAction = EA1, + evParList = EPL1}, + #'SecondRequestedEvent'{pkgdName = N2, + streamID = SID2, + eventAction = EA2, + evParList = EPL2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'SecondRequestedEvent'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, + 'SecondRequestedEvent'), + validate(fun() -> chk_opt_SecondRequestedActions(EA1, EA2) end, + 'SecondRequestedEvent'), + chk_SecondRequestedEvent_evParList(EPL1, EPL2), + ok; +chk_SecondRequestedEvent(RE1, RE2) -> + wrong_type('SecondRequestedEvent', RE1, RE2). + +chk_SecondRequestedEvent_evParList([], []) -> + ok; +chk_SecondRequestedEvent_evParList([] = EPL1, EPL2) -> + not_equal('SecondRequestedEvent_evParList', EPL1, EPL2); +chk_SecondRequestedEvent_evParList(EPL1, [] = EPL2) -> + not_equal('SecondRequestedEvent_evParList', EPL1, EPL2); +chk_SecondRequestedEvent_evParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_SecondRequestedEvent_evParList(T1, T2); + false -> + wrong_type('SecondRequestedEvent_evParList_val', H) + end; +chk_SecondRequestedEvent_evParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'SecondRequestedEvent_evParList_val'), + chk_SecondRequestedEvent_evParList(T1, T2); +chk_SecondRequestedEvent_evParList(EPL1, EPL2) -> + wrong_type('SecondRequestedEvent_evParList', EPL1, EPL2). + + +%% -- SecondRequestedActions -- + +is_opt_SecondRequestedActions(asn1_NOVALUE) -> + true; +is_opt_SecondRequestedActions(SRA) -> + is_SecondRequestedActions(SRA). + +is_SecondRequestedActions( + #'SecondRequestedActions'{keepActive = KA, + eventDM = EDM, + signalsDescriptor = SD, + notifyBehaviour = NB, + resetEventsDescriptor = RED}) -> + is_opt_BOOLEAN(KA) andalso + is_opt_EventDM(EDM) andalso + is_opt_SignalsDescriptor(SD) andalso + is_opt_NotifyBehaviour(NB) andalso + is_opt_NULL(RED); +is_SecondRequestedActions(_) -> + false. + +chk_opt_SecondRequestedActions(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SecondRequestedActions(SRA1, SRA2) -> + chk_SecondRequestedActions(SRA1, SRA2). + +chk_SecondRequestedActions(SRA, SRA) -> + chk_type(fun is_SecondRequestedActions/1, 'SecondRequestedActions', SRA); +chk_SecondRequestedActions( + #'SecondRequestedActions'{keepActive = KA1, + eventDM = EDM1, + signalsDescriptor = SD1, + notifyBehaviour = NB1, + resetEventsDescriptor = RED1}, + #'SecondRequestedActions'{keepActive = KA2, + eventDM = EDM2, + signalsDescriptor = SD2, + notifyBehaviour = NB2, + resetEventsDescriptor = RED2}) -> + chk_SecondRequestedActions_keepActive(KA1, KA2), + chk_SecondRequestedActions_eventDM(EDM1, EDM2), + chk_SecondRequestedActions_signalsDescriptor(SD1, SD2), + chk_SecondRequestedActions_notifyBehaviour(NB1, NB2), + chk_SecondRequestedActions_resetEventsDescriptor(RED1, RED2), + ok; +chk_SecondRequestedActions(SRA1, SRA2) -> + wrong_type('SecondRequestedActions', SRA1, SRA2). + +chk_SecondRequestedActions_keepActive(V1, V2) -> + validate(fun() -> chk_opt_BOOLEAN(V1, V2) end, + 'SecondRequestedActions_keepActive'). + +chk_SecondRequestedActions_eventDM(V1, V2) -> + validate(fun() -> chk_opt_EventDM(V1, V2) end, + 'SecondRequestedActions_eventDM'). + +chk_SecondRequestedActions_signalsDescriptor(V1, V2) -> + validate(fun() -> chk_opt_SignalsDescriptor(V1, V2) end, + 'SecondRequestedActions_signalsDescriptor'). + +chk_SecondRequestedActions_notifyBehaviour(V1, V2) -> + validate(fun() -> chk_opt_NotifyBehaviour(V1, V2) end, + 'SecondRequestedActions_notifyBehaviour'). + +chk_SecondRequestedActions_resetEventsDescriptor(V1, V2) -> + validate(fun() -> chk_opt_NULL(V1, V2) end, + 'SecondRequestedActions_resetEventsDescriptor'). + + +%% -- EventBufferDescriptor -- + +is_EventBufferDescriptor(D) -> + is_SEQUENCE_OF(D, fun is_EventSpec/1). + +chk_EventBufferDescriptor(D1, D2) -> + chk_SEQUENCE_OF(D1, D2, 'EventBufferDescriptor', + fun is_EventSpec/1, fun chk_EventSpec/2). + + +%% -- EventSpec -- + +is_EventSpec(#'EventSpec'{eventName = N, + streamID = SID, + eventParList = EPL}) -> + is_EventName(N) andalso + is_opt_StreamID(SID) andalso + is_EventSpec_eventParList(EPL); +is_EventSpec(_) -> + false. + +is_EventSpec_eventParList([]) -> + true; +is_EventSpec_eventParList([H|T]) -> + is_EventParameter(H) andalso is_EventSpec_eventParList(T); +is_EventSpec_eventParList(_) -> + false. + +chk_EventSpec(ES, ES) -> + chk_type(fun is_EventSpec/1, 'EventSpec', ES); +chk_EventSpec(#'EventSpec'{eventName = N1, + streamID = SID1, + eventParList = EPL1}, + #'EventSpec'{eventName = N2, + streamID = SID2, + eventParList = EPL2}) -> + validate(fun() -> chk_EventName(N1, N2) end, 'EventSpec'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'EventSpec'), + chk_EventSpec_eventParList(EPL1, EPL2), + ok; +chk_EventSpec(ES1, ES2) -> + wrong_type('EventSpec', ES1, ES2). + +chk_EventSpec_eventParList([], []) -> + ok; +chk_EventSpec_eventParList([] = EPL1, EPL2) -> + not_equal('EventSpec_eventParList', EPL1, EPL2); +chk_EventSpec_eventParList(EPL1, [] = EPL2) -> + not_equal('EventSpec_eventParList', EPL1, EPL2); +chk_EventSpec_eventParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_EventSpec_eventParList(T1, T2); + false -> + wrong_type('EventSpec_eventParList_val', H) + end; +chk_EventSpec_eventParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'EventSpec_eventParList_val'), + chk_EventSpec_eventParList(T1, T2); +chk_EventSpec_eventParList(EPL1, EPL2) -> + wrong_type('EventSpec_eventParList', EPL1, EPL2). + + +%% -- SignalsDescriptor -- + +is_opt_SignalsDescriptor(asn1_NOVALUE) -> + true; +is_opt_SignalsDescriptor(D) -> + is_SignalsDescriptor(D). + +is_SignalsDescriptor(D) -> + is_SEQUENCE_OF(D, fun is_SignalRequest/1). + +chk_opt_SignalsDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SignalsDescriptor(D1, D2) -> + chk_SignalsDescriptor(D1, D2). + +chk_SignalsDescriptor(D1, D2) -> + chk_SEQUENCE_OF(D1, D2, 'SignalsDescriptor', + fun is_SignalRequest/1, fun chk_SignalRequest/2). + + +%% -- SignalRequest -- + +tags_SignalRequest() -> + [ + {signal, fun is_Signal/1, fun chk_Signal/2}, + {seqSigList, fun is_SeqSigList/1, fun chk_SeqSigList/2} + ]. + +is_SignalRequest(SR) -> + is_CHOICE(SR, tags_SignalRequest()). + +chk_SignalRequest(R1, R2) -> + chk_CHOICE(R1, R2, 'SignalRequest', tags_SignalRequest()). + + +%% -- SeqSigList -- + +%% fields_SeqSigList() -> +%% [ +%% {id, +%% 'INTEGER(0,65535)', +%% fun(ID) -> is_INTEGER(ID, {range, 0, 65535}) end, +%% fun(ID1, ID2) -> chk_INTEGER(ID1, ID2, {range, 0, 65535}) end}, + +%% {signalList, +%% 'SEQUENCE OF Signal', +%% fun(S) -> +%% is_SEQUENCE_OF(S, fun is_Signal/1) +%% end, +%% fun(S1, S2) -> +%% chk_SEQUENCE_OF(S1, S2, fun is_Signal/1, fun chk_Signal/2) +%% end} +%% ]. + +%% is_SeqSigList(V) -> +%% is_SEQUENCE(V, 'SeqSigList', fields_SeqSigList()). + + +is_SeqSigList(#'SeqSigList'{id = ID, + signalList = SL}) -> + is_INTEGER(ID, {range, 0, 65535}) andalso + is_SeqSigList_signalList(SL); +is_SeqSigList(_) -> + false. + +is_SeqSigList_signalList([]) -> + true; +is_SeqSigList_signalList([H|T]) -> + is_Signal(H) andalso is_SeqSigList_signalList(T); +is_SeqSigList_signalList(_) -> + false. + +chk_SeqSigList(L, L) -> + chk_type(fun is_SeqSigList/1, 'SeqSigList', L); +chk_SeqSigList(#'SeqSigList'{id = ID1, + signalList = SL1}, + #'SeqSigList'{id = ID2, + signalList = SL2}) -> + validate(fun() -> chk_INTEGER(ID1, ID2, {range, 0, 65535}) end, + 'SeqSigList'), + chk_SeqSigList_signalList(SL1, SL2), + ok; +chk_SeqSigList(L1, L2) -> + wrong_type('SeqSigList', L1, L2). + +chk_SeqSigList_signalList([], []) -> + ok; +chk_SeqSigList_signalList([] = L1, L2) -> + not_equal('SeqSigList_signalList', L1, L2); +chk_SeqSigList_signalList(L1, [] = L2) -> + not_equal('SeqSigList_signalList', L1, L2); +chk_SeqSigList_signalList([H|T1], [H|T2]) -> + case is_Signal(H) of + true -> + chk_SeqSigList_signalList(T1, T2); + false -> + wrong_type('SeqSigList_signalList_val', H) + end; +chk_SeqSigList_signalList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_Signal(H1, H2) end, + 'SeqSigList_signalList_val'), + chk_SeqSigList_signalList(T1, T2); +chk_SeqSigList_signalList(L1, L2) -> + wrong_type('SeqSigList_signalList', L1, L2). + + +%% -- Signal -- + +is_Signal(#'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL, + direction = Dir, + requestID = RID, + intersigDelay = ISD}) -> + d("is_Signal -> entry with" + "~n N: ~p" + "~n SID: ~p" + "~n ST: ~p" + "~n Dur: ~p" + "~n NC: ~p" + "~n KA: ~p" + "~n SPL: ~p" + "~n Dir: ~p" + "~n RID: ~p" + "~n ISD: ~p", [N, SID, ST, Dur, NC, KA, SPL, Dir, RID, ISD]), + is_SignalName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_SignalType(ST) andalso + is_opt_INTEGER(Dur, {range, 0, 65535}) andalso + is_opt_NotifyCompletion(NC) andalso + is_opt_BOOLEAN(KA) andalso + is_Signal_sigParList(SPL) andalso + is_opt_SignalDirection(Dir) andalso + is_opt_RequestID(RID) andalso + is_opt_INTEGER(ISD, {range, 0, 65535}). + +is_Signal_sigParList([]) -> + true; +is_Signal_sigParList([H|T]) -> + is_SigParameter(H) andalso is_Signal_sigParList(T); +is_Signal_sigParList(_) -> + false. + +chk_Signal(S, S) -> + chk_type(fun is_Signal/1, 'Signal', S); +chk_Signal(#'Signal'{signalName = N1, + streamID = SID1, + sigType = ST1, + duration = Dur1, + notifyCompletion = NC1, + keepActive = KA1, + sigParList = SPL1, + direction = Dir1, + requestID = RID1, + intersigDelay = ISD1}, + #'Signal'{signalName = N2, + streamID = SID2, + sigType = ST2, + duration = Dur2, + notifyCompletion = NC2, + keepActive = KA2, + sigParList = SPL2, + direction = Dir2, + requestID = RID2, + intersigDelay = ISD2}) -> + chk_Signal_signalName(N1, N2), + chk_Signal_streamID(SID1, SID2), + chk_Signal_sigType(ST1, ST2), + chk_Signal_duration(Dur1, Dur2), + chk_Signal_notifyCompletion(NC1, NC2), + chk_Signal_keepActive(KA1, KA2), + chk_Signal_sigParList(SPL1, SPL2), + chk_Signal_direction(Dir1, Dir2), + chk_Signal_requestID(RID1, RID2), + chk_Signal_intersigDelay(ISD1, ISD2), + ok; +chk_Signal(S1, S2) -> + wrong_type('Signal', S1, S2). + +chk_Signal_signalName(N1, N2) -> + validate(fun() -> chk_SignalName(N1, N2) end, 'Signal_signalName'). + +chk_Signal_streamID(V1, V2) -> + validate(fun() -> chk_opt_StreamID(V1, V2) end, 'Signal_streamID'). + +chk_Signal_sigType(V1, V2) -> + validate(fun() -> chk_opt_SignalType(V1, V2) end, 'Signal_sigType'). + +chk_Signal_duration(V1, V2) -> + validate(fun() -> + chk_opt_INTEGER(V1, V2, {range, 0, 65535}) + end, + 'Signal_duration'). + +chk_Signal_notifyCompletion(V1, V2) -> + validate(fun() -> chk_opt_NotifyCompletion(V1, V2) end, + 'Signal_notifyCompletion'). + +chk_Signal_keepActive(false, asn1_NOVALUE) -> + ok; +chk_Signal_keepActive(asn1_NOVALUE, false) -> + ok; +chk_Signal_keepActive(V1, V2) -> + validate(fun() -> chk_opt_BOOLEAN(V1, V2) end, 'Signal_keepActive'). + +chk_Signal_sigParList([], []) -> + ok; +chk_Signal_sigParList([] = L1, L2) -> + not_equal('Signal_sigParList', L1, L2); +chk_Signal_sigParList(L1, [] = L2) -> + not_equal('Signal_sigParList', L1, L2); +chk_Signal_sigParList([H|T1], [H|T2]) -> + case is_SigParameter(H) of + true -> + chk_Signal_sigParList(T1, T2); + false -> + wrong_type('Signal_sigParList_val', H) + end; +chk_Signal_sigParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_SigParameter(H1, H2) end, + 'Signal_sigParList_val'), + chk_Signal_sigParList(T1, T2); +chk_Signal_sigParList(L1, L2) -> + wrong_type('Signal_sigParList', L1, L2). + +chk_Signal_direction(V1, V2) -> + validate(fun() -> chk_opt_SignalDirection(V1, V2) end, 'Signal_direction'). + +chk_Signal_requestID(V1, V2) -> + validate(fun() -> chk_opt_RequestID(V1, V2) end, 'Signal_requestID'). + +chk_Signal_intersigDelay(V1, V2) -> + validate(fun() -> chk_opt_INTEGER(V1, V2, {range, 0, 65535}) end, + 'Signal_intersigDelay'). + + +%% -- SignalType -- + +is_opt_SignalType(T) -> + is_OPTIONAL(fun is_SignalType/1, T). + +is_SignalType(T) -> + d("is_SignalType -> entry with" + "~n T: ~p", [T]), + Types = [brief, onOff, timeOut], + lists:member(T, Types). + +chk_opt_SignalType(T1, T2) -> + chk_OPTIONAL('SignalType', T1, T2, + fun is_SignalType/1, fun chk_SignalType/2). + +chk_SignalType(T, T) -> + chk_type(fun is_SignalType/1, 'SignalType', T); +chk_SignalType(T1, T2) -> + case (is_SignalType(T1) andalso is_SignalType(T2)) of + true -> + not_equal('SignalType', T1, T2); + false -> + wrong_type('SignalType', T1, T2) + end. + + +%% -- SignalDirection -- + +is_opt_SignalDirection(T) -> + is_OPTIONAL(fun is_SignalDirection/1, T). + +is_SignalDirection(Dir) -> + d("is_SignalDirection -> entry with" + "~n Dir: ~p", [Dir]), + Dirs = [internal, external, both], + lists:member(Dir, Dirs). + +chk_opt_SignalDirection(T1, T2) -> + chk_OPTIONAL('SignalDirection', T1, T2, + fun is_SignalDirection/1, fun chk_SignalDirection/2). + +chk_SignalDirection(Dir, Dir) -> + chk_type(fun is_SignalDirection/1, 'SignalDirection', Dir); +chk_SignalDirection(Dir1, Dir2) -> + case (is_SignalDirection(Dir1) andalso is_SignalDirection(Dir2)) of + true -> + not_equal('SignalDirection', Dir1, Dir2); + false -> + wrong_type('SignalDirection', Dir1, Dir2) + end. + + +%% -- SignalName -- + +is_SignalName(N) -> + d("is_SignalName -> entry with" + "~n N: ~p", [N]), + is_PkgdName(N). + +chk_SignalName(N1, N2) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'SignalName'). + + +%% -- NotifyCompletion -- + +is_opt_NotifyCompletion(NC) -> + is_OPTIONAL(fun is_NotifyCompletion/1, NC). + +is_NotifyCompletion(NC) -> + d("is_NotifyCompletion -> entry with" + "~n NC: ~p", [NC]), + Valids = [onTimeOut, + onInterruptByEvent, + onInterruptByNewSignalDescr, + otherReason], + lists:all(fun(X) -> lists:member(X, Valids) end, NC). + +chk_opt_NotifyCompletion(NC1, NC2) -> + chk_OPTIONAL('NotifyCompletion', NC1, NC2, + fun is_NotifyCompletion/1, + fun chk_NotifyCompletion/2). + +chk_NotifyCompletion(NC, NC) -> + chk_type(fun is_NotifyCompletion/1, 'NotifyCompletion', NC); +chk_NotifyCompletion(NC1, NC2) -> + case (is_NotifyCompletion(NC1) andalso is_NotifyCompletion(NC2)) of + true -> + not_equal('NotifyCompletion', NC1, NC2); + false -> + wrong_type('NotifyCompletion', NC1, NC2) + end. + + +%% -- SigParameter -- + +is_SigParameter(#'SigParameter'{sigParameterName = N, + value = V, + extraInfo = I}) -> + d("is_SigParameter -> entry with" + "~n N: ~p" + "~n V: ~p" + "~n I: ~p", [N, V, I]), + is_Name(N) andalso + is_Value(V) andalso + is_SigParameter_extraInfo(I); +is_SigParameter(_) -> + false. + +is_SigParameter_extraInfo(asn1_NOVALUE) -> + true; +is_SigParameter_extraInfo({Tag, Val}) -> + is_SigParameter_extraInfo_tag(Tag) andalso + is_SigParameter_extraInfo_val(Tag, Val); +is_SigParameter_extraInfo(_) -> + false. + +is_SigParameter_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_SigParameter_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_SigParameter_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_SigParameter_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + +chk_SigParameter(P, P) -> + chk_type(fun is_SigParameter/1, 'SigParameter', P); +chk_SigParameter(#'SigParameter'{sigParameterName = N1, + value = V1, + extraInfo = I1}, + #'SigParameter'{sigParameterName = N2, + value = V2, + extraInfo = I2}) -> + validate(fun() -> chk_Name(N1, N2) end, 'SigParameter'), + validate(fun() -> chk_Value(V1, V2) end, 'SigParameter'), + chk_SigParameter_extraInfo(I1, I2), + ok; +chk_SigParameter(P1, P2) -> + wrong_type('SigParameter', P1, P2). + +chk_SigParameter_extraInfo(EI, EI) -> + chk_type(fun is_SigParameter_extraInfo/1, 'SigParameter_extraInfo', EI); +chk_SigParameter_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> + case (is_SigParameter_extraInfo_tag(Tag) and + is_SigParameter_extraInfo_val(Tag, Val1) and + is_SigParameter_extraInfo_val(Tag, Val2)) of + true -> + chk_SigParameter_extraInfo_val(Tag, Val1, Val2); + false -> + wrong_type('SigParameter_extraInfo', EI1, EI2) + end; +chk_SigParameter_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> + case ((is_SigParameter_extraInfo_tag(Tag1) and + is_SigParameter_extraInfo_val(Tag1, Val1)) and + (is_SigParameter_extraInfo_tag(Tag2) and + is_SigParameter_extraInfo_val(Tag2, Val2))) of + true -> + not_equal('SigParameter_extraInfo', EI1, EI2); + false -> + wrong_type('SigParameter_extraInfo', EI1, EI2) + end; +chk_SigParameter_extraInfo(EI1, EI2) -> + wrong_type('SigParameter_extraInfo', EI1, EI2). + +chk_SigParameter_extraInfo_val(relation, Val1, Val2) -> + validate(fun() -> chk_Relation(Val1, Val2) end, 'SigParameter_extraInfo'); +chk_SigParameter_extraInfo_val(range, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'SigParameter_extraInfo'); +chk_SigParameter_extraInfo_val(sublist, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'SigParameter_extraInfo'). + + +%% -- RequestID -- + +is_opt_RequestID(asn1_NOVALUE) -> + true; +is_opt_RequestID(V) -> + is_RequestID(V). + +is_RequestID(V) -> is_INTEGER(V, {range, 0, 4294967295}). + +chk_opt_RequestID(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_RequestID(V1, V2) -> + chk_RequestID(V1, V2). + +chk_RequestID(ID, ID) -> + chk_type(fun is_RequestID/1, 'RequestID', ID); +chk_RequestID(ID1, ID2) -> + case (is_RequestID(ID1) andalso is_RequestID(ID2)) of + true -> + not_equal('RequestID', ID1, ID2); + false -> + wrong_type('RequestID', ID1, ID2) + end. + + +%% -- ModemDescriptor -- + +is_ModemDescriptor(D) when is_record(D, 'ModemDescriptor') -> + true; +is_ModemDescriptor(_) -> + false. + +chk_ModemDescriptor(D, D) when is_record(D, 'ModemDescriptor') -> + ok; +chk_ModemDescriptor(#'ModemDescriptor'{mtl = MTL1, + mpl = MPL1, + nonStandardData = NSD1}, + #'ModemDescriptor'{mtl = MTL2, + mpl = MPL2, + nonStandardData = NSD2}) -> + chk_ModemDescriptor_mtl(MTL1, MTL2), + chk_ModemDescriptor_mpl(MPL1, MPL2), + chk_opt_NonStandardData(NSD1, NSD2), + ok; +chk_ModemDescriptor(D1, D2) -> + wrong_type('ModemDescriptor', D1, D2). + +chk_ModemDescriptor_mtl([], []) -> + ok; +chk_ModemDescriptor_mtl([] = MTL1, MTL2) -> + not_equal('ModemDescriptor_mtl', MTL1, MTL2); +chk_ModemDescriptor_mtl(MTL1, [] = MTL2) -> + not_equal('ModemDescriptor_mtl', MTL1, MTL2); +chk_ModemDescriptor_mtl([H|T1], [H|T2]) -> + case is_ModemType(H) of + true -> + chk_ModemDescriptor_mtl(T1, T2); + false -> + wrong_type('ModemDescriptor_mtl_val', H) + end; +chk_ModemDescriptor_mtl([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ModemType(H1, H2) end, 'ModemDescriptor_mtl_val'), + chk_ModemDescriptor_mtl(T1, T2); +chk_ModemDescriptor_mtl(MTL1, MTL2) -> + wrong_type('ModemDescriptor_mtl', MTL1, MTL2). + + +chk_ModemDescriptor_mpl([], []) -> + ok; +chk_ModemDescriptor_mpl([] = MPL1, MPL2) -> + not_equal('ModemDescriptor_mpl', MPL1, MPL2); +chk_ModemDescriptor_mpl(MPL1, [] = MPL2) -> + not_equal('ModemDescriptor_mpl', MPL1, MPL2); +chk_ModemDescriptor_mpl([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_ModemDescriptor_mpl(T1, T2); + false -> + wrong_type('ModemDescriptor_mpl_val', H) + end; +chk_ModemDescriptor_mpl([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, 'ModemDescriptor_mpl_val'), + chk_ModemDescriptor_mpl(T1, T2); +chk_ModemDescriptor_mpl(MPL1, MPL2) -> + wrong_type('ModemDescriptor_mpl', MPL1, MPL2). + + +%% -- ModemType -- + +chk_ModemType(MT, MT) -> + case is_ModemType(MT) of + true -> + ok; + false -> + wrong_type('ModemType', MT, MT) + end; +chk_ModemType(MT1, MT2) -> + case (is_ModemType(MT1) andalso is_ModemType(MT2)) of + true -> + not_equal('ModemType', MT1, MT2); + false -> + wrong_type('ModemType', MT1, MT2) + end. + +is_ModemType(MT) -> + lists:member(MT, + [v18, v22, v22bis, v32, v32bis, v34, v90, v91, synchISDN]). + + +%% -- DigitMapDescriptor -- + +is_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Val}) -> + is_opt_DigitMapName(Name) andalso is_opt_DigitMapValue(Val); +is_DigitMapDescriptor(_) -> + false. + +chk_DigitMapDescriptor(D, D) -> + chk_type(fun is_DigitMapDescriptor/1, 'DigitMapDescriptor', D); +chk_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name1, + digitMapValue = Val1}, + #'DigitMapDescriptor'{digitMapName = Name2, + digitMapValue = Val2}) -> + d("chk_DigitMapDescriptor -> entry with" + "~n Name1: ~p" + "~n Name2: ~p" + "~n Val1: ~p" + "~n Val2: ~p", [Name1, Name2, Val1, Val2]), + validate(fun() -> chk_opt_DigitMapName(Name1, Name2) end, + 'DigitMapDescriptor'), + validate(fun() -> chk_opt_DigitMapValue(Val1, Val2) end, + 'DigitMapDescriptor'), + ok; +chk_DigitMapDescriptor(D1, D2) -> + wrong_type('DigitMapDescriptor', D1, D2). + + +%% -- DigitMapName -- + +is_opt_DigitMapName(asn1_NOVALUE) -> + true; +is_opt_DigitMapName(N) -> + is_DigitMapName(N). + +is_DigitMapName(N) -> is_Name(N). + +chk_opt_DigitMapName(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_DigitMapName(N1, N2) -> + chk_DigitMapName(N1, N2). + +chk_DigitMapName(N, N) -> + chk_type(fun is_DigitMapName/1, 'DigitMapName', N); +chk_DigitMapName(N1, N2) -> + case (is_DigitMapName(N1) andalso is_DigitMapName(N2)) of + true -> + not_equal('DigitMapName', N1, N2); + false -> + wrong_type('DigitMapName', N1, N2) + end. + + +%% -- DigitMapValue -- + +is_opt_DigitMapValue(V) -> + is_OPTIONAL(fun is_DigitMapValue/1, V). + +is_DigitMapValue(#'DigitMapValue'{startTimer = Start, + shortTimer = Short, + longTimer = Long, + digitMapBody = Body, + durationTimer = Dur}) -> + is_DigitMapValue_startTimer(Start) andalso + is_DigitMapValue_shortTimer(Short) andalso + is_DigitMapValue_longTimer(Long) andalso + is_IA5String(Body) andalso + is_DigitMapValue_durationTimer(Dur); +is_DigitMapValue(_) -> + false. + +is_DigitMapValue_startTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_startTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +is_DigitMapValue_shortTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_shortTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +is_DigitMapValue_longTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_longTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +is_DigitMapValue_durationTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_durationTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +chk_opt_DigitMapValue(V1, V2) -> + chk_OPTIONAL('DigitMapValue', V1, V2, + fun is_DigitMapValue/1, fun chk_DigitMapValue/2). + +chk_DigitMapValue(#'DigitMapValue'{startTimer = Start1, + shortTimer = Short1, + longTimer = Long1, + digitMapBody = Body1, + durationTimer = Dur1}, + #'DigitMapValue'{startTimer = Start2, + shortTimer = Short2, + longTimer = Long2, + digitMapBody = Body2, + durationTimer = Dur2}) -> + d("chk_DigitMapValue -> entry with" + "~n Start1: ~p" + "~n Start2: ~p" + "~n Short1: ~p" + "~n Short2: ~p" + "~n Long1: ~p" + "~n Long2: ~p" + "~n Body1: ~p" + "~n Body2: ~p" + "~n Dur1: ~p" + "~n Dur2: ~p", [Start1, Start2, + Short1, Short2, + Long1, Long2, + Body1, Body2, + Dur1, Dur2]), + chk_DigitMapValue_startTimer(Start1, Start2), + chk_DigitMapValue_shortTimer(Short1, Short2), + chk_DigitMapValue_longTimer(Long1, Long2), + chk_DigitMapValue_digitMapBody(Body1, Body2), + chk_DigitMapValue_durationTimer(Dur1, Dur2), + ok; +chk_DigitMapValue(V1, V2) -> + wrong_type('DigitMapValue', V1, V2). + +chk_DigitMapValue_startTimer(T, T) -> + chk_type(fun is_DigitMapValue_startTimer/1, 'DigitMapValue_startTimer', T); +chk_DigitMapValue_startTimer(T1, T2) -> + case (is_DigitMapValue_startTimer(T1) andalso + is_DigitMapValue_startTimer(T2)) of + true -> + not_equal('DigitMapValue_startTimer', T1, T2); + false -> + wrong_type('DigitMapValue_startTimer', T1, T2) + end. + +chk_DigitMapValue_shortTimer(T, T) -> + chk_type(fun is_DigitMapValue_shortTimer/1, 'DigitMapValue_shortTimer', T); +chk_DigitMapValue_shortTimer(T1, T2) -> + case (is_DigitMapValue_shortTimer(T1) andalso + is_DigitMapValue_shortTimer(T2)) of + true -> + not_equal('DigitMapValue_shortTimer', T1, T2); + false -> + wrong_type('DigitMapValue_shortTimer', T1, T2) + end. + +chk_DigitMapValue_longTimer(T, T) -> + chk_type(fun is_DigitMapValue_longTimer/1, 'DigitMapValue_longTimer', T); +chk_DigitMapValue_longTimer(T1, T2) -> + case (is_DigitMapValue_longTimer(T1) andalso + is_DigitMapValue_longTimer(T2)) of + true -> + not_equal('DigitMapValue_longTimer', T1, T2); + false -> + wrong_type('DigitMapValue_longTimer', T1, T2) + end. + +chk_DigitMapValue_durationTimer(T, T) -> + chk_type(fun is_DigitMapValue_durationTimer/1, + 'DigitMapValue_durationTimer', T); +chk_DigitMapValue_durationTimer(T1, T2) -> + case (is_DigitMapValue_durationTimer(T1) andalso + is_DigitMapValue_durationTimer(T2)) of + true -> + not_equal('DigitMapValue_durationTimer', T1, T2); + false -> + wrong_type('DigitMapValue_durationTimer', T1, T2) + end. + +chk_DigitMapValue_digitMapBody(B, B) -> + d("chk_DigitMapValue_digitMapBody -> entry with" + "~n B: ~p", [B]), + chk_type(fun is_IA5String/1, 'DigitMapValue_digitMapBody', B); +chk_DigitMapValue_digitMapBody(B1, B2) -> + d("chk_DigitMapValue_digitMapBody -> entry with" + "~n B1: ~p" + "~n B2: ~p", [B1, B2]), + case (is_IA5String(B1) andalso is_IA5String(B2)) of + true -> + %% If they are different it could be because + %% of trailing tab's and newline's. + case compare_strings(B1, B2) of + {[], []} -> + ok; + {Str1, []} -> + case strip_tab_and_newline(Str1) of + [] -> + ok; + _ -> + not_equal('DigitMapValue_digitMapBody', B1, B2) + end; + {[], Str2} -> + case strip_tab_and_newline(Str2) of + [] -> + ok; + _ -> + not_equal('DigitMapValue_digitMapBody', B1, B2) + end; + _ -> + not_equal('DigitMapValue_digitMapBody', B1, B2) + end; + false -> + wrong_type('DigitMapValue_digitMapBody', B1, B2) + end. + +%% -- ServiceChangeParm -- + +is_ServiceChangeParm(#'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeAddress = A, + serviceChangeVersion = V, + serviceChangeProfile = P, + serviceChangeReason = R, + serviceChangeDelay = D, + serviceChangeMgcId = Id, + timeStamp = TS, + nonStandardData = NSD, + serviceChangeInfo = I}) -> + is_ServiceChangeMethod(M) andalso + is_opt_ServiceChangeAddress(A) andalso + is_opt_INTEGER(V, {range, 0, 99}) andalso + is_opt_ServiceChangeProfile(P) andalso + is_Value(R) andalso + is_opt_INTEGER(D, {range, 0, 4294967295}) andalso + is_opt_MId(Id) andalso + is_opt_TimeNotation(TS) andalso + is_opt_NonStandardData(NSD) andalso + is_opt_AuditDescriptor(I); +is_ServiceChangeParm(_) -> + false. + +chk_ServiceChangeParm(P, P) -> + chk_type(fun is_ServiceChangeParm/1, 'ServiceChangeParm', P); +chk_ServiceChangeParm(#'ServiceChangeParm'{serviceChangeMethod = M1, + serviceChangeAddress = A1, + serviceChangeVersion = V1, + serviceChangeProfile = P1, + serviceChangeReason = R1, + serviceChangeDelay = D1, + serviceChangeMgcId = Id1, + timeStamp = TS1, + nonStandardData = NSD1, + serviceChangeInfo = I1}, + #'ServiceChangeParm'{serviceChangeMethod = M2, + serviceChangeAddress = A2, + serviceChangeVersion = V2, + serviceChangeProfile = P2, + serviceChangeReason = R2, + serviceChangeDelay = D2, + serviceChangeMgcId = Id2, + timeStamp = TS2, + nonStandardData = NSD2, + serviceChangeInfo = I2}) -> + validate(fun() -> chk_ServiceChangeMethod(M1, M2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_ServiceChangeAddress(A1, A2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_INTEGER(V1, V2, {range, 0, 99}) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_ServiceChangeProfile(P1, P2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_Value(R1, R2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_INTEGER(D1, D2, {range, 0, 4294967295}) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_MId(Id1, Id2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_TimeNotation(TS1, TS2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_NonStandardData(NSD1, NSD2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_AuditDescriptor(I1, I2) end, + 'ServiceChangeParm'), + ok; +chk_ServiceChangeParm(P1, P2) -> + wrong_type('ServiceChangeParm', P1, P2). + + +%% -- ServiceChangeAddress -- + +is_opt_ServiceChangeAddress(A) -> + is_OPTIONAL(fun is_ServiceChangeAddress/1, A). + +is_ServiceChangeAddress({Tag, Val}) -> + is_ServiceChangeAddress_tag(Tag) andalso + is_ServiceChangeAddress_val(Tag, Val); +is_ServiceChangeAddress(_) -> + false. + +is_ServiceChangeAddress_tag(Tag) -> + Tags = [portNumber, ip4Address, ip6Address, domainName, deviceName, + mtpAddress], + lists:member(Tag, Tags). + +is_ServiceChangeAddress_val(portNumber, Val) -> + is_INTEGER(Val, {range, 0, 65535}); +is_ServiceChangeAddress_val(ip4Address, Val) -> + is_IP4Address(Val); +is_ServiceChangeAddress_val(ip6Address, Val) -> + is_IP6Address(Val); +is_ServiceChangeAddress_val(domainName, Val) -> + is_DomainName(Val); +is_ServiceChangeAddress_val(deviceName, Val) -> + is_PathName(Val); +is_ServiceChangeAddress_val(mtpAddress, Val) -> + is_OCTET_STRING(Val, {range, 2, 4}). + + +chk_opt_ServiceChangeAddress(A1, A2) -> + chk_OPTIONAL('ServiceChangeAddress', A1, A2, + fun is_ServiceChangeAddress/1, + fun chk_ServiceChangeAddress/2). + +chk_ServiceChangeAddress(A, A) -> + chk_type(fun is_ServiceChangeAddress/1, 'ServiceChangeAddress', A); +chk_ServiceChangeAddress({Tag, Val1} = A1, {Tag, Val2} = A2) -> + case (is_ServiceChangeAddress_tag(Tag) andalso + is_ServiceChangeAddress_val(Tag, Val1) andalso + is_ServiceChangeAddress_val(Tag, Val2)) of + true -> + chk_ServiceChangeAddress_val(Tag, Val1, Val2); + false -> + wrong_type('ServiceChangeAddress', A1, A2) + end; +chk_ServiceChangeAddress({Tag1, Val1} = A1, {Tag2, Val2} = A2) -> + case ((is_ServiceChangeAddress_tag(Tag1) andalso + is_ServiceChangeAddress_val(Tag1, Val1)) andalso + (is_ServiceChangeAddress_tag(Tag2) andalso + is_ServiceChangeAddress_val(Tag2, Val2))) of + true -> + not_equal('ServiceChangeAddress', A1, A2); + false -> + wrong_type('ServiceChangeAddress', A1, A2) + end; +chk_ServiceChangeAddress(A1, A2) -> + wrong_type('ServiceChangeAddress', A1, A2). + +chk_ServiceChangeAddress_val(portNumber, Val1, Val2) -> + validate(fun() -> chk_INTEGER(Val1, Val2, {range, 0, 99}) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(ip4Address, Val1, Val2) -> + validate(fun() -> chk_IP4Address(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(ip6Address, Val1, Val2) -> + validate(fun() -> chk_IP6Address(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(domainName, Val1, Val2) -> + validate(fun() -> chk_DomainName(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(deviceName, Val1, Val2) -> + validate(fun() -> chk_PathName(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(mtpAddress, Val1, Val2) -> + validate(fun() -> chk_OCTET_STRING(Val1, Val2, {range, 2, 4}) end, + 'ServiceChangeAddress'). + + +%% -- ServiceChangeResParm -- + +is_ServiceChangeResParm(#'ServiceChangeResParm'{serviceChangeMgcId = Id, + serviceChangeAddress = A, + serviceChangeVersion = V, + serviceChangeProfile = P, + timeStamp = TS}) -> + is_opt_MId(Id) andalso + is_opt_ServiceChangeAddress(A) andalso + is_opt_INTEGER(V, {range, 0, 99}) andalso + is_opt_ServiceChangeProfile(P) andalso + is_opt_TimeNotation(TS); +is_ServiceChangeResParm(_) -> + false. + +chk_ServiceChangeResParm(P, P) -> + chk_type(fun is_ServiceChangeResParm/1, 'ServiceChangeResParm', P); +chk_ServiceChangeResParm( + #'ServiceChangeResParm'{serviceChangeMgcId = Id1, + serviceChangeAddress = A1, + serviceChangeVersion = V1, + serviceChangeProfile = P1, + timeStamp = TS1}, + #'ServiceChangeResParm'{serviceChangeMgcId = Id2, + serviceChangeAddress = A2, + serviceChangeVersion = V2, + serviceChangeProfile = P2, + timeStamp = TS2}) -> + validate(fun() -> chk_opt_MId(Id1, Id2) end, 'ServiceChangeResParm'), + validate(fun() -> chk_opt_ServiceChangeAddress(A1, A2) end, + 'ServiceChangeResParm'), + validate(fun() -> chk_opt_INTEGER(V1, V2, {range, 0, 99}) end, + 'ServiceChangeResParm'), + validate(fun() -> chk_opt_ServiceChangeProfile(P1, P2) end, + 'ServiceChangeResParm'), + validate(fun() -> chk_opt_TimeNotation(TS1, TS2) end, + 'ServiceChangeResParm'), + ok; +chk_ServiceChangeResParm(P1, P2) -> + wrong_type('ServiceChangeResParm', P1, P2). + + +%% -- ServiceChangeMethod -- + +is_ServiceChangeMethod(M) -> + Methods = [failover, forced, graceful, restart, disconnected, handOff], + lists:member(M, Methods). + +chk_ServiceChangeMethod(M, M) -> + chk_type(fun is_ServiceChangeMethod/1, 'ServiceChangeMethod', M); +chk_ServiceChangeMethod(M1, M2) -> + case (is_ServiceChangeMethod(M1) andalso is_ServiceChangeMethod(M2)) of + true -> + not_equal('ServiceChangeMethod', M1, M2); + false -> + wrong_type('ServiceChangeMethod', M1, M2) + end. + + +%% -- ServiceChangeProfile -- + +is_opt_ServiceChangeProfile(P) -> + is_OPTIONAL(fun is_ServiceChangeProfile/1, P). + +is_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = N}) -> + is_IA5String(N, {range, 1, 67}); +is_ServiceChangeProfile(_) -> + false. + +chk_opt_ServiceChangeProfile(P1, P2) -> + chk_OPTIONAL('ServiceChangeProfile', P1, P2, + fun is_ServiceChangeProfile/1, + fun chk_ServiceChangeProfile/2). + +chk_ServiceChangeProfile(P, P) -> + chk_type(fun is_ServiceChangeProfile/1, 'ServiceChangeProfile', P); +chk_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = N1}, + #'ServiceChangeProfile'{profileName = N2}) -> + validate(fun() -> chk_IA5String(N1, N2, {range, 1, 67}) end, + 'ServiceChangeProfile'), + ok; +chk_ServiceChangeProfile(P1, P2) -> + wrong_type('ServiceChangeProfile', P1, P2). + + +%% -- PackagesDescriptor -- + +is_PackagesDescriptor([]) -> + true; +is_PackagesDescriptor([H|T]) -> + is_PackagesItem(H) andalso is_PackagesDescriptor(T); +is_PackagesDescriptor(_) -> + false. + +chk_PackagesDescriptor([], []) -> + ok; +chk_PackagesDescriptor([] = D1, D2) -> + not_equal('PackagesDescriptor', D1, D2); +chk_PackagesDescriptor(D1, [] = D2) -> + not_equal('PackagesDescriptor', D1, D2); +chk_PackagesDescriptor([H|T1], [H|T2]) -> + case is_PackagesItem(H) of + true -> + chk_PackagesDescriptor(T1, T2); + false -> + wrong_type('PackagesDescriptor_val', H) + end; +chk_PackagesDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PackagesItem(H1, H2) end, + 'PackagesDescriptor_val'), + chk_PackagesDescriptor(T1, T2); +chk_PackagesDescriptor(D1, D2) -> + wrong_type('PackagesDescriptor_val', D1, D2). + + +%% -- PackagesItem -- + +is_PackagesItem(#'PackagesItem'{packageName = N, + packageVersion = V}) -> + is_Name(N) andalso is_INTEGER(V, {range, 0, 99}); +is_PackagesItem(_) -> + false. + +chk_PackagesItem(I, I) -> + chk_type(fun is_PackagesItem/1, 'PackagesItem', I); +chk_PackagesItem(#'PackagesItem'{packageName = N1, + packageVersion = V1}, + #'PackagesItem'{packageName = N2, + packageVersion = V2}) -> + validate(fun() -> chk_Name(N1, N2) end, 'PackagesItem'), + validate(fun() -> chk_INTEGER(V1, V2, {range, 0, 99}) end, 'PackagesItem'), + ok; +chk_PackagesItem(I1, I2) -> + wrong_type('PackagesItem', I1, I2). + + +%% -- StatisticsDescriptor -- + +is_opt_StatisticsDescriptor(D) -> + is_OPTIONAL(fun is_StatisticsDescriptor/1, D). + +is_StatisticsDescriptor([]) -> + true; +is_StatisticsDescriptor([H|T]) -> + is_StatisticsParameter(H) andalso is_StatisticsDescriptor(T); +is_StatisticsDescriptor(_) -> + false. + +chk_opt_StatisticsDescriptor(D1, D2) -> + chk_OPTIONAL('StatisticsDescriptor', D1, D2, + fun is_StatisticsDescriptor/1, + fun chk_StatisticsDescriptor/2). + +chk_StatisticsDescriptor([], []) -> + ok; +chk_StatisticsDescriptor([] = D1, D2) -> + not_equal('StatisticsDescriptor', D1, D2); +chk_StatisticsDescriptor(D1, [] = D2) -> + not_equal('StatisticsDescriptor', D1, D2); +chk_StatisticsDescriptor([H|T1], [H|T2]) -> + case is_StatisticsParameter(H) of + true -> + chk_StatisticsDescriptor(T1, T2); + false -> + wrong_type('StatisticsDescriptor_val', H) + end; +chk_StatisticsDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_StatisticsParameter(H1, H2) end, + 'StatisticsDescriptor_val'), + chk_StatisticsDescriptor(T1, T2); +chk_StatisticsDescriptor(D1, D2) -> + wrong_type('StatisticsDescriptor_val', D1, D2). + + +%% -- StatisticsParameter -- + +is_StatisticsParameter(#'StatisticsParameter'{statName = N, + statValue = V}) -> + is_PkgdName(N) andalso is_opt_Value(V); +is_StatisticsParameter(_) -> + false. + +chk_StatisticsParameter(P, P) -> + chk_type(fun is_StatisticsParameter/1, 'StatisticsParameter', P); +chk_StatisticsParameter(#'StatisticsParameter'{statName = N1, + statValue = V1}, + #'StatisticsParameter'{statName = N2, + statValue = V2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'StatisticsParameter'), + validate(fun() -> chk_opt_Value(V1, V2) end, 'StatisticsParameter'), + ok; +chk_StatisticsParameter(P1, P2) -> + wrong_type('StatisticsParameter', P1, P2). + + +%% -- NonStandardData -- + +is_opt_NonStandardData(asn1_NOVALUE) -> + true; +is_opt_NonStandardData(NSD) -> + is_NonStandardData(NSD). + +%% is_NonStandardData(#'NonStandardData'{nonStandardIdentifier = Id, +%% data = D}) -> +%% is_NonStandardIdentifier(Id) andalso is_OCTET_STRING(D); +%% is_NonStandardData(_) -> +%% false. + +is_NonStandardData(_) -> + true. + +chk_opt_NonStandardData(asn1_NOVALUE, asn1_NOVALUE) -> + true; +chk_opt_NonStandardData(NSD1, NSD2) -> + chk_NonStandardData(NSD1, NSD2). + +chk_NonStandardData(NSD, NSD) -> + chk_type(fun is_NonStandardData/1, 'NonStandardData', NSD); +%% chk_NonStandardData(#'NonStandardData'{nonStandardIdentifier = Id1, +%% data = D1}, +%% #'NonStandardData'{nonStandardIdentifier = Id2, +%% data = D2}) -> +%% validate(fun() -> chk_NonStandardIdentifier(Id1, Id2) end, +%% 'NonStandardData'), +%% validate(fun() -> chk_OCTET_STRING(D1, D2) end, 'NonStandardData'), +%% ok; +%% chk_NonStandardData(NSD1, NSD2) -> +%% wrong_type('NonStandardData', NSD1, NSD2). +chk_NonStandardData(NSD1, NSD2) -> + not_equal('NonStandardData', NSD1, NSD2). + + +%% -- NonStandardIdentifier -- + +%% is_NonStandardIdentifier({Tag, Val}) -> +%% is_NonStandardIdentifier_tag(Tag) andalso +%% is_NonStandardIdentifier_val(Tag, Val); +%% is_NonStandardIdentifier(_) -> +%% false. + +%% is_NonStandardIdentifier_tag(Tag) -> +%% Tags = [object, h221NonStandard, experimental], +%% lists:member(Tag, Tags). + +%% is_NonStandardIdentifier_val(object, Val) -> +%% is_OBJECT_IDENTIFIER(Val); +%% is_NonStandardIdentifier_val(h221NonStandard, Val) -> +%% is_H221NonStandard(Val); +%% is_NonStandardIdentifier_val(experimental, Val) -> +%% is_IA5String(Val, {exact, 8}). + +%% chk_NonStandardIdentifier(Id, Id) -> +%% chk_type(fun is_NonStandardIdentifier/1, 'NonStandardIdentifier', Id); +%% chk_NonStandardIdentifier({Tag, Val1} = Id1, {Tag, Val2} = Id2) -> +%% case (is_NonStandardIdentifier_tag(Tag) andalso +%% is_NonStandardIdentifier_val(Tag, Val1) andalso +%% is_NonStandardIdentifier_val(Tag, Val1)) of +%% true -> +%% chk_NonStandardIdentifier_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('NonStandardIdentifier', Id1, Id2) +%% end; +%% chk_NonStandardIdentifier({Tag1, Val1} = Id1, {Tag2, Val2} = Id2) -> +%% case ((is_NonStandardIdentifier_tag(Tag1) andalso +%% is_NonStandardIdentifier_val(Tag1, Val1)) andalso +%% (is_NonStandardIdentifier_tag(Tag2) andalso +%% is_NonStandardIdentifier_val(Tag2, Val1))) of +%% true -> +%% not_equal('NonStandardIdentifier', Id1, Id2); +%% false -> +%% wrong_type('NonStandardIdentifier', Id1, Id2) +%% end; +%% chk_NonStandardIdentifier(Id1, Id2) -> +%% wrong_type('NonStandardIdentifier', Id1, Id2). + +%% chk_NonStandardIdentifier_val(object, Val1, Val2) -> +%% chk_OBJECT_IDENTIFIER(Val1, Val2); +%% chk_NonStandardIdentifier_val(h221NonStandard, Val1, Val2) -> +%% chk_H221NonStandard(Val1, Val2); +%% chk_NonStandardIdentifier_val(experimental, Val1, Val2) -> +%% chk_IA5String(Val1, Val2, {exact, 8}). + + +%% -- H221NonStandard -- + +%% is_H221NonStandard(#'H221NonStandard'{t35CountryCode1 = CC1, +%% t35CountryCode2 = CC2, +%% t35Extension = Ext, +%% manufacturerCode = MC}) -> +%% is_INTEGER(CC1, {range, 0, 255}) andalso +%% is_INTEGER(CC2, {range, 0, 255}) andalso +%% is_INTEGER(Ext, {range, 0, 255}) andalso +%% is_INTEGER(Ext, {range, 0, 65535}); +%% is_H221NonStandard(_) -> +%% false. + +%% chk_H221NonStandard(NS, NS) -> +%% chk_type(fun is_H221NonStandard/1, 'H221NonStandard', NS); +%% chk_H221NonStandard(#'H221NonStandard'{t35CountryCode1 = CC11, +%% t35CountryCode2 = CC21, +%% t35Extension = Ext1, +%% manufacturerCode = MC1}, +%% #'H221NonStandard'{t35CountryCode1 = CC12, +%% t35CountryCode2 = CC22, +%% t35Extension = Ext2, +%% manufacturerCode = MC2}) -> +%% validate(fun() -> chk_INTEGER(CC11, CC12, {range, 0, 255}) end, +%% 'H221NonStandard'), +%% validate(fun() -> chk_INTEGER(CC21, CC22, {range, 0, 255}) end, +%% 'H221NonStandard'), +%% validate(fun() -> chk_INTEGER(Ext1, Ext2, {range, 0, 255}) end, +%% 'H221NonStandard'), +%% validate(fun() -> chk_INTEGER(MC1, MC2, {range, 0, 65535}) end, +%% 'H221NonStandard'), +%% ok; +%% chk_H221NonStandard(NS1, NS2) -> +%% wrong_type('H221NonStandard', NS1, NS2). + + +%% -- TimeNotation -- + +is_opt_TimeNotation(asn1_NOVALUE) -> + true; +is_opt_TimeNotation(TN) -> + is_TimeNotation(TN). + +is_TimeNotation(#'TimeNotation'{date = D, time = T}) -> + is_IA5String(D, {exact, 8}) andalso is_IA5String(T, {exact, 8}); +is_TimeNotation(_) -> + false. + +chk_opt_TimeNotation(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_TimeNotation(TN1, TN2) -> + chk_TimeNotation(TN1, TN2). + +chk_TimeNotation(TN, TN) -> + chk_type(fun is_TimeNotation/1, 'TimeNotation', TN); +chk_TimeNotation(#'TimeNotation'{date = D1, time = T1}, + #'TimeNotation'{date = D2, time = T2}) -> + validate(fun() -> chk_IA5String(D1, D2, {exact, 8}) end, 'TimeNotation'), + validate(fun() -> chk_IA5String(T1, T2, {exact, 8}) end, 'TimeNotation'), + ok; +chk_TimeNotation(TN1, TN2) -> + wrong_type('TimeNotation', TN1, TN2). + + +%% -- Value -- + +is_opt_Value(V) -> + is_OPTIONAL(fun is_Value/1, V). + +is_Value([]) -> + true; +is_Value([H|T]) -> + is_OCTET_STRING(H) andalso is_Value(T); +is_Value(_) -> + false. + +chk_opt_Value(V1, V2) -> + chk_OPTIONAL('Value', V1, V2, fun is_Value/1, fun chk_Value/2). + +chk_Value(V, V) -> + case is_Value(V) of + true -> + ok; + false -> + wrong_type('Value', V, V) + end; +chk_Value(V1, V2) -> + case (is_Value(V1) andalso is_Value(V2)) of + true -> + not_equal('Value', V1, V2); + false -> + wrong_type('Value', V1, V2) + end. + + +%% ---------------------------------------------------------------------- +%% Basic type check functions +%% ---------------------------------------------------------------------- + + +is_opt_BOOLEAN(B) -> + is_OPTIONAL(fun is_BOOLEAN/1, B). + +is_BOOLEAN(B) -> + d("is_BOOLEAN -> entry with" + "~n B: ~p", [B]), + lists:member(B, [true, false]). + +chk_opt_BOOLEAN(B1, B2) -> + chk_OPTIONAL('BOOLEAN', B1, B2, fun is_BOOLEAN/1, fun chk_BOOLEAN/2). + +chk_BOOLEAN(B, B) -> + chk_type(fun is_BOOLEAN/1, 'BOOLEAN', B); +chk_BOOLEAN(B1, B2) -> + case (is_BOOLEAN(B1) andalso is_BOOLEAN(B2)) of + true -> + not_equal('BOOLEAN', B1, B2); + false -> + wrong_type('BOOLEAN', B1, B2) + end. + + +is_IA5String(S) when is_list(S) -> + true; +is_IA5String(_) -> + false. + +% chk_IA5String(S, S) -> +% chk_type(fun is_IA5String/1, 'IA5String', S); +% chk_IA5String(S1, S2) -> +% case (is_IA5String(S1) andalso is_IA5String(S2)) of +% true -> +% not_equal('IA5String', S1, S2); +% false -> +% wrong_type('IA5String', S1, S2) +% end. + +is_IA5String(S, _) when is_list(S) -> + true; +is_IA5String(_, _) -> + false. + +chk_IA5String(S, S, R) -> + chk_type(fun is_IA5String/2, 'IA5String', S, R); +chk_IA5String(S1, S2, R) -> + case (is_IA5String(S1, R) andalso is_IA5String(S2, R)) of + true -> + not_equal('IA5String', S1, S2); + false -> + wrong_type('IA5String', S1, S2) + end. + + +is_OCTET_STRING(L) -> is_OCTET_STRING(L, any). + +is_OCTET_STRING(L, any) when is_list(L) -> + true; +is_OCTET_STRING(L, {exact, Len}) when is_list(L) andalso (length(L) =:= Len) -> + true; +is_OCTET_STRING(L, {atleast, Len}) when is_list(L) andalso (Len =< length(L)) -> + true; +is_OCTET_STRING(L, {atmost, Len}) when is_list(L) andalso (length(L) =< Len) -> + true; +is_OCTET_STRING(L, {range, Min, Max}) + when is_list(L) andalso (Min =< length(L)) andalso (length(L) =< Max) -> + true; +is_OCTET_STRING(_, _) -> + false. + +%% chk_OCTET_STRING(L1, L2) -> +%% chk_OCTET_STRING(L1, L2, any). + +chk_OCTET_STRING(L, L, R) -> + chk_type(fun is_OCTET_STRING/2, 'OCTET STRING', L, R); +chk_OCTET_STRING(L1, L2, R) -> + case (is_OCTET_STRING(L1, R) andalso is_OCTET_STRING(L2, R)) of + true -> + not_equal('OCTET STRING', L1, L2); + false -> + wrong_type('OCTET STRING', L1, L2) + end. + + +%% is_OBJECT_IDENTIFIER(_) -> +%% true. + +%% chk_OBJECT_IDENTIFIER(X, X) -> +%% ok; +%% chk_OBJECT_IDENTIFIER(X1, X2) -> +%% not_equal('OBJECT IDENTIFIER', X1, X2). + + +is_opt_NULL(N) -> + is_OPTIONAL(fun is_NULL/1, N). + +is_NULL('NULL') -> + true; +is_NULL(_) -> + false. + +chk_opt_NULL(N1, N2) -> + chk_OPTIONAL('NULL', N1, N2, fun is_NULL/1, fun chk_NULL/2). + +chk_NULL(N, N) -> + chk_type(fun is_NULL/1, 'NULL', N); +chk_NULL(N1, N2) -> + case (is_NULL(N1) andalso is_NULL(N2)) of + true -> + not_equal('NULL', N1, N2); + false -> + wrong_type('NULL', N1, N2) + end. + + +is_opt_INTEGER(I, R) -> + d("is_opt_INTEGER -> entry with" + "~n I: ~p" + "~n R: ~p", [I, R]), + is_OPTIONAL(fun(X) -> is_INTEGER(X, R) end, I). + +is_INTEGER(I, any) when is_integer(I) -> + true; +is_INTEGER(I, {exact, I}) when is_integer(I) -> + true; +is_INTEGER(I, {atleast, Min}) + when is_integer(I) andalso is_integer(Min) andalso (Min =< I) -> + true; +is_INTEGER(I, {atmost, Max}) + when is_integer(I) andalso is_integer(Max) andalso (I =< Max) -> + true; +is_INTEGER(I, {range, Min, Max}) + when is_integer(I) andalso + is_integer(Min) andalso + is_integer(Max) andalso + (Min =< I) andalso + (I =< Max) -> + true; +is_INTEGER(_, _) -> + false. + +chk_opt_INTEGER(I1, I2, R) -> + chk_OPTIONAL('INTEGER', I1, I2, + fun(X) -> is_INTEGER(X, R) end, + fun(Y1, Y2) -> chk_INTEGER(Y1, Y2, R) end). + +chk_INTEGER(I, I, R) -> + chk_type(fun is_INTEGER/2, 'INTEGER', I, R); +chk_INTEGER(I1, I2, R) -> + case (is_INTEGER(I1, R) andalso is_INTEGER(I2, R)) of + true -> + not_equal('INTEGER', I1, I2); + false -> + wrong_type('INTEGER', I1, I2) + end. + + +%% ---------------------------------------------------------------------- +%% Various utility functions +%% ---------------------------------------------------------------------- + + +to_lower([C|Cs]) when (C >= $A) andalso (C =< $Z) -> + [C+($a-$A)|to_lower(Cs)]; +to_lower([C|Cs]) -> + [C|to_lower(Cs)]; +to_lower([]) -> + []. + + +validate(F, Type) when is_function(F) -> + case (catch F()) of + {error, Reason} -> + error({Type, Reason}); + ok -> + ok + end. + + +chk_type(F, T, V) when is_function(F) andalso is_atom(T) -> + case F(V) of + true -> + ok; + false -> + wrong_type(T, V) + end. + +chk_type(F, T, V1, V2) when is_function(F) andalso is_atom(T) -> + case F(V1, V2) of + true -> + ok; + false -> + wrong_type(T, V1) + end. + + +is_OPTIONAL(_, asn1_NOVALUE) -> + true; +is_OPTIONAL(F, Val) when is_function(F) -> + F(Val). + +chk_OPTIONAL(_, asn1_NOVALUE, asn1_NOVALUE, _, _) -> + ok; +chk_OPTIONAL(Type, asn1_NOVALUE = V1, V2, IS, _CHK) when is_function(IS) -> + case IS(V2) of + true -> + not_equal(Type, V1, V2); + false -> + wrong_type(Type, V1, V2) + end; +chk_OPTIONAL(Type, V1, asn1_NOVALUE = V2, IS, _CHK) when is_function(IS) -> + case IS(V1) of + true -> + not_equal(Type, V1, V2); + false -> + wrong_type(Type, V1, V2) + end; +chk_OPTIONAL(_Type, V1, V2, _IS, CHK) when is_function(CHK) -> + CHK(V1, V2). + + +%% -- CHOICE -- + +is_CHOICE({Tag, Val}, Tags) when is_list(Tags) -> + d("is_CHOICE -> entry with" + "~n Tag: ~p" + "~n Val: ~p", [Tag, Val]), + is_CHOICE_tag(Tag, Tags) andalso + is_CHOICE_val(Tag, Val, Tags); +is_CHOICE(_, _) -> + false. + +is_CHOICE_tag(Tag, Tags) -> + lists:keymember(Tag, 1, Tags). + +is_CHOICE_val(Tag, Val, Tags) -> + {value, {_, IsVal, _}} = lists:keysearch(Tag, 1, Tags), + IsVal(Val). + + +chk_CHOICE(V1, V2, Type, Tags) when is_atom(Type) and is_list(Tags) -> + IsTag = fun(Tag) -> is_CHOICE_tag(Tag, Tags) end, + IsVal = fun(Tag, Val) -> is_CHOICE_val(Tag, Val, Tags) end, + ChkVal = fun(Tag, Val1, Val2) -> + chk_CHOICE_val(Tag, Val1, Val2, Tags) + end, + chk_CHOICE(V1, V2, Type, IsTag, IsVal, ChkVal). + +chk_CHOICE_val(Tag, Val1, Val2, Tags) -> + {value, {_, _, ChkVal}} = lists:keysearch(Tag, 1, Tags), + ChkVal(Val1, Val2). + +chk_CHOICE({Tag, Val1} = V1, {Tag, Val2} = V2, Type, IsTag, IsVal, ChkVal) -> + case (IsTag(Tag) andalso + IsVal(Tag, Val1) andalso IsVal(Tag, Val2)) of + true -> + ChkVal(Tag, Val1, Val2); + false -> + wrong_type(Type, V1, V2) + end; +chk_CHOICE({Tag1, Val1} = V1, {Tag2, Val2} = V2, Type, + IsTag, IsVal, _ChkVal) -> + case ((IsTag(Tag1) andalso IsVal(Tag1, Val1)) andalso + (IsTag(Tag2) andalso IsVal(Tag2, Val2))) of + true -> + not_equal(Type, V1, V2); + false -> + wrong_type(Type, V1, V2) + end; +chk_CHOICE(V1, V2, Type, _, _, _) -> + wrong_type(Type, V1, V2). + + +%% -- SEQUENCE OF -- + +is_SEQUENCE_OF([], _) -> + true; +is_SEQUENCE_OF([H|T], IS) when is_function(IS) -> + IS(H) andalso is_SEQUENCE_OF(T, IS); +is_SEQUENCE_OF(_, _) -> + false. + +chk_SEQUENCE_OF([], [], _, _, _) -> + ok; +chk_SEQUENCE_OF([] = V1, V2, Type, _, _) -> + not_equal(Type, V1, V2); +chk_SEQUENCE_OF(V1, [] = V2, Type, _, _) -> + not_equal(Type, V1, V2); +chk_SEQUENCE_OF([H|T1], [H|T2], Type, IS, CHK) -> + case IS(H) of + true -> + chk_SEQUENCE_OF(T1, T2, Type, IS, CHK); + false -> + Type2 = list_to_atom(atom_to_list(Type) ++ "_val"), + wrong_type(Type2, H) + end; +chk_SEQUENCE_OF([H1|T1], [H2|T2], Type, IS, CHK) -> + Type2 = list_to_atom(atom_to_list(Type) ++ "_val"), + validate(fun() -> CHK(H1, H2) end, Type2), + chk_SEQUENCE_OF(T1, T2, Type, IS, CHK); +chk_SEQUENCE_OF(V1, V2, Type, _, _) -> + wrong_type(Type, V1, V2). + + +%% ---------------------------------------------------------------------- + +compare_strings([] = L1, L2) -> + {L1, L2}; +compare_strings(L1, [] = L2) -> + {L1, L2}; +compare_strings([H|T1], [H|T2]) -> + compare_strings(T1, T2); +compare_strings(L1, L2) -> + {L1, L2}. + +strip_tab_and_newline([]) -> + []; +strip_tab_and_newline([$\n|T]) -> + strip_tab_and_newline(T); +strip_tab_and_newline([$\t|T]) -> + strip_tab_and_newline(T); +strip_tab_and_newline([H|T]) -> + [H|strip_tab_and_newline(T)]. + + +%% ---------------------------------------------------------------------- + +maybe_sort(L) when is_list(L) -> + lists:sort(L); +maybe_sort(X) -> + X. + + +%% ---------------------------------------------------------------------- + +atmost_once(Type, Val) -> + error({atmost_once, {Type, Val}}). + +wrong_type(Type, Val) -> + error({wrong_type, {Type, Val}}). + +wrong_type(Type, Val1, Val2) -> + error({wrong_type, {Type, Val1, Val2}}). + +not_equal(What, Val1, Val2) -> + error({not_equal, {What, Val1, Val2}}). + +error(Reason) -> + throw({error, Reason}). + + +%% ---------------------------------------------------------------------- + +d(F) -> + d(F, []). + +d(F, A) -> + d(get(dbg), F, A). + +d(true, F, A) -> + io:format("DBG:" ++ F ++ "~n", A); +d(_, _, _) -> + ok. + diff --git a/lib/megaco/test/megaco_test_msg_v1_lib.erl b/lib/megaco/test/megaco_test_msg_v1_lib.erl new file mode 100644 index 0000000000..638215e8c1 --- /dev/null +++ b/lib/megaco/test/megaco_test_msg_v1_lib.erl @@ -0,0 +1,7024 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Utility functions for creating the megaco types +%% This file is originally a copy of megaco_test_msg_v2_lib.erl +%% which is why so much of it is commented out. +%%---------------------------------------------------------------------- + +-module(megaco_test_msg_v1_lib). + +%% ---- + +-include_lib("megaco/include/megaco_message_v1.hrl"). +-include_lib("megaco/include/megaco.hrl"). + +%% ---- + +-export([ + cre_MegacoMessage/1, cre_MegacoMessage/2, +%% cre_AuthenticationHeader/3, + cre_Message/3, +%% cre_ErrorDescriptor/1, cre_ErrorDescriptor/2, +%% cre_ErrorCode/1, +%% cre_ErrorText/1, + cre_ContextID/1, + cre_Transaction/1, + cre_TransactionId/1, + cre_TransactionRequest/2, +%% cre_TransactionPending/1, +%% cre_TransactionReply/2, cre_TransactionReply/3, +%% cre_TransactionAck/1, cre_TransactionAck/2, + cre_ActionRequest/2, cre_ActionRequest/3, cre_ActionRequest/4, +%% cre_ActionReply/2, cre_ActionReply/3, cre_ActionReply/4, +%% cre_ContextRequest/0, cre_ContextRequest/1, cre_ContextRequest/2, +%% cre_ContextRequest/3, +%% cre_ContextAttrAuditRequest/0, cre_ContextAttrAuditRequest/3, +%% cre_CommandRequest/1, cre_CommandRequest/2, cre_CommandRequest/3, +%% cre_Command/2, +%% cre_CommandReply/2, +%% cre_TopologyRequest/3, cre_TopologyRequest/4, +%% cre_AmmRequest/2, + cre_AmmDescriptor/1, +%% cre_AmmsReply/1, cre_AmmsReply/2, +%% cre_SubtractRequest/1, cre_SubtractRequest/2, +%% cre_AuditRequest/2, +%% cre_AuditReply/1, +%% cre_AuditResult/2, +%% cre_AuditReturnParameter/1, +%% cre_AuditDescriptor/0, cre_AuditDescriptor/1, cre_AuditDescriptor/2, +%% cre_IndAuditParameter/1, +%% cre_IndAudMediaDescriptor/0, cre_IndAudMediaDescriptor/1, +%% cre_IndAudMediaDescriptor/2, +%% cre_IndAudStreamDescriptor/2, +%% cre_IndAudStreamParms/0, cre_IndAudStreamParms/1, +%% cre_IndAudStreamParms/3, +%% cre_IndAudLocalControlDescriptor/0, +%% cre_IndAudLocalControlDescriptor/4, +%% cre_IndAudPropertyParm/1, +%% cre_IndAudLocalRemoteDescriptor/1, +%% cre_IndAudLocalRemoteDescriptor/2, +%% cre_IndAudPropertyGroup/1, +%% cre_IndAudTerminationStateDescriptor/1, +%% cre_IndAudTerminationStateDescriptor/3, +%% cre_IndAudEventsDescriptor/1, cre_IndAudEventsDescriptor/2, +%% cre_IndAudEventsDescriptor/3, +%% cre_IndAudEventBufferDescriptor/1, +%% cre_IndAudEventBufferDescriptor/2, +%% cre_IndAudSignalsDescriptor/1, +%% cre_IndAudSeqSigList/1, +%% cre_IndAudSeqSigList/2, +%% cre_IndAudSignal/1, cre_IndAudSignal/2, +%% cre_IndAudDigitMapDescriptor/0, cre_IndAudDigitMapDescriptor/1, +%% cre_IndAudStatisticsDescriptor/1, +%% cre_IndAudPackagesDescriptor/2, +%% cre_NotifyRequest/2, cre_NotifyRequest/3, +%% cre_NotifyReply/1, cre_NotifyReply/2, +%% cre_ObservedEventsDescriptor/2, +%% cre_ObservedEvent/2, cre_ObservedEvent/3, cre_ObservedEvent/4, + cre_EventName/1, + cre_EventParameter/2, cre_EventParameter/4, +%% cre_ServiceChangeRequest/2, +%% cre_ServiceChangeReply/2, +%% cre_ServiceChangeResult/1, +%% %% cre_WildcardField/1, +%% cre_TerminationID/2, +%% cre_TerminationIDList/1, +%% cre_MediaDescriptor/0, cre_MediaDescriptor/1, cre_MediaDescriptor/2, +%% cre_StreamDescriptor/2, +%% cre_StreamParms/0, cre_StreamParms/1, cre_StreamParms/2, +%% cre_StreamParms/3, +%% cre_LocalControlDescriptor/1, cre_LocalControlDescriptor/2, +%% cre_LocalControlDescriptor/4, +%% cre_StreamMode/1, +%% cre_PropertyParm/2, cre_PropertyParm/4, +%% cre_Name/1, + cre_PkgdName/1, + cre_PkgdName/2, +%% cre_Relation/1, +%% cre_LocalRemoteDescriptor/1, +%% cre_PropertyGroup/1, +%% cre_TerminationStateDescriptor/1, +%% cre_TerminationStateDescriptor/2, +%% cre_TerminationStateDescriptor/3, +%% cre_EventBufferControl/1, +%% cre_ServiceState/1, +%% cre_MuxDescriptor/2, %% cre_MuxDescriptor/3, +%% cre_MuxType/1, +%% cre_StreamID/1, +%% cre_EventsDescriptor/0, cre_EventsDescriptor/2, +%% cre_RequestedEvent/1, +%% cre_RequestedEvent/2, cre_RequestedEvent/3, cre_RequestedEvent/4, +%% cre_RequestedActions/0, +%% cre_RequestedActions/1, cre_RequestedActions/4, +%% cre_EventDM/1, +%% cre_SecondEventsDescriptor/1, cre_SecondEventsDescriptor/2, +%% cre_SecondRequestedEvent/2, cre_SecondRequestedEvent/3, +%% cre_SecondRequestedEvent/4, +%% cre_SecondRequestedActions/0, cre_SecondRequestedActions/1, +%% cre_SecondRequestedActions/2, cre_SecondRequestedActions/3, + cre_EventBufferDescriptor/1, + cre_EventSpec/2, + cre_EventSpec/3, +%% cre_SignalsDescriptor/1, +%% cre_SignalRequest/1, +%% cre_SeqSigList/2, +%% cre_Signal/1, cre_Signal/2, cre_Signal/7, +%% cre_SignalType/1, +%% cre_SignalName/1, +%% cre_NotifyCompletion/1, +%% cre_SigParameter/2, cre_SigParameter/4, +%% cre_RequestID/1, +%% cre_ModemDescriptor/2, %% cre_ModemDescriptor/3, +%% cre_ModemType/1, +%% cre_DigitMapDescriptor/0, cre_DigitMapDescriptor/1, +%% cre_DigitMapDescriptor/2, +%% cre_DigitMapName/1, +%% cre_DigitMapValue/1, cre_DigitMapValue/4, cre_DigitMapValue/5, +%% cre_ServiceChangeParm/2, cre_ServiceChangeParm/4, +%% cre_ServiceChangeParm/9, +%% cre_ServiceChangeAddress/2, +%% cre_ServiceChangeResParm/0, cre_ServiceChangeResParm/2, +%% cre_ServiceChangeResParm/5, +%% cre_ServiceChangeMethod/1, +%% cre_ServiceChangeProfile/1, cre_ServiceChangeProfile/2, +%% cre_PackagesDescriptor/1, +%% cre_PackagesItem/2, +%% cre_StatisticsDescriptor/1, +%% cre_StatisticsParameter/1, cre_StatisticsParameter/2, +%% %% cre_NonStandardData/2, +%% %% cre_NonStandardIdentifier/1, +%% %% cre_H221NonStandard/4, +%% cre_TimeNotation/2, +%% cre_Value/1, + cre_BOOLEAN/1 + ]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +cre_MegacoMessage(M) when is_record(M, 'Message') -> + #'MegacoMessage'{mess = M}. + +cre_MegacoMessage(AH, M) + when is_record(AH, 'AuthenticationHeader') andalso + is_record(M, 'Message') -> + #'MegacoMessage'{authHeader = AH, + mess = M}. + +%% cre_AuthenticationHeader(SPI, SN, AD) -> +%% #'AuthenticationHeader'{secParmIndex = SPI, +%% seqNum = SN, +%% ad = AD}. + +cre_Message(V, Mid, ED) when is_record(ED, 'ErrorDescriptor') -> + Body = {errorDescriptor, ED}, + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, Transactions) when is_list(Transactions) -> + Body = {transactions, Transactions}, + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, {transactions, T} = Body) when is_list(T) -> + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, {errorDescriptor, ED} = Body) + when is_record(ED, 'ErrorDescriptor') -> + #'Message'{version = V, + mId = Mid, + messageBody = Body}. + + +%% cre_ErrorDescriptor(EC) when integer(EC) -> +%% #'ErrorDescriptor'{errorCode = EC}. + +%% cre_ErrorDescriptor(EC, ET) when integer(EC), list(ET) -> +%% #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + +%% cre_ErrorCode(C) when integer(C), 0 =< C, C =< 65535 -> +%% C; +%% cre_ErrorCode(C) -> +%% exit({invalid_ErrorCode, C}). + +%% cre_ErrorText(T) when list(T) -> +%% T. + +cre_ContextID(Val) when (0 =< Val) and (Val =< 4294967295) -> + Val; +cre_ContextID(Val) -> + exit({invalid_ContextID, Val}). + +cre_Transaction(TR) when is_record(TR, 'TransactionRequest') -> + {transactionRequest, TR}; +cre_Transaction(TP) when is_record(TP, 'TransactionPending') -> + {transactionPending, TP}; +cre_Transaction(TR) when is_record(TR, 'TransactionReply') -> + {transactionReply, TR}; +cre_Transaction(TRA) when is_list(TRA) -> + {transactionResponseAck, TRA}. + +cre_TransactionId(Val) when (0 =< Val) andalso (Val =< 4294967295) -> + Val; +cre_TransactionId(Val) -> + exit({invalid_TransactionId, Val}). + +cre_TransactionRequest(TransID, ARs) when is_integer(TransID) andalso is_list(ARs) -> + #'TransactionRequest'{transactionId = TransID, + actions = ARs}. + +%% cre_TransactionPending(TransID) when integer(TransID) -> +%% #'TransactionPending'{transactionId = TransID}. + +%% cre_TransactionReply(TransID, ED) +%% when integer(TransID), record(ED, 'ErrorDescriptor') -> +%% Res = {transactionError, ED}, +%% #'TransactionReply'{transactionId = TransID, +%% transactionResult = Res}; +%% cre_TransactionReply(TransID, ARs) +%% when integer(TransID), list(ARs) -> +%% Res = {actionReplies, ARs}, +%% #'TransactionReply'{transactionId = TransID, +%% transactionResult = Res}. + +%% cre_TransactionReply(TransID, IAR, ED) +%% when is_integer(TransID) and +%% ((IAR == 'NULL') or (IAR == asn1_NOVALUE)) and +%% is_record(ED, 'ErrorDescriptor') -> +%% Res = {transactionError, ED}, +%% #'TransactionReply'{transactionId = TransID, +%% transactionResult = Res}; +%% cre_TransactionReply(TransID, IAR, ARs) +%% when is_integer(TransID) and +%% ((IAR == 'NULL') or (IAR == asn1_NOVALUE)) and +%% is_list(ARs) -> +%% Res = {actionReplies, ARs}, +%% #'TransactionReply'{transactionId = TransID, +%% transactionResult = Res}. + +%% cre_TransactionAck(FirstAck) -> +%% #'TransactionAck'{firstAck = FirstAck}. + +%% cre_TransactionAck(FirstAck, FirstAck) -> +%% #'TransactionAck'{firstAck = FirstAck}; +%% cre_TransactionAck(FirstAck, LastAck) -> +%% #'TransactionAck'{firstAck = FirstAck, +%% lastAck = LastAck}. + +cre_ActionRequest(CtxID, CmdReqs) + when is_integer(CtxID) and is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + commandRequests = CmdReqs}. + +cre_ActionRequest(CtxID, CtxReq, CmdReqs) + when is_integer(CtxID) and + is_record(CtxReq, 'ContextRequest') and + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextRequest = CtxReq, + commandRequests = CmdReqs}; +cre_ActionRequest(CtxID, CAAR, CmdReqs) + when is_integer(CtxID) and + is_record(CAAR, 'ContextAttrAuditRequest') and + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextAttrAuditReq = CAAR, + commandRequests = CmdReqs}. + +cre_ActionRequest(CtxID, CtxReq, CAAR, CmdReqs) + when is_integer(CtxID) and + is_record(CtxReq, 'ContextRequest') and + is_record(CAAR, 'ContextAttrAuditRequest') and + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextRequest = CtxReq, + contextAttrAuditReq = CAAR, + commandRequests = CmdReqs}. + +%% cre_ActionReply(CtxID, CmdReps) +%% when integer(CtxID), +%% list(CmdReps) -> +%% #'ActionReply'{contextId = CtxID, +%% commandReply = CmdReps}. + +%% cre_ActionReply(CtxID, ED, CmdReps) +%% when integer(CtxID), +%% record(ED, 'ErrorDescriptor'), +%% list(CmdReps) -> +%% #'ActionReply'{contextId = CtxID, +%% errorDescriptor = ED, +%% commandReply = CmdReps}; +%% cre_ActionReply(CtxID, CtxReq, CmdReps) +%% when integer(CtxID), +%% record(CtxReq, 'ContextRequest'), +%% list(CmdReps) -> +%% #'ActionReply'{contextId = CtxID, +%% contextReply = CtxReq, +%% commandReply = CmdReps}. + +%% cre_ActionReply(CtxID, ED, CtxReq, CmdReps) +%% when integer(CtxID), +%% record(ED, 'ErrorDescriptor'), +%% record(CtxReq, 'ContextRequest'), +%% list(CmdReps) -> +%% #'ActionReply'{contextId = CtxID, +%% errorDescriptor = ED, +%% contextReply = CtxReq, +%% commandReply = CmdReps}. + +%% cre_ContextRequest() -> +%% #'ContextRequest'{}. + +%% cre_ContextRequest(Prio) when integer(Prio), 0 =< Prio, Prio =< 15 -> +%% #'ContextRequest'{priority = Prio}; +%% cre_ContextRequest(Em) when Em == true; Em == false; Em == asn1_NOVALUE -> +%% #'ContextRequest'{emergency = Em}; +%% cre_ContextRequest(Top) when list(Top) -> +%% #'ContextRequest'{topologyReq = Top}. + +%% cre_ContextRequest(Prio, Em) +%% when (is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) and +%% ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) -> +%% #'ContextRequest'{priority = Prio, +%% emergency = Em}; +%% cre_ContextRequest(Prio, Top) +%% when integer(Prio), 0 =< Prio, Prio =< 15, list(Top) -> +%% #'ContextRequest'{priority = Prio, +%% topologyReq = Top}. + +%% cre_ContextRequest(Prio, Em, Top) +%% when (is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) and +%% ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) and +%% is_list(Top) -> +%% #'ContextRequest'{priority = Prio, +%% emergency = Em, +%% topologyReq = Top}. + +%% cre_ContextAttrAuditRequest() -> +%% #'ContextAttrAuditRequest'{}. + +%% cre_ContextAttrAuditRequest(Top, Em, Prio) +%% when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and +%% ((Em == 'NULL') or (Em == asn1_NOVALUE)) and +%% ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) -> +%% #'ContextAttrAuditRequest'{topology = Top, +%% emergency = Em, +%% priority = Prio}. + +%% cre_CommandRequest(Cmd) -> +%% #'CommandRequest'{command = Cmd}. + +%% cre_CommandRequest(Cmd, Opt) +%% when ((Opt == 'NULL') or (Opt == asn1_NOVALUE)) -> +%% #'CommandRequest'{command = Cmd, +%% optional = Opt}. + +%% cre_CommandRequest(Cmd, Opt, WR) +%% when ((Opt == 'NULL') or (Opt == asn1_NOVALUE)) and +%% ((WR == 'NULL') or (WR == asn1_NOVALUE)) -> +%% #'CommandRequest'{command = Cmd, +%% optional = Opt, +%% wildcardReturn = WR}. + +%% cre_Command(addReq = Tag, Req) +%% when record(Req, 'AmmRequest') -> +%% {Tag, Req}; +%% cre_Command(moveReq = Tag, Req) +%% when record(Req, 'AmmRequest') -> +%% {Tag, Req}; +%% cre_Command(modReq = Tag, Req) +%% when record(Req, 'AmmRequest') -> +%% {Tag, Req}; +%% cre_Command(subtractReq = Tag, Req) +%% when record(Req, 'SubtractRequest') -> +%% {Tag, Req}; +%% cre_Command(auditCapRequest = Tag, Req) +%% when record(Req, 'AuditRequest') -> +%% {Tag, Req}; +%% cre_Command(auditValueRequest = Tag, Req) +%% when record(Req, 'AuditRequest') -> +%% {Tag, Req}; +%% cre_Command(notifyReq = Tag, Req) +%% when record(Req, 'NotifyRequest') -> +%% {Tag, Req}; +%% cre_Command(serviceChangeReq = Tag, Req) +%% when record(Req, 'ServiceChangeRequest') -> +%% {Tag, Req}. + +%% cre_CommandReply(addReply = Tag, Rep) +%% when record(Rep, 'AmmsReply') -> +%% {Tag, Rep}; +%% cre_CommandReply(moveReply = Tag, Rep) +%% when record(Rep, 'AmmsReply') -> +%% {Tag, Rep}; +%% cre_CommandReply(modReply = Tag, Rep) +%% when record(Rep, 'AmmsReply') -> +%% {Tag, Rep}; +%% cre_CommandReply(subtractReply = Tag, Rep) +%% when record(Rep, 'AmmsReply') -> +%% {Tag, Rep}; +%% cre_CommandReply(auditCapReply = Tag, Rep) +%% when tuple(Rep) -> +%% {Tag, Rep}; +%% cre_CommandReply(auditValueReply = Tag, Rep) +%% when tuple(Rep) -> +%% {Tag, Rep}; +%% cre_CommandReply(notifyReply = Tag, Rep) +%% when record(Rep, 'NotifyReply') -> +%% {Tag, Rep}; +%% cre_CommandReply(serviceChangeReply = Tag, Rep) +%% when record(Rep, 'ServiceChangeReply') -> +%% {Tag, Rep}. + +%% cre_TopologyRequest(From, To, Dir) +%% when is_record(From, 'TerminationID') and +%% is_record(To, 'TerminationID') and +%% ((Dir == bothway) or (Dir == isolate) or (Dir == oneway)) -> +%% #'TopologyRequest'{terminationFrom = From, +%% terminationTo = To, +%% topologyDirection = Dir}. + +%% cre_TopologyRequest(From, To, Dir, SID) +%% when is_record(From, 'TerminationID') and +%% is_record(To, 'TerminationID') and +%% ((Dir == bothway) or (Dir == isolate) or (Dir == oneway)) and +%% (is_integer(SID) or (SID == asn1_NOVALUE)) -> +%% #'TopologyRequest'{terminationFrom = From, +%% terminationTo = To, +%% topologyDirection = Dir, +%% streamID = SID}. + +%% cre_AmmRequest(TermIDs, Descs) when list(TermIDs), list(Descs) -> +%% #'AmmRequest'{terminationID = TermIDs, +%% descriptors = Descs}. + +cre_AmmDescriptor(D) when is_record(D, 'MediaDescriptor') -> + {mediaDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'ModemDescriptor') -> + {modemDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'MuxDescriptor') -> + {muxDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'EventsDescriptor') -> + {eventsDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'DigitMapDescriptor') -> + {digitMapDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'AuditDescriptor') -> + {auditDescriptor, D}; +cre_AmmDescriptor(D) when is_list(D) -> + case is_EventBufferDescriptor(D) of + true -> + {eventBufferDescriptor, D}; + false -> + case is_SignalsDescriptor(D) of + true -> + {signalsDescriptor, D}; + false -> + error({invalid_AmmDescriptor, D}) + end + end. + +%% cre_AmmsReply(TermIDs) when list(TermIDs) -> +%% #'AmmsReply'{terminationID = TermIDs}. + +%% cre_AmmsReply(TermIDs, TAs) when list(TermIDs), list(TAs) -> +%% #'AmmsReply'{terminationID = TermIDs, +%% terminationAudit = TAs}. + +%% cre_SubtractRequest(TermIDs) when list(TermIDs) -> +%% #'SubtractRequest'{terminationID = TermIDs}. + +%% cre_SubtractRequest(TermIDs, Audit) +%% when list(TermIDs), record(Audit, 'AuditDescriptor') -> +%% #'SubtractRequest'{terminationID = TermIDs, +%% auditDescriptor = Audit}. + +%% cre_AuditRequest(TermID, Audit) +%% when record(TermID, megaco_term_id), record(Audit, 'AuditDescriptor') -> +%% #'AuditRequest'{terminationID = TermID, +%% auditDescriptor = Audit}. + +%% cre_AuditReply(TermIDs) when list(TermIDs) -> +%% {contextAuditResult, TermIDs}; +%% cre_AuditReply(ED) when record(ED, 'ErrorDescriptor') -> +%% {error, ED}; +%% cre_AuditReply(Audit) when record(Audit, 'AuditResult') -> +%% {auditResult, Audit}. + +%% cre_AuditResult(TermID, TAs) +%% when record(TermID, megaco_term_id), list(TAs) -> +%% #'AuditResult'{terminationID = TermID, +%% terminationAuditResult = TAs}. + +%% cre_AuditReturnParameter(D) when record(D, 'ErrorDescriptor') -> +%% {errorDescriptor, D}; +%% cre_AuditReturnParameter(D) when record(D, 'MediaDescriptor') -> +%% {mediaDescriptor, D}; +%% cre_AuditReturnParameter(D) when record(D, 'ModemDescriptor') -> +%% {modemDescriptor, D}; +%% cre_AuditReturnParameter(D) when record(D, 'MuxDescriptor') -> +%% {muxDescriptor, D}; +%% cre_AuditReturnParameter(D) when record(D, 'EventsDescriptor') -> +%% {eventsDescriptor, D}; +%% cre_AuditReturnParameter([H|_] = D) when record(H, 'EventSpec') -> +%% {eventBufferDescriptor, D}; +%% cre_AuditReturnParameter(D) when record(D, 'DigitMapDescriptor') -> +%% {digitMapDescriptor, D}; +%% cre_AuditReturnParameter(D) when record(D, 'ObservedEventsDescriptor') -> +%% {observedEventsDescriptor, D}; +%% cre_AuditReturnParameter([H|_] = D) when record(H, 'StatisticsParameter') -> +%% {statisticsDescriptor, D}; +%% cre_AuditReturnParameter([H|_] = D) when record(H, 'PackagesItem') -> +%% {packagesDescriptor, D}; +%% cre_AuditReturnParameter(D) when record(D, 'AuditDescriptor') -> +%% {emptyDescriptors, D}; +%% cre_AuditReturnParameter([H|_] = D) when tuple(H) -> +%% {signalsDescriptor, D}. + +%% cre_AuditDescriptor() -> +%% #'AuditDescriptor'{}. + +%% cre_AuditDescriptor([H|_] = AT) when atom(H) -> +%% #'AuditDescriptor'{auditToken = AT}; +%% cre_AuditDescriptor(APT) -> +%% #'AuditDescriptor'{auditPropertyToken = APT}. + +%% cre_AuditDescriptor(AT, APT) -> +%% #'AuditDescriptor'{auditToken = AT, +%% auditPropertyToken = APT}. + +%% cre_IndAuditParameter(D) when record(D, 'IndAudMediaDescriptor') -> +%% {indAudMediaDescriptor, D}; +%% cre_IndAuditParameter(D) when record(D, 'IndAudEventsDescriptor') -> +%% {indAudEventsDescriptor, D}; +%% cre_IndAuditParameter(D) when record(D, 'IndAudEventBufferDescriptor') -> +%% {indAudEventBufferDescriptor, D}; +%% cre_IndAuditParameter({signal, _} = D) -> +%% {indAudSignalsDescriptor, D}; +%% cre_IndAuditParameter({seqSigList, _} = D) -> +%% {indAudSignalsDescriptor, D}; +%% cre_IndAuditParameter(D) when record(D, 'IndAudDigitMapDescriptor') -> +%% {indAudDigitMapDescriptor, D}; +%% cre_IndAuditParameter(D) when record(D, 'IndAudStatisticsDescriptor') -> +%% {indAudStatisticsDescriptor, D}; +%% cre_IndAuditParameter(D) when record(D, 'IndAudPackagesDescriptor') -> +%% {indAudPackagesDescriptor, D}. + +%% cre_IndAudMediaDescriptor() -> +%% #'IndAudMediaDescriptor'{}. + +%% cre_IndAudMediaDescriptor(TSD) +%% when record(TSD, 'IndAudTerminationStateDescriptor') -> +%% #'IndAudMediaDescriptor'{termStateDescr = TSD}; +%% cre_IndAudMediaDescriptor(Parms) when record(Parms, 'IndAudStreamParms') -> +%% Streams = {oneStream, Parms}, +%% #'IndAudMediaDescriptor'{streams = Streams}; +%% cre_IndAudMediaDescriptor(Descs) when list(Descs) -> +%% Streams = {multiStream, Descs}, +%% #'IndAudMediaDescriptor'{streams = Streams}. + +%% cre_IndAudMediaDescriptor(TSD, Parms) +%% when record(TSD, 'IndAudTerminationStateDescriptor'), +%% record(Parms, 'IndAudStreamParms') -> +%% Streams = {oneStream, Parms}, +%% #'IndAudMediaDescriptor'{termStateDescr = TSD, +%% streams = Streams}; +%% cre_IndAudMediaDescriptor(TSD, Descs) +%% when record(TSD, 'IndAudTerminationStateDescriptor'), list(Descs) -> +%% Streams = {multiStream, Descs}, +%% #'IndAudMediaDescriptor'{termStateDescr = TSD, +%% streams = Streams}. + +%% cre_IndAudStreamDescriptor(SID, Parms) +%% when integer(SID), record(Parms, 'IndAudStreamParms') -> +%% #'IndAudStreamDescriptor'{streamID = SID, +%% streamParms = Parms}. + +%% cre_IndAudStreamParms() -> +%% #'IndAudStreamParms'{}. + +%% cre_IndAudStreamParms(LCD) when record(LCD, 'IndAudLocalControlDescriptor') -> +%% #'IndAudStreamParms'{localControlDescriptor = LCD}. + +%% cre_IndAudStreamParms(LCD, L, R) +%% when record(LCD, 'IndAudLocalControlDescriptor'), +%% record(L, 'IndAudLocalRemoteDescriptor'), +%% record(R, 'IndAudLocalRemoteDescriptor') -> +%% #'IndAudStreamParms'{localControlDescriptor = LCD, +%% localDescriptor = L, +%% remoteDescriptor = R}. + +%% cre_IndAudLocalControlDescriptor() -> +%% #'IndAudLocalControlDescriptor'{}. + +%% cre_IndAudLocalControlDescriptor(SM, RV, RG, PP) +%% when ((SM == 'NULL') or (SM == asn1_NOVALUE)) and +%% ((RV == 'NULL') or (RV == asn1_NOVALUE)) and +%% ((RG == 'NULL') or (RG == asn1_NOVALUE)) and +%% (is_list(PP) or (PP == asn1_NOVALUE)) -> +%% #'IndAudLocalControlDescriptor'{streamMode = SM, +%% reserveValue = RV, +%% reserveGroup = RG, +%% propertyParms = PP}. + +%% cre_IndAudPropertyParm(PkgdName) when list(PkgdName) -> +%% #'IndAudPropertyParm'{name = PkgdName}. + +%% cre_IndAudLocalRemoteDescriptor(Grps) +%% when list(Grps) -> +%% #'IndAudLocalRemoteDescriptor'{propGrps = Grps}. + +%% cre_IndAudLocalRemoteDescriptor(GrpID, Grps) +%% when integer(GrpID), 0 =< GrpID, GrpID =< 65535, list(Grps) -> +%% #'IndAudLocalRemoteDescriptor'{propGroupID = GrpID, +%% propGrps = Grps}. + +%% cre_IndAudPropertyGroup([]) -> +%% []; +%% cre_IndAudPropertyGroup([H|_] = PG) +%% when record(H, 'IndAudPropertyParm') -> +%% PG. + +%% cre_IndAudTerminationStateDescriptor([] = PP) -> +%% #'IndAudTerminationStateDescriptor'{propertyParms = PP}; +%% cre_IndAudTerminationStateDescriptor([H|_] = PP) +%% when record(H, 'IndAudPropertyParm') -> +%% #'IndAudTerminationStateDescriptor'{propertyParms = PP}. + +%% cre_IndAudTerminationStateDescriptor([] = PP, EBC, SS) +%% when ((EBC == 'NULL') or (EBC == asn1_NOVALUE)) and +%% ((SS == 'NULL') or (SS == asn1_NOVALUE)) -> +%% #'IndAudTerminationStateDescriptor'{propertyParms = PP, +%% eventBufferControl = EBC, +%% serviceState = SS}; +%% cre_IndAudTerminationStateDescriptor([H|_] = PP, EBC, SS) +%% when is_record(H, 'IndAudPropertyParm') and +%% ((EBC == 'NULL') or (EBC == asn1_NOVALUE)) and +%% ((SS == 'NULL') or (SS == asn1_NOVALUE)) -> +%% #'IndAudTerminationStateDescriptor'{propertyParms = PP, +%% eventBufferControl = EBC, +%% serviceState = SS}. + +%% cre_IndAudEventsDescriptor(PkgdName) +%% when list(PkgdName) -> +%% #'IndAudEventsDescriptor'{pkgdName = PkgdName}. + +%% cre_IndAudEventsDescriptor(RID, PkgdName) +%% when integer(RID), list(PkgdName) -> +%% #'IndAudEventsDescriptor'{requestID = RID, pkgdName = PkgdName}; +%% cre_IndAudEventsDescriptor(PkgdName, SID) +%% when list(PkgdName), integer(SID) -> +%% #'IndAudEventsDescriptor'{pkgdName = PkgdName, streamID = SID}. + +%% cre_IndAudEventsDescriptor(RID, PkgdName, SID) +%% when integer(RID), list(PkgdName), integer(SID) -> +%% #'IndAudEventsDescriptor'{requestID = RID, +%% pkgdName = PkgdName, +%% streamID = SID}. + +%% cre_IndAudEventBufferDescriptor(EventName) when list(EventName) -> +%% #'IndAudEventBufferDescriptor'{eventName = EventName}. + +%% cre_IndAudEventBufferDescriptor(EventName, SID) +%% when list(EventName), integer(SID) -> +%% #'IndAudEventBufferDescriptor'{eventName = EventName, streamID = SID}. + +%% cre_IndAudSignalsDescriptor(S) when record(S, 'IndAudSignal') -> +%% {signal, S}; +%% cre_IndAudSignalsDescriptor(S) when record(S, 'IndAudSeqSigList') -> +%% {seqSigList, S}. + +%% cre_IndAudSeqSigList(ID) when integer(ID), 0=< ID, ID =< 65535 -> +%% #'IndAudSeqSigList'{id = ID}. + +%% cre_IndAudSeqSigList(ID, S) +%% when integer(ID), 0=< ID, ID =< 65535, +%% record(S, 'IndAudSignal') -> +%% #'IndAudSeqSigList'{id = ID, signalList = S}. + +%% cre_IndAudSignal(SigName) when list(SigName) -> +%% #'IndAudSignal'{signalName = SigName}. + +%% cre_IndAudSignal(SigName, SID) when list(SigName), integer(SID) -> +%% #'IndAudSignal'{signalName = SigName, streamID = SID}. + +%% cre_IndAudDigitMapDescriptor() -> +%% #'IndAudDigitMapDescriptor'{}. + +%% cre_IndAudDigitMapDescriptor(DMN) when list(DMN) -> +%% #'IndAudDigitMapDescriptor'{digitMapName = DMN}. + +%% cre_IndAudStatisticsDescriptor(StatName) when list(StatName) -> +%% #'IndAudStatisticsDescriptor'{statName = StatName}. + +%% cre_IndAudPackagesDescriptor(N, V) +%% when list(N), +%% integer(V), 0 =< V, V =< 99 -> +%% #'IndAudPackagesDescriptor'{packageName = N, +%% packageVersion = V}. + +%% cre_NotifyRequest(TermIDs, D) +%% when list(TermIDs), record(D, 'ObservedEventsDescriptor') -> +%% #'NotifyRequest'{terminationID = TermIDs, +%% observedEventsDescriptor = D}. + +%% cre_NotifyRequest(TermIDs, D, ED) +%% when list(TermIDs), +%% record(D, 'ObservedEventsDescriptor'), +%% record(ED, 'ErrorDescriptor') -> +%% #'NotifyRequest'{terminationID = TermIDs, +%% observedEventsDescriptor = D, +%% errorDescriptor = ED}. + +%% cre_NotifyReply(TermIDs) when list(TermIDs) -> +%% #'NotifyReply'{terminationID = TermIDs}. + +%% cre_NotifyReply(TermIDs, ED) +%% when list(TermIDs), +%% record(ED, 'ErrorDescriptor') -> +%% #'NotifyReply'{terminationID = TermIDs, +%% errorDescriptor = ED}. + +%% cre_ObservedEventsDescriptor(RID, [H|_] = L) +%% when integer(RID), record(H, 'ObservedEvent') -> +%% #'ObservedEventsDescriptor'{requestId = RID, +%% observedEventLst = L}. + +%% cre_ObservedEvent(EN, EPL) when list(EN), list(EPL) -> +%% #'ObservedEvent'{eventName = EN, +%% eventParList = EPL}; +%% cre_ObservedEvent(EN, TN) when list(EN), record(TN, 'TimeNotation') -> +%% #'ObservedEvent'{eventName = EN, +%% timeNotation = TN}. + +%% cre_ObservedEvent(EN, SID, EPL) when list(EN), integer(SID), list(EPL) -> +%% #'ObservedEvent'{eventName = EN, +%% streamID = SID, +%% eventParList = EPL}; +%% cre_ObservedEvent(EN, EPL, TN) +%% when list(EN), list(EPL), record(TN, 'TimeNotation') -> +%% #'ObservedEvent'{eventName = EN, +%% eventParList = EPL, +%% timeNotation = TN}. + +%% cre_ObservedEvent(EN, SID, EPL, TN) +%% when list(EN), integer(SID), list(EPL), record(TN, 'TimeNotation') -> +%% #'ObservedEvent'{eventName = EN, +%% streamID = SID, +%% eventParList = EPL, +%% timeNotation = TN}. + +cre_EventName(N) when is_list(N) -> + N. + +cre_EventParameter(N, V) when is_list(N) andalso is_list(V) -> + #'EventParameter'{eventParameterName = N, + value = V}. + +cre_EventParameter(N, V, relation = Tag, R) + when is_list(N) andalso is_list(V) andalso is_atom(R) -> + EI = {Tag, R}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}; +cre_EventParameter(N, V, range = Tag, B) + when is_list(N) andalso is_list(V) andalso is_atom(B) -> + EI = {Tag, B}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}; +cre_EventParameter(N, V, sublist = Tag, B) + when is_list(N) andalso is_list(V) andalso is_atom(B) -> + EI = {Tag, B}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}. + +%% cre_ServiceChangeRequest(TermIDs, SCP) +%% when list(TermIDs), +%% record(SCP, 'ServiceChangeParm') -> +%% #'ServiceChangeRequest'{terminationID = TermIDs, +%% serviceChangeParms = SCP}. + +%% cre_ServiceChangeReply(TermIDs, {Tag, R} = SCR) +%% when list(TermIDs), atom(Tag), tuple(R) -> +%% #'ServiceChangeReply'{terminationID = TermIDs, +%% serviceChangeResult = SCR}. + +%% cre_ServiceChangeResult(ED) when record(ED, 'ErrorDescriptor') -> +%% {errorDescriptor, ED}; +%% cre_ServiceChangeResult(SCRP) when record(SCRP, 'ServiceChangeResParm') -> +%% {serviceChangeResParms, SCRP}. + +%% %% cre_WildcardField(L) when list(L), length(L) == 1 -> L. + +%% cre_TerminationID(W, ID) +%% when list(W), +%% list(ID), 1 =< length(ID), length(ID) =< 8 -> +%% #'TerminationID'{wildcard = W, +%% id = ID}. + +%% cre_TerminationIDList(L) when list(L) -> +%% L. + +%% cre_MediaDescriptor() -> +%% #'MediaDescriptor'{}. + +%% cre_MediaDescriptor(TSD) when record(TSD, 'TerminationStateDescriptor') -> +%% #'MediaDescriptor'{termStateDescr = TSD}; +%% cre_MediaDescriptor(SP) when record(SP, 'StreamParms') -> +%% Streams = {oneStream, SP}, +%% #'MediaDescriptor'{streams = Streams}; +%% cre_MediaDescriptor([H|_] = SDs) when record(H, 'StreamDescriptor') -> +%% Streams = {multiStream, SDs}, +%% #'MediaDescriptor'{streams = Streams}. + +%% cre_MediaDescriptor(TSD, SP) +%% when record(TSD, 'TerminationStateDescriptor'), +%% record(SP, 'StreamParms') -> +%% Streams = {oneStream, SP}, +%% #'MediaDescriptor'{termStateDescr = TSD, +%% streams = Streams}; +%% cre_MediaDescriptor(TSD, [H|_] = SDs) +%% when record(TSD, 'TerminationStateDescriptor'), +%% record(H, 'StreamDescriptor') -> +%% Streams = {multiStream, SDs}, +%% #'MediaDescriptor'{termStateDescr = TSD, +%% streams = Streams}. + +%% cre_StreamDescriptor(SID, SP) when integer(SID), record(SP, 'StreamParms') -> +%% #'StreamDescriptor'{streamID = SID, +%% streamParms = SP}. + +%% cre_StreamParms() -> +%% #'StreamParms'{}. + +%% cre_StreamParms(LCD) when record(LCD, 'LocalControlDescriptor') -> +%% #'StreamParms'{localControlDescriptor = LCD}; +%% cre_StreamParms(LD) when record(LD, 'LocalRemoteDescriptor') -> +%% #'StreamParms'{localDescriptor = LD}. + +%% cre_StreamParms(LCD, LD) +%% when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and +%% (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) -> +%% #'StreamParms'{localControlDescriptor = LCD, +%% localDescriptor = LD}. + +%% cre_StreamParms(LCD, LD, RD) +%% when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and +%% (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) and +%% (is_record(RD, 'LocalRemoteDescriptor') or (RD == asn1_NOVALUE)) -> +%% #'StreamParms'{localControlDescriptor = LCD, +%% localDescriptor = LD, +%% remoteDescriptor = RD}. + +%% cre_LocalControlDescriptor(SM) when atom(SM) -> +%% #'LocalControlDescriptor'{streamMode = SM, propertyParms = []}; +%% cre_LocalControlDescriptor([H|_] = PP) when record(H, 'PropertyParm') -> +%% #'LocalControlDescriptor'{propertyParms = PP}. + +%% cre_LocalControlDescriptor(SM, [H|_] = PP) +%% when atom(SM), record(H, 'PropertyParm') -> +%% #'LocalControlDescriptor'{streamMode = SM, +%% propertyParms = PP}. + +%% cre_LocalControlDescriptor(SM, RV, RG, [H|_] = PP) +%% when is_atom(SM) and +%% ((RV == true) or (RV == false) or (RV == asn1_NOVALUE)) and +%% ((RG == true) or (RG == false) or (RG == asn1_NOVALUE)) and +%% is_record(H, 'PropertyParm') -> +%% #'LocalControlDescriptor'{streamMode = SM, +%% reserveValue = RV, +%% reserveGroup = RG, +%% propertyParms = PP}. + +%% cre_StreamMode(sendOnly = M) -> +%% M; +%% cre_StreamMode(recvOnly = M) -> +%% M; +%% cre_StreamMode(sendRecv = M) -> +%% M; +%% cre_StreamMode(inactive = M) -> +%% M; +%% cre_StreamMode(loopBack = M) -> +%% M. + +%% cre_PropertyParm(N, [H|_] = V) when list(N), list(H) -> +%% #'PropertyParm'{name = N, value = V}. + +%% cre_PropertyParm(N, [H|_] = V, relation = Tag, R) +%% when list(N), list(H), atom(R) -> +%% EI = {Tag, R}, +%% #'PropertyParm'{name = N, value = V, extraInfo = EI}; +%% cre_PropertyParm(N, [H|_] = V, range = Tag, B) +%% when list(N), list(H), atom(B) -> +%% EI = {Tag, B}, +%% #'PropertyParm'{name = N, value = V, extraInfo = EI}; +%% cre_PropertyParm(N, [H|_] = V, sublist = Tag, B) +%% when list(N), list(H), atom(B) -> +%% EI = {Tag, B}, +%% #'PropertyParm'{name = N, value = V, extraInfo = EI}. + + +%% cre_Name(N) when list(N), length(N) == 2 -> +%% N. + +cre_PkgdName(N) when is_list(N) -> + case string:tokens(N, [$\\]) of + [_PkgName, _ItemID] -> + N; + _ -> + error({invalid_PkgdName, N}) + end. +cre_PkgdName(root, root) -> + "*/*"; +cre_PkgdName(PackageName, root) + when is_list(PackageName) and (length(PackageName) =< 64) -> + PackageName ++ "/*"; +cre_PkgdName(PackageName, ItemID) + when ((is_list(PackageName) and (length(PackageName) =< 64)) and + (is_list(ItemID) and (length(ItemID) =< 64))) -> + PackageName ++ "/" ++ ItemID; +cre_PkgdName(PackageName, ItemID) -> + error({invalid_PkgdName, {PackageName, ItemID}}). + +%% cre_Relation(greaterThan = R) -> +%% R; +%% cre_Relation(smallerThan = R) -> +%% R; +%% cre_Relation(unequalTo = R) -> +%% R. + +%% cre_LocalRemoteDescriptor([H|_] = PGs) when list(H) -> +%% #'LocalRemoteDescriptor'{propGrps = PGs}. + +%% cre_PropertyGroup([H|_] = PG) when record(H, 'PropertyParm') -> +%% PG. + +%% cre_TerminationStateDescriptor([H|_] = PPs) when record(H, 'PropertyParm') -> +%% #'TerminationStateDescriptor'{propertyParms = PPs}. + +%% cre_TerminationStateDescriptor([H|_] = PPs, off = EBC) +%% when record(H, 'PropertyParm') -> +%% #'TerminationStateDescriptor'{propertyParms = PPs, +%% eventBufferControl = EBC}; +%% cre_TerminationStateDescriptor([H|_] = PPs, lockStep = EBC) +%% when record(H, 'PropertyParm') -> +%% #'TerminationStateDescriptor'{propertyParms = PPs, +%% eventBufferControl = EBC}; +%% cre_TerminationStateDescriptor([H|_] = PPs, test = SS) +%% when record(H, 'PropertyParm') -> +%% #'TerminationStateDescriptor'{propertyParms = PPs, +%% serviceState = SS}; +%% cre_TerminationStateDescriptor([H|_] = PPs, outOfSvc = SS) +%% when record(H, 'PropertyParm') -> +%% #'TerminationStateDescriptor'{propertyParms = PPs, +%% serviceState = SS}; +%% cre_TerminationStateDescriptor([H|_] = PPs, inSvc = SS) +%% when record(H, 'PropertyParm') -> +%% #'TerminationStateDescriptor'{propertyParms = PPs, +%% serviceState = SS}. + +%% cre_TerminationStateDescriptor([H|_] = PPs, EMC, SS) +%% when record(H, 'PropertyParm'), +%% ((EMC == off) or (EMC == lockStep)) and +%% ((SS == test) or (SS == outOfSvc) or (SS == inSvc)) -> +%% #'TerminationStateDescriptor'{propertyParms = PPs, +%% eventBufferControl = EMC, +%% serviceState = SS}. + +%% cre_EventBufferControl(off = EBC) -> +%% EBC; +%% cre_EventBufferControl(lockStep = EBC) -> +%% EBC. + +%% cre_ServiceState(test = SS) -> +%% SS; +%% cre_ServiceState(outOfSvc = SS) -> +%% SS; +%% cre_ServiceState(inSvc = SS) -> +%% SS. + +%% cre_MuxDescriptor(MT, [H|_] = TL) +%% when atom(MT), record(H, 'TerminationID') -> +%% #'MuxDescriptor'{muxType = MT, termList = TL}. + +%% %% cre_MuxDescriptor(MT, [H|_] = TL, NSD) +%% %% when atom(MT), record(H, 'TerminationID'), record(NSD, 'NonStandardData') -> +%% %% #'MuxDescriptor'{muxType = MT, termList = TL, nonStandardData = NSD}. + +%% cre_MuxType(h221 = MT) -> +%% MT; +%% cre_MuxType(h223 = MT) -> +%% MT; +%% cre_MuxType(h226 = MT) -> +%% MT; +%% cre_MuxType(v76 = MT) -> +%% MT; +%% cre_MuxType(nx64k = MT) -> +%% MT. + +%% cre_StreamID(Val) when 0 =< Val, Val =< 65535 -> +%% Val; +%% cre_StreamID(Val) -> +%% exit({invalid_ContextID, Val}). + +%% %% RequestID must be present if eventList is non empty +%% cre_EventsDescriptor() -> +%% #'EventsDescriptor'{eventList = []}. + +%% cre_EventsDescriptor(RID, [H|_] = EL) +%% when integer(RID), record(H, 'RequestedEvent') -> +%% #'EventsDescriptor'{requestID = RID, eventList = EL}. + +%% cre_RequestedEvent(N) -> +%% #'RequestedEvent'{pkgdName = N}. + +%% cre_RequestedEvent(N, [H|_] = EPL) +%% when list(N), +%% record(H, 'EventParameter') -> +%% #'RequestedEvent'{pkgdName = N, +%% evParList = EPL}; +%% cre_RequestedEvent(N, EA) +%% when list(N), +%% record(EA, 'RequestedActions')-> +%% #'RequestedEvent'{pkgdName = N, +%% eventAction = EA}. + + +%% cre_RequestedEvent(N, SID, [H|_] = EPL) +%% when list(N), +%% integer(SID), +%% record(H, 'EventParameter') -> +%% #'RequestedEvent'{pkgdName = N, +%% streamID = SID, +%% evParList = EPL}; +%% cre_RequestedEvent(N, EA, [H|_] = EPL) +%% when list(N), +%% record(EA, 'RequestedActions'), +%% record(H, 'EventParameter') -> +%% #'RequestedEvent'{pkgdName = N, +%% eventAction = EA, +%% evParList = EPL}. + +%% cre_RequestedEvent(N, SID, EA, [H|_] = EPL) +%% when list(N), +%% integer(SID), +%% record(EA, 'RequestedActions'), +%% record(H, 'EventParameter') -> +%% #'RequestedEvent'{pkgdName = N, +%% streamID = SID, +%% eventAction = EA, +%% evParList = EPL}. + +%% cre_RequestedActions() -> +%% #'RequestedActions'{}. + +%% cre_RequestedActions(KA) +%% when (KA == true) or (KA == true) or (KA == asn1_NOVALUE) -> +%% #'RequestedActions'{keepActive = KA}; +%% cre_RequestedActions(SE) +%% when is_record(SE, 'SecondEventsDescriptor') or (SE == asn1_NOVALUE) -> +%% #'RequestedActions'{secondEvent = SE}; +%% cre_RequestedActions(SD) +%% when is_list(SD) or (SD == asn1_NOVALUE) -> +%% #'RequestedActions'{signalsDescriptor = SD}; +%% cre_RequestedActions({Tag, _} = EDM) +%% when is_atom(Tag) or (EDM == asn1_NOVALUE) -> +%% #'RequestedActions'{eventDM = EDM}. + +%% cre_RequestedActions(KA, {Tag, _} = EDM, SE, SD) +%% when ((KA == true) or (KA == true) or (KA == asn1_NOVALUE)) and +%% (is_atom(Tag) or (EDM == asn1_NOVALUE)) and +%% (is_record(SE, 'SecondEventsDescriptor') or (SE == asn1_NOVALUE)) and +%% (is_list(SD) or (SD == asn1_NOVALUE)) -> +%% #'RequestedActions'{keepActive = KA, +%% eventDM = EDM, +%% secondEvent = SE, +%% signalsDescriptor = SD}. + +%% cre_EventDM(N) when list(N) -> +%% {digitMapName, N}; +%% cre_EventDM(V) when record(V, 'DigitMapValue') -> +%% {digitMapValue, V}. + +%% cre_SecondEventsDescriptor([H|_] = EL) +%% when record(H, 'SecondRequestedEvent') -> +%% #'SecondEventsDescriptor'{eventList = EL}. + +%% cre_SecondEventsDescriptor(RID, [H|_] = EL) +%% when integer(RID), record(H, 'SecondRequestedEvent') -> +%% #'SecondEventsDescriptor'{requestID = RID, eventList = EL}. + +%% cre_SecondRequestedEvent(N, [H|_] = EPL) +%% when list(N), +%% record(H, 'EventParameter') -> +%% #'SecondRequestedEvent'{pkgdName = N, +%% evParList = EPL}. + +%% cre_SecondRequestedEvent(N, SID, [H|_] = EPL) +%% when list(N), +%% integer(SID), +%% record(H, 'EventParameter') -> +%% #'SecondRequestedEvent'{pkgdName = N, +%% streamID = SID, +%% evParList = EPL}; +%% cre_SecondRequestedEvent(N, EA, [H|_] = EPL) +%% when list(N), +%% record(EA, 'SecondRequestedActions'), +%% record(H, 'EventParameter') -> +%% #'SecondRequestedEvent'{pkgdName = N, +%% eventAction = EA, +%% evParList = EPL}. + +%% cre_SecondRequestedEvent(N, SID, EA, [H|_] = EPL) +%% when list(N), +%% integer(SID), +%% record(EA, 'SecondRequestedActions'), +%% record(H, 'EventParameter') -> +%% #'SecondRequestedEvent'{pkgdName = N, +%% streamID = SID, +%% eventAction = EA, +%% evParList = EPL}. + +%% cre_SecondRequestedActions() -> +%% #'SecondRequestedActions'{}. + +%% cre_SecondRequestedActions(KA) +%% when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) -> +%% #'SecondRequestedActions'{keepActive = KA}; +%% cre_SecondRequestedActions(SD) when list(SD) -> +%% #'SecondRequestedActions'{signalsDescriptor = SD}; +%% cre_SecondRequestedActions({Tag, _} = EDM) when atom(Tag) -> +%% #'SecondRequestedActions'{eventDM = EDM}. + +%% cre_SecondRequestedActions(KA, SD) +%% when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and +%% is_list(SD) -> +%% #'SecondRequestedActions'{keepActive = KA, signalsDescriptor = SD}; +%% cre_SecondRequestedActions(KA, {Tag, _} = EDM) +%% when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and +%% is_atom(Tag) -> +%% #'SecondRequestedActions'{keepActive = KA, eventDM = EDM}. + +%% cre_SecondRequestedActions(KA, {Tag, _} = EDM, SD) +%% when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and +%% is_atom(Tag), +%% is_list(SD) -> +%% #'SecondRequestedActions'{keepActive = KA, +%% eventDM = EDM, +%% signalsDescriptor = SD}. + +cre_EventBufferDescriptor([H|_] = D) + when is_record(H, 'EventSpec') -> + D. + +cre_EventSpec(N, [H|_] = EPL) + when is_list(N) andalso is_record(H, 'EventParameter') -> + #'EventSpec'{eventName = N, eventParList = EPL}. + +cre_EventSpec(N, SID, [H|_] = EPL) + when is_list(N) andalso is_integer(SID) andalso is_record(H, 'EventParameter') -> + #'EventSpec'{eventName = N, streamID = SID, eventParList = EPL}. + +%% cre_SignalsDescriptor(D) when list(D) -> +%% D. + +%% cre_SignalRequest(S) when record(S, 'Signal') -> +%% {signal, S}; +%% cre_SignalRequest(S) when record(S, 'SeqSigList') -> +%% {seqSigList, S}. + +%% cre_SeqSigList(ID, [H|_] = SL) +%% when integer(ID), 0 =< ID, ID =< 65535, record(H, 'Signal') -> +%% #'SeqSigList'{id = ID, signalList = SL}. + +%% cre_Signal(N) when list(N) -> +%% #'Signal'{signalName = N}. + +%% cre_Signal(N, [H|_] = SPL) when list(N), record(H, 'SigParameter') -> +%% #'Signal'{signalName = N, +%% sigParList = SPL}. + +%% cre_Signal(N, SID, ST, Dur, NC, KA, [H|_] = SPL) +%% when is_list(N) and +%% (is_integer(SID) or (SID == asn1_NOVALUE)) and +%% ((ST == brief) or (ST == onOff) or (ST == timeOut) or +%% (ST == asn1_NOVALUE)) and +%% ((is_integer(Dur) and (0 =< Dur) and (Dur =< 65535)) or +%% (Dur == asm1_NOVALUE)) and +%% is_list(NC) and +%% ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and +%% is_record(H, 'SigParameter') -> +%% #'Signal'{signalName = N, +%% streamID = SID, +%% sigType = ST, +%% duration = Dur, +%% notifyCompletion = NC, +%% keepActive = KA, +%% sigParList = SPL}. + +%% cre_SignalType(brief = ST) -> +%% ST; +%% cre_SignalType(onOff = ST) -> +%% ST; +%% cre_SignalType(timeOut = ST) -> +%% ST. + +%% cre_SignalName(N) -> +%% cre_PkgdName(N). + +%% cre_NotifyCompletion(L) when list(L) -> +%% Vals = [onTimeOut, onInterruptByEvent, +%% onInterruptByNewSignalDescr, otherReason], +%% F = fun(E) -> case lists:member(E, Vals) of +%% true -> +%% ok; +%% false -> +%% exit({invalid_NotifyCompletion, E}) +%% end +%% end, +%% lists:foreach(F, L), +%% L. + +%% cre_SigParameter(N, V) when list(N), list(V) -> +%% #'SigParameter'{sigParameterName = N, value = V}. + +%% cre_SigParameter(N, V, relation = Tag, R) +%% when is_list(N) and is_list(V) and is_atom(R) -> +%% EI = {Tag, R}, +%% #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}; +%% cre_SigParameter(N, V, range = Tag, B) +%% when is_list(N) and is_list(V) and is_atom(B) -> +%% EI = {Tag, B}, +%% #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}; +%% cre_SigParameter(N, V, sublist = Tag, B) +%% when is_list(N) and is_list(V) and is_atom(B) -> +%% EI = {Tag, B}, +%% #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}. + +%% cre_RequestID(Val) when 0 =< Val, Val =< 4294967295 -> +%% Val; +%% cre_RequestID(Val) -> +%% exit({invalid_RequestID, Val}). + +%% cre_ModemDescriptor(MTL, MPL) when list(MTL), list(MPL) -> +%% #'ModemDescriptor'{mtl = MTL, mpl = MPL}. + +%% %% cre_ModemDescriptor(MTL, MPL, NSD) +%% %% when list(MTL), list(MPL), record(NSD, 'NonStandardData') -> +%% %% #'ModemDescriptor'{mtl = MTL, mpl = MPL}. + +%% cre_ModemType(v18 = MT) -> +%% MT; +%% cre_ModemType(v22 = MT) -> +%% MT; +%% cre_ModemType(v22bis = MT) -> +%% MT; +%% cre_ModemType(v32 = MT) -> +%% MT; +%% cre_ModemType(v32bis = MT) -> +%% MT; +%% cre_ModemType(v34 = MT) -> +%% MT; +%% cre_ModemType(v90 = MT) -> +%% MT; +%% cre_ModemType(v91 = MT) -> +%% MT; +%% cre_ModemType(synchISDN = MT) -> +%% MT. + +%% cre_DigitMapDescriptor() -> +%% #'DigitMapDescriptor'{}. + +%% cre_DigitMapDescriptor(N) when list(N) -> +%% #'DigitMapDescriptor'{digitMapName = N}; +%% cre_DigitMapDescriptor(V) when record(V, 'DigitMapValue') -> +%% #'DigitMapDescriptor'{digitMapValue = V}. + +%% cre_DigitMapDescriptor(N, V) when list(N), record(V, 'DigitMapValue') -> +%% #'DigitMapDescriptor'{digitMapName = N, digitMapValue = V}. + +%% cre_DigitMapName(N) -> +%% cre_Name(N). + +%% cre_DigitMapValue(DMB) when list(DMB) -> +%% #'DigitMapValue'{digitMapBody = DMB}. + +%% cre_DigitMapValue(Start, Short, Long, DMB) -> +%% cre_DigitMapValue(Start, Short, Long, DMB, asn1_NOVALUE). + +%% cre_DigitMapValue(Start, Short, Long, DMB, Dur) +%% when ((is_integer(Start) and (0 =< Start) and (Start =< 99)) or +%% (Start == asn1_NOVALUE)) and +%% ((is_integer(Short) and (0 =< Short) and (Short =< 99)) or +%% (Short == asn1_NOVALUE)) and +%% ((is_integer(Long) and (0 =< Long) and (Long =< 99)) or +%% (Long == asn1_NOVALUE)) and +%% is_list(DMB) and +%% ((is_integer(Dur) and (0 =< Dur) and (Dur =< 99)) or +%% (Dur == asn1_NOVALUE)) -> +%% #'DigitMapValue'{startTimer = Start, +%% shortTimer = Short, +%% longTimer = Long, +%% digitMapBody = DMB, +%% durationTimer = Dur}. + +%% cre_ServiceChangeParm(M, R) when atom(M), list(R) -> +%% #'ServiceChangeParm'{serviceChangeMethod = M, +%% serviceChangeReason = R}. + +%% cre_ServiceChangeParm(M, Addr, Prof, Reason) -> +%% cre_ServiceChangeParm(M, Addr, asn1_NOVALUE, Prof, Reason, asn1_NOVALUE, +%% asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE). + +%% %% Addr = asn1_NOVALUE | {AddrTag, AddrVal} +%% cre_ServiceChangeParm(M, Addr, Ver, Prof, R, D, Mid, TS, I) +%% when is_atom(M) and +%% ((is_integer(Ver) and (0 =< Ver) and (Ver =< 99)) or +%% (Ver == asn1_NOVALUE)) and +%% (is_record(Prof, 'ServiceChangeProfile') or (Prof == asn1_NOVALUE)) and +%% is_list(R) and +%% ((is_integer(D) and (0 =< D) and (D =< 4294967295)) or +%% (D == asn1_NOVALUE)) and +%% (is_record(TS, 'TimeNotation') or (TS == asn1_NOVALUE)) and +%% (is_record(I, 'AuditDescriptor') or (I == asn1_NOVALUE)) -> +%% F = fun(A) -> +%% (A == asn1_NOVALUE) orelse +%% (is_tuple(A) +%% andalso is_atom(element(1, A))) +%% end, +%% case (F(Addr) andalso F(Mid)) of +%% true -> +%% #'ServiceChangeParm'{serviceChangeMethod = M, +%% serviceChangeAddress = Addr, +%% serviceChangeVersion = Ver, +%% serviceChangeProfile = Prof, +%% serviceChangeReason = R, +%% serviceChangeDelay = D, +%% serviceChangeMgcId = Mid, +%% timeStamp = TS, +%% serviceChangeInfo = I}; +%% _ -> +%% exit({invalid_ServiceChangeParm_args, {Addr, Mid}}) +%% end. + +%% cre_ServiceChangeAddress(portNumber = Tag, P) +%% when integer(P), 0 =< P, P =< 65535 -> +%% {Tag, P}; +%% cre_ServiceChangeAddress(ip4Address = Tag, A) when record(A, 'IP4Address') -> +%% {Tag, A}; +%% cre_ServiceChangeAddress(ip6Address = Tag, A) when record(A, 'IP6Address') -> +%% {Tag, A}; +%% cre_ServiceChangeAddress(domainName = Tag, N) when record(N, 'DomainName') -> +%% {Tag, N}; +%% cre_ServiceChangeAddress(deviceName = Tag, N) when list(N) -> +%% {Tag, N}; +%% cre_ServiceChangeAddress(mtpAddress = Tag, A) when list(A) -> +%% {Tag, A}. + +%% cre_ServiceChangeResParm() -> +%% #'ServiceChangeResParm'{}. +%% cre_ServiceChangeResParm(Addr, Prof) -> +%% cre_ServiceChangeResParm(asn1_NOVALUE, Addr, asn1_NOVALUE, +%% Prof, asn1_NOVALUE). +%% cre_ServiceChangeResParm(Mid, Addr, Ver, Prof, TS) +%% when ((is_integer(Ver) and (0 =< Ver) and (Ver =< 99)) or +%% (Ver == asn1_NOVALUE)) and +%% (is_record(Prof, 'ServiceChangeProfile') or (Prof == asn1_NOVALUE)) and +%% (is_record(TS, 'TimeNotation') or (TS == asn1_NOVALUE)) -> +%% F = fun(A) -> +%% (A == asn1_NOVALUE) orelse +%% (is_tuple(A) +%% andalso is_atom(element(1, A))) +%% end, +%% case (F(Addr) andalso F(Mid)) of +%% true -> +%% #'ServiceChangeResParm'{serviceChangeMgcId = Mid, +%% serviceChangeAddress = Addr, +%% serviceChangeVersion = Ver, +%% serviceChangeProfile = Prof, +%% timeStamp = TS}; +%% _ -> +%% exit({invalid_ServiceChangeResParm_args, {Addr, Mid}}) +%% end. + +%% cre_ServiceChangeMethod(failover = M) -> +%% M; +%% cre_ServiceChangeMethod(forced = M) -> +%% M; +%% cre_ServiceChangeMethod(graceful = M) -> +%% M; +%% cre_ServiceChangeMethod(restart = M) -> +%% M; +%% cre_ServiceChangeMethod(disconnected = M) -> +%% M; +%% cre_ServiceChangeMethod(handOff = M) -> +%% M. + +%% %% The version field is added to make it look more like ABNF +%% cre_ServiceChangeProfile(N) -> +%% cre_ServiceChangeProfile(N, 1). + +%% cre_ServiceChangeProfile(N, V) +%% when is_list(N) and is_integer(V) and (0 =< V) and (V =< 99) -> +%% #'ServiceChangeProfile'{profileName = N, version = V}. + +%% cre_PackagesDescriptor([H|_] = D) when record(H, 'PackagesItem') -> +%% D. + +%% cre_PackagesItem(N, Ver) when list(N), integer(Ver), 0 =< Ver, Ver =< 99 -> +%% #'PackagesItem'{packageName = N, +%% packageVersion = Ver}. + +%% cre_StatisticsDescriptor([H|_] = D) when record(H, 'StatisticsParameter') -> +%% D. + +%% cre_StatisticsParameter(N) when list(N) -> +%% #'StatisticsParameter'{statName = N}. + +%% cre_StatisticsParameter(N, V) when list(N), list(V) -> +%% #'StatisticsParameter'{statName = N, statValue = V}. + +%% %% cre_NonStandardData({Tag, _} = Id, Data) when atom(Tag), list(Data) -> +%% %% #'NonStandardData'{nonStandardIdentifier = Id, data = Data}. + +%% %% cre_NonStandardIdentifier(H221) when record(H221, 'H221NonStandard') -> +%% %% {h221NonStandard, H221}; +%% %% cre_NonStandardIdentifier(Obj) when tuple(Obj) -> +%% %% {object, Obj}; +%% %% cre_NonStandardIdentifier(Exp) when list(Exp), length(Exp) == 8 -> +%% %% {experimental, Exp}. + +%% %% cre_H221NonStandard(CC1, CC2, Ext, MC) +%% %% when (is_integer(CC1) and (0 =< CC1) and (CC1 =< 255)) and +%% %% (is_integer(CC2) and (0 =< CC2) and (CC2 =< 255)) and +%% %% (is_integer(Ext) and (0 =< Ext) and (Ext =< 255)) and +%% %% (is_integer(MC) and (0 =< MC) and (MC =< 255)) -> +%% %% #'H221NonStandard'{t35CountryCode1 = CC1, +%% %% t35CountryCode2 = CC2, +%% %% t35Extension = Ext, +%% %% manufacturerCode = MC}. + +%% cre_TimeNotation(D, T) +%% when list(D), length(D) == 8, list(T), length(T) == 8 -> +%% #'TimeNotation'{date = D, time = T}. + +%% cre_Value([H|_] = V) when list(H) -> +%% V. + +cre_BOOLEAN(true = B) -> + B; +cre_BOOLEAN(false = B) -> + B. + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% %% -- MegacoMessage -- + +%% is_MegacoMessage(#'MegacoMessage'{authHeader = Auth, +%% mess = Mess}) -> +%% is_opt_AuthenticationHeader(Auth) andalso is_Message(Mess); +%% is_MegacoMessage(_) -> +%% false. + + +%% chk_MegacoMessage(M, M) -> +%% chk_type(fun is_MegacoMessage/1, 'MegacoMessage', M); +%% chk_MegacoMessage(#'MegacoMessage'{authHeader = Auth1, +%% mess = Mess1}, +%% #'MegacoMessage'{authHeader = Auth2, +%% mess = Mess2}) -> +%% chk_opt_AuthenticationHeader(Auth1,Auth2), +%% chk_Message(Mess1,Mess2), +%% ok; +%% chk_MegacoMessage(M1, M2) -> +%% wrong_type('MegacoMessage', M1, M2). + + +%% %% -- AuthenticationHeader -- + +%% is_opt_AuthenticationHeader(AH) -> +%% is_OPTIONAL(fun is_AuthenticationHeader/1, AH). + +%% is_AuthenticationHeader(#'AuthenticationHeader'{secParmIndex = SPI, +%% seqNum = SN, +%% ad = AD}) -> +%% is_SecurityParmIndex(SPI) andalso +%% is_SequenceNum(SN) andalso +%% is_AuthData(AD); +%% is_AuthenticationHeader(_) -> +%% false. + +%% %% This stuff is not really used, so make it simple... +%% chk_opt_AuthenticationHeader(A1, A2) -> +%% chk_OPTIONAL('AuthenticationHeader', A1, A2, +%% fun is_AuthenticationHeader/1, +%% fun chk_AuthenticationHeader/2). + +%% chk_AuthenticationHeader(A, A) -> +%% chk_type(fun is_AuthenticationHeader/1, 'AuthenticationHeader', A); +%% chk_AuthenticationHeader(A1, A2) -> +%% case (is_AuthenticationHeader(A1) andalso is_AuthenticationHeader(A2)) of +%% true -> +%% not_equal('AuthenticationHeader', A1, A2); +%% false -> +%% wrong_type('AuthenticationHeader', A1, A2) +%% end. + + +%% %% -- SecurityParmIndex -- + +%% is_SecurityParmIndex(V) -> is_OCTET_STRING(V, {exact, 4}). + + +%% %% -- SequenceNum -- + +%% is_SequenceNum(V) -> is_OCTET_STRING(V, {exact, 4}). + + +%% %% -- AuthData -- + +%% is_AuthData(V) -> is_OCTET_STRING(V, {range, 12, 32}). + + +%% %% -- Message -- + +%% is_Message(#'Message'{version = V, +%% mId = MID, +%% messageBody = Body}) -> +%% is_INTEGER(V, {range, 0, 99}) andalso +%% is_MId(MID) andalso +%% is_Message_messageBody(Body); +%% is_Message(_) -> +%% false. + +%% chk_Message(M,M) when record(M,'Message') -> +%% ok; +%% chk_Message(#'Message'{version = V1, +%% mId = MID1, +%% messageBody = Body1}, +%% #'Message'{version = V2, +%% mId = MID2, +%% messageBody = Body2}) -> +%% validate(fun() -> chk_INTEGER(V1, V2, {range, 0, 99}) end, 'Message'), +%% validate(fun() -> chk_MId(MID1, MID2) end, 'Message'), +%% chk_Message_messageBody(Body1, Body2), +%% ok; +%% chk_Message(M1, M2) -> +%% wrong_type('Message', M1, M2). + + +%% is_Message_messageBody({Tag, Val}) -> +%% is_Message_messageBody_tag(Tag) andalso +%% is_Message_messageBody_val(Tag, Val); +%% is_Message_messageBody(_) -> +%% false. + +%% is_Message_messageBody_tag(Tag) -> +%% Tags = [messageError, transactions], +%% lists:member(Tag, Tags). + +%% is_Message_messageBody_val(messageError, Val) -> +%% is_ErrorDescriptor(Val); +%% is_Message_messageBody_val(transactions, Val) -> +%% is_Message_messageBody_transactions(Val). + +%% is_Message_messageBody_transactions([]) -> +%% true; +%% is_Message_messageBody_transactions([H|T]) -> +%% is_Transaction(H) andalso is_Message_messageBody_transactions(T); +%% is_Message_messageBody_transactions(_) -> +%% false. + +%% chk_Message_messageBody(B, B) -> +%% chk_type(fun is_Message_messageBody/1, 'Message_messageBody', B); +%% chk_Message_messageBody({Tag, Val1} = B1, {Tag, Val2} = B2) -> +%% case (is_Message_messageBody_tag(Tag) andalso +%% is_Message_messageBody_val(Tag, Val1) andalso +%% is_Message_messageBody_val(Tag, Val2)) of +%% true -> +%% chk_Message_messageBody_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('Message_messageBody', B1, B2) +%% end; +%% chk_Message_messageBody({Tag1, Val1} = B1, {Tag2, Val2} = B2) -> +%% case ((is_Message_messageBody_tag(Tag1) andalso +%% is_Message_messageBody_val(Tag1, Val1)) andalso +%% (is_Message_messageBody_tag(Tag2) andalso +%% is_Message_messageBody_val(Tag2, Val2))) of +%% true -> +%% not_equal('Message_messageBody', B1, B2); +%% false -> +%% wrong_type('Message_messageBody', B1, B2) +%% end; +%% chk_Message_messageBody(B1, B2) -> +%% wrong_type('Message_messageBody', B1, B2). + +%% chk_Message_messageBody_val(messageError, Val1, Val2) -> +%% validate(fun() -> chk_ErrorDescriptor(Val1, Val2) end, +%% 'Message_messageBody'); +%% chk_Message_messageBody_val(transactions, Val1, Val2) -> +%% chk_Message_messageBody_transactions(Val1, Val2). + +%% chk_Message_messageBody_transactions([], []) -> +%% ok; +%% chk_Message_messageBody_transactions([] = T1, T2) -> +%% not_equal('Message_messageBody_transactions', T1, T2); +%% chk_Message_messageBody_transactions(T1, [] = T2) -> +%% not_equal('Message_messageBody_transactions', T1, T2); +%% chk_Message_messageBody_transactions([H|T1], [H|T2]) -> +%% case is_Transaction(H) of +%% true -> +%% chk_Message_messageBody_transactions(T1, T2); +%% false -> +%% wrong_type('Message_messageBody_transactions_val', H) +%% end; +%% chk_Message_messageBody_transactions([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_Transaction(H1, H2) end, +%% 'Message_messageBody_transactions_val'), +%% chk_Message_messageBody_transactions(T1, T2); +%% chk_Message_messageBody_transactions(T1, T2) -> +%% wrong_type('Message_messageBody_transactions', T1, T2). + + +%% %% -- MId -- + +%% is_opt_MId(M) -> +%% is_OPTIONAL(fun is_MId/1, M). + +%% is_MId({Tag, Val}) -> +%% is_MId_tag(Tag) andalso is_MId_val(Tag, Val); +%% is_MId(_) -> +%% false. + +%% is_MId_tag(Tag) -> +%% Tags = [ip4Address, ip6Address, domainName, deviceName, mtpAddress], +%% lists:member(Tag, Tags). + +%% is_MId_val(ip4Address, Val) -> is_IP4Address(Val); +%% is_MId_val(ip6Address, Val) -> is_IP6Address(Val); +%% is_MId_val(domainName, Val) -> is_DomainName(Val); +%% is_MId_val(deviceName, Val) -> is_PathName(Val); +%% is_MId_val(mtpAddress, Val) -> is_OCTET_STRING(Val, {range, 2, 4}). + +%% chk_opt_MId(M1, M2) -> +%% chk_OPTIONAL('MId', M1, M2, fun is_MId/1, fun chk_MId/2). + +%% chk_MId(M, M) -> +%% chk_type(fun is_MId/1, 'MId', M); +%% chk_MId({Tag, Val1} = M1, {Tag, Val2} = M2) -> +%% case (is_MId_tag(Tag) andalso +%% is_MId_val(Tag, Val1) andalso +%% is_MId_val(Tag, Val2)) of +%% true -> +%% chk_MId_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('MId', M1, M2) +%% end; +%% chk_MId({Tag1, Val1} = M1, {Tag2, Val2} = M2) -> +%% case ((is_MId_tag(Tag1) andalso +%% is_MId_val(Tag1, Val1)) andalso +%% (is_MId_tag(Tag2) andalso +%% is_MId_val(Tag2, Val2))) of +%% true -> +%% not_equal('MId', M1, M2); +%% false -> +%% wrong_type('MId', M1, M2) +%% end; +%% chk_MId(M1, M2) -> +%% wrong_type('MId', M1, M2). + +%% chk_MId_val(ip4Address, M1, M2) -> chk_IP4Address(M1, M2); +%% chk_MId_val(ip6Address, M1, M2) -> chk_IP6Address(M1, M2); +%% chk_MId_val(domainName, M1, M2) -> chk_DomainName(M1, M2); +%% chk_MId_val(deviceName, M1, M2) -> chk_PathName(M1, M2); +%% chk_MId_val(mtpAddress, M1, M2) -> chk_OCTET_STRING(M1, M2, {range, 2, 4}). + + +%% %% -- DomainName -- + +%% is_DomainName(#'DomainName'{name = N, portNumber = PN}) -> +%% is_IA5String(N) andalso is_opt_INTEGER(PN, {range, 0, 65535}); +%% is_DomainName(_) -> +%% false. + +%% chk_DomainName(N, N) -> +%% ok; +%% chk_DomainName(N1, N2) -> +%% not_equal('DomainName', N1, N2). + + +%% %% -- IP4Address -- + +%% is_IP4Address(#'IP4Address'{address = A, portNumber = PN}) -> +%% is_OCTET_STRING(A, {exact, 4}) andalso +%% is_opt_INTEGER(PN, {range, 0, 65535}); +%% is_IP4Address(_) -> +%% false. + +%% chk_IP4Address(A, A) -> +%% ok; +%% chk_IP4Address(A1, A2) -> +%% not_equal('IP4Address', A1, A2). + + +%% %% -- IP6Address -- + +%% is_IP6Address(#'IP6Address'{address = A, portNumber = PN}) -> +%% is_OCTET_STRING(A, {exact, 16}) andalso +%% is_opt_INTEGER(PN, {range, 0, 65535}); +%% is_IP6Address(_) -> +%% false. + +%% chk_IP6Address(A, A) -> +%% ok; +%% chk_IP6Address(A1, A2) -> +%% not_equal('IP6Address', A1, A2). + + +%% %% -- PathName -- + +%% is_PathName(N) -> is_IA5String(N, {range, 1, 64}). + +%% chk_PathName(N, N) -> +%% ok; +%% chk_PathName(N1, N2) -> +%% not_equal('PathName', N1, N2). + + +%% %% -- Transaction -- + +%% is_Transaction({Tag, Val}) -> +%% is_Transaction_tag(Tag) andalso is_Transaction_val(Tag, Val); +%% is_Transaction(_) -> +%% false. + +%% is_Transaction_tag(Tag) -> +%% Tags = [transactionRequest, +%% transactionPending, +%% transactionReply, +%% transactionResponseAck], +%% lists:member(Tag, Tags). + +%% is_Transaction_val(transactionRequest, V) -> is_TransactionRequest(V); +%% is_Transaction_val(transactionPending, V) -> is_TransactionPending(V); +%% is_Transaction_val(transactionReply, V) -> is_TransactionReply(V); +%% is_Transaction_val(transactionResponseAck, V) -> is_TransactionResponseAck(V). + + +%% chk_Transaction({Tag, Val} = Trans, {Tag, Val}) -> +%% case (is_Transaction_tag(Tag) andalso is_Transaction_val(Tag, Val)) of +%% true -> +%% ok; +%% false -> +%% wrong_type('Transaction', Trans, Trans) +%% end; +%% chk_Transaction({Tag, Val1} = Trans1, {Tag, Val2} = Trans2) -> +%% case (is_Transaction_tag(Tag) and +%% is_Transaction_val(Tag, Val1) and +%% is_Transaction_val(Tag, Val2)) of +%% true -> +%% chk_Transaction_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('Transaction', Trans1, Trans2) +%% end; +%% chk_Transaction({Tag1, Val1} = Trans1, {Tag2, Val2} = Trans2) -> +%% case ((is_Transaction_tag(Tag1) andalso +%% is_Transaction_val(Tag1, Val1)) andalso +%% (is_Transaction_tag(Tag2) andalso +%% is_Transaction_val(Tag2, Val2))) of +%% true -> +%% not_equal('Transaction', Trans1, Trans2); +%% false -> +%% wrong_type('Transaction', Trans1, Trans2) +%% end; +%% chk_Transaction(Trans1, Trans2) -> +%% wrong_type('Transaction', Trans1, Trans2). + +%% chk_Transaction_val(transactionRequest, T1, T2) -> +%% chk_TransactionRequest(T1, T2); +%% chk_Transaction_val(transactionPending, T1, T2) -> +%% chk_TransactionPending(T1, T2); +%% chk_Transaction_val(transactionReply, T1, T2) -> +%% chk_TransactionReply(T1,T2); +%% chk_Transaction_val(transactionResponseAck, T1, T2) -> +%% chk_TransactionResponseAck(T1, T2). + + +%% %% -- TransactionId -- + +%% is_opt_TransactionId(TID) -> +%% is_OPTIONAL(fun is_TransactionId/1, TID). + +%% is_TransactionId(TID) -> is_INTEGER(TID, {range, 0, 4294967295}). + +%% chk_opt_TransactionId(TID1, TID2) -> +%% chk_OPTIONAL('TransactionId', TID1, TID2, +%% fun is_TransactionId/1, fun chk_TransactionId/2). + +%% chk_TransactionId(TID, TID) -> +%% chk_type(fun is_TransactionId/1, 'TransactionId', TID); +%% chk_TransactionId(TID1, TID2) -> +%% case (is_TransactionId(TID1) andalso is_TransactionId(TID2)) of +%% true -> +%% not_equal('TransactionId', TID1, TID2); +%% false -> +%% wrong_type('TransactionId', TID1, TID2) +%% end. + + +%% %% -- TransactionRequest -- + +%% is_TransactionRequest(#'TransactionRequest'{transactionId = TID, +%% actions = Acts}) -> +%% is_TransactionId(TID) andalso is_TransactionRequest_actions(Acts); +%% is_TransactionRequest(_) -> +%% false. + +%% chk_TransactionRequest(T, T) -> +%% chk_type(fun is_TransactionRequest/1, 'TransactionRequest', T); +%% chk_TransactionRequest(#'TransactionRequest'{transactionId = TID1, +%% actions = Acts1}, +%% #'TransactionRequest'{transactionId = TID2, +%% actions = Acts2}) -> +%% validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionRequest'), +%% chk_TransactionRequest_actions(Acts1, Acts2), +%% ok; +%% chk_TransactionRequest(T1, T2) -> +%% wrong_type('TransactionRequest', T1, T2). + +%% is_TransactionRequest_actions([]) -> +%% true; +%% is_TransactionRequest_actions([H|T]) -> +%% is_ActionRequest(H) andalso is_TransactionRequest_actions(T); +%% is_TransactionRequest_actions(_) -> +%% false. + +%% chk_TransactionRequest_actions([], []) -> +%% ok; +%% chk_TransactionRequest_actions([] = Acts1, Acts2) -> +%% not_equal('TransactionRequest_actions', Acts1, Acts2); +%% chk_TransactionRequest_actions(Acts1, [] = Acts2) -> +%% not_equal('TransactionRequest_actions', Acts1, Acts2); +%% chk_TransactionRequest_actions([H|T1], [H|T2]) -> +%% case is_ActionRequest(H) of +%% true -> +%% chk_TransactionRequest_actions(T1, T2); +%% false -> +%% wrong_type('TransactionRequest_actions_val', H) +%% end; +%% chk_TransactionRequest_actions([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_ActionRequest(H1, H2) end, +%% 'TransactionRequest_actions_val'), +%% chk_TransactionRequest_actions(T1, T2); +%% chk_TransactionRequest_actions(Acts1, Acts2) -> +%% wrong_type('TransactionRequest_actions', Acts1, Acts2). + + +%% %% -- TransactionPending -- + +%% is_TransactionPending(#'TransactionPending'{transactionId = TID}) -> +%% is_TransactionId(TID); +%% is_TransactionPending(_) -> +%% false. + +%% chk_TransactionPending(T, T) -> +%% chk_type(fun is_TransactionPending/1, 'TransactionPending', T); +%% chk_TransactionPending(#'TransactionPending'{transactionId = TID1}, +%% #'TransactionPending'{transactionId = TID2}) -> +%% validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionPending'), +%% ok; +%% chk_TransactionPending(T1, T2) -> +%% wrong_type('TransactionPending', T1, T2). + + +%% %% -- TransactionReply -- + +%% is_TransactionReply(#'TransactionReply'{transactionId = TID, +%% immAckRequired = IAR, +%% transactionResult = TR}) -> +%% is_TransactionId(TID) andalso +%% is_opt_NULL(IAR) andalso +%% is_TransactionReply_transactionResult(TR); +%% is_TransactionReply(_) -> +%% false. + +%% chk_TransactionReply(T, T) -> +%% chk_type(fun is_TransactionReply/1, 'TransactionReply', T); +%% chk_TransactionReply(#'TransactionReply'{transactionId = TID1, +%% immAckRequired = IAR1, +%% transactionResult = TR1}, +%% #'TransactionReply'{transactionId = TID2, +%% immAckRequired = IAR2, +%% transactionResult = TR2}) -> +%% validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionReply'), +%% validate(fun() -> chk_opt_NULL(IAR1, IAR2) end, 'TransactionReply'), +%% chk_TransactionReply_transactionResult(TR1, TR2), +%% ok; +%% chk_TransactionReply(T1, T2) -> +%% wrong_type('TransactionReply', T1, T2). + +%% is_TransactionReply_transactionResult({Tag, Val}) -> +%% is_TransactionReply_transactionResult_tag(Tag) andalso +%% is_TransactionReply_transactionResult_val(Tag, Val); +%% is_TransactionReply_transactionResult(_) -> +%% false. + +%% is_TransactionReply_transactionResult_tag(T) -> +%% lists:member(T, [transactionError, actionReplies]). + +%% is_TransactionReply_transactionResult_val(transactionError, V) -> +%% is_ErrorDescriptor(V); +%% is_TransactionReply_transactionResult_val(actionReplies, V) -> +%% is_TransactionReply_actionReplies(V). + +%% chk_TransactionReply_transactionResult(Res, Res) -> +%% chk_type(fun is_TransactionReply_transactionResult/1, +%% 'TransactionReply_transactionResult', Res); +%% chk_TransactionReply_transactionResult({Tag, Val1} = Res1, +%% {Tag, Val2} = Res2) -> +%% case (is_TransactionReply_transactionResult_tag(Tag) and +%% is_TransactionReply_transactionResult_val(Tag, Val1) and +%% is_TransactionReply_transactionResult_val(Tag, Val2)) of +%% true -> +%% chk_TransactionReply_transactionResult_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('TransactionReply_transactionResult', Res1, Res2) +%% end; +%% chk_TransactionReply_transactionResult({Tag1, Val1} = Res1, +%% {Tag2, Val2} = Res2) -> +%% case ((is_TransactionReply_transactionResult_tag(Tag1) and +%% is_TransactionReply_transactionResult_val(Tag1, Val1)) and +%% (is_TransactionReply_transactionResult_tag(Tag2) and +%% is_TransactionReply_transactionResult_val(Tag2, Val2))) of +%% true -> +%% not_equal('TransactionReply_transactionResult', Res1, Res2); +%% false -> +%% wrong_type('TransactionReply_transactionResult', Res1, Res2) +%% end; +%% chk_TransactionReply_transactionResult(Res1, Res2) -> +%% wrong_type('TransactionReply_transactionResult', Res1, Res2). + +%% chk_TransactionReply_transactionResult_val(transactionError, E1, E2) -> +%% validate(fun() -> chk_ErrorDescriptor(E1, E2) end, +%% 'TransactionReply_transactionResult'); +%% chk_TransactionReply_transactionResult_val(actionReplies, R1, R2) -> +%% validate(fun() -> chk_TransactionReply_actionReplies(R1, R2) end, +%% 'TransactionReply_transactionResult'). + +%% is_TransactionReply_actionReplies([]) -> +%% true; +%% is_TransactionReply_actionReplies([H|T]) -> +%% is_ActionReply(H) andalso is_TransactionReply_actionReplies(T); +%% is_TransactionReply_actionReplies(_) -> +%% false. + +%% chk_TransactionReply_actionReplies([], []) -> +%% ok; +%% chk_TransactionReply_actionReplies([] = AR1, AR2) -> +%% not_equal('TransactionReply_actionReplies', AR1, AR2); +%% chk_TransactionReply_actionReplies(AR1, [] = AR2) -> +%% not_equal('TransactionReply_actionReplies', AR1, AR2); +%% chk_TransactionReply_actionReplies([H|T1], [H|T2]) -> +%% case is_ActionReply(H) of +%% true -> +%% chk_TransactionReply_actionReplies(T1, T2); +%% false -> +%% wrong_type('TransactionReply_actionReplies_val', H) +%% end; +%% chk_TransactionReply_actionReplies([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_ActionReply(H1, H2) end, +%% 'TransactionReply_actionReplies_val'), +%% chk_TransactionReply_actionReplies(T1, T2); +%% chk_TransactionReply_actionReplies(AR1, AR2) -> +%% wrong_type('TransactionReply_actionReplies', AR1, AR2). + + +%% %% -- TransactionResponseAck -- + +%% is_TransactionResponseAck([]) -> +%% true; +%% is_TransactionResponseAck([H|T]) -> +%% is_TransactionAck(H) andalso is_TransactionResponseAck(T); +%% is_TransactionResponseAck(_) -> +%% false. + +%% chk_TransactionResponseAck([], []) -> +%% ok; +%% chk_TransactionResponseAck([] = AR1, AR2) -> +%% not_equal('TransactionResponseAck', AR1, AR2); +%% chk_TransactionResponseAck(AR1, [] = AR2) -> +%% not_equal('TransactionResponseAck', AR1, AR2); +%% chk_TransactionResponseAck([H|T1], [H|T2]) -> +%% case is_TransactionAck(H) of +%% true -> +%% chk_TransactionResponseAck(T1, T2); +%% false -> +%% wrong_type('TransactionResponseAck_val', H) +%% end; +%% chk_TransactionResponseAck([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_TransactionAck(H1, H2) end, +%% 'TransactionResponseAck'), +%% chk_TransactionResponseAck(T1, T2); +%% chk_TransactionResponseAck(AR1, AR2) -> +%% wrong_type('TransactionResponseAck', AR1, AR2). + + +%% %% -- TransactionAck -- + +%% is_TransactionAck(#'TransactionAck'{firstAck = F, +%% lastAck = L}) -> +%% is_TransactionId(F) andalso is_opt_TransactionId(L); +%% is_TransactionAck(_) -> +%% false. + +%% chk_TransactionAck(T, T) -> +%% chk_type(fun is_TransactionAck/1, 'TransactionAck', T); +%% chk_TransactionAck(#'TransactionAck'{firstAck = F1, +%% lastAck = L1}, +%% #'TransactionAck'{firstAck = F2, +%% lastAck = L2}) -> +%% validate(fun() -> chk_TransactionId(F1, F2) end, 'TransactionAck'), +%% validate(fun() -> chk_opt_TransactionId(L1, L2) end, 'TransactionAck'), +%% ok; +%% chk_TransactionAck(T1, T2) -> +%% wrong_type('TransactionAck', T1, T2). + + +%% %% -- ErrorDescriptor -- + +%% is_opt_ErrorDescriptor(V) -> +%% is_OPTIONAL(fun is_ErrorDescriptor/1, V). + +%% is_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code, +%% errorText = Text}) -> +%% is_ErrorCode(Code) andalso is_opt_ErrorText(Text); +%% is_ErrorDescriptor(_) -> +%% false. + +%% chk_opt_ErrorDescriptor(E1, E2) -> +%% chk_OPTIONAL('ErrorDescriptor', E1, E2, +%% fun is_ErrorDescriptor/1, fun chk_ErrorDescriptor/2). + +%% chk_ErrorDescriptor(E, E) -> +%% chk_type(fun is_ErrorDescriptor/1, 'ErrorDescriptor', E); +%% chk_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code1, +%% errorText = Text1}, +%% #'ErrorDescriptor'{errorCode = Code2, +%% errorText = Text2}) -> +%% chk_ErrorCode(Code1, Code2), +%% chk_opt_ErrorText(Text1, Text2), +%% ok; +%% chk_ErrorDescriptor(E1, E2) -> +%% wrong_type('ErrorDescriptor', E1, E2). + + +%% %% -- ErrorCode -- + +%% is_ErrorCode(C) -> is_INTEGER(C, {range, 0, 65535}). + +%% chk_ErrorCode(C, C) -> +%% case is_ErrorCode(C) of +%% true -> +%% ok; +%% false -> +%% wrong_type(errorCode, C, C) +%% end; +%% chk_ErrorCode(C1, C2) -> +%% case (is_ErrorCode(C1) andalso is_ErrorCode(C2)) of +%% true -> +%% not_equal(errorCode, C1, C2); +%% false -> +%% wrong_type(errorCode, C1, C2) +%% end. + + +%% %% -- ErrorText -- + +%% is_opt_ErrorText(V) -> +%% is_OPTIONAL(fun is_ErrorText/1, V). + +%% is_ErrorText(V) -> is_IA5String(V). + +%% chk_opt_ErrorText(T1, T2) -> +%% chk_OPTIONAL('ErrorText', T1, T2, fun is_ErrorText/1, fun chk_ErrorText/2). + +%% chk_ErrorText(T, T) -> +%% chk_type(fun is_ErrorText/1, 'ErrorText', T); +%% chk_ErrorText(T1, T2) -> +%% case (is_ErrorText(T1) andalso is_ErrorText(T2)) of +%% true -> +%% case {to_lower(T1), to_lower(T2)} of +%% {T, T} -> +%% ok; +%% _ -> +%% not_equal('ErrorText', T1, T2) +%% end; +%% false -> +%% wrong_type('ErrorText', T1, T2) +%% end. + + +%% %% -- ContextID -- + +%% is_ContextID(Id) -> is_INTEGER(Id, {range, 0, 4294967295}). + +%% chk_ContextID(Id, Id) -> +%% chk_type(fun is_ContextID/1, 'ContextID', Id); +%% chk_ContextID(Id1, Id2) -> +%% case (is_ContextID(Id1) andalso is_ContextID(Id2)) of +%% true -> +%% not_equal('ContextID', Id1, Id2); +%% false -> +%% wrong_type('ContextID', Id1, Id2) +%% end. + + +%% %% -- ActionRequest -- + +%% is_ActionRequest(#'ActionRequest'{contextId = Id, +%% contextRequest = CtxReq, +%% contextAttrAuditReq = AuditReq, +%% commandRequests = CmdReqs}) -> +%% is_ContextID(Id) andalso +%% is_opt_ContextRequest(CtxReq) andalso +%% is_opt_ContextAttrAuditRequest(AuditReq) andalso +%% is_ActionRequest_commandRequests(CmdReqs); +%% is_ActionRequest(_) -> +%% false. + +%% chk_ActionRequest(A, A) -> +%% chk_type(fun is_ActionRequest/1, 'ActionRequest', A); +%% chk_ActionRequest(#'ActionRequest'{contextId = Id1, +%% contextRequest = Req1, +%% contextAttrAuditReq = AuditReq1, +%% commandRequests = CmdReqs1}, +%% #'ActionRequest'{contextId = Id2, +%% contextRequest = Req2, +%% contextAttrAuditReq = AuditReq2, +%% commandRequests = CmdReqs2}) -> +%% validate(fun() -> chk_ContextID(Id1, Id2) end, 'ActionRequest'), +%% validate(fun() -> chk_opt_ContextRequest(Req1, Req2) end, 'ActionRequest'), +%% validate(fun() -> +%% chk_opt_ContextAttrAuditRequest(AuditReq1, AuditReq2) +%% end, +%% 'ActionRequest'), +%% chk_ActionRequest_commandRequests(CmdReqs1, CmdReqs2), +%% ok. + + +%% is_ActionRequest_commandRequests([]) -> +%% true; +%% is_ActionRequest_commandRequests([H|T]) -> +%% is_CommandRequest(H) andalso is_ActionRequest_commandRequests(T); +%% is_ActionRequest_commandRequests(_) -> +%% false. + +%% chk_ActionRequest_commandRequests([], []) -> +%% ok; +%% chk_ActionRequest_commandRequests([] = CmdReqs1, CmdReqs2) -> +%% not_equal('ActionRequest_commandRequests', CmdReqs1, CmdReqs2); +%% chk_ActionRequest_commandRequests(CmdReqs1, [] = CmdReqs2) -> +%% not_equal('ActionRequest_commandRequests', CmdReqs1, CmdReqs2); +%% chk_ActionRequest_commandRequests([H|T1], [H|T2]) -> +%% case is_CommandRequest(H) of +%% true -> +%% chk_ActionRequest_commandRequests(T1, T2); +%% false -> +%% wrong_type('ActionRequest_commandRequest_val', H) +%% end; +%% chk_ActionRequest_commandRequests([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_CommandRequest(H1, H2) end, +%% 'ActionRequest_commandRequests_val'), +%% chk_ActionRequest_commandRequests(T1, T2); +%% chk_ActionRequest_commandRequests(R1, R2) -> +%% wrong_type('ActionRequest_commandRequests', R1, R2). + + +%% %% -- ActionReply -- + +%% is_ActionReply(#'ActionReply'{contextId = Id, +%% errorDescriptor = ED, +%% contextReply = CtxRep, +%% commandReply = CmdRep}) -> +%% is_ContextID(Id) andalso +%% is_opt_ErrorDescriptor(ED) andalso +%% is_opt_ContextRequest(CtxRep) andalso +%% is_ActionReply_commandReply(CmdRep); +%% is_ActionReply(_) -> +%% false. + +%% is_ActionReply_commandReply([]) -> +%% true; +%% is_ActionReply_commandReply([H|T]) -> +%% is_CommandReply(H) andalso is_ActionReply_commandReply(T); +%% is_ActionReply_commandReply(_) -> +%% false. + +%% chk_ActionReply(A, A) -> +%% chk_type(fun is_ActionReply/1, 'ActionReply', A); +%% chk_ActionReply(#'ActionReply'{contextId = Id1, +%% errorDescriptor = ED1, +%% contextReply = CtxRep1, +%% commandReply = CmdRep1}, +%% #'ActionReply'{contextId = Id2, +%% errorDescriptor = ED2, +%% contextReply = CtxRep2, +%% commandReply = CmdRep2}) -> +%% chk_ContextID(Id1, Id2), +%% chk_opt_ErrorDescriptor(ED1, ED2), +%% chk_opt_ContextRequest(CtxRep1, CtxRep2), +%% chk_ActionReply_commandReply(CmdRep1, CmdRep2). + +%% chk_ActionReply_commandReply([], []) -> +%% ok; +%% chk_ActionReply_commandReply([] = Reps1, Reps2) -> +%% not_equal('ActionReply_commandReply', Reps1, Reps2); +%% chk_ActionReply_commandReply(Reps1, [] = Reps2) -> +%% not_equal('ActionReply_commandReply', Reps1, Reps2); +%% chk_ActionReply_commandReply([H|T1], [H|T2]) -> +%% case is_CommandReply(H) of +%% true -> +%% chk_ActionReply_commandReply(T1, T2); +%% false -> +%% wrong_type('ActionReply_commandReply_val', H) +%% end; +%% chk_ActionReply_commandReply([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_CommandReply(H1, H2) end, +%% 'ActionReply_commandReply_val'), +%% chk_ActionReply_commandReply(T1, T2); +%% chk_ActionReply_commandReply(R1, R2) -> +%% wrong_type('ActionReply_commandReply', R1, R2). + + +%% %% -- ContextRequest -- + +%% is_opt_ContextRequest(asn1_NOVALUE) -> +%% true; +%% is_opt_ContextRequest(V) -> +%% is_ContextRequest(V). + +%% is_ContextRequest(#'ContextRequest'{priority = Prio, +%% emergency = Em, +%% topologyReq = TopReq}) -> +%% is_ContextRequest_priority(Prio) andalso +%% is_ContextRequest_emergency(Em) andalso +%% is_ContextRequest_topologyReq(TopReq); +%% is_ContextRequest(_) -> +%% false. + +%% is_ContextRequest_priority(asn1_NOVALUE) -> +%% true; +%% is_ContextRequest_priority(V) -> +%% is_INTEGER(V, {range, 1, 15}). + +%% is_ContextRequest_emergency(asn1_NOVALUE) -> +%% true; +%% is_ContextRequest_emergency(V) -> +%% is_BOOLEAN(V). + +%% is_ContextRequest_topologyReq(asn1_NOVALUE) -> +%% true; +%% is_ContextRequest_topologyReq([]) -> +%% true; +%% is_ContextRequest_topologyReq([H|T]) -> +%% is_TopologyRequest(H) andalso is_ContextRequest_topologyReq(T); +%% is_ContextRequest_topologyReq(_) -> +%% false. + +%% chk_opt_ContextRequest(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_ContextRequest(R, R) -> +%% chk_ContextRequest(R, R). + +%% chk_ContextRequest(R, R) -> +%% chk_type(fun is_ContextRequest/1, 'ContextRequest', R); +%% chk_ContextRequest(#'ContextRequest'{priority = Prio1, +%% emergency = Em1, +%% topologyReq = TopReq1}, +%% #'ContextRequest'{priority = Prio2, +%% emergency = Em2, +%% topologyReq = TopReq2}) -> +%% chk_ContextRequest_priority(Prio1, Prio2), +%% chk_ContextRequest_emergency(Em1, Em2), +%% chk_ContextRequest_topologyReq(TopReq1, TopReq2), +%% ok; +%% chk_ContextRequest(R1, R2) -> +%% wrong_type('ContextRequest', R1, R2). + + +%% chk_ContextRequest_priority(asn1_NOVALUE,asn1_NOVALUE) -> +%% ok; +%% chk_ContextRequest_priority(P, P) -> +%% chk_type(fun is_ContextRequest_priority/1, 'ContextRequest_priority', P); +%% chk_ContextRequest_priority(P1, P2) -> +%% case (is_ContextRequest_priority(P1) andalso +%% is_ContextRequest_priority(P2)) of +%% true -> +%% not_equal('ContextRequest_priority', P1, P2); +%% false -> +%% wrong_type(contextRequest_priority, P1, P2) +%% end. + + +%% chk_ContextRequest_emergency(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_ContextRequest_emergency(E, E) -> +%% chk_type(fun is_ContextRequest_emergency/1, 'ContextRequest_emergency', E); +%% chk_ContextRequest_emergency(E1, E2) -> +%% case (is_ContextRequest_emergency(E1) andalso +%% is_ContextRequest_emergency(E2)) of +%% true -> +%% not_equal('ContextRequest_emergency', E1, E2); +%% false -> +%% wrong_type('ContextRequest_emergency', E1, E2) +%% end. + +%% chk_ContextRequest_topologyReq(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_ContextRequest_topologyReq([], []) -> +%% ok; +%% chk_ContextRequest_topologyReq([] = T1, T2) -> +%% not_equal('ContextRequest_topologyReq', T1, T2); +%% chk_ContextRequest_topologyReq(T1, [] = T2) -> +%% not_equal('ContextRequest_topologyReq', T1, T2); +%% chk_ContextRequest_topologyReq([H|T1], [H|T2]) -> +%% case is_TopologyRequest(H) of +%% true -> +%% chk_ContextRequest_topologyReq(T1, T2); +%% false -> +%% wrong_type('ContextRequest_topologyReq_val', H) +%% end; +%% chk_ContextRequest_topologyReq([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_TopologyRequest(H1, H2) end, +%% 'ContextRequest_topologyReq_val'), +%% chk_ContextRequest_topologyReq(T1, T2); +%% chk_ContextRequest_topologyReq(T1, T2) -> +%% wrong_type('ContextRequest_topologyReq', T1, T2). + + +%% %% -- ContextAttrAuditRequest -- + +%% is_opt_ContextAttrAuditRequest(asn1_NOVALUE) -> +%% true; +%% is_opt_ContextAttrAuditRequest(V) -> +%% is_ContextAttrAuditRequest(V). + +%% is_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{topology = T, +%% emergency = E, +%% priority = P}) -> +%% is_opt_NULL(T) andalso is_opt_NULL(E) andalso is_opt_NULL(P); +%% is_ContextAttrAuditRequest(_) -> +%% false. + +%% chk_opt_ContextAttrAuditRequest(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_ContextAttrAuditRequest(R1, R2) -> +%% chk_ContextAttrAuditRequest(R1, R2). + +%% chk_ContextAttrAuditRequest(R, R) -> +%% chk_type(fun is_ContextAttrAuditRequest/1, 'ContextAttrAuditRequest', R); +%% chk_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{topology = T1, +%% emergency = E1, +%% priority = P1}, +%% #'ContextAttrAuditRequest'{topology = T2, +%% emergency = E2, +%% priority = P2}) -> +%% validate(fun() -> chk_opt_NULL(T1, T2) end, +%% 'ContextAttrAuditRequest_topology'), +%% validate(fun() -> chk_opt_NULL(E1, E2) end, +%% 'ContextAttrAuditRequest_emergency'), +%% validate(fun() -> chk_opt_NULL(P1, P2) end, +%% 'ContextAttrAuditRequest_priority'), +%% ok. + + +%% %% -- CommandRequest -- + +%% is_CommandRequest(#'CommandRequest'{command = Cmd, +%% optional = Opt, +%% wildcardReturn = WR}) -> +%% is_Command(Cmd) andalso is_opt_NULL(Opt) andalso is_opt_NULL(WR); +%% is_CommandRequest(_) -> +%% false. + +%% chk_CommandRequest(C, C) -> +%% chk_type(fun is_CommandRequest/1, 'CommandRequest', C); +%% chk_CommandRequest(#'CommandRequest'{command = Cmd1, +%% optional = Opt1, +%% wildcardReturn = WR1}, +%% #'CommandRequest'{command = Cmd2, +%% optional = Opt2, +%% wildcardReturn = WR2}) -> +%% validate(fun() -> chk_Command(Cmd1, Cmd2) end, 'CommandRequest'), +%% validate(fun() -> chk_opt_NULL(Opt1, Opt2) end, 'CommandRequest'), +%% validate(fun() -> chk_opt_NULL(WR1, WR2) end, 'CommandRequest'), +%% ok; +%% chk_CommandRequest(R1, R2) -> +%% wrong_type('CommandRequest', R1, R2). + + +%% %% -- Command -- + +%% is_Command({Tag, Val}) -> +%% is_Command_tag(Tag) andalso is_Command_val(Tag, Val); +%% is_Command(_) -> +%% false. + +%% is_Command_tag(Tag) -> +%% Tags = [addReq, moveReq, modReq, subtractReq, auditCapRequest, +%% auditValueRequest, notifyReq, serviceChangeReq], +%% lists:member(Tag, Tags). + +%% is_Command_val(addReq, V) -> is_AmmRequest(V); +%% is_Command_val(moveReq, V) -> is_AmmRequest(V); +%% is_Command_val(modReq, V) -> is_AmmRequest(V); +%% is_Command_val(subtractReq, V) -> is_SubtractRequest(V); +%% is_Command_val(auditCapRequest, V) -> is_AuditRequest(V); +%% is_Command_val(auditValueRequest, V) -> is_AuditRequest(V); +%% is_Command_val(notifyReq, V) -> is_NotifyRequest(V); +%% is_Command_val(serviceChangeReq, V) -> is_ServiceChangeRequest(V). + +%% chk_Command(Cmd, Cmd) -> +%% chk_type(fun is_Command/1, 'Command', Cmd); +%% chk_Command({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> +%% case (is_Command_tag(Tag) andalso +%% is_Command_val(Tag, Val1) andalso +%% is_Command_val(Tag, Val2)) of +%% true -> +%% chk_Command_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('Command', Cmd1, Cmd2) +%% end; +%% chk_Command({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> +%% case ((is_Command_tag(Tag1) andalso is_Command_val(Tag1, Val1)) andalso +%% (is_Command_tag(Tag2) andalso is_Command_val(Tag2, Val2))) of +%% true -> +%% not_equal('Command', Cmd1, Cmd2); +%% false -> +%% wrong_type('Command', Cmd1, Cmd2) +%% end; +%% chk_Command(Cmd1, Cmd2) -> +%% wrong_type('Command', Cmd1, Cmd2). + + +%% chk_Command_val(addReq, R1, R2) -> +%% validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_addReq'); +%% chk_Command_val(moveReq, R1, R2) -> +%% validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_moveReq'); +%% chk_Command_val(modReq, R1, R2) -> +%% validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_modReq'); +%% chk_Command_val(subtractReq, R1, R2) -> +%% validate(fun() -> chk_SubtractRequest(R1, R2) end, 'Command_subtractReq'); +%% chk_Command_val(auditCapRequest, R1, R2) -> +%% validate(fun() -> chk_AuditRequest(R1, R2) end, 'Command_auditCapRequest'); +%% chk_Command_val(auditValueRequest, R1, R2) -> +%% validate(fun() -> chk_AuditRequest(R1, R2) end, +%% 'Command_auditValueRequest'); +%% chk_Command_val(notifyReq, R1, R2) -> +%% validate(fun() -> chk_NotifyRequest(R1, R2) end, 'Command_notifyReq'); +%% chk_Command_val(serviceChangeReq, R1, R2) -> +%% validate(fun() -> chk_ServiceChangeRequest(R1, R2) end, +%% 'Command_serviceChangeReq'). + + +%% %% -- CommandReply -- + +%% is_CommandReply({Tag, Val}) -> +%% is_CommandReply_tag(Tag) andalso is_CommandReply_val(Tag, Val); +%% is_CommandReply(_) -> +%% false. + +%% is_CommandReply_tag(Tag) -> +%% Tags = [addReply, moveReply, modReply, subtractReply, +%% auditCapReply, auditValueReply, notifyReply, serviceChangeReply], +%% lists:member(Tag, Tags). + +%% is_CommandReply_val(addReply, V) -> is_AmmsReply(V); +%% is_CommandReply_val(moveReply, V) -> is_AmmsReply(V); +%% is_CommandReply_val(modReply, V) -> is_AmmsReply(V); +%% is_CommandReply_val(subtractReply, V) -> is_AmmsReply(V); +%% is_CommandReply_val(auditCapReply, V) -> is_AuditReply(V); +%% is_CommandReply_val(auditValueReply, V) -> is_AuditReply(V); +%% is_CommandReply_val(notifyReply, V) -> is_NotifyReply(V); +%% is_CommandReply_val(serviceChangeReply, V) -> is_ServiceChangeReply(V). + +%% chk_CommandReply({Tag, Val} = Cmd, Cmd) -> +%% case (is_CommandReply_tag(Tag) andalso is_CommandReply_val(Tag, Val)) of +%% true -> +%% ok; +%% false -> +%% wrong_type('CommandReply', Cmd) +%% end; +%% chk_CommandReply({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> +%% case (is_CommandReply_tag(Tag) andalso +%% is_CommandReply_val(Tag, Val1) andalso +%% is_CommandReply_val(Tag, Val2)) of +%% true -> +%% chk_CommandReply_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('CommandReply', Cmd1, Cmd2) +%% end; +%% chk_CommandReply({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> +%% case ((is_CommandReply_tag(Tag1) andalso +%% is_CommandReply_val(Tag1, Val1)) andalso +%% (is_CommandReply_tag(Tag2) andalso +%% is_CommandReply_val(Tag2, Val2))) of +%% true -> +%% not_equal('CommandReply', Cmd1, Cmd2); +%% false -> +%% wrong_type('CommandReply', Cmd1, Cmd2) +%% end; +%% chk_CommandReply(Cmd1, Cmd2) -> +%% wrong_type('CommandReply', Cmd1, Cmd2). + +%% chk_CommandReply_val(addReply, V1, V2) -> +%% validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_addReply'); +%% chk_CommandReply_val(moveReply, V1, V2) -> +%% validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_moveReply'); +%% chk_CommandReply_val(modReply, V1, V2) -> +%% validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_modReply'); +%% chk_CommandReply_val(subtractReply, V1, V2) -> +%% validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_subtractReply'); +%% chk_CommandReply_val(auditCapReply, V1, V2) -> +%% validate(fun() -> chk_AuditReply(V1, V2) end, +%% 'CommandReply_auditCapReply'); +%% chk_CommandReply_val(auditValueReply, V1, V2) -> +%% validate(fun() -> chk_AuditReply(V1, V2) end, +%% 'CommandReply_auditValueReply'); +%% chk_CommandReply_val(notifyReply, V1, V2) -> +%% validate(fun() -> chk_NotifyReply(V1, V2) end, 'CommandReply_notifyReply'); +%% chk_CommandReply_val(serviceChangeReply, V1, V2) -> +%% validate(fun() -> chk_ServiceChangeReply(V1, V2) end, +%% 'CommandReply_serviceChangeReply'). + + +%% %% -- TopologyRequest -- + +%% is_TopologyRequest(#'TopologyRequest'{terminationFrom = F, +%% terminationTo = T, +%% topologyDirection = D, +%% streamID = S}) -> +%% is_TerminationID(F) andalso +%% is_TerminationID(T) andalso +%% is_TopologyRequest_topologyDirection(D) andalso +%% is_opt_StreamID(S); +%% is_TopologyRequest(_) -> +%% false. + +%% is_TopologyRequest_topologyDirection(D) -> +%% lists:member(D, [bothway, isolate, oneway]). + + +%% chk_TopologyRequest(T, T) when record(T,'TopologyRequest') -> +%% ok; +%% chk_TopologyRequest(#'TopologyRequest'{terminationFrom = F1, +%% terminationTo = T1, +%% topologyDirection = D1, +%% streamID = S1}, +%% #'TopologyRequest'{terminationFrom = F2, +%% terminationTo = T2, +%% topologyDirection = D2, +%% streamID = S2}) -> +%% validate(fun() -> chk_TerminationID(F1, F2) end, +%% 'TopologyRequest_terminationFrom'), +%% validate(fun() -> chk_TerminationID(T1, T2) end, +%% 'TopologyRequest_terminationTo'), +%% chk_TopologyRequest_topologyDirection(D1,D2), +%% validate(fun() -> chk_StreamID(S1, S2) end, 'TopologyRequest_streamID'), +%% ok. + +%% chk_TopologyRequest_topologyDirection(D, D) -> +%% case is_TopologyRequest_topologyDirection(D) of +%% true -> +%% ok; +%% false -> +%% wrong_type('TopologyRequest_topologyDirection', D) +%% end; +%% chk_TopologyRequest_topologyDirection(D1, D2) -> +%% case (is_TopologyRequest_topologyDirection(D1) andalso +%% is_TopologyRequest_topologyDirection(D1)) of +%% true -> +%% not_equal('TopologyRequest_topologyDirection', D1, D2); +%% false -> +%% wrong_type('TopologyRequest_topologyDirection', D1, D2) +%% end. + + +%% %% -- AmmRequest -- + +%% is_AmmRequest(#'AmmRequest'{terminationID = Tids, +%% descriptors = Descs}) -> +%% d("is_AmmRequest -> entry with" +%% "~n Tids: ~p", [Tids]), +%% is_TerminationIDList(Tids) andalso is_AmmRequest_descriptors(Descs); +%% is_AmmRequest(_) -> +%% false. + +%% is_AmmRequest_descriptors(Descs) -> +%% is_AmmRequest_descriptors(Descs, []). + +%% is_AmmRequest_descriptors([], _) -> +%% true; +%% is_AmmRequest_descriptors([{Tag, _} = Desc|Descs], FoundDescs) -> +%% d("is_AmmRequest_descriptors -> entry with" +%% "~n Tag: ~p" +%% "~n FoundDescs: ~p", [Tag, FoundDescs]), +%% case lists:member(Tag, FoundDescs) of +%% true -> +%% atmost_once('AmmRequest_descriptors', Tag); +%% false -> +%% case is_AmmDescriptor(Desc) of +%% true -> +%% is_AmmRequest_descriptors(Descs, [Tag|FoundDescs]); +%% false -> +%% wrong_type('AmmRequest_descriptors', Desc) +%% end +%% end; +%% is_AmmRequest_descriptors(Descs, _) -> +%% d("is_AmmRequest_descriptors -> entry with WRONG TYPE" +%% "~n Descs: ~p", [Descs]), +%% wrong_type('AmmRequest_descriptors', Descs). + + +%% chk_AmmRequest(R, R) when record(R, 'AmmRequest') -> +%% d("chk_AmmRequest -> entry when equal"), +%% chk_type(fun is_AmmRequest/1, 'AmmRequest', R); +%% chk_AmmRequest(#'AmmRequest'{terminationID = Tids1, +%% descriptors = Descs1}, +%% #'AmmRequest'{terminationID = Tids2, +%% descriptors = Descs2}) -> +%% d("chk_AmmRequest -> entry with not equal" +%% "~n Tids1: ~p" +%% "~n Tids2: ~p", [Tids1, Tids2]), +%% validate( +%% fun() -> chk_TerminationIDList(Tids1, Tids2) end, +%% 'AmmRequest'), +%% validate( +%% fun() -> chk_AmmRequest_descriptors(Descs1, Descs2) end, +%% 'AmmRequest'), +%% ok. + + +%% chk_AmmRequest_descriptors([], []) -> +%% d("chk_AmmRequest_descriptors -> done when OK"), +%% ok; +%% chk_AmmRequest_descriptors([] = Descs1, Descs2) -> +%% d("chk_AmmRequest_descriptors -> done when NOT EQUAL:" +%% "~n Descs1: ~p" +%% "~n Descs1: ~p", [Descs1, Descs2]), +%% not_equal('AmmRequest_descriptors', Descs1, Descs2); +%% chk_AmmRequest_descriptors(Descs1, [] = Descs2) -> +%% d("chk_AmmRequest_descriptors -> done when NOT EQUAL:" +%% "~n Descs1: ~p" +%% "~n Descs1: ~p", [Descs1, Descs2]), +%% not_equal('AmmRequest_descriptors', Descs1, Descs2); +%% chk_AmmRequest_descriptors([H|T1], [H|T2]) -> +%% d("chk_AmmRequest_descriptors -> entry when equal"), +%% case is_AmmDescriptor(H) of +%% true -> +%% chk_AmmRequest_descriptors(T1, T2); +%% false -> +%% wrong_type('AmmRequest_descriptors_val', H) +%% end; +%% chk_AmmRequest_descriptors([H1|T1], [H2|T2]) -> +%% d("chk_AmmRequest_descriptors -> entry when not equal"), +%% validate(fun() -> chk_AmmDescriptor(H1, H2) end, +%% 'AmmRequest_descriptors_val'), +%% chk_AmmRequest_descriptors(T1, T2); +%% chk_AmmRequest_descriptors(Descs1, Descs2) -> +%% d("chk_AmmRequest_descriptors -> done when WRONG TYPE:" +%% "~n Descs1: ~p" +%% "~n Descs1: ~p", [Descs1, Descs2]), +%% wrong_type('AmmRequest_descriptors', Descs1, Descs2). + + +%% %% -- AmmDescriptor -- + +%% is_AmmDescriptor({Tag, Val}) -> +%% d("is_AmmDescriptor -> entry with" +%% "~n Tag: ~p" +%% "~n Val: ~p",[Tag, Val]), +%% is_AmmDescriptor_tag(Tag) andalso is_AmmDescriptor_val(Tag, Val); +%% is_AmmDescriptor(_) -> +%% false. + +%% is_AmmDescriptor_tag(Tag) -> +%% Tags = [mediaDescriptor, modemDescriptor, muxDescriptor, eventsDescriptor, +%% eventBufferDescriptor, signalsDescriptor, digitMapDescriptor, +%% auditDescriptor], +%% lists:member(Tag, Tags). + +%% is_AmmDescriptor_val(mediaDescriptor, D) -> +%% is_MediaDescriptor(D); +%% is_AmmDescriptor_val(modemDescriptor, D) -> +%% is_ModemDescriptor(D); +%% is_AmmDescriptor_val(muxDescriptor, D) -> +%% is_MuxDescriptor(D); +%% is_AmmDescriptor_val(eventsDescriptor, D) -> +%% is_EventsDescriptor(D); +%% is_AmmDescriptor_val(eventBufferDescriptor, D) -> +%% is_EventBufferDescriptor(D); +%% is_AmmDescriptor_val(signalsDescriptor, D) -> +%% is_SignalsDescriptor(D); +%% is_AmmDescriptor_val(digitMapDescriptor, D) -> +%% is_DigitMapDescriptor(D); +%% is_AmmDescriptor_val(auditDescriptor, D) -> +%% is_AuditDescriptor(D). + +%% chk_AmmDescriptor(D, D) -> +%% chk_type(fun is_AmmDescriptor_tag/1, 'AmmDescriptor', D); +%% chk_AmmDescriptor({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> +%% case (is_AmmDescriptor_tag(Tag) andalso +%% is_AmmDescriptor_val(Tag, Val1) andalso +%% is_AmmDescriptor_val(Tag, Val2)) of +%% true -> +%% chk_AmmDescriptor_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('AmmDescriptor', Cmd1, Cmd2) +%% end; +%% chk_AmmDescriptor({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> +%% case ((is_AmmDescriptor_tag(Tag1) andalso +%% is_AmmDescriptor_val(Tag1, Val1)) andalso +%% (is_AmmDescriptor_tag(Tag2) andalso +%% is_AmmDescriptor_val(Tag2, Val2))) of +%% true -> +%% not_equal('AmmDescriptor', Cmd1, Cmd2); +%% false -> +%% wrong_type('AmmDescriptor', Cmd1, Cmd2) +%% end; +%% chk_AmmDescriptor(Cmd1, Cmd2) -> +%% wrong_type('AmmDescriptor', Cmd1, Cmd2). + +%% chk_AmmDescriptor_val(mediaDescriptor, D1, D2) -> +%% validate(fun() -> chk_MediaDescriptor(D1, D2) end, 'AmmDescriptor'); +%% chk_AmmDescriptor_val(modemDescriptor, D1, D2) -> +%% validate(fun() -> chk_ModemDescriptor(D1, D2) end, 'AmmDescriptor'); +%% chk_AmmDescriptor_val(muxDescriptor, D1, D2) -> +%% validate(fun() -> chk_MuxDescriptor(D1, D2) end, 'AmmDescriptor'); +%% chk_AmmDescriptor_val(eventsDescriptor, D1, D2) -> +%% validate(fun() -> chk_EventsDescriptor(D1, D2) end, 'AmmDescriptor'); +%% chk_AmmDescriptor_val(eventBufferDescriptor, D1, D2) -> +%% validate(fun() -> chk_EventBufferDescriptor(D1, D2) end, 'AmmDescriptor'); +%% chk_AmmDescriptor_val(signalsDescriptor, D1, D2) -> +%% validate(fun() -> chk_SignalsDescriptor(D1, D2) end, 'AmmDescriptor'); +%% chk_AmmDescriptor_val(digitMapDescriptor, D1, D2) -> +%% validate(fun() -> chk_DigitMapDescriptor(D1, D2) end, 'AmmDescriptor'); +%% chk_AmmDescriptor_val(auditDescriptor, D1, D2) -> +%% validate(fun() -> chk_AuditDescriptor(D1, D2) end, 'AmmDescriptor'). + + +%% %% -- AmmsReply -- + +%% is_AmmsReply(#'AmmsReply'{terminationID = Tids, +%% terminationAudit = TA}) -> +%% is_TerminationIDList(Tids) andalso is_opt_TerminationAudit(TA); +%% is_AmmsReply(_) -> +%% false. + +%% chk_AmmsReply(R, R) -> +%% is_AmmsReply(R); +%% chk_AmmsReply(#'AmmsReply'{terminationID = TID1, +%% terminationAudit = TA1}, +%% #'AmmsReply'{terminationID = TID2, +%% terminationAudit = TA2}) -> +%% validate(fun() -> chk_TerminationIDList(TID1, TID2) end, 'AmmsReply'), +%% validate(fun() -> chk_opt_TerminationAudit(TA1, TA2) end, 'AmmsReply'), +%% ok; +%% chk_AmmsReply(R1, R2) -> +%% wrong_type('AmmsReply', R1, R2). + + +%% %% -- SubtractRequest -- + +%% is_SubtractRequest(#'SubtractRequest'{terminationID = Tids, +%% auditDescriptor = AD}) -> +%% is_TerminationIDList(Tids) andalso is_opt_AuditDescriptor(AD); +%% is_SubtractRequest(_) -> +%% false. + +%% chk_SubtractRequest(R, R) -> +%% chk_type(fun is_SubtractRequest/1, 'SubtractRequest', R); +%% chk_SubtractRequest(#'SubtractRequest'{terminationID = Tids1, +%% auditDescriptor = AD1}, +%% #'SubtractRequest'{terminationID = Tids2, +%% auditDescriptor = AD2}) -> +%% validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, +%% 'SubtractRequest'), +%% validate(fun() -> chk_opt_AuditDescriptor(AD1, AD2) end, +%% 'SubtractRequest'), +%% ok; +%% chk_SubtractRequest(SR1, SR2) -> +%% wrong_type('SubtractRequest', SR1, SR2). + + +%% %% -- AuditRequest -- + +%% is_AuditRequest(#'AuditRequest'{terminationID = Tid, +%% auditDescriptor = AD}) -> +%% is_TerminationID(Tid) andalso is_AuditDescriptor(AD); +%% is_AuditRequest(_) -> +%% false. + +%% chk_AuditRequest(R, R) -> +%% chk_type(fun is_AuditRequest/1, 'AuditRequest', R); +%% chk_AuditRequest(#'AuditRequest'{terminationID = Tids1, +%% auditDescriptor = AD1}, +%% #'AuditRequest'{terminationID = Tids2, +%% auditDescriptor = AD2}) -> +%% validate(fun() -> chk_TerminationID(Tids1, Tids2) end, +%% 'AuditRequest'), +%% validate(fun() -> chk_AuditDescriptor(AD1, AD2) end, +%% 'AuditRequest'), +%% ok; +%% chk_AuditRequest(AR1, AR2) -> +%% wrong_type('AuditRequest', AR1, AR2). + + +%% %% -- AuditReply -- + +%% is_AuditReply({Tag, Val}) -> +%% is_AuditReply_tag(Tag) andalso is_AuditReply_val(Tag, Val); +%% is_AuditReply(_) -> +%% false. + +%% is_AuditReply_tag(Tag) -> +%% Tags = [contextAuditResult, error, auditResult], +%% lists:member(Tag, Tags). + +%% is_AuditReply_val(contextAuditResult, Val) -> +%% is_TerminationIDList(Val); +%% is_AuditReply_val(error, Val) -> +%% is_ErrorDescriptor(Val); +%% is_AuditReply_val(auditResult, Val) -> +%% is_AuditResult(Val). + +%% chk_AuditReply(R, R) -> +%% chk_type(fun is_AuditReply/1, 'AuditReply', R); +%% chk_AuditReply({Tag, Val1} = R1, {Tag, Val2} = R2) -> +%% case (is_AuditReply_tag(Tag) andalso +%% is_AuditReply_val(Tag, Val1)andalso +%% is_AuditReply_val(Tag, Val2)) of +%% true -> +%% chk_AuditReply_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('AuditReply', R1, R2) +%% end; +%% chk_AuditReply({Tag1, Val1} = R1, {Tag2, Val2} = R2) -> +%% case ((is_AuditReply_tag(Tag1) andalso +%% is_AuditReply_val(Tag1, Val1)) andalso +%% (is_AuditReply_tag(Tag2) andalso +%% is_AuditReply_val(Tag2, Val2))) of +%% true -> +%% not_equal('AuditReply', R1, R2); +%% false -> +%% wrong_type('AuditReply', R1, R2) +%% end; +%% chk_AuditReply(AR1, AR2) -> +%% wrong_type('AuditReply', AR1, AR2). + +%% chk_AuditReply_val(contextAuditResult, Val1, Val2) -> +%% chk_TerminationIDList(Val1, Val2); +%% chk_AuditReply_val(error, Val1, Val2) -> +%% chk_ErrorDescriptor(Val1, Val2); +%% chk_AuditReply_val(auditResult, Val1, Val2) -> +%% chk_AuditResult(Val1, Val2). + + +%% %% -- AuditResult -- + +%% is_AuditResult(#'AuditResult'{terminationID = TID, +%% terminationAuditResult = TAR}) -> +%% is_TerminationID(TID) andalso is_TerminationAudit(TAR); +%% is_AuditResult(_) -> +%% false. + +%% chk_AuditResult(R, R) -> +%% chk_type(fun is_AuditResult/1, 'AuditResult', R); +%% chk_AuditResult(#'AuditResult'{terminationID = TID1, +%% terminationAuditResult = TAR1}, +%% #'AuditResult'{terminationID = TID2, +%% terminationAuditResult = TAR2}) -> +%% validate(fun() -> chk_TerminationID(TID1, TID2) end, 'AuditResult'), +%% validate(fun() -> chk_TerminationAudit(TAR1, TAR2) end, 'AuditResult'), +%% ok; +%% chk_AuditResult(AR1, AR2) -> +%% wrong_type('AuditResult', AR1, AR2). + + +%% %% -- TerminationAudit -- + +%% is_opt_TerminationAudit(TA) -> +%% is_OPTIONAL(fun is_TerminationAudit/1, TA). + +%% is_TerminationAudit([]) -> +%% true; +%% is_TerminationAudit([H|T]) -> +%% is_AuditReturnParameter(H) andalso is_TerminationAudit(T); +%% is_TerminationAudit(_) -> +%% false. + +%% chk_opt_TerminationAudit(TA1, TA2) -> +%% chk_OPTIONAL('TerminationAudit', TA1, TA2, +%% fun is_TerminationAudit/1, fun chk_TerminationAudit/2). + +%% chk_TerminationAudit([], []) -> +%% ok; +%% chk_TerminationAudit([] = TA1, TA2) -> +%% not_equal('TerminationAudit', TA1, TA2); +%% chk_TerminationAudit(TA1, [] = TA2) -> +%% not_equal('TerminationAudit', TA1, TA2); +%% chk_TerminationAudit([H|T1], [H|T2]) -> +%% case is_AuditReturnParameter(H) of +%% true -> +%% chk_TerminationAudit(T1, T2); +%% false -> +%% wrong_type('TerminationAudit', H) +%% end; +%% chk_TerminationAudit([H1|_], [H2|_]) -> +%% chk_AuditReturnParameter(H1, H2), +%% not_equal('TerminationAudit_val', H1, H2); +%% chk_TerminationAudit(TA1, TA2) -> +%% not_equal('TerminationAudit', TA1, TA2). + + +%% %% -- AuditReturnParameter -- + +%% is_AuditReturnParameter({Tag, Val}) -> +%% is_AuditReturnParameter_tag(Tag) andalso +%% is_AuditReturnParameter_val(Tag, Val); +%% is_AuditReturnParameter(_) -> +%% false. + +%% is_AuditReturnParameter_tag(Tag) -> +%% Tags = [errorDescriptor, +%% mediaDescriptor, +%% modemDescriptor, +%% muxDescriptor, +%% eventsDescriptor, +%% eventBufferDescriptor, +%% signalsDescriptor, +%% digitMapDescriptor, +%% observedEventsDescriptor, +%% statisticsDescriptor, +%% packagesDescriptor, +%% emptyDescriptors], +%% lists:member(Tag, Tags). + +%% is_AuditReturnParameter_val(errorDescriptor, V) -> +%% is_ErrorDescriptor(V); +%% is_AuditReturnParameter_val(mediaDescriptor, V) -> +%% is_MediaDescriptor(V); +%% is_AuditReturnParameter_val(modemDescriptor, V) -> +%% is_ModemDescriptor(V); +%% is_AuditReturnParameter_val(muxDescriptor, V) -> +%% is_MuxDescriptor(V); +%% is_AuditReturnParameter_val(eventsDescriptor, V) -> +%% is_EventsDescriptor(V); +%% is_AuditReturnParameter_val(eventBufferDescriptor, V) -> +%% is_EventBufferDescriptor(V); +%% is_AuditReturnParameter_val(signalsDescriptor, V) -> +%% is_SignalsDescriptor(V); +%% is_AuditReturnParameter_val(digitMapDescriptor, V) -> +%% is_DigitMapDescriptor(V); +%% is_AuditReturnParameter_val(observedEventsDescriptor, V) -> +%% is_ObservedEventsDescriptor(V); +%% is_AuditReturnParameter_val(statisticsDescriptor, V) -> +%% is_StatisticsDescriptor(V); +%% is_AuditReturnParameter_val(packagesDescriptor, V) -> +%% is_PackagesDescriptor(V); +%% is_AuditReturnParameter_val(emptyDescriptors, V) -> +%% is_AuditDescriptor(V). + +%% chk_AuditReturnParameter(ARP, ARP) -> +%% chk_type(fun is_AuditReturnParameter/1, 'AuditReturnParameter', ARP); +%% chk_AuditReturnParameter({Tag, Val1} = ARP1, {Tag, Val2} = ARP2) -> +%% case (is_AuditReturnParameter_tag(Tag) andalso +%% is_AuditReturnParameter_val(Tag, Val1) andalso +%% is_AuditReturnParameter_val(Tag, Val2)) of +%% true -> +%% chk_AuditReturnParameter_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('AuditReturnParameter', ARP1, ARP2) +%% end; +%% chk_AuditReturnParameter({Tag1, Val1} = ARP1, {Tag2, Val2} = ARP2) -> +%% case ((is_AuditReturnParameter_tag(Tag1) andalso +%% is_AuditReturnParameter_val(Tag1, Val1)) andalso +%% (is_AuditReturnParameter_tag(Tag2) andalso +%% is_AuditReturnParameter_val(Tag2, Val2))) of +%% true -> +%% not_equal('AuditReturnParameter', ARP1, ARP2); +%% false -> +%% wrong_type('AuditReturnParameter', ARP1, ARP2) +%% end; +%% chk_AuditReturnParameter(ARP1, ARP2) -> +%% wrong_type('AuditReturnParameter', ARP1, ARP2). + +%% chk_AuditReturnParameter_val(errorDescriptor, V1, V2) -> +%% validate(fun() -> chk_ErrorDescriptor(V1, V2) end, +%% 'AuditReturnParameter'); +%% chk_AuditReturnParameter_val(mediaDescriptor, V1, V2) -> +%% validate(fun() -> chk_MediaDescriptor(V1, V2) end, +%% 'AuditReturnParameter'); +%% chk_AuditReturnParameter_val(modemDescriptor, V1, V2) -> +%% validate(fun() -> chk_ModemDescriptor(V1, V2) end, +%% 'AuditReturnParameter'); +%% chk_AuditReturnParameter_val(muxDescriptor, V1, V2) -> +%% validate(fun() -> chk_MuxDescriptor(V1, V2) end, +%% 'AuditReturnParameter'); +%% chk_AuditReturnParameter_val(eventsDescriptor, V1, V2) -> +%% validate(fun() -> chk_EventsDescriptor(V1, V2) end, +%% 'AuditReturnParameter'); +%% chk_AuditReturnParameter_val(eventBufferDescriptor, V1, V2) -> +%% validate(fun() -> chk_EventBufferDescriptor(V1, V2) end, +%% 'AuditReturnParameter'); +%% chk_AuditReturnParameter_val(signalsDescriptor, V1, V2) -> +%% validate(fun() -> chk_SignalsDescriptor(V1, V2) end, +%% 'AuditReturnParameter'); +%% chk_AuditReturnParameter_val(digitMapDescriptor, V1, V2) -> +%% validate(fun() -> chk_DigitMapDescriptor(V1, V2) end, +%% 'AuditReturnParameter'); +%% chk_AuditReturnParameter_val(observedEventsDescriptor, V1, V2) -> +%% validate(fun() -> chk_ObservedEventsDescriptor(V1, V2) end, +%% 'AuditReturnParameter'); +%% chk_AuditReturnParameter_val(statisticsDescriptor, V1, V2) -> +%% validate(fun() -> chk_StatisticsDescriptor(V1, V2) end, +%% 'AuditReturnParameter'); +%% chk_AuditReturnParameter_val(packagesDescriptor, V1, V2) -> +%% validate(fun() -> chk_PackagesDescriptor(V1, V2) end, +%% 'AuditReturnParameter'); +%% chk_AuditReturnParameter_val(emptyDescriptors, V1, V2) -> +%% validate(fun() -> chk_AuditDescriptor(V1, V2) end, +%% 'AuditReturnParameter'). + + +%% %% -- AuditDescriptor -- + +%% is_opt_AuditDescriptor(asn1_NOVALUE) -> +%% true; +%% is_opt_AuditDescriptor(V) -> +%% is_AuditDescriptor(V). + +%% is_AuditDescriptor(#'AuditDescriptor'{auditToken = AT, +%% auditPropertyToken = APT}) -> +%% is_AuditDescriptor_auditToken(AT) andalso +%% is_AuditDescriptor_auditPropertyToken(APT); +%% is_AuditDescriptor(_) -> +%% false. + +%% is_AuditDescriptor_auditToken(asn1_NOVALUE) -> +%% true; +%% is_AuditDescriptor_auditToken([]) -> +%% true; +%% is_AuditDescriptor_auditToken([H|T]) -> +%% is_AuditDescriptor_auditToken_val(H) andalso +%% is_AuditDescriptor_auditToken(T); +%% is_AuditDescriptor_auditToken(_) -> +%% false. + +%% is_AuditDescriptor_auditToken_val(V) -> +%% Toks = [muxToken, modemToken, mediaToken, eventsToken, signalsToken, +%% digitMapToken, statsToken, observedEventsToken, +%% packagesToken, eventBufferToken], +%% lists:member(V, Toks). + +%% is_AuditDescriptor_auditPropertyToken(asn1_NOVALUE) -> +%% true; +%% is_AuditDescriptor_auditPropertyToken([]) -> +%% true; +%% is_AuditDescriptor_auditPropertyToken([H|T]) -> +%% is_IndAuditParameter(H) andalso is_AuditDescriptor_auditPropertyToken(T); +%% is_AuditDescriptor_auditPropertyToken(_) -> +%% false. + +%% chk_opt_AuditDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_AuditDescriptor(AD1, AD2) -> +%% chk_AuditDescriptor(AD1, AD2). + +%% chk_AuditDescriptor(AD, AD) -> +%% chk_type(fun is_AuditDescriptor/1, 'AuditDescriptor', AD); +%% chk_AuditDescriptor(#'AuditDescriptor'{auditToken = AT1, +%% auditPropertyToken = APT1}, +%% #'AuditDescriptor'{auditToken = AT2, +%% auditPropertyToken = APT2}) -> +%% chk_AuditDescriptor_auditToken(AT1, AT2), +%% chk_AuditDescriptor_auditPropertyToken(APT1, APT2), +%% ok; +%% chk_AuditDescriptor(AD1, AD2) -> +%% wrong_type('AuditDescriptor', AD1, AD2). + +%% chk_AuditDescriptor_auditToken(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_AuditDescriptor_auditToken([], []) -> +%% ok; +%% chk_AuditDescriptor_auditToken([] = AT1, AT2) -> +%% not_equal('AuditDescriptor_auditToken', AT1, AT2); +%% chk_AuditDescriptor_auditToken(AT1, [] = AT2) -> +%% not_equal('AuditDescriptor_auditToken', AT1, AT2); +%% chk_AuditDescriptor_auditToken([H|T1], [H|T2]) -> +%% case is_AuditDescriptor_auditToken_val(H) of +%% true -> +%% chk_AuditDescriptor_auditToken(T1, T2); +%% false -> +%% wrong_type('AuditDescriptor_auditToken_val', H) +%% end; +%% chk_AuditDescriptor_auditToken([H1|_T1], [H2|_T2]) -> +%% case (is_AuditDescriptor_auditToken_val(H1) andalso +%% is_AuditDescriptor_auditToken_val(H2)) of +%% true -> +%% not_equal('AuditDescriptor_auditToken_val', H1, H2); +%% false -> +%% wrong_type('AuditDescriptor_auditToken_val', H1, H2) +%% end; +%% chk_AuditDescriptor_auditToken(AT1, AT2) -> +%% wrong_type('AuditDescriptor_auditToken', AT1, AT2). + +%% chk_AuditDescriptor_auditPropertyToken(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_AuditDescriptor_auditPropertyToken([], []) -> +%% ok; +%% chk_AuditDescriptor_auditPropertyToken([] = AT1, AT2) -> +%% not_equal('AuditDescriptor_auditPropertyToken', AT1, AT2); +%% chk_AuditDescriptor_auditPropertyToken(AT1, [] = AT2) -> +%% not_equal('AuditDescriptor_auditPropertyToken', AT1, AT2); +%% chk_AuditDescriptor_auditPropertyToken([H|T1], [H|T2]) -> +%% case is_IndAuditParameter(H) of +%% true -> +%% chk_AuditDescriptor_auditPropertyToken(T1, T2); +%% false -> +%% wrong_type('AuditDescriptor_auditPropertyToken_val', H) +%% end; +%% chk_AuditDescriptor_auditPropertyToken([H1|_], [H2|_]) -> +%% chk_IndAuditParameter(H1, H2), +%% not_equal('AuditDescriptor_auditPropertyToken_val', H1, H2); +%% chk_AuditDescriptor_auditPropertyToken(AT1, AT2) -> +%% wrong_type('AuditDescriptor_auditPropertyToken', AT1, AT2). + + +%% %% -- IndAuditParameter -- + +%% is_IndAuditParameter({Tag, Val}) -> +%% is_IndAuditParameter_tag(Tag) andalso is_IndAuditParameter_val(Tag, Val); +%% is_IndAuditParameter(_) -> +%% false. + +%% is_IndAuditParameter_tag(Tag) -> +%% Tags = [indAudMediaDescriptor, +%% indAudEventsDescriptor, +%% indAudEventBufferDescriptor, +%% indAudSignalsDescriptor, +%% indAudDigitMapDescriptor, +%% indAudStatisticsDescriptor, +%% indAudPackagesDescriptor], +%% lists:member(Tag, Tags). + +%% is_IndAuditParameter_val(indAudMediaDescriptor, Val) -> +%% is_IndAudMediaDescriptor(Val); +%% is_IndAuditParameter_val(indAudEventsDescriptor, Val) -> +%% is_IndAudEventsDescriptor(Val); +%% is_IndAuditParameter_val(indAudEventBufferDescriptor, Val) -> +%% is_IndAudEventBufferDescriptor(Val); +%% is_IndAuditParameter_val(indAudSignalsDescriptor, Val) -> +%% is_IndAudSignalsDescriptor(Val); +%% is_IndAuditParameter_val(indAudDigitMapDescriptor, Val) -> +%% is_IndAudDigitMapDescriptor(Val); +%% is_IndAuditParameter_val(indAudStatisticsDescriptor, Val) -> +%% is_IndAudStatisticsDescriptor(Val); +%% is_IndAuditParameter_val(indAudPackagesDescriptor, Val) -> +%% is_IndAudPackagesDescriptor(Val). + +%% chk_IndAuditParameter(IAP, IAP) -> +%% chk_type(fun is_IndAuditParameter/1, 'IndAuditParameter', IAP); +%% chk_IndAuditParameter({Tag, Val1} = IAP1, {Tag, Val2} = IAP2) -> +%% case (is_IndAuditParameter_tag(Tag) andalso +%% is_IndAuditParameter_val(Tag, Val1) andalso +%% is_IndAuditParameter_val(Tag, Val2)) of +%% true -> +%% chk_IndAuditParameter_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('IndAuditParameter', IAP1, IAP2) +%% end; +%% chk_IndAuditParameter({Tag1, Val1} = IAP1, {Tag2, Val2} = IAP2) -> +%% case ((is_IndAuditParameter_tag(Tag1) andalso +%% is_IndAuditParameter_val(Tag1, Val1)) andalso +%% (is_IndAuditParameter_tag(Tag2) andalso +%% is_IndAuditParameter_val(Tag2, Val2))) of +%% true -> +%% not_equal('IndAuditParameter', IAP1, IAP2); +%% false -> +%% wrong_type('IndAuditParameter', IAP1, IAP2) +%% end; +%% chk_IndAuditParameter(IAP1, IAP2) -> +%% wrong_type('IndAuditParameter', IAP1, IAP2). + +%% chk_IndAuditParameter_val(indAudMediaDescriptor, Val1, Val2) -> +%% validate(fun() -> chk_IndAudMediaDescriptor(Val1, Val2) end, +%% 'IndAuditParameter'); +%% chk_IndAuditParameter_val(indAudEventsDescriptor, Val1, Val2) -> +%% validate(fun() -> chk_IndAudEventsDescriptor(Val1, Val2) end, +%% 'IndAuditParameter'); +%% chk_IndAuditParameter_val(indAudEventBufferDescriptor, Val1, Val2) -> +%% validate(fun() -> chk_IndAudEventBufferDescriptor(Val1, Val2) end, +%% 'IndAuditParameter'); +%% chk_IndAuditParameter_val(indAudSignalsDescriptor, Val1, Val2) -> +%% validate(fun() -> chk_IndAudSignalsDescriptor(Val1, Val2) end, +%% 'IndAuditParameter'); +%% chk_IndAuditParameter_val(indAudDigitMapDescriptor, Val1, Val2) -> +%% validate(fun() -> chk_IndAudDigitMapDescriptor(Val1, Val2) end, +%% 'IndAuditParameter'); +%% chk_IndAuditParameter_val(indAudStatisticsDescriptor, Val1, Val2) -> +%% validate(fun() -> chk_IndAudStatisticsDescriptor(Val1, Val2) end, +%% 'IndAuditParameter'); +%% chk_IndAuditParameter_val(indAudPackagesDescriptor, Val1, Val2) -> +%% validate(fun() -> chk_IndAudPackagesDescriptor(Val1, Val2) end, +%% 'IndAuditParameter'). + + +%% %% -- IndAudMediaDescriptor -- + +%% is_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD, +%% streams = S}) -> +%% is_opt_IndAudTerminationStateDescriptor(TSD) andalso +%% is_IndAudMediaDescriptor_streams(S); +%% is_IndAudMediaDescriptor(_) -> +%% false. + +%% is_IndAudMediaDescriptor_streams(asn1_NOVALUE) -> +%% true; +%% is_IndAudMediaDescriptor_streams({Tag, Val}) -> +%% is_IndAudMediaDescriptor_streams_tag(Tag) andalso +%% is_IndAudMediaDescriptor_streams_val(Tag, Val); +%% is_IndAudMediaDescriptor_streams(_) -> +%% false. + +%% is_IndAudMediaDescriptor_streams_tag(Tag) -> +%% Tags = [oneStream, multiStream], +%% lists:member(Tag, Tags). + +%% is_IndAudMediaDescriptor_streams_val(oneStream, Val) -> +%% is_IndAudStreamParms(Val); +%% is_IndAudMediaDescriptor_streams_val(multiStream, Val) -> +%% is_IndAudMediaDescriptor_multiStream(Val). + +%% is_IndAudMediaDescriptor_multiStream([]) -> +%% true; +%% is_IndAudMediaDescriptor_multiStream([H|T]) -> +%% is_IndAudStreamDescriptor(H) andalso +%% is_IndAudMediaDescriptor_multiStream(T); +%% is_IndAudMediaDescriptor_multiStream(_) -> +%% false. + +%% chk_IndAudMediaDescriptor(IAMD, IAMD) -> +%% chk_type(fun is_IndAudMediaDescriptor/1, 'IndAudMediaDescriptor', IAMD); +%% chk_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD1, +%% streams = S1}, +%% #'IndAudMediaDescriptor'{termStateDescr = TSD2, +%% streams = S2}) -> +%% validate(fun() -> chk_opt_IndAudTerminationStateDescriptor(TSD1, TSD2) end, +%% 'IndAudMediaDescriptor'), +%% validate(fun() -> chk_IndAudMediaDescriptor_streams(S1, S2) end, +%% 'IndAudMediaDescriptor'), +%% ok; +%% chk_IndAudMediaDescriptor(IAMD1, IAMD2) -> +%% wrong_type('IndAudMediaDescriptor', IAMD1, IAMD2). + +%% chk_IndAudMediaDescriptor_streams(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_IndAudMediaDescriptor_streams({Tag, Val1} = S1, +%% {Tag, Val2} = S2) -> +%% case (is_IndAudMediaDescriptor_streams_tag(Tag) andalso +%% is_IndAudMediaDescriptor_streams_val(Tag, Val1) andalso +%% is_IndAudMediaDescriptor_streams_val(Tag, Val2)) of +%% true -> +%% chk_IndAudMediaDescriptor_streams_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('IndAudMediaDescriptor_streams', S1, S2) +%% end; +%% chk_IndAudMediaDescriptor_streams({Tag1, Val1} = S1, +%% {Tag2, Val2} = S2) -> +%% case ((is_IndAudMediaDescriptor_streams_tag(Tag1) andalso +%% is_IndAudMediaDescriptor_streams_val(Tag1, Val1)) andalso +%% (is_IndAudMediaDescriptor_streams_tag(Tag2) andalso +%% is_IndAudMediaDescriptor_streams_val(Tag2, Val2))) of +%% true -> +%% not_equal('IndAudMediaDescriptor_streams', S1, S2); +%% false -> +%% wrong_type('IndAudMediaDescriptor_streams', S1, S2) +%% end; +%% chk_IndAudMediaDescriptor_streams(S1, S2) -> +%% wrong_type('IndAudMediaDescriptor_streams', S1, S2). + +%% chk_IndAudMediaDescriptor_streams_val(oneStream, Val1, Val2) -> +%% validate(fun() -> chk_IndAudStreamParms(Val1, Val2) end, +%% 'IndAudMediaDescriptor_streams'); +%% chk_IndAudMediaDescriptor_streams_val(multiStream, Val1, Val2) -> +%% validate(fun() -> chk_IndAudMediaDescriptor_multiStream(Val1, Val2) end, +%% 'IndAudMediaDescriptor_streams'). + +%% chk_IndAudMediaDescriptor_multiStream([], []) -> +%% ok; +%% chk_IndAudMediaDescriptor_multiStream([] = MS1, MS2) -> +%% not_equal('IndAudMediaDescriptor_multiStream', MS1, MS2); +%% chk_IndAudMediaDescriptor_multiStream(MS1, [] = MS2) -> +%% not_equal('IndAudMediaDescriptor_multiStream', MS1, MS2); +%% chk_IndAudMediaDescriptor_multiStream([H|T1], [H|T2]) -> +%% case is_IndAudStreamDescriptor(H) of +%% true -> +%% chk_IndAudMediaDescriptor_multiStream(T1, T2); +%% false -> +%% wrong_type('IndAudMediaDescriptor_multiStream_val', H) +%% end; +%% chk_IndAudMediaDescriptor_multiStream([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_IndAudStreamDescriptor(H1, H2) end, +%% 'IndAudMediaDescriptor_multiStream_val'), +%% chk_IndAudMediaDescriptor_multiStream(T1, T2); +%% chk_IndAudMediaDescriptor_multiStream(MS1, MS2) -> +%% wrong_type('IndAudMediaDescriptor_multiStream', MS1, MS2). + + +%% %% -- IndAudStreamDescriptor -- + +%% is_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID, +%% streamParms = Parms}) -> +%% is_StreamID(SID) andalso is_IndAudStreamParms(Parms); +%% is_IndAudStreamDescriptor(_) -> +%% false. + +%% chk_IndAudStreamDescriptor(D, D) -> +%% chk_type(fun is_IndAudStreamDescriptor/1, 'IndAudStreamDescriptor', D); +%% chk_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID1, +%% streamParms = Parms1}, +%% #'IndAudStreamDescriptor'{streamID = SID2, +%% streamParms = Parms2}) -> +%% validate(fun() -> chk_StreamID(SID1, SID2) end, 'IndAudStreamDescriptor'), +%% validate(fun() -> chk_IndAudStreamParms(Parms1, Parms2) end, +%% 'IndAudStreamDescriptor'), +%% ok; +%% chk_IndAudStreamDescriptor(D1, D2) -> +%% wrong_type('IndAudStreamDescriptor', D1, D2). + + +%% %% -- IndAudStreamParms -- + +%% is_IndAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD, +%% localDescriptor = LD, +%% remoteDescriptor = RD}) -> +%% is_opt_IndAudLocalControlDescriptor(LCD) andalso +%% is_opt_IndAudLocalRemoteDescriptor(LD) andalso +%% is_opt_IndAudLocalRemoteDescriptor(RD); +%% is_IndAudStreamParms(_) -> +%% false. + +%% chk_IndAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD1, +%% localDescriptor = LD1, +%% remoteDescriptor = RD1}, +%% #'IndAudStreamParms'{localControlDescriptor = LCD2, +%% localDescriptor = LD2, +%% remoteDescriptor = RD2}) -> +%% validate(fun() -> chk_opt_IndAudLocalControlDescriptor(LCD1, LCD2) end, +%% 'IndAudStreamParms'), +%% validate(fun() -> chk_opt_IndAudLocalRemoteDescriptor(LD1, LD2) end, +%% 'IndAudStreamParms'), +%% validate(fun() -> chk_opt_IndAudLocalRemoteDescriptor(RD1, RD2) end, +%% 'IndAudStreamParms'), +%% ok; +%% chk_IndAudStreamParms(D1, D2) -> +%% wrong_type('IndAudStreamParms', D1, D2). + + +%% %% -- IndAudLocalControlDescriptor -- + +%% is_opt_IndAudLocalControlDescriptor(asn1_NOVALUE) -> +%% true; +%% is_opt_IndAudLocalControlDescriptor(D) -> +%% is_IndAudLocalControlDescriptor(D). + +%% is_IndAudLocalControlDescriptor( +%% #'IndAudLocalControlDescriptor'{streamMode = SM, +%% reserveValue = RV, +%% reserveGroup = RG, +%% propertyParms = PPs}) -> +%% is_opt_NULL(SM) andalso is_opt_NULL(RV) andalso is_opt_NULL(RG) andalso +%% is_IndAudLocalControlDescriptor_propertyParms(PPs); +%% is_IndAudLocalControlDescriptor(_) -> +%% false. + +%% is_IndAudLocalControlDescriptor_propertyParms(asn1_NOVALUE) -> +%% true; +%% is_IndAudLocalControlDescriptor_propertyParms([]) -> +%% true; +%% is_IndAudLocalControlDescriptor_propertyParms([H|T]) -> +%% is_IndAudPropertyParm(H) andalso +%% is_IndAudLocalControlDescriptor_propertyParms(T); +%% is_IndAudLocalControlDescriptor_propertyParms(_) -> +%% false. + +%% chk_opt_IndAudLocalControlDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_IndAudLocalControlDescriptor( +%% #'IndAudLocalControlDescriptor'{streamMode = SM1, +%% reserveValue = RV1, +%% reserveGroup = RG1, +%% propertyParms = PPs1}, +%% #'IndAudLocalControlDescriptor'{streamMode = SM2, +%% reserveValue = RV2, +%% reserveGroup = RG2, +%% propertyParms = PPs2}) -> +%% chk_opt_NULL(SM1, SM2), +%% chk_opt_NULL(RV1, RV2), +%% chk_opt_NULL(RG1, RG2), +%% chk_IndAudLocalControlDescriptor_propertyParms(PPs1, PPs2), +%% ok; +%% chk_opt_IndAudLocalControlDescriptor(D1, D2) -> +%% wrong_type('IndAudLocalControlDescriptor', D1, D2). + +%% chk_IndAudLocalControlDescriptor_propertyParms(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_IndAudLocalControlDescriptor_propertyParms([], []) -> +%% ok; +%% chk_IndAudLocalControlDescriptor_propertyParms([] = PPs1, PPs2) -> +%% not_equal('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2); +%% chk_IndAudLocalControlDescriptor_propertyParms(PPs1, [] = PPs2) -> +%% not_equal('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2); +%% chk_IndAudLocalControlDescriptor_propertyParms([H|T1], [H|T2]) -> +%% case is_IndAudPropertyParm(H) of +%% true -> +%% chk_IndAudLocalControlDescriptor_propertyParms(T1, T2); +%% false -> +%% wrong_type('IndAudLocalControlDescriptor_propertyParms_val', H) +%% end; +%% chk_IndAudLocalControlDescriptor_propertyParms([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, +%% 'IndAudLocalControlDescriptor_propertyParms_val'), +%% chk_IndAudLocalControlDescriptor_propertyParms(T1, T2); +%% chk_IndAudLocalControlDescriptor_propertyParms(PPs1, PPs2) -> +%% wrong_type('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2). + + +%% %% -- IndAudPropertyParm -- + +%% is_IndAudPropertyParm(#'IndAudPropertyParm'{name = Name}) -> +%% is_PkgdName(Name); +%% is_IndAudPropertyParm(_) -> +%% false. + +%% chk_IndAudPropertyParm(#'IndAudPropertyParm'{name = Name1}, +%% #'IndAudPropertyParm'{name = Name2}) -> +%% chk_PkgdName(Name1, Name2), +%% ok; +%% chk_IndAudPropertyParm(P1, P2) -> +%% wrong_type('IndAudPropertyParm', P1, P2). + + +%% %% -- IndAudLocalRemoteDescriptor -- + +%% is_opt_IndAudLocalRemoteDescriptor(asn1_NOVALUE) -> +%% true; +%% is_opt_IndAudLocalRemoteDescriptor(D) -> +%% is_IndAudLocalRemoteDescriptor(D). + +%% is_IndAudLocalRemoteDescriptor( +%% #'IndAudLocalRemoteDescriptor'{propGroupID = ID, +%% propGrps = Grps}) -> +%% is_IndAudLocalRemoteDescriptor_propGroupID(ID) andalso +%% is_IndAudPropertyGroup(Grps); +%% is_IndAudLocalRemoteDescriptor(_) -> +%% false. + +%% is_IndAudLocalRemoteDescriptor_propGroupID(asn1_NOVALUE) -> +%% true; +%% is_IndAudLocalRemoteDescriptor_propGroupID(V) -> +%% is_INTEGER(V, {range, 0, 65535}). + +%% chk_opt_IndAudLocalRemoteDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_IndAudLocalRemoteDescriptor(D1, D2) -> +%% chk_IndAudLocalRemoteDescriptor(D1, D2). + +%% chk_IndAudLocalRemoteDescriptor(D, D) -> +%% chk_type(fun is_IndAudLocalRemoteDescriptor/1, +%% 'IndAudLocalRemoteDescriptor', D); +%% chk_IndAudLocalRemoteDescriptor( +%% #'IndAudLocalRemoteDescriptor'{propGroupID = ID1, +%% propGrps = Grps1}, +%% #'IndAudLocalRemoteDescriptor'{propGroupID = ID2, +%% propGrps = Grps2}) -> +%% chk_IndAudLocalRemoteDescriptor_propGroupID(ID1, ID2), +%% chk_IndAudPropertyGroup(Grps1, Grps2), +%% ok; +%% chk_IndAudLocalRemoteDescriptor(D1, D2) -> +%% wrong_type('IndAudLocalRemoteDescriptor', D1, D2). + +%% chk_IndAudLocalRemoteDescriptor_propGroupID(ID, ID) -> +%% chk_type(fun is_IndAudLocalRemoteDescriptor_propGroupID/1, +%% 'IndAudLocalRemoteDescriptor_propGroupID', ID); +%% chk_IndAudLocalRemoteDescriptor_propGroupID(ID1, ID2) -> +%% case (is_IndAudLocalRemoteDescriptor_propGroupID(ID1) andalso +%% is_IndAudLocalRemoteDescriptor_propGroupID(ID2)) of +%% true -> +%% not_equal('IndAudLocalRemoteDescriptor_propGroupID', ID1, ID2); +%% false -> +%% wrong_type('IndAudLocalRemoteDescriptor_propGroupID', ID1, ID2) +%% end. + + +%% %% -- IndAudPropertyGroup -- + +%% is_IndAudPropertyGroup([]) -> +%% true; +%% is_IndAudPropertyGroup([H|T]) -> +%% is_IndAudPropertyParm(H) andalso is_IndAudPropertyGroup(T); +%% is_IndAudPropertyGroup(_) -> +%% false. + +%% chk_IndAudPropertyGroup([], []) -> +%% ok; +%% chk_IndAudPropertyGroup([] = PG1, PG2) -> +%% not_equal('IndAudPropertyGroup', PG1, PG2); +%% chk_IndAudPropertyGroup(PG1, [] = PG2) -> +%% not_equal('IndAudPropertyGroup', PG1, PG2); +%% chk_IndAudPropertyGroup([H|T1], [H|T2]) -> +%% case is_IndAudPropertyParm(H) of +%% true -> +%% chk_IndAudPropertyGroup(T1, T2); +%% false -> +%% wrong_type('IndAudPropertyGroup_val', H) +%% end; +%% chk_IndAudPropertyGroup([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, +%% 'IndAudPropertyGroup_val'), +%% chk_IndAudPropertyGroup(T1, T2); +%% chk_IndAudPropertyGroup(P1, P2) -> +%% wrong_type('IndAudPropertyGroup', P1, P2). + + +%% %% -- IndAudTerminationStateDescriptor -- + +%% is_opt_IndAudTerminationStateDescriptor(asn1_NOVALUE) -> +%% true; +%% is_opt_IndAudTerminationStateDescriptor(D) -> +%% is_IndAudTerminationStateDescriptor(D). + +%% is_IndAudTerminationStateDescriptor( +%% #'IndAudTerminationStateDescriptor'{propertyParms = Parms, +%% eventBufferControl = EBC, +%% serviceState = SS}) -> +%% is_IndAudTerminationStateDescriptor_propertyParms(Parms) andalso +%% is_opt_NULL(EBC) andalso is_opt_NULL(SS); +%% is_IndAudTerminationStateDescriptor(_) -> +%% false. + +%% is_IndAudTerminationStateDescriptor_propertyParms([]) -> +%% true; +%% is_IndAudTerminationStateDescriptor_propertyParms([H|T]) -> +%% is_IndAudPropertyParm(H) andalso +%% is_IndAudTerminationStateDescriptor_propertyParms(T); +%% is_IndAudTerminationStateDescriptor_propertyParms(_) -> +%% false. + +%% chk_opt_IndAudTerminationStateDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_IndAudTerminationStateDescriptor(D1, D2) -> +%% chk_IndAudTerminationStateDescriptor(D1, D2). + +%% chk_IndAudTerminationStateDescriptor( +%% #'IndAudTerminationStateDescriptor'{propertyParms = Parms1, +%% eventBufferControl = EBC1, +%% serviceState = SS1}, +%% #'IndAudTerminationStateDescriptor'{propertyParms = Parms2, +%% eventBufferControl = EBC2, +%% serviceState = SS2}) -> +%% chk_IndAudTerminationStateDescriptor_propertyParms(Parms1, Parms2), +%% validate(fun() -> chk_opt_NULL(EBC1, EBC2) end, +%% 'IndAudTerminationStateDescriptor'), +%% validate(fun() -> chk_opt_NULL(SS1, SS2) end, +%% 'IndAudTerminationStateDescriptor'), +%% ok; +%% chk_IndAudTerminationStateDescriptor(D1, D2) -> +%% wrong_type('IndAudTerminationStateDescriptor', D1, D2). + +%% chk_IndAudTerminationStateDescriptor_propertyParms([], []) -> +%% ok; +%% chk_IndAudTerminationStateDescriptor_propertyParms([] = PP1, PP2) -> +%% not_equal('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2); +%% chk_IndAudTerminationStateDescriptor_propertyParms(PP1, [] = PP2) -> +%% not_equal('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2); +%% chk_IndAudTerminationStateDescriptor_propertyParms([H|T1], [H|T2]) -> +%% case is_IndAudPropertyParm(H) of +%% true -> +%% chk_IndAudTerminationStateDescriptor_propertyParms(T1, T2); +%% false -> +%% wrong_type('IndAudTerminationStateDescriptor_propertyParms', H) +%% end; +%% chk_IndAudTerminationStateDescriptor_propertyParms([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, +%% 'IndAudTerminationStateDescriptor_propertyParms'), +%% chk_IndAudTerminationStateDescriptor_propertyParms(T1, T2); +%% chk_IndAudTerminationStateDescriptor_propertyParms(PP1, PP2) -> +%% wrong_type('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2). + + +%% %% -- IndAudEventsDescriptor -- + +%% is_IndAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID, +%% pkgdName = Name, +%% streamID = SID}) -> +%% is_opt_RequestID(RID) andalso +%% is_PkgdName(Name) andalso +%% is_opt_StreamID(SID); +%% is_IndAudEventsDescriptor(_) -> +%% false. + +%% chk_IndAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID1, +%% pkgdName = Name1, +%% streamID = SID1}, +%% #'IndAudEventsDescriptor'{requestID = RID2, +%% pkgdName = Name2, +%% streamID = SID2}) -> +%% chk_opt_RequestID(RID1, RID2), +%% chk_PkgdName(Name1, Name2), +%% chk_opt_StreamID(SID1, SID2), +%% ok; +%% chk_IndAudEventsDescriptor(D1, D2) -> +%% wrong_type('IndAudEventsDescriptor', D1, D2). + + +%% %% -- IndAudEventBufferDescriptor -- + +%% is_IndAudEventBufferDescriptor( +%% #'IndAudEventBufferDescriptor'{eventName = Name, +%% streamID = SID}) -> +%% is_PkgdName(Name) andalso is_opt_StreamID(SID); +%% is_IndAudEventBufferDescriptor(_) -> +%% false. + +%% chk_IndAudEventBufferDescriptor( +%% #'IndAudEventBufferDescriptor'{eventName = Name1, +%% streamID = SID1}, +%% #'IndAudEventBufferDescriptor'{eventName = Name2, +%% streamID = SID2}) -> +%% chk_PkgdName(Name1, Name2), +%% chk_opt_StreamID(SID1, SID2), +%% ok; +%% chk_IndAudEventBufferDescriptor(D1, D2) -> +%% wrong_type('IndAudEventBufferDescriptor', D1, D2). + + +%% %% -- IndAudSignalsDescriptor -- + +%% is_IndAudSignalsDescriptor({Tag, Val}) -> +%% is_IndAudSignalsDescriptor_tag(Tag) andalso +%% is_IndAudSignalsDescriptor_val(Tag, Val); +%% is_IndAudSignalsDescriptor(_) -> +%% false. + +%% is_IndAudSignalsDescriptor_tag(Tag) -> +%% Tags = [signal, seqSigList], +%% lists:member(Tag, Tags). + +%% is_IndAudSignalsDescriptor_val(signal, Val) -> +%% is_IndAudSignal(Val); +%% is_IndAudSignalsDescriptor_val(seqSigList, Val) -> +%% is_IndAudSeqSigList(Val). + +%% chk_IndAudSignalsDescriptor(D, D) -> +%% chk_type(fun is_IndAudSignalsDescriptor/1, 'IndAudSignalsDescriptor', D); +%% chk_IndAudSignalsDescriptor({Tag, Val1} = D1, {Tag, Val2} = D2) -> +%% case (is_IndAudSignalsDescriptor_tag(Tag) andalso +%% is_IndAudSignalsDescriptor_val(Tag, Val1) andalso +%% is_IndAudSignalsDescriptor_val(Tag, Val2)) of +%% true -> +%% chk_IndAudSignalsDescriptor_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('IndAudSignalsDescriptor', D1, D2) +%% end; +%% chk_IndAudSignalsDescriptor({Tag1, Val1} = D1, {Tag2, Val2} = D2) -> +%% case ((is_IndAudSignalsDescriptor_tag(Tag1) andalso +%% is_IndAudSignalsDescriptor_val(Tag1, Val1)) andalso +%% (is_IndAudSignalsDescriptor_tag(Tag2) andalso +%% is_IndAudSignalsDescriptor_val(Tag2, Val2))) of +%% true -> +%% not_equal('IndAudSignalsDescriptor', D1, D2); +%% false -> +%% wrong_type('IndAudSignalsDescriptor', D1, D2) +%% end; +%% chk_IndAudSignalsDescriptor(D1, D2) -> +%% wrong_type('IndAudSignalsDescriptor', D1, D2). + +%% chk_IndAudSignalsDescriptor_val(signal, Val1, Val2) -> +%% chk_IndAudSignal(Val1, Val2); +%% chk_IndAudSignalsDescriptor_val(seqSigList, Val1, Val2) -> +%% chk_IndAudSeqSigList(Val1, Val2). + + +%% %% -- IndAudSeqSigList -- + +%% is_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID, +%% signalList = SL}) -> +%% is_IndAudSeqSigList_id(ID) andalso is_opt_IndAudSignal(SL); +%% is_IndAudSeqSigList(_) -> +%% false. + +%% is_IndAudSeqSigList_id(ID) -> is_INTEGER(ID, {range, 0, 65535}). + +%% chk_IndAudSeqSigList(L, L) -> +%% chk_type(fun is_IndAudSeqSigList/1, 'IndAudSeqSigList', L); +%% chk_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID1, +%% signalList = SL1}, +%% #'IndAudSeqSigList'{id = ID2, +%% signalList = SL2}) -> +%% chk_IndAudSeqSigList_id(ID1, ID2), +%% chk_opt_IndAudSignal(SL1, SL2), +%% ok; +%% chk_IndAudSeqSigList(L1, L2) -> +%% wrong_type('IndAudSeqSigList', L1, L2). + +%% chk_IndAudSeqSigList_id(ID, ID) -> +%% chk_type(fun is_IndAudSeqSigList_id/1, 'IndAudSeqSigList_id', ID); +%% chk_IndAudSeqSigList_id(ID1, ID2) -> +%% case (is_IndAudSeqSigList_id(ID1) andalso +%% is_IndAudSeqSigList_id(ID2)) of +%% true -> +%% not_equal('IndAudSeqSigList_id', ID1, ID2); +%% false -> +%% wrong_type('IndAudSeqSigList_id', ID1, ID2) +%% end. + + +%% %% -- IndAudSignal -- + +%% is_opt_IndAudSignal(asn1_NOVALUE) -> +%% true; +%% is_opt_IndAudSignal(V) -> +%% is_IndAudSignal(V). + +%% is_IndAudSignal(#'IndAudSignal'{signalName = Name, +%% streamID = SID}) -> +%% is_PkgdName(Name) andalso is_opt_StreamID(SID); +%% is_IndAudSignal(_) -> +%% false. + +%% chk_opt_IndAudSignal(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_IndAudSignal(S1, S2) -> +%% chk_IndAudSignal(S1, S2). + +%% chk_IndAudSignal(S, S) -> +%% chk_type(fun is_IndAudSignal/1, 'IndAudSignal', S); +%% chk_IndAudSignal(#'IndAudSignal'{signalName = Name1, +%% streamID = SID1}, +%% #'IndAudSignal'{signalName = Name2, +%% streamID = SID2}) -> +%% chk_PkgdName(Name1, Name2), +%% chk_opt_StreamID(SID1, SID2), +%% ok; +%% chk_IndAudSignal(S1, S2) -> +%% wrong_type('IndAudSignal', S1, S2). + + +%% %% -- IndAudDigitMapDescriptor -- + +%% is_IndAudDigitMapDescriptor( +%% #'IndAudDigitMapDescriptor'{digitMapName = Name}) -> +%% is_opt_DigitMapName(Name); +%% is_IndAudDigitMapDescriptor(_) -> +%% false. + +%% chk_IndAudDigitMapDescriptor(D, D) -> +%% chk_type(fun is_IndAudDigitMapDescriptor/1, 'IndAudDigitMapDescriptor', D); +%% chk_IndAudDigitMapDescriptor( +%% #'IndAudDigitMapDescriptor'{digitMapName = Name1}, +%% #'IndAudDigitMapDescriptor'{digitMapName = Name2}) -> +%% validate(fun() -> chk_opt_DigitMapName(Name1, Name2) end, +%% 'IndAudDigitMapDescriptor'), +%% ok; +%% chk_IndAudDigitMapDescriptor(D1, D2) -> +%% wrong_type('IndAudDigitMapDescriptor', D1, D2). + + +%% %% -- IndAudStatisticsDescriptor -- + +%% is_IndAudStatisticsDescriptor( +%% #'IndAudStatisticsDescriptor'{statName = Name}) -> +%% is_PkgdName(Name); +%% is_IndAudStatisticsDescriptor(_) -> +%% false. + +%% chk_IndAudStatisticsDescriptor(D, D) -> +%% chk_type(fun is_IndAudStatisticsDescriptor/1, +%% 'IndAudStatisticsDescriptor', D); +%% chk_IndAudStatisticsDescriptor( +%% #'IndAudStatisticsDescriptor'{statName = Name1}, +%% #'IndAudStatisticsDescriptor'{statName = Name2}) -> +%% validate(fun() -> chk_PkgdName(Name1, Name2) end, +%% 'IndAudStatisticsDescriptor'), +%% ok; +%% chk_IndAudStatisticsDescriptor(D1, D2) -> +%% wrong_type('IndAudStatisticsDescriptor', D1, D2). + + +%% %% -- IndAudPackagesDescriptor -- + +%% is_IndAudPackagesDescriptor( +%% #'IndAudPackagesDescriptor'{packageName = Name, +%% packageVersion = Ver}) -> +%% is_Name(Name) andalso is_IndAudPackagesDescriptor_packageVersion(Ver); +%% is_IndAudPackagesDescriptor(_) -> +%% false. + +%% is_IndAudPackagesDescriptor_packageVersion(V) -> +%% is_INTEGER(V, {range, 0, 99}). + +%% chk_IndAudPackagesDescriptor( +%% #'IndAudPackagesDescriptor'{packageName = Name1, +%% packageVersion = Ver1}, +%% #'IndAudPackagesDescriptor'{packageName = Name2, +%% packageVersion = Ver2}) -> +%% validate(fun() -> chk_Name(Name1, Name2) end, 'IndAudPackagesDescriptor'), +%% chk_IndAudPackagesDescriptor_packageVersion(Ver1, Ver2), +%% ok; +%% chk_IndAudPackagesDescriptor(D1, D2) -> +%% wrong_type('IndAudPackagesDescriptor', D1, D2). + +%% chk_IndAudPackagesDescriptor_packageVersion(V, V) -> +%% chk_type(fun is_IndAudPackagesDescriptor_packageVersion/1, +%% 'IndAudPackagesDescriptor_packageVersion', V); +%% chk_IndAudPackagesDescriptor_packageVersion(V1, V2) -> +%% case (is_IndAudPackagesDescriptor_packageVersion(V1) andalso +%% is_IndAudPackagesDescriptor_packageVersion(V2)) of +%% true -> +%% not_equal('IndAudPackagesDescriptor_packageVersion', V1, V2); +%% false -> +%% wrong_type('IndAudPackagesDescriptor_packageVersion', V1, V2) +%% end. + + +%% %% -- NotifyRequest -- + +%% is_NotifyRequest(#'NotifyRequest'{terminationID = Tids, +%% observedEventsDescriptor = OED, +%% errorDescriptor = ED}) -> +%% is_TerminationIDList(Tids) andalso +%% is_ObservedEventsDescriptor(OED) andalso +%% is_opt_ErrorDescriptor(ED); +%% is_NotifyRequest(_) -> +%% false. + +%% chk_NotifyRequest(#'NotifyRequest'{terminationID = Tids1, +%% observedEventsDescriptor = OED1, +%% errorDescriptor = ED1}, +%% #'NotifyRequest'{terminationID = Tids2, +%% observedEventsDescriptor = OED2, +%% errorDescriptor = ED2}) -> +%% validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, +%% 'NotifyRequest'), +%% validate(fun() -> chk_ObservedEventsDescriptor(OED1, OED2) end, +%% 'NotifyRequest'), +%% validate(fun() -> chk_opt_ErrorDescriptor(ED1, ED2) end, +%% 'NotifyRequest'), +%% ok; +%% chk_NotifyRequest(NR1, NR2) -> +%% wrong_type('NotifyRequest', NR1, NR2). + + +%% %% -- NotifyReply -- + +%% is_NotifyReply(#'NotifyReply'{terminationID = Tids, +%% errorDescriptor = ED}) -> +%% is_TerminationIDList(Tids) andalso is_opt_ErrorDescriptor(ED); +%% is_NotifyReply(_) -> +%% false. + +%% chk_NotifyReply(#'NotifyReply'{terminationID = Tids1, +%% errorDescriptor = ED1}, +%% #'NotifyReply'{terminationID = Tids2, +%% errorDescriptor = ED2}) -> +%% validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, 'NotifyReply'), +%% validate(fun() -> chk_opt_ErrorDescriptor(ED1, ED2) end, 'NotifyReply'), +%% ok; +%% chk_NotifyReply(NR1, NR2) -> +%% wrong_type('NotifyReply', NR1, NR2). + + +%% %% -- ObservedEventsDescriptor -- + +%% is_ObservedEventsDescriptor( +%% #'ObservedEventsDescriptor'{requestId = RID, +%% observedEventLst = OEL}) -> +%% is_RequestID(RID) andalso +%% is_ObservedEventsDescriptor_observedEventLst(OEL); +%% is_ObservedEventsDescriptor(_) -> +%% false. + +%% is_ObservedEventsDescriptor_observedEventLst([]) -> +%% true; +%% is_ObservedEventsDescriptor_observedEventLst([H|T]) -> +%% is_ObservedEvent(H) andalso +%% is_ObservedEventsDescriptor_observedEventLst(T); +%% is_ObservedEventsDescriptor_observedEventLst(_) -> +%% false. + +%% chk_ObservedEventsDescriptor( +%% #'ObservedEventsDescriptor'{requestId = RID1, +%% observedEventLst = OEL1}, +%% #'ObservedEventsDescriptor'{requestId = RID2, +%% observedEventLst = OEL2}) -> +%% validate(fun() -> chk_RequestID(RID1, RID2) end, +%% 'ObservedEventsDescriptor'), +%% validate( +%% fun() -> +%% chk_ObservedEventsDescriptor_observedEventLst(OEL1, OEL2) +%% end, +%% 'ObservedEventsDescriptor'), +%% ok; +%% chk_ObservedEventsDescriptor(D1, D2) -> +%% wrong_type('ObservedEventsDescriptor', D1, D2). + +%% chk_ObservedEventsDescriptor_observedEventLst([], []) -> +%% ok; +%% chk_ObservedEventsDescriptor_observedEventLst([] = L1, L2) -> +%% not_equal('ObservedEventsDescriptor_observedEventLst', L1, L2); +%% chk_ObservedEventsDescriptor_observedEventLst(L1, [] = L2) -> +%% not_equal('ObservedEventsDescriptor_observedEventLst', L1, L2); +%% chk_ObservedEventsDescriptor_observedEventLst([H|T1], [H|T2]) -> +%% case is_ObservedEvent(H) of +%% true -> +%% chk_ObservedEventsDescriptor_observedEventLst(T1, T2); +%% false -> +%% wrong_type('ObservedEventsDescriptor_observedEventLst_val', H) +%% end; +%% chk_ObservedEventsDescriptor_observedEventLst([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_ObservedEvent(H1, H2) end, +%% 'ObservedEventsDescriptor_observedEventLst_val'), +%% chk_ObservedEventsDescriptor_observedEventLst(T1, T2); +%% chk_ObservedEventsDescriptor_observedEventLst(L1, L2) -> +%% wrong_type('ObservedEventsDescriptor_observedEventLst', L1, L2). + + +%% %% -- ObservedEvent -- + +%% is_ObservedEvent(#'ObservedEvent'{eventName = Name, +%% streamID = SID, +%% eventParList = EPL, +%% timeNotation = TN}) -> +%% is_EventName(Name) andalso +%% is_opt_StreamID(SID) andalso +%% is_ObservedEvent_eventParList(EPL) andalso +%% is_opt_TimeNotation(TN); +%% is_ObservedEvent(_) -> +%% false. + +%% is_ObservedEvent_eventParList([]) -> +%% true; +%% is_ObservedEvent_eventParList([H|T]) -> +%% is_EventParameter(H) andalso is_ObservedEvent_eventParList(T); +%% is_ObservedEvent_eventParList(_) -> +%% false. + +%% chk_ObservedEvent(E, E) -> +%% chk_type(fun is_ObservedEvent/1, 'ObservedEvent', E); +%% chk_ObservedEvent(#'ObservedEvent'{eventName = Name1, +%% streamID = SID1, +%% eventParList = EPL1, +%% timeNotation = TN1}, +%% #'ObservedEvent'{eventName = Name2, +%% streamID = SID2, +%% eventParList = EPL2, +%% timeNotation = TN2}) -> +%% validate(fun() -> chk_EventName(Name1, Name2) end, 'ObservedEvent'), +%% validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'ObservedEvent'), +%% chk_ObservedEvent_eventParList(EPL1, EPL2), +%% validate(fun() -> chk_opt_TimeNotation(TN1, TN2) end, 'ObservedEvent'), +%% ok; +%% chk_ObservedEvent(E1, E2) -> +%% wrong_type('ObservedEvent', E1, E2). + +%% chk_ObservedEvent_eventParList([], []) -> +%% ok; +%% chk_ObservedEvent_eventParList([] = EPL1, EPL2) -> +%% not_equal('ObservedEvent_eventParList', EPL1, EPL2); +%% chk_ObservedEvent_eventParList(EPL1, [] = EPL2) -> +%% not_equal('ObservedEvent_eventParList', EPL1, EPL2); +%% chk_ObservedEvent_eventParList([H|T1], [H|T2]) -> +%% case is_EventParameter(H) of +%% true -> +%% chk_ObservedEvent_eventParList(T1, T2); +%% false -> +%% wrong_type('ObservedEvent_eventParList_val', H) +%% end; +%% chk_ObservedEvent_eventParList([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_EventParameter(H1, H2) end, +%% 'ObservedEvent_eventParList'), +%% chk_ObservedEvent_eventParList(T1, T2); +%% chk_ObservedEvent_eventParList(L1, L2) -> +%% wrong_type('ObservedEvent_eventParList', L1, L2). + + +%% %% -- EventName -- + +is_EventName(N) -> is_PkgdName(N). + +%% chk_EventName(N, N) -> +%% chk_type(fun is_EventName/1, 'EventName', N); +%% chk_EventName(N1, N2) -> +%% case (is_EventName(N1) andalso is_EventName(N2)) of +%% true -> +%% not_equal('EventName', N1, N2); +%% false -> +%% wrong_type('EventName', N1, N2) +%% end. + + +%% %% -- EventParameter -- + +is_EventParameter(#'EventParameter'{eventParameterName = Name, + value = Val, + extraInfo = EI}) -> + d("is_EventParameter -> entery with" + "~n Name: ~p" + "~n Val: ~p" + "~n EI: ~p", [Name, Val, EI]), + is_Name(Name) andalso + is_Value(Val) andalso + is_EventParameter_extraInfo(EI); +is_EventParameter(_) -> + false. + +is_EventParameter_extraInfo(asn1_NOVALUE) -> + true; +is_EventParameter_extraInfo({Tag, Val}) -> + is_EventParameter_extraInfo_tag(Tag) andalso + is_EventParameter_extraInfo_val(Tag, Val); +is_EventParameter_extraInfo(_) -> + false. + +is_EventParameter_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_EventParameter_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_EventParameter_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_EventParameter_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + +%% chk_EventParameter(#'EventParameter'{eventParameterName = Name1, +%% value = Val1, +%% extraInfo = EI1}, +%% #'EventParameter'{eventParameterName = Name2, +%% value = Val2, +%% extraInfo = EI2}) -> +%% validate(fun() -> chk_Name(Name1, Name2) end, 'EventParameter'), +%% validate(fun() -> chk_Value(Val1, Val2) end, 'EventParameter'), +%% chk_EventParameter_extraInfo(EI1, EI2), +%% ok; +%% chk_EventParameter(P1, P2) -> +%% wrong_type('EventParameter', P1, P2). + +%% chk_EventParameter_extraInfo(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_EventParameter_extraInfo(EI, EI) -> +%% chk_type(fun is_EventParameter_extraInfo/1, +%% 'EventParameter_extraInfo', EI); +%% chk_EventParameter_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> +%% case (is_EventParameter_extraInfo_tag(Tag) andalso +%% is_EventParameter_extraInfo_val(Tag, Val1) andalso +%% is_EventParameter_extraInfo_val(Tag, Val2)) of +%% true -> +%% chk_EventParameter_extraInfo_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('EventParameter_extraInfo', EI1, EI2) +%% end; +%% chk_EventParameter_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> +%% case ((is_EventParameter_extraInfo_tag(Tag1) andalso +%% is_EventParameter_extraInfo_val(Tag1, Val1)) andalso +%% (is_EventParameter_extraInfo_tag(Tag2) andalso +%% is_EventParameter_extraInfo_val(Tag2, Val2))) of +%% true -> +%% not_equal('EventParameter_extraInfo', EI1, EI2); +%% false -> +%% wrong_type('EventParameter_extraInfo', EI1, EI2) +%% end; +%% chk_EventParameter_extraInfo(EI1, EI2) -> +%% wrong_type('EventParameter_extraInfo', EI1, EI2). + +%% chk_EventParameter_extraInfo_val(relation, Val1, Val2) -> +%% validate(fun() -> chk_Relation(Val1, Val2) end, +%% 'EventParameter_extraInfo_val'); +%% chk_EventParameter_extraInfo_val(range, Val1, Val2) -> +%% validate(fun() -> chk_BOOLEAN(Val1, Val2) end, +%% 'EventParameter_extraInfo_val'); +%% chk_EventParameter_extraInfo_val(sublist, Val1, Val2) -> +%% validate(fun() -> chk_BOOLEAN(Val1, Val2) end, +%% 'EventParameter_extraInfo_val'). + + +%% %% -- ServiceChangeRequest -- + +%% is_ServiceChangeRequest(#'ServiceChangeRequest'{terminationID = Tids, +%% serviceChangeParms = Parms}) -> +%% is_TerminationIDList(Tids) andalso is_ServiceChangeParm(Parms); +%% is_ServiceChangeRequest(_) -> +%% false. + +%% chk_ServiceChangeRequest(R, R) -> +%% chk_type(fun is_ServiceChangeRequest/1, 'ServiceChangeRequest', R); +%% chk_ServiceChangeRequest( +%% #'ServiceChangeRequest'{terminationID = Tids1, +%% serviceChangeParms = Parms1}, +%% #'ServiceChangeRequest'{terminationID = Tids2, +%% serviceChangeParms = Parms2}) -> +%% validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, +%% 'ServiceChangeRequest'), +%% validate(fun() -> chk_ServiceChangeParm(Parms1, Parms2) end, +%% 'ServiceChangeRequest'), +%% ok; +%% chk_ServiceChangeRequest(R1, R2) -> +%% wrong_type('ServiceChangeRequest', R1, R2). + + +%% %% -- ServiceChangeReply -- + +%% is_ServiceChangeReply(#'ServiceChangeReply'{terminationID = Tids, +%% serviceChangeResult = Res}) -> +%% is_TerminationIDList(Tids) andalso is_ServiceChangeResult(Res); +%% is_ServiceChangeReply(_) -> +%% false. + +%% chk_ServiceChangeReply(R, R) -> +%% chk_type(fun is_ServiceChangeReply/1, 'ServiceChangeReply', R); +%% chk_ServiceChangeReply( +%% #'ServiceChangeReply'{terminationID = Tids1, +%% serviceChangeResult = Res1}, +%% #'ServiceChangeReply'{terminationID = Tids2, +%% serviceChangeResult = Res2}) -> +%% validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, +%% 'ServiceChangeReply'), +%% validate(fun() -> chk_ServiceChangeResult(Res1, Res2) end, +%% 'ServiceChangeReply'), +%% ok; +%% chk_ServiceChangeReply(R1, R2) -> +%% wrong_type('ServiceChangeReply', R1, R2). + + +%% %% -- ServiceChangeResult -- + +%% is_ServiceChangeResult({Tag, Val}) -> +%% is_ServiceChangeResult_tag(Tag) andalso +%% is_ServiceChangeResult_val(Tag, Val); +%% is_ServiceChangeResult(_) -> +%% false. + +%% is_ServiceChangeResult_tag(Tag) -> +%% Tags = [errorDescriptor, serviceChangeResParms], +%% lists:member(Tag, Tags). + +%% is_ServiceChangeResult_val(errorDescriptor, Val) -> +%% is_ErrorDescriptor(Val); +%% is_ServiceChangeResult_val(serviceChangeResParms, Val) -> +%% is_ServiceChangeResParm(Val). + +%% chk_ServiceChangeResult(Res, Res) -> +%% chk_type(fun is_ServiceChangeResult/1, 'ServiceChangeResult', Res); +%% chk_ServiceChangeResult({Tag, Val1} = Res1, {Tag, Val2} = Res2) -> +%% case (is_ServiceChangeResult_tag(Tag) andalso +%% is_ServiceChangeResult_val(Tag, Val1) andalso +%% is_ServiceChangeResult_val(Tag, Val2)) of +%% true -> +%% chk_ServiceChangeResult_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('ServiceChangeResult', Res1, Res2) +%% end; +%% chk_ServiceChangeResult({Tag1, Val1} = Res1, {Tag2, Val2} = Res2) -> +%% case ((is_ServiceChangeResult_tag(Tag1) andalso +%% is_ServiceChangeResult_val(Tag1, Val1)) andalso +%% (is_ServiceChangeResult_tag(Tag2) andalso +%% is_ServiceChangeResult_val(Tag2, Val2))) of +%% true -> +%% not_equal('ServiceChangeResult', Res1, Res2); +%% false -> +%% wrong_type('ServiceChangeResult', Res1, Res2) +%% end; +%% chk_ServiceChangeResult(Res1, Res2) -> +%% wrong_type('ServiceChangeResult', Res1, Res2). + +%% chk_ServiceChangeResult_val(errorDescriptor, Val1, Val2) -> +%% validate(fun() -> chk_ErrorDescriptor(Val1, Val2) end, +%% 'ServiceChangeResult'); +%% chk_ServiceChangeResult_val(serviceChangeResParms, Val1, Val2) -> +%% validate(fun() -> chk_ServiceChangeResParm(Val1, Val2) end, +%% 'ServiceChangeResult'). + + +%% %% -- WildcardField -- + +%% is_WildcardField(WF) -> is_OCTET_STRING(WF, {exact, 1}). + +%% chk_WildcardField(WF, WF) -> +%% case is_WildcardField(WF) of +%% true -> +%% ok; +%% false -> +%% wrong_type('WildcardField', WF) +%% end; +%% chk_WildcardField(WF1, WF2) -> +%% case (is_WildcardField(WF1) andalso is_WildcardField(WF2)) of +%% true -> +%% not_equal('WildcardField', WF1, WF2); +%% false -> +%% wrong_type('WildcardField', WF1, WF2) +%% end. + + +%% %% -- TerminationID -- + +%% is_TerminationID(#'TerminationID'{wildcard = W, +%% id = ID}) -> +%% is_TerminationID_wildcard(W) andalso is_TerminationID_id(ID); +%% is_TerminationID(#megaco_term_id{contains_wildcards = _W, +%% id = _ID}) -> +%% true; % What are the types? +%% is_TerminationID(_) -> +%% false. + +%% is_TerminationID_wildcard([]) -> +%% true; +%% is_TerminationID_wildcard([H|T]) -> +%% is_WildcardField(H) andalso is_TerminationID_wildcard(T); +%% is_TerminationID_wildcard(_) -> +%% false. + +%% is_TerminationID_id(ID) -> is_OCTET_STRING(ID, {range, 1, 8}). + +%% chk_TerminationID(Id,Id) -> +%% chk_type(fun is_TerminationID/1, 'TerminationID', Id); +%% chk_TerminationID(#'TerminationID'{wildcard = W1, +%% id = I1}, +%% #'TerminationID'{wildcard = W2, +%% id = I2}) -> +%% chk_TerminationID_wildcard(W1, W2), +%% chk_TerminationID_id(I1, I2), +%% ok; +%% chk_TerminationID(#megaco_term_id{contains_wildcards = W1, +%% id = I1}, +%% #megaco_term_id{contains_wildcards = W2, +%% id = I2}) -> +%% chk_TerminationID_wildcard(W1, W2), +%% chk_TerminationID_id(I1, I2), +%% ok; +%% chk_TerminationID(Tid1, Tid2) -> +%% wrong_type('TerminationID', Tid1, Tid2). + +%% chk_TerminationID_wildcard([], []) -> +%% ok; +%% chk_TerminationID_wildcard([] = WF1, WF2) -> +%% not_equal('TerminationID_wildcard', WF1, WF2); +%% chk_TerminationID_wildcard(WF1, [] = WF2) -> +%% not_equal('TerminationID_wildcard', WF1, WF2); +%% chk_TerminationID_wildcard([H|T1], [H|T2]) -> +%% case is_WildcardField(H) of +%% true -> +%% chk_TerminationID_wildcard(T1, T2); +%% false -> +%% wrong_type('TerminationID_wildcard_val', H) +%% end; +%% chk_TerminationID_wildcard([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_WildcardField(H1, H2) end, +%% 'TerminationID_wildcard_val'), +%% chk_TerminationID_wildcard(T1, T2); +%% chk_TerminationID_wildcard(WF1,WF2) -> +%% not_equal('TerminationId_wildcard', WF1, WF2). + +%% chk_TerminationID_id(Id, Id) -> +%% case is_OCTET_STRING(Id, {range, 1, 8}) of +%% true -> +%% ok; +%% false -> +%% wrong_type('TerminationID_id', Id, Id) +%% end; +%% chk_TerminationID_id(Id1, Id2) -> +%% not_equal(terminationId_id, Id1, Id2). + + +%% %% -- TerminationIDList -- + +%% is_TerminationIDList([]) -> +%% true; +%% is_TerminationIDList([H|T]) -> +%% is_TerminationID(H) andalso is_TerminationIDList(T); +%% is_TerminationIDList(_) -> +%% false. + +%% chk_TerminationIDList([], []) -> +%% ok; +%% chk_TerminationIDList([] = L1, L2) -> +%% not_equal('TerminationIDList', L1, L2); +%% chk_TerminationIDList(L1, [] = L2) -> +%% not_equal('TerminationIDList', L1, L2); +%% chk_TerminationIDList([H|T1], [H|T2]) -> +%% case is_TerminationID(H) of +%% true -> +%% chk_TerminationIDList(T1, T2); +%% false -> +%% wrong_type('TerminationIDList', H) +%% end; +%% chk_TerminationIDList([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_TerminationID(H1, H2) end, 'TerminationIDList'), +%% chk_TerminationIDList(T1, T2); +%% chk_TerminationIDList(L1, L2) -> +%% wrong_type('TerminationIDList', L1, L2). + + +%% %% -- MediaDescriptor -- + +%% is_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TSD, +%% streams = S}) -> +%% is_opt_TerminationStateDescriptor(TSD) andalso +%% is_MediaDescriptor_streams(S); +%% is_MediaDescriptor(_) -> +%% false. + +%% is_MediaDescriptor_streams(asn1_NOVALUE) -> +%% true; +%% is_MediaDescriptor_streams({Tag, Val}) -> +%% is_MediaDescriptor_streams_tag(Tag) andalso +%% is_MediaDescriptor_streams_val(Tag, Val); +%% is_MediaDescriptor_streams(_) -> +%% false. + +%% is_MediaDescriptor_streams_tag(Tag) -> +%% Tags = [oneStream, multiStream], +%% lists:member(Tag, Tags). + +%% is_MediaDescriptor_streams_val(oneStream, SP) -> +%% is_StreamParms(SP); +%% is_MediaDescriptor_streams_val(multiStream, SDL) -> +%% is_MediaDescriptor_multiStream(SDL). + +%% is_MediaDescriptor_multiStream([]) -> +%% true; +%% is_MediaDescriptor_multiStream([H|T]) -> +%% is_StreamDescriptor(H) andalso is_MediaDescriptor_multiStream(T); +%% is_MediaDescriptor_multiStream(_) -> +%% false. + +%% chk_MediaDescriptor(D, D) -> +%% chk_type(fun is_MediaDescriptor/1, 'MediaDescriptor', D); +%% chk_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TSD1, +%% streams = S1}, +%% #'MediaDescriptor'{termStateDescr = TSD2, +%% streams = S2}) -> +%% validate( +%% fun() -> +%% chk_opt_TerminationStateDescriptor(TSD1, TSD2) +%% end, +%% 'MediaDescriptor'), +%% validate( +%% fun() -> +%% chk_MediaDescriptor_streams(S1, S2) +%% end, +%% 'MediaDescriptor'), +%% ok; +%% chk_MediaDescriptor(D1, D2) -> +%% wrong_type('MediaDescriptor', D1, D2). + + +%% chk_MediaDescriptor_streams(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_MediaDescriptor_streams({oneStream, SP1}, {oneStream, SP2}) -> +%% validate(fun() -> +%% chk_StreamParms(SP1, SP2) +%% end, +%% 'MediaDescriptor_streams'); +%% chk_MediaDescriptor_streams({multiStream, SDs1}, {multiStream, SDs2}) -> +%% validate(fun() -> +%% chk_MediaDescriptor_multiStream(SDs1, SDs2) +%% end, +%% 'MediaDescriptor_streams'); +%% chk_MediaDescriptor_streams(S1, S2) -> +%% wrong_type('MediaDescriptor_streams', S1, S2). + +%% chk_MediaDescriptor_multiStream([], []) -> +%% ok; +%% chk_MediaDescriptor_multiStream([] = MS1, MS2) -> +%% not_equal('MediaDescriptor_multiStream', MS1, MS2); +%% chk_MediaDescriptor_multiStream(MS1, [] = MS2) -> +%% not_equal('MediaDescriptor_multiStream', MS1, MS2); +%% chk_MediaDescriptor_multiStream([H|T1], [H|T2]) -> +%% case is_StreamDescriptor(H) of +%% true -> +%% chk_MediaDescriptor_multiStream(T1, T2); +%% false -> +%% wrong_type('MediaDescriptor_multiStream_val', H) +%% end; +%% chk_MediaDescriptor_multiStream([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_StreamDescriptor(H1, H2) end, +%% 'MediaDescriptor_multiStream_val'), +%% chk_MediaDescriptor_multiStream(T1, T2); +%% chk_MediaDescriptor_multiStream(MS1, MS2) -> +%% wrong_type('MediaDescriptor_multiStream_val', MS1, MS2). + + +%% %% -- StreamDescriptor -- + +%% is_StreamDescriptor(#'StreamDescriptor'{streamID = SID, +%% streamParms = Parms}) -> +%% is_StreamID(SID) andalso is_StreamParms(Parms); +%% is_StreamDescriptor(_) -> +%% false. + +%% chk_StreamDescriptor(D, D) -> +%% chk_type(fun is_StreamDescriptor/1, 'StreamDescriptor', D); +%% chk_StreamDescriptor(#'StreamDescriptor'{streamID = SID1, +%% streamParms = Parms1}, +%% #'StreamDescriptor'{streamID = SID2, +%% streamParms = Parms2}) -> +%% validate(fun() -> chk_StreamID(SID1, SID2) end, 'StreamDescriptor'), +%% validate(fun() -> chk_StreamParms(Parms1, Parms2) end, 'StreamDescriptor'), +%% ok; +%% chk_StreamDescriptor(D1, D2) -> +%% wrong_type('StreamDescriptor', D1, D2). + + +%% %% -- StreamParms -- + +%% is_StreamParms(#'StreamParms'{localControlDescriptor = LCD, +%% localDescriptor = LD, +%% remoteDescriptor = RD}) -> +%% is_opt_LocalControlDescriptor(LCD) andalso +%% is_opt_LocalRemoteDescriptor(LD) andalso +%% is_opt_LocalRemoteDescriptor(RD); +%% is_StreamParms(_) -> +%% false. + +%% chk_StreamParms(SP, SP) -> +%% chk_type(fun is_StreamParms/1, 'StreamParms', SP); +%% chk_StreamParms(#'StreamParms'{localControlDescriptor = LCD1, +%% localDescriptor = LD1, +%% remoteDescriptor = RD1}, +%% #'StreamParms'{localControlDescriptor = LCD2, +%% localDescriptor = LD2, +%% remoteDescriptor = RD2}) -> +%% chk_opt_LocalControlDescriptor(LCD1, LCD2), +%% validate(fun() -> chk_opt_LocalRemoteDescriptor(LD1, LD2) end, +%% localDescriptor), +%% validate(fun() -> chk_opt_LocalRemoteDescriptor(RD1, RD2) end, +%% remoteDescriptor), +%% ok; +%% chk_StreamParms(P1, P2) -> +%% wrong_type('StreamParms', P1, P2). + + +%% %% -- LocalControlDescriptor -- + +%% is_opt_LocalControlDescriptor(asn1_NOVALUE) -> +%% true; +%% is_opt_LocalControlDescriptor(D) -> +%% is_LocalControlDescriptor(D). + +%% is_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = SM, +%% reserveValue = RV, +%% reserveGroup = RG, +%% propertyParms = PP}) -> +%% is_opt_StreamMode(SM) andalso +%% is_opt_BOOLEAN(RV) andalso +%% is_opt_BOOLEAN(RG) andalso +%% is_LocalControlDescriptor_propertyParms(PP); +%% is_LocalControlDescriptor(_) -> +%% false. + +%% is_LocalControlDescriptor_propertyParms([]) -> +%% true; +%% is_LocalControlDescriptor_propertyParms([H|T]) -> +%% is_PropertyParm(H) andalso is_LocalControlDescriptor_propertyParms(T); +%% is_LocalControlDescriptor_propertyParms(_) -> +%% false. + +%% chk_opt_LocalControlDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_LocalControlDescriptor(LCD1, LCD2) -> +%% chk_LocalControlDescriptor(LCD1, LCD2). + +%% chk_LocalControlDescriptor(LCD, LCD) -> +%% chk_type(fun is_LocalControlDescriptor/1, 'LocalControlDescriptor', LCD); +%% chk_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = SM1, +%% reserveValue = RV1, +%% reserveGroup = RG1, +%% propertyParms = PP1}, +%% #'LocalControlDescriptor'{streamMode = SM2, +%% reserveValue = RV2, +%% reserveGroup = RG2, +%% propertyParms = PP2}) -> +%% validate( +%% fun() -> chk_opt_StreamMode(SM1, SM2) end, +%% 'LocalControlDescriptor'), +%% validate( +%% fun() -> chk_opt_BOOLEAN(RV1, RV2) end, +%% 'LocalControlDescriptor_reserveValue'), +%% validate( +%% fun() -> chk_opt_BOOLEAN(RG1, RG2) end, +%% 'LocalControlDescriptor_reserveGroup'), +%% chk_LocalControlDescriptor_propertyParms(PP1, PP2), +%% ok; +%% chk_LocalControlDescriptor(LCD1, LCD2) -> +%% wrong_type('LocalControlDescriptor', LCD1, LCD2). + + +%% chk_LocalControlDescriptor_propertyParms([], []) -> +%% ok; +%% chk_LocalControlDescriptor_propertyParms([] = PP1, PP2) -> +%% not_equal('LocalControlDescriptor_propertyParms', PP1, PP2); +%% chk_LocalControlDescriptor_propertyParms(PP1, [] = PP2) -> +%% not_equal('LocalControlDescriptor_propertyParms', PP1, PP2); +%% chk_LocalControlDescriptor_propertyParms([H|T1], [H|T2]) -> +%% case is_PropertyParm(H) of +%% true -> +%% chk_LocalControlDescriptor_propertyParms(T1, T2); +%% false -> +%% wrong_type('LocalControlDescriptor_propertyParms_val', H) +%% end; +%% chk_LocalControlDescriptor_propertyParms([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_PropertyParm(H1, H2) end, +%% 'LocalControlDescriptor_propertyParms_val'), +%% chk_LocalControlDescriptor_propertyParms(T1, T2); +%% chk_LocalControlDescriptor_propertyParms(PP1, PP2) -> +%% wrong_type('LocalControlDescriptor_propertyParms', PP1, PP2). + + +%% %% -- StreamMode -- + +%% is_opt_StreamMode(asn1_NOVALUE) -> +%% true; +%% is_opt_StreamMode(SM) -> +%% is_StreamMode(SM). + +%% is_StreamMode(SM) -> +%% lists:member(SM, [sendOnly, recvOnly, sendRecv, inactive, loopBack]). + +%% chk_opt_StreamMode(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_StreamMode(SM1, SM2) -> +%% chk_StreamMode(SM1, SM2). + +%% chk_StreamMode(SM, SM) -> +%% chk_type(fun is_StreamMode/1, 'StreamMode', SM); +%% chk_StreamMode(SM1, SM2) -> +%% case (is_StreamMode(SM1) andalso is_StreamMode(SM2)) of +%% true -> +%% not_equal('StreamMode', SM1, SM2); +%% false -> +%% wrong_type('StreamMode', SM1, SM2) +%% end. + + +%% %% -- PropertyParm -- + +%% is_PropertyParm(#'PropertyParm'{name = N, +%% value = V, +%% extraInfo = I}) -> +%% is_PkgdName(N) andalso +%% is_PropertyParm_value(V) andalso +%% is_PropertyParm_extraInfo(I); +%% is_PropertyParm(_) -> +%% false. + +%% is_PropertyParm_value([]) -> +%% true; +%% is_PropertyParm_value([H|T]) -> +%% is_OCTET_STRING(H) andalso is_PropertyParm_value(T); +%% is_PropertyParm_value(_) -> +%% false. + +%% is_PropertyParm_extraInfo(asn1_NOVALUE) -> +%% true; +%% is_PropertyParm_extraInfo({Tag, Val}) -> +%% is_PropertyParm_extraInfo_tag(Tag) andalso +%% is_PropertyParm_extraInfo_val(Tag, Val); +%% is_PropertyParm_extraInfo(_) -> +%% false. + +%% is_PropertyParm_extraInfo_tag(Tag) -> +%% Tags = [relation, range, sublist], +%% lists:member(Tag, Tags). + +%% is_PropertyParm_extraInfo_val(relation, Val) -> +%% is_Relation(Val); +%% is_PropertyParm_extraInfo_val(range, Val) -> +%% is_BOOLEAN(Val); +%% is_PropertyParm_extraInfo_val(sublist, Val) -> +%% is_BOOLEAN(Val). + +%% chk_PropertyParm(P, P) -> +%% chk_type(fun is_PropertyParm/1, 'PropertyParm', P); +%% chk_PropertyParm(#'PropertyParm'{name = N1, +%% value = V1, +%% extraInfo = I1}, +%% #'PropertyParm'{name = N2, +%% value = V2, +%% extraInfo = I2}) -> +%% validate(fun() -> chk_PkgdName(N1, N2) end, 'PropertyParm'), +%% chk_PropertyParm_value(V1, V2), +%% chk_PropertyParm_extraInfo(I1, I2), +%% ok; +%% chk_PropertyParm(P1, P2) -> +%% wrong_type('PropertyParm', P1, P2). + +%% chk_PropertyParm_value([], []) -> +%% ok; +%% chk_PropertyParm_value([] = V1, V2) -> +%% not_equal('PropertyParm_value', V1, V2); +%% chk_PropertyParm_value(V1, [] = V2) -> +%% not_equal('PropertyParm_value', V1, V2); +%% chk_PropertyParm_value([H|T1], [H|T2]) -> +%% case is_OCTET_STRING(H) of +%% true -> +%% chk_PropertyParm_value(T1, T2); +%% false -> +%% wrong_type('PropertyParm_value_val', H) +%% end; +%% chk_PropertyParm_value([H1|_], [H2|_]) -> +%% case (is_OCTET_STRING(H1) andalso is_OCTET_STRING(H2)) of +%% true -> +%% not_equal('PropertyParm_value_val', H1, H2); +%% false -> +%% wrong_type('PropertyParm_value_val', H1, H2) +%% end; +%% chk_PropertyParm_value(V1, V2) -> +%% wrong_type('PropertyParm_value', V1, V2). + +%% chk_PropertyParm_extraInfo(EI, EI) -> +%% chk_type(fun is_PropertyParm_extraInfo/1, 'PropertyParm_extraInfo', EI); +%% chk_PropertyParm_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> +%% case (is_PropertyParm_extraInfo_tag(Tag) and +%% is_PropertyParm_extraInfo_val(Tag, Val1) and +%% is_PropertyParm_extraInfo_val(Tag, Val2)) of +%% true -> +%% chk_PropertyParm_extraInfo_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('PropertyParm_extraInfo', EI1, EI2) +%% end; +%% chk_PropertyParm_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> +%% case ((is_PropertyParm_extraInfo_tag(Tag1) and +%% is_PropertyParm_extraInfo_val(Tag1, Val1)) and +%% (is_PropertyParm_extraInfo_tag(Tag2) and +%% is_PropertyParm_extraInfo_val(Tag2, Val2))) of +%% true -> +%% not_equal('PropertyParm_extraInfo', EI1, EI2); +%% false -> +%% wrong_type('PropertyParm_extraInfo', EI1, EI2) +%% end; +%% chk_PropertyParm_extraInfo(EI1, EI2) -> +%% wrong_type('PropertyParm_extraInfo', EI1, EI2). + +%% chk_PropertyParm_extraInfo_val(relation, Val1, Val2) -> +%% validate(fun() -> chk_Relation(Val1, Val2) end, 'PropertyParm_extraInfo'); +%% chk_PropertyParm_extraInfo_val(range, Val1, Val2) -> +%% validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'PropertyParm_extraInfo'); +%% chk_PropertyParm_extraInfo_val(sublist, Val1, Val2) -> +%% validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'PropertyParm_extraInfo'). + + +%% %% -- Name -- + +is_Name(N) -> + %% Binary: is_OCTET_STRING(N, {exact, 2}). + case is_OCTET_STRING(N, {range, 1, 64}) of + true -> + is_NAME(N); + false -> + false + end. + +is_NAME([H|T]) when H =< $z, $a =< H -> + is_NAME2(T); +is_NAME([H|T]) when H =< $Z, $A =< H -> + is_NAME2(T); +is_NAME(_) -> + false. + +is_NAME2([]) -> + true; +is_NAME2([$_|T]) -> + is_NAME2(T); +is_NAME2([H|T]) when H =< $z, $a =< H -> + is_NAME2(T); +is_NAME2([H|T]) when H =< $Z, $A =< H -> + is_NAME2(T); +is_NAME2([H|T]) when H =< $9, $0 =< H -> + is_NAME2(T); +is_NAME2(_) -> + false. + + + +%% chk_Name(N, N) -> +%% chk_type(fun is_Name/1, 'Name', N); +%% chk_Name(N1, N2) -> +%% case (is_Name(N1) andalso is_Name(N2)) of +%% true -> +%% not_equal('Name', N1, N2); +%% false -> +%% wrong_type('Name', N1, N2) +%% end. + + +%% %% -- PkgdName -- + +%% PkgdName is either "AB/CD" or just plain "ABCD" +%% Note that in ASN.1 the parts is exactly 2 char +%% each, unless you don't use the native config +%% option. In text and in binary without the native +%% option, it is 63 + 1 chars for each. +is_PkgdName(N) -> + d("is_PkgdName -> entry with" + "~n N: ~p", [N]), + case string:tokens(N, "/") of + ["*" = PackageName, "*" = ItemID] -> + d("is_PkgdName -> tokenized (0): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + true; + [PackageName, "*" = ItemID] -> + d("is_PkgdName -> tokenized (1): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + is_Name(PackageName); + [PackageName, ItemID] -> + d("is_PkgdName -> tokenized (2): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + is_Name(PackageName) andalso is_Name(ItemID); + _ -> + is_Name(N) + end. + +%% chk_PkgdName(N, N) -> +%% case is_PkgdName(N) of +%% true -> +%% ok; +%% false -> +%% wrong_type('PkgdName', N, N) +%% end; +%% chk_PkgdName(N1, N2) -> +%% case (is_PkgdName(N1) andalso is_PkgdName(N2)) of +%% true -> +%% not_equal('PkgdName', N1, N2); +%% false -> +%% wrong_type('PkgdName', N1, N2) +%% end. + + +%% %% -- Relation -- + +is_Relation(R) -> + lists:member(R, [greaterThan, smallerThan, unequalTo]). + +%% chk_Relation(R, R) -> +%% chk_type(fun is_Relation/1, 'Relation', R); +%% chk_Relation(R1, R2) -> +%% case (is_Relation(R1) andalso is_Relation(R2)) of +%% true -> +%% not_equal('Relation', R1, R2); +%% false -> +%% wrong_type('Relation', R1, R2) +%% end. + + +%% %% -- LocalRemoteDescriptor -- + +%% is_opt_LocalRemoteDescriptor(D) -> +%% is_OPTIONAL(fun is_LocalRemoteDescriptor/1, D). + +%% is_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = PGs}) -> +%% is_LocalRemoteDescriptor_propGrps(PGs); +%% is_LocalRemoteDescriptor(_) -> +%% false. + +%% is_LocalRemoteDescriptor_propGrps([]) -> +%% true; +%% is_LocalRemoteDescriptor_propGrps([H|T]) -> +%% is_PropertyGroup(H) andalso is_LocalRemoteDescriptor_propGrps(T); +%% is_LocalRemoteDescriptor_propGrps(_) -> +%% false. + +%% chk_opt_LocalRemoteDescriptor(D1, D2) -> +%% chk_OPTIONAL('LocalRemoteDescriptor', D1, D2, +%% fun is_LocalRemoteDescriptor/1, +%% fun chk_LocalRemoteDescriptor/2). + +%% chk_LocalRemoteDescriptor(LRD, LRD) -> +%% chk_type(fun is_LocalRemoteDescriptor/1, 'LocalRemoteDescriptor', LRD); +%% chk_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = PG1}, +%% #'LocalRemoteDescriptor'{propGrps = PG2}) -> +%% chk_LocalRemoteDescriptor_propGrps(PG1, PG2), +%% ok; +%% chk_LocalRemoteDescriptor(LRD1, LRD2) -> +%% wrong_type('LocalRemoteDescriptor', LRD1, LRD2). + +%% chk_LocalRemoteDescriptor_propGrps([], []) -> +%% ok; +%% chk_LocalRemoteDescriptor_propGrps([] = PG1, PG2) -> +%% not_equal('LocalRemoteDescriptor_propGrps', PG1, PG2); +%% chk_LocalRemoteDescriptor_propGrps(PG1, [] = PG2) -> +%% not_equal('LocalRemoteDescriptor_propGrps', PG1, PG2); +%% chk_LocalRemoteDescriptor_propGrps([H|T1], [H|T2]) -> +%% case is_PropertyGroup(H) of +%% true -> +%% chk_LocalRemoteDescriptor_propGrps(T1, T2); +%% false -> +%% wrong_type('LocalRemoteDescriptor_propGrps_val', H) +%% end; +%% chk_LocalRemoteDescriptor_propGrps([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_PropertyGroup(H1, H2) end, +%% 'LocalRemoteDescriptor_propGrps_val'), +%% chk_LocalRemoteDescriptor_propGrps(T1, T2); +%% chk_LocalRemoteDescriptor_propGrps(PG1, PG2) -> +%% wrong_type('LocalRemoteDescriptor_propGrps', PG1, PG2). + + +%% %% -- PropertyGroup -- + +%% is_PropertyGroup([]) -> +%% true; +%% is_PropertyGroup([H|T]) -> +%% is_PropertyParm(H) andalso is_PropertyGroup(T); +%% is_PropertyGroup(_) -> +%% false. + +%% chk_PropertyGroup([], []) -> +%% ok; +%% chk_PropertyGroup([] = PG1, PG2) -> +%% not_equal('PropertyGroup', PG1, PG2); +%% chk_PropertyGroup(PG1, [] = PG2) -> +%% not_equal('PropertyGroup', PG1, PG2); +%% chk_PropertyGroup([H|T1], [H|T2]) -> +%% case is_PropertyParm(H) of +%% true -> +%% chk_PropertyGroup(T1, T2); +%% false -> +%% wrong_type('PropertyGroup_val', H) +%% end; +%% chk_PropertyGroup([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_PropertyParm(H1, H2) end, 'PropertyGroup_val'), +%% chk_PropertyGroup(T1, T2); +%% chk_PropertyGroup(PG1, PG2) -> +%% wrong_type('PropertyGroup', PG1, PG2). + + +%% %% -- TerminationStateDescriptor -- + +%% is_opt_TerminationStateDescriptor(D) -> +%% is_OPTIONAL(fun is_TerminationStateDescriptor/1, D). + +%% is_TerminationStateDescriptor( +%% #'TerminationStateDescriptor'{propertyParms = PP, +%% eventBufferControl = EBC, +%% serviceState = SS}) -> +%% is_TerminationStateDescriptor_propertyParms(PP) andalso +%% is_opt_EventBufferControl(EBC) andalso +%% is_opt_ServiceState(SS); +%% is_TerminationStateDescriptor(_) -> +%% false. + +%% is_TerminationStateDescriptor_propertyParms([]) -> +%% true; +%% is_TerminationStateDescriptor_propertyParms([H|T]) -> +%% is_PropertyParm(H) andalso is_TerminationStateDescriptor_propertyParms(T); +%% is_TerminationStateDescriptor_propertyParms(_) -> +%% false. + +%% chk_opt_TerminationStateDescriptor(D1, D2) -> +%% chk_OPTIONAL('TerminationStateDescriptor', D1, D2, +%% fun is_TerminationStateDescriptor/1, +%% fun chk_TerminationStateDescriptor/2). + +%% chk_TerminationStateDescriptor(D, D) -> +%% chk_type(fun is_TerminationStateDescriptor/1, +%% 'TerminationStateDescriptor', D); +%% chk_TerminationStateDescriptor( +%% #'TerminationStateDescriptor'{propertyParms = PP1, +%% eventBufferControl = EBC1, +%% serviceState = SS1}, +%% #'TerminationStateDescriptor'{propertyParms = PP2, +%% eventBufferControl = EBC2, +%% serviceState = SS2}) -> +%% chk_TerminationStateDescriptor_propertyParms(PP1, PP2), +%% validate( +%% fun() -> +%% chk_opt_EventBufferControl(EBC1, EBC2) +%% end, +%% 'TerminationStateDescriptor'), +%% validate( +%% fun() -> +%% chk_opt_ServiceState(SS1, SS2) +%% end, +%% 'TerminationStateDescriptor'), +%% ok; +%% chk_TerminationStateDescriptor(D1, D2) -> +%% wrong_type('TerminationStateDescriptor', D1, D2). + + +%% chk_TerminationStateDescriptor_propertyParms([], []) -> +%% ok; +%% chk_TerminationStateDescriptor_propertyParms([] = P1, P2) -> +%% not_equal('TerminationStateDescriptor_propertyParms', P1, P2); +%% chk_TerminationStateDescriptor_propertyParms(P1, [] = P2) -> +%% not_equal('TerminationStateDescriptor_propertyParms', P1, P2); +%% chk_TerminationStateDescriptor_propertyParms([H|T1], [H|T2]) -> +%% case is_PropertyParm(H) of +%% true -> +%% chk_TerminationStateDescriptor_propertyParms(T1, T2); +%% false -> +%% wrong_type('TerminationStateDescriptor_propertyParms_val', H) +%% end; +%% chk_TerminationStateDescriptor_propertyParms([H1|_], [H2|_]) -> +%% case (is_PropertyParm(H1) andalso is_PropertyParm(H2)) of +%% true -> +%% not_equal('TerminationStateDescriptor_propertyParms_val', H1, H2); +%% false -> +%% wrong_type('TerminationStateDescriptor_propertyParms_val', H1, H2) +%% end; +%% chk_TerminationStateDescriptor_propertyParms(P1, P2) -> +%% wrong_type('TerminationStateDescriptor_propertyParms', P1, P2). + + +%% %% -- EventBufferControl -- + +%% is_opt_EventBufferControl(asn1_NOVALUE) -> +%% true; +%% is_opt_EventBufferControl(EBC) -> +%% is_EventBufferControl(EBC). + +%% is_EventBufferControl(EBC) -> +%% lists:member(EBC, [off, lockStep]). + +%% chk_opt_EventBufferControl(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_EventBufferControl(EBC1, EBC2) -> +%% chk_EventBufferControl(EBC1, EBC2). + +%% chk_EventBufferControl(EBC, EBC) -> +%% chk_type(fun is_EventBufferControl/1, 'EventBufferControl', EBC); +%% chk_EventBufferControl(EBC1, EBC2) -> +%% case (is_EventBufferControl(EBC1) andalso is_EventBufferControl(EBC2)) of +%% true -> +%% not_equal('EventBufferControl', EBC1, EBC2); +%% false -> +%% wrong_type('EventBufferControl', EBC1, EBC2) +%% end. + + +%% %% -- ServiceState -- + +%% is_opt_ServiceState(asn1_NOVALUE) -> +%% true; +%% is_opt_ServiceState(SS) -> +%% is_ServiceState(SS). + +%% is_ServiceState(SS) -> +%% lists:member(SS, [test, outOfSvc, inSvc]). + +%% chk_opt_ServiceState(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_ServiceState(SS1, SS2) -> +%% chk_ServiceState(SS1, SS2). + +%% chk_ServiceState(SS, SS) -> +%% chk_type(fun is_ServiceState/1, 'ServiceState', SS); +%% chk_ServiceState(SS1, SS2) -> +%% case (is_ServiceState(SS1) andalso is_ServiceState(SS2)) of +%% true -> +%% not_equal('ServiceState', SS1, SS2); +%% false -> +%% wrong_type('ServiceState', SS1, SS2) +%% end. + + +%% %% -- MuxDescriptor -- + +%% is_MuxDescriptor(#'MuxDescriptor'{muxType = MT, +%% termList = TL, +%% nonStandardData = NSD}) -> +%% is_MuxType(MT) andalso +%% is_MuxDescriptor_termList(TL) andalso +%% is_NonStandardData(NSD); +%% is_MuxDescriptor(_) -> +%% false. + +%% is_MuxDescriptor_termList([]) -> +%% true; +%% is_MuxDescriptor_termList([H|T]) -> +%% is_TerminationID(H) andalso is_MuxDescriptor_termList(T); +%% is_MuxDescriptor_termList(_) -> +%% false. + +%% chk_MuxDescriptor(D, D) -> +%% chk_type(fun is_MuxDescriptor/1, 'MuxDescriptor', D); +%% chk_MuxDescriptor(#'MuxDescriptor'{muxType = MT1, +%% termList = TL1, +%% nonStandardData = NSD1}, +%% #'MuxDescriptor'{muxType = MT2, +%% termList = TL2, +%% nonStandardData = NSD2}) -> +%% validate(fun() -> chk_MuxType(MT1, MT2) end, 'MuxDescriptor'), +%% chk_MuxDescriptor_termList(TL1, TL2), +%% validate(fun() -> chk_NonStandardData(NSD1, NSD2) end, 'MuxDescriptor'), +%% ok; +%% chk_MuxDescriptor(D1, D2) -> +%% wrong_type('MuxDescriptor', D1, D2). + +%% chk_MuxDescriptor_termList([], []) -> +%% ok; +%% chk_MuxDescriptor_termList([] = TL1, TL2) -> +%% not_equal('MuxDescriptor_termList', TL1, TL2); +%% chk_MuxDescriptor_termList(TL1, [] = TL2) -> +%% not_equal('MuxDescriptor_termList', TL1, TL2); +%% chk_MuxDescriptor_termList([H|T1], [H|T2]) -> +%% case is_TerminationID(H) of +%% true -> +%% chk_MuxDescriptor_termList(T1, T2); +%% false -> +%% wrong_type('MuxDescriptor_termList_val', H) +%% end; +%% chk_MuxDescriptor_termList([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_TerminationID(H1, H2) end, +%% 'MuxDescriptor_termList_val'), +%% chk_MuxDescriptor_termList(T1, T2); +%% chk_MuxDescriptor_termList(TL1, TL2) -> +%% wrong_type('MuxDescriptor_termList', TL1, TL2). + + +%% %% -- MuxType -- + +%% is_MuxType(MT) -> +%% lists:member(MT, [h221, h223, h226, v76, nx64k]). + +%% chk_MuxType(MT, MT) -> +%% chk_type(fun is_MuxType/1, 'MuxType', MT); +%% chk_MuxType(MT1, MT2) -> +%% case (is_MuxType(MT1) andalso is_MuxType(MT2)) of +%% true -> +%% not_equal('MuxType', MT1, MT2); +%% false -> +%% wrong_type('MuxType', MT1, MT2) +%% end. + + +%% %% -- StreamID -- + +is_opt_StreamID(asn1_NOVALUE) -> + true; +is_opt_StreamID(V) -> + is_StreamID(V). + +is_StreamID(V) -> is_INTEGER(V, {range, 0, 65535}). + +%% chk_opt_StreamID(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_StreamID(V1, V2) -> +%% chk_StreamID(V1, V2). + +%% chk_StreamID(ID, ID) -> +%% chk_type(fun is_StreamID/1, 'StreamID', ID); +%% chk_StreamID(ID1, ID2) -> +%% case (is_StreamID(ID1) andalso is_StreamID(ID2)) of +%% true -> +%% not_equal('StreamID', ID1, ID2); +%% false -> +%% wrong_type('StreamID', ID1, ID2) +%% end. + + +%% %% -- EventsDescriptor -- + +%% is_EventsDescriptor(#'EventsDescriptor'{requestID = RID, +%% eventList = EVL}) -> +%% d("is_EventsDescriptor -> entry with" +%% "~n RID: ~p" +%% "~n EVL: ~p", [RID, EVL]), +%% is_opt_RequestID(RID) andalso is_EventsDescriptor_eventList(EVL); +%% is_EventsDescriptor(_) -> +%% false. + +%% is_EventsDescriptor_eventList([]) -> +%% true; +%% is_EventsDescriptor_eventList([H|T]) -> +%% is_RequestedEvent(H) andalso is_EventsDescriptor_eventList(T); +%% is_EventsDescriptor_eventList(_) -> +%% false. + +%% chk_EventsDescriptor(D, D) -> +%% chk_type(fun is_EventsDescriptor/1, 'EventsDescriptor', D); +%% chk_EventsDescriptor(#'EventsDescriptor'{requestID = RID1, +%% eventList = EVL1}, +%% #'EventsDescriptor'{requestID = RID2, +%% eventList = EVL2}) -> +%% validate(fun() -> chk_opt_RequestID(RID1, RID2) end, 'EventsDescriptor'), +%% chk_EventsDescriptor_eventList(EVL1, EVL2), +%% ok; +%% chk_EventsDescriptor(D1, D2) -> +%% wrong_type('EventsDescriptor', D1, D2). + +%% chk_EventsDescriptor_eventList([], []) -> +%% ok; +%% chk_EventsDescriptor_eventList([] = EVL1, EVL2) -> +%% not_equal('EventsDescriptor_eventList', EVL1, EVL2); +%% chk_EventsDescriptor_eventList(EVL1, [] = EVL2) -> +%% not_equal('EventsDescriptor_eventList', EVL1, EVL2); +%% chk_EventsDescriptor_eventList([H|T1], [H|T2]) -> +%% case is_RequestedEvent(H) of +%% true -> +%% chk_EventsDescriptor_eventList(T1, T2); +%% false -> +%% wrong_type('EventsDescriptor_eventList_val', H) +%% end; +%% chk_EventsDescriptor_eventList([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_RequestedEvent(H1, H2) end, +%% 'EventsDescriptor_eventList_val'), +%% chk_EventsDescriptor_eventList(T1, T2); +%% chk_EventsDescriptor_eventList(EVL1, EVL2) -> +%% wrong_type('EventsDescriptor_eventList', EVL1, EVL2). + + +%% %% -- RequestedEvent -- + +%% is_RequestedEvent(#'RequestedEvent'{pkgdName = N, +%% streamID = SID, +%% eventAction = EA, +%% evParList = EPL}) -> +%% d("is_RequestedEvent -> entry with" +%% "~n N: ~p" +%% "~n SID: ~p" +%% "~n EA: ~p" +%% "~n EPL: ~p", [N, SID, EA, EPL]), +%% is_PkgdName(N) andalso +%% is_opt_StreamID(SID) andalso +%% is_opt_RequestedActions(EA) andalso +%% is_RequestedEvent_evParList(EPL); +%% is_RequestedEvent(_) -> +%% false. + +%% is_RequestedEvent_evParList([]) -> +%% true; +%% is_RequestedEvent_evParList([H|T]) -> +%% is_EventParameter(H) andalso is_RequestedEvent_evParList(T); +%% is_RequestedEvent_evParList(_) -> +%% false. + +%% chk_RequestedEvent(RE, RE) -> +%% chk_type(fun is_RequestedEvent/1, 'RequestedEvent', RE); +%% chk_RequestedEvent(#'RequestedEvent'{pkgdName = N1, +%% streamID = SID1, +%% eventAction = EA1, +%% evParList = EPL1}, +%% #'RequestedEvent'{pkgdName = N2, +%% streamID = SID2, +%% eventAction = EA2, +%% evParList = EPL2}) -> +%% validate(fun() -> chk_PkgdName(N1, N2) end, 'RequestedEvent'), +%% validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'RequestedEvent'), +%% validate(fun() -> chk_opt_RequestedActions(EA1, EA2) end, +%% 'RequestedEvent'), +%% chk_RequestedEvent_evParList(EPL1, EPL2), +%% ok; +%% chk_RequestedEvent(RE1, RE2) -> +%% wrong_type('RequestedEvent', RE1, RE2). + +%% chk_RequestedEvent_evParList([], []) -> +%% ok; +%% chk_RequestedEvent_evParList([] = EPL1, EPL2) -> +%% not_equal('RequestedEvent_evParList', EPL1, EPL2); +%% chk_RequestedEvent_evParList(EPL1, [] = EPL2) -> +%% not_equal('RequestedEvent_evParList', EPL1, EPL2); +%% chk_RequestedEvent_evParList([H|T1], [H|T2]) -> +%% case is_EventParameter(H) of +%% true -> +%% chk_RequestedEvent_evParList(T1, T2); +%% false -> +%% wrong_type('RequestedEvent_evParList_val', H) +%% end; +%% chk_RequestedEvent_evParList([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_EventParameter(H1, H2) end, +%% 'RequestedEvent_evParList_val'), +%% chk_RequestedEvent_evParList(T1, T2); +%% chk_RequestedEvent_evParList(EPL1, EPL2) -> +%% wrong_type('RequestedEvent_evParList', EPL1, EPL2). + + +%% %% -- RequestedActions -- + +%% is_opt_RequestedActions(asn1_NOVALUE) -> +%% true; +%% is_opt_RequestedActions(RA) -> +%% is_RequestedActions(RA). + +%% is_RequestedActions(#'RequestedActions'{keepActive = KA, +%% eventDM = EDM, +%% secondEvent = SE, +%% signalsDescriptor = SD}) -> +%% d("is_RequestedActions -> entry with" +%% "~n KA: ~p" +%% "~n EDM: ~p" +%% "~n SE: ~p" +%% "~n SD: ~p", [KA, EDM, SE, SD]), +%% is_opt_BOOLEAN(KA) andalso +%% is_opt_EventDM(EDM) andalso +%% is_opt_SecondEventsDescriptor(SE) andalso +%% is_opt_SignalsDescriptor(SD); +%% is_RequestedActions(_) -> +%% false. + +%% chk_opt_RequestedActions(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_RequestedActions(RA1, RA2) -> +%% chk_RequestedActions(RA1, RA2). + +%% chk_RequestedActions(RA, RA) -> +%% chk_type(fun is_RequestedActions/1, 'RequestedActions', RA); +%% chk_RequestedActions(#'RequestedActions'{keepActive = KA1, +%% eventDM = EDM1, +%% secondEvent = SA1, +%% signalsDescriptor = SD1}, +%% #'RequestedActions'{keepActive = KA2, +%% eventDM = EDM2, +%% secondEvent = SA2, +%% signalsDescriptor = SD2}) -> +%% validate(fun() -> chk_opt_BOOLEAN(KA1, KA2) end, 'RequestedActions'), +%% validate(fun() -> chk_opt_EventDM(EDM1, EDM2) end, 'RequestedActions'), +%% validate(fun() -> chk_opt_SecondEventsDescriptor(SA1, SA2) end, +%% 'RequestedActions'), +%% validate(fun() -> chk_opt_SignalsDescriptor(SD1, SD2) end, +%% 'RequestedActions'), +%% ok; +%% chk_RequestedActions(RA1, RA2) -> +%% wrong_type('RequestedActions', RA1, RA2). + + +%% %% -- EventDM -- + +%% is_opt_EventDM(EDM) -> +%% is_OPTIONAL(fun is_EventDM/1, EDM). + +%% is_EventDM({Tag, Val}) -> +%% is_EventDM_tag(Tag) andalso is_EventDM_val(Tag, Val); +%% is_EventDM(_) -> +%% false. + +%% is_EventDM_tag(Tag) -> +%% Tags = [digitMapName, digitMapValue], +%% lists:member(Tag, Tags). + +%% is_EventDM_val(digitMapName, Val) -> +%% is_DigitMapName(Val); +%% is_EventDM_val(digitMapValue, Val) -> +%% is_DigitMapValue(Val). + +%% chk_opt_EventDM(EDM1, EDM2) -> +%% chk_OPTIONAL('EventDM', EDM1, EDM2, fun is_EventDM/1, fun chk_EventDM/2). + +%% chk_EventDM(EDM, EDM) -> +%% chk_type(fun is_EventDM/1, 'EventDM', EDM); +%% chk_EventDM({Tag, Val1} = EDM1, {Tag, Val2} = EDM2) -> +%% case (is_EventDM_tag(Tag) andalso +%% is_EventDM_val(Tag, Val1) andalso +%% is_EventDM_val(Tag, Val2)) of +%% true -> +%% chk_EventDM_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('EventDM', EDM1, EDM2) +%% end; +%% chk_EventDM({Tag1, Val1} = EDM1, {Tag2, Val2} = EDM2) -> +%% case ((is_EventDM_tag(Tag1) andalso +%% is_EventDM_val(Tag1, Val1)) andalso +%% (is_EventDM_tag(Tag2) andalso +%% is_EventDM_val(Tag2, Val2))) of +%% true -> +%% not_equal('EventDM', EDM1, EDM2); +%% false -> +%% wrong_type('EventDM', EDM1, EDM2) +%% end; +%% chk_EventDM(EDM1, EDM2) -> +%% wrong_type('EventDM', EDM1, EDM2). + +%% chk_EventDM_val(digitMapName, Val1, Val2) -> +%% validate(fun() -> chk_DigitMapName(Val1, Val2) end, 'EventDM'); +%% chk_EventDM_val(digitMapValue, Val1, Val2) -> +%% validate(fun() -> chk_DigitMapValue(Val1, Val2) end, 'EventDM'). + + +%% %% -- SecondEventsDescriptor -- + +%% is_opt_SecondEventsDescriptor(asn1_NOVALUE) -> +%% true; +%% is_opt_SecondEventsDescriptor(D) -> +%% is_SecondEventsDescriptor(D). + +%% is_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = RID, +%% eventList = EL}) -> +%% is_opt_RequestID(RID) andalso is_SecondEventsDescriptor_eventList(EL); +%% is_SecondEventsDescriptor(_) -> +%% false. + +%% is_SecondEventsDescriptor_eventList([]) -> +%% true; +%% is_SecondEventsDescriptor_eventList([H|T]) -> +%% is_SecondRequestedEvent(H) andalso is_SecondEventsDescriptor_eventList(T); +%% is_SecondEventsDescriptor_eventList(_) -> +%% false. + +%% chk_opt_SecondEventsDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_SecondEventsDescriptor(D1, D2) -> +%% chk_SecondEventsDescriptor(D1, D2). + +%% chk_SecondEventsDescriptor(D, D) -> +%% chk_type(fun is_SecondEventsDescriptor/1, 'SecondEventsDescriptor', D); +%% chk_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = RID1, +%% eventList = EL1}, +%% #'SecondEventsDescriptor'{requestID = RID2, +%% eventList = EL2}) -> +%% validate(fun() -> chk_opt_RequestID(RID1, RID2) end, +%% 'SecondEventsDescriptor'), +%% chk_SecondEventsDescriptor_eventList(EL1, EL2), +%% ok; +%% chk_SecondEventsDescriptor(D1, D2) -> +%% wrong_type('SecondEventsDescriptor', D1, D2). + +%% chk_SecondEventsDescriptor_eventList([], []) -> +%% ok; +%% chk_SecondEventsDescriptor_eventList([] = EL1, EL2) -> +%% not_equal('SecondEventsDescriptor_eventList', EL1, EL2); +%% chk_SecondEventsDescriptor_eventList(EL1, [] = EL2) -> +%% not_equal('SecondEventsDescriptor_eventList', EL1, EL2); +%% chk_SecondEventsDescriptor_eventList([H|T1], [H|T2]) -> +%% case is_SecondRequestedEvent(H) of +%% true -> +%% chk_SecondEventsDescriptor_eventList(T1, T2); +%% false -> +%% wrong_type('SecondEventsDescriptor_eventList_val', H) +%% end; +%% chk_SecondEventsDescriptor_eventList([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_SecondRequestedEvent(H1, H2) end, +%% 'SecondEventsDescriptor_eventList_val'), +%% chk_SecondEventsDescriptor_eventList(T1, T2); +%% chk_SecondEventsDescriptor_eventList(L1, L2) -> +%% wrong_type('SecondEventsDescriptor_eventList_val', L1, L2). + + +%% %% -- SecondRequestedEvent -- + +%% is_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N, +%% streamID = SID, +%% eventAction = EA, +%% evParList = EPL}) -> +%% is_PkgdName(N) andalso +%% is_opt_StreamID(SID) andalso +%% is_opt_SecondRequestedActions(EA) andalso +%% is_SecondRequestedEvent_evParList(EPL); +%% is_SecondRequestedEvent(_) -> +%% false. + +%% is_SecondRequestedEvent_evParList([]) -> +%% true; +%% is_SecondRequestedEvent_evParList([H|T]) -> +%% is_EventParameter(H) andalso is_SecondRequestedEvent_evParList(T); +%% is_SecondRequestedEvent_evParList(_) -> +%% false. + +%% chk_SecondRequestedEvent(RE, RE) -> +%% chk_type(fun is_SecondRequestedEvent/1, 'SecondRequestedEvent', RE); +%% chk_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N1, +%% streamID = SID1, +%% eventAction = EA1, +%% evParList = EPL1}, +%% #'SecondRequestedEvent'{pkgdName = N2, +%% streamID = SID2, +%% eventAction = EA2, +%% evParList = EPL2}) -> +%% validate(fun() -> chk_PkgdName(N1, N2) end, 'SecondRequestedEvent'), +%% validate(fun() -> chk_opt_StreamID(SID1, SID2) end, +%% 'SecondRequestedEvent'), +%% validate(fun() -> chk_opt_SecondRequestedActions(EA1, EA2) end, +%% 'SecondRequestedEvent'), +%% chk_SecondRequestedEvent_evParList(EPL1, EPL2), +%% ok; +%% chk_SecondRequestedEvent(RE1, RE2) -> +%% wrong_type('SecondRequestedEvent', RE1, RE2). + +%% chk_SecondRequestedEvent_evParList([], []) -> +%% ok; +%% chk_SecondRequestedEvent_evParList([] = EPL1, EPL2) -> +%% not_equal('SecondRequestedEvent_evParList', EPL1, EPL2); +%% chk_SecondRequestedEvent_evParList(EPL1, [] = EPL2) -> +%% not_equal('SecondRequestedEvent_evParList', EPL1, EPL2); +%% chk_SecondRequestedEvent_evParList([H|T1], [H|T2]) -> +%% case is_EventParameter(H) of +%% true -> +%% chk_SecondRequestedEvent_evParList(T1, T2); +%% false -> +%% wrong_type('SecondRequestedEvent_evParList_val', H) +%% end; +%% chk_SecondRequestedEvent_evParList([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_EventParameter(H1, H2) end, +%% 'SecondRequestedEvent_evParList_val'), +%% chk_SecondRequestedEvent_evParList(T1, T2); +%% chk_SecondRequestedEvent_evParList(EPL1, EPL2) -> +%% wrong_type('SecondRequestedEvent_evParList', EPL1, EPL2). + + +%% %% -- SecondRequestedActions -- + +%% is_opt_SecondRequestedActions(asn1_NOVALUE) -> +%% true; +%% is_opt_SecondRequestedActions(SRA) -> +%% is_SecondRequestedActions(SRA). + +%% is_SecondRequestedActions(#'SecondRequestedActions'{keepActive = KA, +%% eventDM = EDM, +%% signalsDescriptor = SD}) -> +%% is_opt_BOOLEAN(KA) andalso +%% is_opt_EventDM(EDM) andalso +%% is_opt_SignalsDescriptor(SD); +%% is_SecondRequestedActions(_) -> +%% false. + +%% chk_opt_SecondRequestedActions(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_SecondRequestedActions(SRA1, SRA2) -> +%% chk_SecondRequestedActions(SRA1, SRA2). + +%% chk_SecondRequestedActions(SRA, SRA) -> +%% chk_type(fun is_SecondRequestedActions/1, 'SecondRequestedActions', SRA); +%% chk_SecondRequestedActions( +%% #'SecondRequestedActions'{keepActive = KA1, +%% eventDM = EDM1, +%% signalsDescriptor = SD1}, +%% #'SecondRequestedActions'{keepActive = KA2, +%% eventDM = EDM2, +%% signalsDescriptor = SD2}) -> +%% validate(fun() -> chk_opt_BOOLEAN(KA1, KA2) end, +%% 'SecondRequestedActions'), +%% validate(fun() -> chk_opt_EventDM(EDM1, EDM2) end, +%% 'SecondRequestedActions'), +%% validate(fun() -> chk_opt_SignalsDescriptor(SD1, SD2) end, +%% 'SecondRequestedActions'), +%% ok; +%% chk_SecondRequestedActions(SRA1, SRA2) -> +%% wrong_type('SecondRequestedActions', SRA1, SRA2). + + +%% %% -- EventBufferDescriptor -- + +is_EventBufferDescriptor([]) -> + true; +is_EventBufferDescriptor([H|T]) -> + is_EventSpec(H) andalso is_EventBufferDescriptor(T); +is_EventBufferDescriptor(_) -> + false. + +%% chk_EventBufferDescriptor([], []) -> +%% ok; +%% chk_EventBufferDescriptor([] = D1, D2) -> +%% not_equal('EventBufferDescriptor', D1, D2); +%% chk_EventBufferDescriptor(D1, [] = D2) -> +%% not_equal('EventBufferDescriptor', D1, D2); +%% chk_EventBufferDescriptor([H|T1], [H|T2]) -> +%% case is_EventSpec(H) of +%% true -> +%% chk_EventBufferDescriptor(T1, T2); +%% false -> +%% wrong_type('EventBufferDescriptor_val', H) +%% end; +%% chk_EventBufferDescriptor([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_EventSpec(H1, H2) end, +%% 'EventBufferDescriptor_val'), +%% chk_EventBufferDescriptor(T1, T2); +%% chk_EventBufferDescriptor(D1, D2) -> +%% wrong_type('EventBufferDescriptor_val', D1, D2). + + +%% %% -- EventSpec -- + +is_EventSpec(#'EventSpec'{eventName = N, + streamID = SID, + eventParList = EPL}) -> + is_EventName(N) andalso + is_opt_StreamID(SID) andalso + is_EventSpec_eventParList(EPL); +is_EventSpec(_) -> + false. + +is_EventSpec_eventParList([]) -> + true; +is_EventSpec_eventParList([H|T]) -> + is_EventParameter(H) andalso is_EventSpec_eventParList(T); +is_EventSpec_eventParList(_) -> + false. + +%% chk_EventSpec(ES, ES) -> +%% chk_type(fun is_EventSpec/1, 'EventSpec', ES); +%% chk_EventSpec(#'EventSpec'{eventName = N1, +%% streamID = SID1, +%% eventParList = EPL1}, +%% #'EventSpec'{eventName = N2, +%% streamID = SID2, +%% eventParList = EPL2}) -> +%% validate(fun() -> chk_EventName(N1, N2) end, 'EventSpec'), +%% validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'EventSpec'), +%% chk_EventSpec_eventParList(EPL1, EPL2), +%% ok; +%% chk_EventSpec(ES1, ES2) -> +%% wrong_type('EventSpec', ES1, ES2). + +%% chk_EventSpec_eventParList([], []) -> +%% ok; +%% chk_EventSpec_eventParList([] = EPL1, EPL2) -> +%% not_equal('EventSpec_eventParList', EPL1, EPL2); +%% chk_EventSpec_eventParList(EPL1, [] = EPL2) -> +%% not_equal('EventSpec_eventParList', EPL1, EPL2); +%% chk_EventSpec_eventParList([H|T1], [H|T2]) -> +%% case is_EventParameter(H) of +%% true -> +%% chk_EventSpec_eventParList(T1, T2); +%% false -> +%% wrong_type('EventSpec_eventParList_val', H) +%% end; +%% chk_EventSpec_eventParList([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_EventParameter(H1, H2) end, +%% 'EventSpec_eventParList_val'), +%% chk_EventSpec_eventParList(T1, T2); +%% chk_EventSpec_eventParList(EPL1, EPL2) -> +%% wrong_type('EventSpec_eventParList', EPL1, EPL2). + + +%% %% -- SignalsDescriptor -- + +%% is_opt_SignalsDescriptor(asn1_NOVALUE) -> +%% true; +%% is_opt_SignalsDescriptor(D) -> +%% is_SignalsDescriptor(D). + +is_SignalsDescriptor([]) -> + true; +is_SignalsDescriptor([H|T]) -> + is_SignalRequest(H) andalso is_SignalsDescriptor(T); +is_SignalsDescriptor(_) -> + false. + +%% chk_opt_SignalsDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_SignalsDescriptor(D1, D2) -> +%% chk_SignalsDescriptor(D1, D2). + +%% chk_SignalsDescriptor([], []) -> +%% ok; +%% chk_SignalsDescriptor([] = D1, D2) -> +%% not_equal('SignalsDescriptor', D1, D2); +%% chk_SignalsDescriptor(D1, [] = D2) -> +%% not_equal('SignalsDescriptor', D1, D2); +%% chk_SignalsDescriptor([H|T1], [H|T2]) -> +%% case is_SignalRequest(H) of +%% true -> +%% chk_SignalsDescriptor(T1, T2); +%% false -> +%% wrong_type('SignalsDescriptor_val', H) +%% end; +%% chk_SignalsDescriptor([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_SignalRequest(H1, H2) end, 'SignalsDescriptor_val'), +%% chk_SignalsDescriptor(T1, T2); +%% chk_SignalsDescriptor(D1, D2) -> +%% wrong_type('SignalsDescriptor', D1, D2). + + +%% %% -- SignalRequest -- + +is_SignalRequest({Tag, Val}) -> + is_SignalRequest_tag(Tag) andalso is_SignalRequest_val(Tag, Val); +is_SignalRequest(_) -> + false. + +is_SignalRequest_tag(Tag) -> + Tags = [signal, seqSigList], + lists:member(Tag, Tags). + +is_SignalRequest_val(signal, Val) -> + is_Signal(Val); +is_SignalRequest_val(seqSigList, Val) -> + is_SeqSigList(Val). + +%% chk_SignalRequest(R, R) -> +%% chk_type(fun is_SignalRequest/1, 'SignalRequest', R); +%% chk_SignalRequest({Tag, Val1} = R1, {Tag, Val2} = R2) -> +%% case (is_SignalRequest_tag(Tag) andalso +%% is_SignalRequest_val(Tag, Val1) andalso +%% is_SignalRequest_val(Tag, Val2)) of +%% true -> +%% chk_SignalRequest_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('SignalRequest', R1, R2) +%% end; +%% chk_SignalRequest({Tag1, Val1} = R1, {Tag2, Val2} = R2) -> +%% case ((is_SignalRequest_tag(Tag1) andalso +%% is_SignalRequest_val(Tag1, Val1)) andalso +%% (is_SignalRequest_tag(Tag2) andalso +%% is_SignalRequest_val(Tag2, Val2))) of +%% true -> +%% not_equal('SignalRequest', R1, R2); +%% false -> +%% wrong_type('SignalRequest', R1, R2) +%% end; +%% chk_SignalRequest(R1, R2) -> +%% wrong_type('SignalRequest', R1, R2). + +%% chk_SignalRequest_val(signal, Val1, Val2) -> +%% validate(fun() -> chk_Signal(Val1, Val2) end, 'SignalRequest'); +%% chk_SignalRequest_val(seqSigList, Val1, Val2) -> +%% validate(fun() -> chk_SeqSigList(Val1, Val2) end, 'SignalRequest'). + + +%% %% -- SeqSigList -- + +is_SeqSigList(#'SeqSigList'{id = ID, + signalList = SL}) -> + is_INTEGER(ID, {range, 0, 65535}) andalso + is_SeqSigList_signalList(SL); +is_SeqSigList(_) -> + false. + +is_SeqSigList_signalList([]) -> + true; +is_SeqSigList_signalList([H|T]) -> + is_Signal(H) andalso is_SeqSigList_signalList(T); +is_SeqSigList_signalList(_) -> + false. + +%% chk_SeqSigList(L, L) -> +%% chk_type(fun is_SeqSigList/1, 'SeqSigList', L); +%% chk_SeqSigList(#'SeqSigList'{id = ID1, +%% signalList = SL1}, +%% #'SeqSigList'{id = ID2, +%% signalList = SL2}) -> +%% validate(fun() -> chk_INTEGER(ID1, ID2, {range, 0, 65535}) end, +%% 'SeqSigList'), +%% chk_SeqSigList_signalList(SL1, SL2), +%% ok; +%% chk_SeqSigList(L1, L2) -> +%% wrong_type('SeqSigList', L1, L2). + +%% chk_SeqSigList_signalList([], []) -> +%% ok; +%% chk_SeqSigList_signalList([] = L1, L2) -> +%% not_equal('SeqSigList_signalList', L1, L2); +%% chk_SeqSigList_signalList(L1, [] = L2) -> +%% not_equal('SeqSigList_signalList', L1, L2); +%% chk_SeqSigList_signalList([H|T1], [H|T2]) -> +%% case is_Signal(H) of +%% true -> +%% chk_SeqSigList_signalList(T1, T2); +%% false -> +%% wrong_type('SeqSigList_signalList_val', H) +%% end; +%% chk_SeqSigList_signalList([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_Signal(H1, H2) end, +%% 'SeqSigList_signalList_val'), +%% chk_SeqSigList_signalList(T1, T2); +%% chk_SeqSigList_signalList(L1, L2) -> +%% wrong_type('SeqSigList_signalList', L1, L2). + + +%% %% -- Signal -- + +is_Signal(#'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL}) -> + is_SignalName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_SignalType(ST) andalso + is_opt_INTEGER(Dur, {range, 0, 65535}) andalso + is_opt_NotifyCompletion(NC) andalso + is_opt_BOOLEAN(KA) andalso + is_Signal_sigParList(SPL). + +is_Signal_sigParList([]) -> + true; +is_Signal_sigParList([H|T]) -> + is_SigParameter(H) andalso is_Signal_sigParList(T); +is_Signal_sigParList(_) -> + false. + +%% chk_Signal(S, S) -> +%% chk_type(fun is_Signal/1, 'Signal', S); +%% chk_Signal(#'Signal'{signalName = N1, +%% streamID = SID1, +%% sigType = ST1, +%% duration = Dur1, +%% notifyCompletion = NC1, +%% keepActive = KA1, +%% sigParList = SPL1}, +%% #'Signal'{signalName = N2, +%% streamID = SID2, +%% sigType = ST2, +%% duration = Dur2, +%% notifyCompletion = NC2, +%% keepActive = KA2, +%% sigParList = SPL2}) -> +%% validate(fun() -> chk_SignalName(N1, N2) end, 'Signal'), +%% validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'Signal'), +%% validate(fun() -> chk_opt_SignalType(ST1, ST2) end, 'Signal'), +%% validate(fun() -> chk_opt_INTEGER(Dur1, Dur2, {range, 0, 65535}) end, +%% 'Signal'), +%% validate(fun() -> chk_opt_NotifyCompletion(NC1, NC2) end, 'Signal'), +%% validate(fun() -> chk_opt_BOOLEAN(KA1, KA2) end, 'Signal'), +%% chk_Signal_sigParList(SPL1, SPL2), +%% ok; +%% chk_Signal(S1, S2) -> +%% wrong_type('Signal', S1, S2). + +%% chk_Signal_sigParList([], []) -> +%% ok; +%% chk_Signal_sigParList([] = L1, L2) -> +%% not_equal('Signal_sigParList', L1, L2); +%% chk_Signal_sigParList(L1, [] = L2) -> +%% not_equal('Signal_sigParList', L1, L2); +%% chk_Signal_sigParList([H|T1], [H|T2]) -> +%% case is_SigParameter(H) of +%% true -> +%% chk_Signal_sigParList(T1, T2); +%% false -> +%% wrong_type('Signal_sigParList_val', H) +%% end; +%% chk_Signal_sigParList([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_SigParameter(H1, H2) end, +%% 'Signal_sigParList_val'), +%% chk_Signal_sigParList(T1, T2); +%% chk_Signal_sigParList(L1, L2) -> +%% wrong_type('Signal_sigParList', L1, L2). + + +%% %% -- SignalType -- + +is_opt_SignalType(asn1_NOVALUE) -> + true; +is_opt_SignalType(T) -> + is_SignalType(T). + +is_SignalType(T) -> + Types = [brief, onOff, timeOut], + lists:member(T, Types). + +%% chk_opt_SignalType(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_SignalType(T1, T2) -> +%% chk_SignalType(T1, T2). + +%% chk_SignalType(T, T) -> +%% chk_type(fun is_SignalType/1, 'SignalType', T); +%% chk_SignalType(T1, T2) -> +%% case (is_SignalType(T1) andalso is_SignalType(T2)) of +%% true -> +%% not_equal('SignalType', T1, T2); +%% false -> +%% wrong_type('SignalType', T1, T2) +%% end. + + +%% %% -- SignalName -- + +is_SignalName(N) -> is_PkgdName(N). + +%% chk_SignalName(N1, N2) -> +%% validate(fun() -> chk_PkgdName(N1, N2) end, 'SignalName'). + + +%% %% -- NotifyCompletion -- + +is_opt_NotifyCompletion(NC) -> + is_OPTIONAL(fun is_NotifyCompletion/1, NC). + +is_NotifyCompletion(NC) -> + Valids = [onTimeOut, + onInterruptByEvent, + onInterruptByNewSignalDescr, + otherReason], + lists:member(NC, Valids). + +%% chk_opt_NotifyCompletion(NC1, NC2) -> +%% chk_OPTIONAL('NotifyCompletion', NC1, NC2, +%% fun is_NotifyCompletion/1, +%% fun chk_NotifyCompletion/2). + +%% chk_NotifyCompletion(NC, NC) -> +%% chk_type(fun is_NotifyCompletion/1, 'NotifyCompletion', NC); +%% chk_NotifyCompletion(NC1, NC2) -> +%% case (is_NotifyCompletion(NC1) andalso is_NotifyCompletion(NC2)) of +%% true -> +%% not_equal('NotifyCompletion', NC1, NC2); +%% false -> +%% wrong_type('NotifyCompletion', NC1, NC2) +%% end. + + +%% %% -- SigParameter -- + +is_SigParameter(#'SigParameter'{sigParameterName = N, + value = V, + extraInfo = I}) -> + is_Name(N) andalso + is_Value(V) andalso + is_SigParameter_extraInfo(I); +is_SigParameter(_) -> + false. + +is_SigParameter_extraInfo({Tag, Val}) -> + is_SigParameter_extraInfo_tag(Tag) andalso + is_SigParameter_extraInfo_val(Tag, Val); +is_SigParameter_extraInfo(_) -> + false. + +is_SigParameter_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_SigParameter_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_SigParameter_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_SigParameter_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + +%% chk_SigParameter(P, P) -> +%% chk_type(fun is_SigParameter/1, 'SigParameter', P); +%% chk_SigParameter(#'SigParameter'{sigParameterName = N1, +%% value = V1, +%% extraInfo = I1}, +%% #'SigParameter'{sigParameterName = N2, +%% value = V2, +%% extraInfo = I2}) -> +%% validate(fun() -> chk_Name(N1, N2) end, 'SigParameter'), +%% validate(fun() -> chk_Value(V1, V2) end, 'SigParameter'), +%% chk_SigParameter_extraInfo(I1, I2), +%% ok; +%% chk_SigParameter(P1, P2) -> +%% wrong_type('SigParameter', P1, P2). + +%% chk_SigParameter_extraInfo(EI, EI) -> +%% chk_type(fun is_SigParameter_extraInfo/1, 'SigParameter_extraInfo', EI); +%% chk_SigParameter_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> +%% case (is_SigParameter_extraInfo_tag(Tag) and +%% is_SigParameter_extraInfo_val(Tag, Val1) and +%% is_SigParameter_extraInfo_val(Tag, Val2)) of +%% true -> +%% chk_SigParameter_extraInfo_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('SigParameter_extraInfo', EI1, EI2) +%% end; +%% chk_SigParameter_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> +%% case ((is_SigParameter_extraInfo_tag(Tag1) and +%% is_SigParameter_extraInfo_val(Tag1, Val1)) and +%% (is_SigParameter_extraInfo_tag(Tag2) and +%% is_SigParameter_extraInfo_val(Tag2, Val2))) of +%% true -> +%% not_equal('SigParameter_extraInfo', EI1, EI2); +%% false -> +%% wrong_type('SigParameter_extraInfo', EI1, EI2) +%% end; +%% chk_SigParameter_extraInfo(EI1, EI2) -> +%% wrong_type('SigParameter_extraInfo', EI1, EI2). + +%% chk_SigParameter_extraInfo_val(relation, Val1, Val2) -> +%% validate(fun() -> chk_Relation(Val1, Val2) end, 'SigParameter_extraInfo'); +%% chk_SigParameter_extraInfo_val(range, Val1, Val2) -> +%% validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'SigParameter_extraInfo'); +%% chk_SigParameter_extraInfo_val(sublist, Val1, Val2) -> +%% validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'SigParameter_extraInfo'). + + +%% %% -- RequestID -- + +%% is_opt_RequestID(asn1_NOVALUE) -> +%% true; +%% is_opt_RequestID(V) -> +%% is_RequestID(V). + +%% is_RequestID(V) -> is_INTEGER(V, {range, 0, 4294967295}). + +%% chk_opt_RequestID(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_RequestID(V1, V2) -> +%% chk_RequestID(V1, V2). + +%% chk_RequestID(ID, ID) -> +%% chk_type(fun is_RequestID/1, 'RequestID', ID); +%% chk_RequestID(ID1, ID2) -> +%% case (is_RequestID(ID1) andalso is_RequestID(ID2)) of +%% true -> +%% not_equal('RequestID', ID1, ID2); +%% false -> +%% wrong_type('RequestID', ID1, ID2) +%% end. + + +%% %% -- ModemDescriptor -- + +%% is_ModemDescriptor(D) when record(D, 'ModemDescriptor') -> +%% true; +%% is_ModemDescriptor(_) -> +%% false. + +%% chk_ModemDescriptor(D, D) when record(D, 'ModemDescriptor') -> +%% ok; +%% chk_ModemDescriptor(#'ModemDescriptor'{mtl = MTL1, +%% mpl = MPL1, +%% nonStandardData = NSD1}, +%% #'ModemDescriptor'{mtl = MTL2, +%% mpl = MPL2, +%% nonStandardData = NSD2}) -> +%% chk_ModemDescriptor_mtl(MTL1, MTL2), +%% chk_ModemDescriptor_mpl(MPL1, MPL2), +%% chk_opt_NonStandardData(NSD1, NSD2), +%% ok; +%% chk_ModemDescriptor(D1, D2) -> +%% wrong_type('ModemDescriptor', D1, D2). + +%% chk_ModemDescriptor_mtl([], []) -> +%% ok; +%% chk_ModemDescriptor_mtl([] = MTL1, MTL2) -> +%% not_equal('ModemDescriptor_mtl', MTL1, MTL2); +%% chk_ModemDescriptor_mtl(MTL1, [] = MTL2) -> +%% not_equal('ModemDescriptor_mtl', MTL1, MTL2); +%% chk_ModemDescriptor_mtl([H|T1], [H|T2]) -> +%% case is_ModemType(H) of +%% true -> +%% chk_ModemDescriptor_mtl(T1, T2); +%% false -> +%% wrong_type('ModemDescriptor_mtl_val', H) +%% end; +%% chk_ModemDescriptor_mtl([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_ModemType(H1, H2) end, 'ModemDescriptor_mtl_val'), +%% chk_ModemDescriptor_mtl(T1, T2); +%% chk_ModemDescriptor_mtl(MTL1, MTL2) -> +%% wrong_type('ModemDescriptor_mtl', MTL1, MTL2). + + +%% chk_ModemDescriptor_mpl([], []) -> +%% ok; +%% chk_ModemDescriptor_mpl([] = MPL1, MPL2) -> +%% not_equal('ModemDescriptor_mpl', MPL1, MPL2); +%% chk_ModemDescriptor_mpl(MPL1, [] = MPL2) -> +%% not_equal('ModemDescriptor_mpl', MPL1, MPL2); +%% chk_ModemDescriptor_mpl([H|T1], [H|T2]) -> +%% case is_PropertyParm(H) of +%% true -> +%% chk_ModemDescriptor_mpl(T1, T2); +%% false -> +%% wrong_type('ModemDescriptor_mpl_val', H) +%% end; +%% chk_ModemDescriptor_mpl([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_PropertyParm(H1, H2) end, 'ModemDescriptor_mpl_val'), +%% chk_ModemDescriptor_mpl(T1, T2); +%% chk_ModemDescriptor_mpl(MPL1, MPL2) -> +%% wrong_type('ModemDescriptor_mpl', MPL1, MPL2). + + +%% %% -- ModemType -- + +%% chk_ModemType(MT, MT) -> +%% case is_ModemType(MT) of +%% true -> +%% ok; +%% false -> +%% wrong_type('ModemType', MT, MT) +%% end; +%% chk_ModemType(MT1, MT2) -> +%% case (is_ModemType(MT1) andalso is_ModemType(MT2)) of +%% true -> +%% not_equal('ModemType', MT1, MT2); +%% false -> +%% wrong_type('ModemType', MT1, MT2) +%% end. + +%% is_ModemType(MT) -> +%% lists:member(MT, +%% [v18, v22, v22bis, v32, v32bis, v34, v90, v91, synchISDN]). + + +%% %% -- DigitMapDescriptor -- + +%% is_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name, +%% digitMapValue = Val}) -> +%% is_opt_DigitMapName(Name) andalso is_opt_DigitMapValue(Val); +%% is_DigitMapDescriptor(_) -> +%% false. + +%% chk_DigitMapDescriptor(D, D) -> +%% chk_type(fun is_DigitMapDescriptor/1, 'DigitMapDescriptor', D); +%% chk_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name1, +%% digitMapValue = Val1}, +%% #'DigitMapDescriptor'{digitMapName = Name2, +%% digitMapValue = Val2}) -> +%% d("chk_DigitMapDescriptor -> entry with" +%% "~n Name1: ~p" +%% "~n Name2: ~p" +%% "~n Val1: ~p" +%% "~n Val2: ~p", [Name1, Name2, Val1, Val2]), +%% validate(fun() -> chk_opt_DigitMapName(Name1, Name2) end, +%% 'DigitMapDescriptor'), +%% validate(fun() -> chk_opt_DigitMapValue(Val1, Val2) end, +%% 'DigitMapDescriptor'), +%% ok; +%% chk_DigitMapDescriptor(D1, D2) -> +%% wrong_type('DigitMapDescriptor', D1, D2). + + +%% %% -- DigitMapName -- + +%% is_opt_DigitMapName(asn1_NOVALUE) -> +%% true; +%% is_opt_DigitMapName(N) -> +%% is_DigitMapName(N). + +%% is_DigitMapName(N) -> is_Name(N). + +%% chk_opt_DigitMapName(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_DigitMapName(N1, N2) -> +%% chk_DigitMapName(N1, N2). + +%% chk_DigitMapName(N, N) -> +%% chk_type(fun is_DigitMapName/1, 'DigitMapName', N); +%% chk_DigitMapName(N1, N2) -> +%% case (is_DigitMapName(N1) andalso is_DigitMapName(N2)) of +%% true -> +%% not_equal('DigitMapName', N1, N2); +%% false -> +%% wrong_type('DigitMapName', N1, N2) +%% end. + + +%% %% -- DigitMapValue -- + +%% is_opt_DigitMapValue(V) -> +%% is_OPTIONAL(fun is_DigitMapValue/1, V). + +%% is_DigitMapValue(#'DigitMapValue'{startTimer = Start, +%% shortTimer = Short, +%% longTimer = Long, +%% digitMapBody = Body, +%% durationTimer = Dur}) -> +%% is_DigitMapValue_startTimer(Start) andalso +%% is_DigitMapValue_shortTimer(Short) andalso +%% is_DigitMapValue_longTimer(Long) andalso +%% is_IA5String(Body) andalso +%% is_DigitMapValue_durationTimer(Dur); +%% is_DigitMapValue(_) -> +%% false. + +%% is_DigitMapValue_startTimer(asn1_NOVALUE) -> true; +%% is_DigitMapValue_startTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +%% is_DigitMapValue_shortTimer(asn1_NOVALUE) -> true; +%% is_DigitMapValue_shortTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +%% is_DigitMapValue_longTimer(asn1_NOVALUE) -> true; +%% is_DigitMapValue_longTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +%% is_DigitMapValue_durationTimer(asn1_NOVALUE) -> true; +%% is_DigitMapValue_durationTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +%% chk_opt_DigitMapValue(V1, V2) -> +%% chk_OPTIONAL('DigitMapValue', V1, V2, +%% fun is_DigitMapValue/1, fun chk_DigitMapValue/2). + +%% chk_DigitMapValue(#'DigitMapValue'{startTimer = Start1, +%% shortTimer = Short1, +%% longTimer = Long1, +%% digitMapBody = Body1, +%% durationTimer = Dur1}, +%% #'DigitMapValue'{startTimer = Start2, +%% shortTimer = Short2, +%% longTimer = Long2, +%% digitMapBody = Body2, +%% durationTimer = Dur2}) -> +%% d("chk_DigitMapValue -> entry with" +%% "~n Start1: ~p" +%% "~n Start2: ~p" +%% "~n Short1: ~p" +%% "~n Short2: ~p" +%% "~n Long1: ~p" +%% "~n Long2: ~p" +%% "~n Body1: ~p" +%% "~n Body2: ~p" +%% "~n Dur1: ~p" +%% "~n Dur2: ~p", [Start1, Start2, +%% Short1, Short2, +%% Long1, Long2, +%% Body1, Body2, +%% Dur1, Dur2]), +%% chk_DigitMapValue_startTimer(Start1, Start2), +%% chk_DigitMapValue_shortTimer(Short1, Short2), +%% chk_DigitMapValue_longTimer(Long1, Long2), +%% chk_DigitMapValue_digitMapBody(Body1, Body2), +%% chk_DigitMapValue_durationTimer(Dur1, Dur2), +%% ok; +%% chk_DigitMapValue(V1, V2) -> +%% wrong_type('DigitMapValue', V1, V2). + +%% chk_DigitMapValue_startTimer(T, T) -> +%% chk_type(fun is_DigitMapValue_startTimer/1, 'DigitMapValue_startTimer', T); +%% chk_DigitMapValue_startTimer(T1, T2) -> +%% case (is_DigitMapValue_startTimer(T1) andalso +%% is_DigitMapValue_startTimer(T2)) of +%% true -> +%% not_equal('DigitMapValue_startTimer', T1, T2); +%% false -> +%% wrong_type('DigitMapValue_startTimer', T1, T2) +%% end. + +%% chk_DigitMapValue_shortTimer(T, T) -> +%% chk_type(fun is_DigitMapValue_shortTimer/1, 'DigitMapValue_shortTimer', T); +%% chk_DigitMapValue_shortTimer(T1, T2) -> +%% case (is_DigitMapValue_shortTimer(T1) andalso +%% is_DigitMapValue_shortTimer(T2)) of +%% true -> +%% not_equal('DigitMapValue_shortTimer', T1, T2); +%% false -> +%% wrong_type('DigitMapValue_shortTimer', T1, T2) +%% end. + +%% chk_DigitMapValue_longTimer(T, T) -> +%% chk_type(fun is_DigitMapValue_longTimer/1, 'DigitMapValue_longTimer', T); +%% chk_DigitMapValue_longTimer(T1, T2) -> +%% case (is_DigitMapValue_longTimer(T1) andalso +%% is_DigitMapValue_longTimer(T2)) of +%% true -> +%% not_equal('DigitMapValue_longTimer', T1, T2); +%% false -> +%% wrong_type('DigitMapValue_longTimer', T1, T2) +%% end. + +%% chk_DigitMapValue_durationTimer(T, T) -> +%% chk_type(fun is_DigitMapValue_durationTimer/1, +%% 'DigitMapValue_durationTimer', T); +%% chk_DigitMapValue_durationTimer(T1, T2) -> +%% case (is_DigitMapValue_durationTimer(T1) andalso +%% is_DigitMapValue_durationTimer(T2)) of +%% true -> +%% not_equal('DigitMapValue_durationTimer', T1, T2); +%% false -> +%% wrong_type('DigitMapValue_durationTimer', T1, T2) +%% end. + +%% chk_DigitMapValue_digitMapBody(B, B) -> +%% d("chk_DigitMapValue_digitMapBody -> entry with" +%% "~n B: ~p", [B]), +%% chk_type(fun is_IA5String/1, 'DigitMapValue_digitMapBody', B); +%% chk_DigitMapValue_digitMapBody(B1, B2) -> +%% d("chk_DigitMapValue_digitMapBody -> entry with" +%% "~n B1: ~p" +%% "~n B2: ~p", [B1, B2]), +%% case (is_IA5String(B1) andalso is_IA5String(B2)) of +%% true -> +%% %% If they are different it could be because +%% %% of trailing tab's and newline's. +%% case compare_strings(B1, B2) of +%% {[], []} -> +%% ok; +%% {Str1, []} -> +%% case strip_tab_and_newline(Str1) of +%% [] -> +%% ok; +%% _ -> +%% not_equal('DigitMapValue_digitMapBody', B1, B2) +%% end; +%% {[], Str2} -> +%% case strip_tab_and_newline(Str2) of +%% [] -> +%% ok; +%% _ -> +%% not_equal('DigitMapValue_digitMapBody', B1, B2) +%% end; +%% _ -> +%% not_equal('DigitMapValue_digitMapBody', B1, B2) +%% end; +%% false -> +%% wrong_type('DigitMapValue_digitMapBody', B1, B2) +%% end. + +%% %% -- ServiceChangeParm -- + +%% is_ServiceChangeParm(#'ServiceChangeParm'{serviceChangeMethod = M, +%% serviceChangeAddress = A, +%% serviceChangeVersion = V, +%% serviceChangeProfile = P, +%% serviceChangeReason = R, +%% serviceChangeDelay = D, +%% serviceChangeMgcId = Id, +%% timeStamp = TS, +%% nonStandardData = NSD, +%% serviceChangeInfo = I}) -> +%% is_ServiceChangeMethod(M) andalso +%% is_opt_ServiceChangeAddress(A) andalso +%% is_opt_INTEGER(V, {range, 0, 99}) andalso +%% is_opt_ServiceChangeProfile(P) andalso +%% is_Value(R) andalso +%% is_opt_INTEGER(D, {range, 0, 4294967295}) andalso +%% is_opt_MId(Id) andalso +%% is_opt_TimeNotation(TS) andalso +%% is_opt_NonStandardData(NSD) andalso +%% is_opt_AuditDescriptor(I); +%% is_ServiceChangeParm(_) -> +%% false. + +%% chk_ServiceChangeParm(P, P) -> +%% chk_type(fun is_ServiceChangeParm/1, 'ServiceChangeParm', P); +%% chk_ServiceChangeParm(#'ServiceChangeParm'{serviceChangeMethod = M1, +%% serviceChangeAddress = A1, +%% serviceChangeVersion = V1, +%% serviceChangeProfile = P1, +%% serviceChangeReason = R1, +%% serviceChangeDelay = D1, +%% serviceChangeMgcId = Id1, +%% timeStamp = TS1, +%% nonStandardData = NSD1, +%% serviceChangeInfo = I1}, +%% #'ServiceChangeParm'{serviceChangeMethod = M2, +%% serviceChangeAddress = A2, +%% serviceChangeVersion = V2, +%% serviceChangeProfile = P2, +%% serviceChangeReason = R2, +%% serviceChangeDelay = D2, +%% serviceChangeMgcId = Id2, +%% timeStamp = TS2, +%% nonStandardData = NSD2, +%% serviceChangeInfo = I2}) -> +%% validate(fun() -> chk_ServiceChangeMethod(M1, M2) end, +%% 'ServiceChangeParm'), +%% validate(fun() -> chk_opt_ServiceChangeAddress(A1, A2) end, +%% 'ServiceChangeParm'), +%% validate(fun() -> chk_opt_INTEGER(V1, V2, {range, 0, 99}) end, +%% 'ServiceChangeParm'), +%% validate(fun() -> chk_opt_ServiceChangeProfile(P1, P2) end, +%% 'ServiceChangeParm'), +%% validate(fun() -> chk_Value(R1, R2) end, +%% 'ServiceChangeParm'), +%% validate(fun() -> chk_opt_INTEGER(D1, D2, {range, 0, 4294967295}) end, +%% 'ServiceChangeParm'), +%% validate(fun() -> chk_opt_MId(Id1, Id2) end, +%% 'ServiceChangeParm'), +%% validate(fun() -> chk_opt_TimeNotation(TS1, TS2) end, +%% 'ServiceChangeParm'), +%% validate(fun() -> chk_opt_NonStandardData(NSD1, NSD2) end, +%% 'ServiceChangeParm'), +%% validate(fun() -> chk_opt_AuditDescriptor(I1, I2) end, +%% 'ServiceChangeParm'), +%% ok; +%% chk_ServiceChangeParm(P1, P2) -> +%% wrong_type('ServiceChangeParm', P1, P2). + + +%% %% -- ServiceChangeAddress -- + +%% is_opt_ServiceChangeAddress(A) -> +%% is_OPTIONAL(fun is_ServiceChangeAddress/1, A). + +%% is_ServiceChangeAddress({Tag, Val}) -> +%% is_ServiceChangeAddress_tag(Tag) andalso +%% is_ServiceChangeAddress_val(Tag, Val); +%% is_ServiceChangeAddress(_) -> +%% false. + +%% is_ServiceChangeAddress_tag(Tag) -> +%% Tags = [portNumber, ip4Address, ip6Address, domainName, deviceName, +%% mtpAddress], +%% lists:member(Tag, Tags). + +%% is_ServiceChangeAddress_val(portNumber, Val) -> +%% is_INTEGER(Val, {range, 0, 65535}); +%% is_ServiceChangeAddress_val(ip4Address, Val) -> +%% is_IP4Address(Val); +%% is_ServiceChangeAddress_val(ip6Address, Val) -> +%% is_IP6Address(Val); +%% is_ServiceChangeAddress_val(domainName, Val) -> +%% is_DomainName(Val); +%% is_ServiceChangeAddress_val(deviceName, Val) -> +%% is_PathName(Val); +%% is_ServiceChangeAddress_val(mtpAddress, Val) -> +%% is_OCTET_STRING(Val, {range, 2, 4}). + + +%% chk_opt_ServiceChangeAddress(A1, A2) -> +%% chk_OPTIONAL('ServiceChangeAddress', A1, A2, +%% fun is_ServiceChangeAddress/1, +%% fun chk_ServiceChangeAddress/2). + +%% chk_ServiceChangeAddress(A, A) -> +%% chk_type(fun is_ServiceChangeAddress/1, 'ServiceChangeAddress', A); +%% chk_ServiceChangeAddress({Tag, Val1} = A1, {Tag, Val2} = A2) -> +%% case (is_ServiceChangeAddress_tag(Tag) andalso +%% is_ServiceChangeAddress_val(Tag, Val1) andalso +%% is_ServiceChangeAddress_val(Tag, Val2)) of +%% true -> +%% chk_ServiceChangeAddress_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('ServiceChangeAddress', A1, A2) +%% end; +%% chk_ServiceChangeAddress({Tag1, Val1} = A1, {Tag2, Val2} = A2) -> +%% case ((is_ServiceChangeAddress_tag(Tag1) andalso +%% is_ServiceChangeAddress_val(Tag1, Val1)) andalso +%% (is_ServiceChangeAddress_tag(Tag2) andalso +%% is_ServiceChangeAddress_val(Tag2, Val2))) of +%% true -> +%% not_equal('ServiceChangeAddress', A1, A2); +%% false -> +%% wrong_type('ServiceChangeAddress', A1, A2) +%% end; +%% chk_ServiceChangeAddress(A1, A2) -> +%% wrong_type('ServiceChangeAddress', A1, A2). + +%% chk_ServiceChangeAddress_val(portNumber, Val1, Val2) -> +%% validate(fun() -> chk_INTEGER(Val1, Val2, {range, 0, 99}) end, +%% 'ServiceChangeAddress'); +%% chk_ServiceChangeAddress_val(ip4Address, Val1, Val2) -> +%% validate(fun() -> chk_IP4Address(Val1, Val2) end, +%% 'ServiceChangeAddress'); +%% chk_ServiceChangeAddress_val(ip6Address, Val1, Val2) -> +%% validate(fun() -> chk_IP6Address(Val1, Val2) end, +%% 'ServiceChangeAddress'); +%% chk_ServiceChangeAddress_val(domainName, Val1, Val2) -> +%% validate(fun() -> chk_DomainName(Val1, Val2) end, +%% 'ServiceChangeAddress'); +%% chk_ServiceChangeAddress_val(deviceName, Val1, Val2) -> +%% validate(fun() -> chk_PathName(Val1, Val2) end, +%% 'ServiceChangeAddress'); +%% chk_ServiceChangeAddress_val(mtpAddress, Val1, Val2) -> +%% validate(fun() -> chk_OCTET_STRING(Val1, Val2, {range, 2, 4}) end, +%% 'ServiceChangeAddress'). + + +%% %% -- ServiceChangeResParm -- + +%% is_ServiceChangeResParm(#'ServiceChangeResParm'{serviceChangeMgcId = Id, +%% serviceChangeAddress = A, +%% serviceChangeVersion = V, +%% serviceChangeProfile = P, +%% timeStamp = TS}) -> +%% is_opt_MId(Id) andalso +%% is_opt_ServiceChangeAddress(A) andalso +%% is_opt_INTEGER(V, {range, 0, 99}) andalso +%% is_opt_ServiceChangeProfile(P) andalso +%% is_opt_TimeNotation(TS); +%% is_ServiceChangeResParm(_) -> +%% false. + +%% chk_ServiceChangeResParm(P, P) -> +%% chk_type(fun is_ServiceChangeResParm/1, 'ServiceChangeResParm', P); +%% chk_ServiceChangeResParm( +%% #'ServiceChangeResParm'{serviceChangeMgcId = Id1, +%% serviceChangeAddress = A1, +%% serviceChangeVersion = V1, +%% serviceChangeProfile = P1, +%% timeStamp = TS1}, +%% #'ServiceChangeResParm'{serviceChangeMgcId = Id2, +%% serviceChangeAddress = A2, +%% serviceChangeVersion = V2, +%% serviceChangeProfile = P2, +%% timeStamp = TS2}) -> +%% validate(fun() -> chk_opt_MId(Id1, Id2) end, 'ServiceChangeResParm'), +%% validate(fun() -> chk_opt_ServiceChangeAddress(A1, A2) end, +%% 'ServiceChangeResParm'), +%% validate(fun() -> chk_opt_INTEGER(V1, V2, {range, 0, 99}) end, +%% 'ServiceChangeResParm'), +%% validate(fun() -> chk_opt_ServiceChangeProfile(P1, P2) end, +%% 'ServiceChangeResParm'), +%% validate(fun() -> chk_opt_TimeNotation(TS1, TS2) end, +%% 'ServiceChangeResParm'), +%% ok; +%% chk_ServiceChangeResParm(P1, P2) -> +%% wrong_type('ServiceChangeResParm', P1, P2). + + +%% %% -- ServiceChangeMethod -- + +%% is_ServiceChangeMethod(M) -> +%% Methods = [failover, forced, graceful, restart, disconnected, handOff], +%% lists:member(M, Methods). + +%% chk_ServiceChangeMethod(M, M) -> +%% chk_type(fun is_ServiceChangeMethod/1, 'ServiceChangeMethod', M); +%% chk_ServiceChangeMethod(M1, M2) -> +%% case (is_ServiceChangeMethod(M1) andalso is_ServiceChangeMethod(M2)) of +%% true -> +%% not_equal('ServiceChangeMethod', M1, M2); +%% false -> +%% wrong_type('ServiceChangeMethod', M1, M2) +%% end. + + +%% %% -- ServiceChangeProfile -- + +%% is_opt_ServiceChangeProfile(P) -> +%% is_OPTIONAL(fun is_ServiceChangeProfile/1, P). + +%% is_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = N}) -> +%% is_IA5String(N, {range, 1, 67}); +%% is_ServiceChangeProfile(_) -> +%% false. + +%% chk_opt_ServiceChangeProfile(P1, P2) -> +%% chk_OPTIONAL('ServiceChangeProfile', P1, P2, +%% fun is_ServiceChangeProfile/1, +%% fun chk_ServiceChangeProfile/2). + +%% chk_ServiceChangeProfile(P, P) -> +%% chk_type(fun is_ServiceChangeProfile/1, 'ServiceChangeProfile', P); +%% chk_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = N1}, +%% #'ServiceChangeProfile'{profileName = N2}) -> +%% validate(fun() -> chk_IA5String(N1, N2, {range, 1, 67}) end, +%% 'ServiceChangeProfile'), +%% ok; +%% chk_ServiceChangeProfile(P1, P2) -> +%% wrong_type('ServiceChangeProfile', P1, P2). + + +%% %% -- PackagesDescriptor -- + +%% is_PackagesDescriptor([]) -> +%% true; +%% is_PackagesDescriptor([H|T]) -> +%% is_PackagesItem(H) andalso is_PackagesDescriptor(T); +%% is_PackagesDescriptor(_) -> +%% false. + +%% chk_PackagesDescriptor([], []) -> +%% ok; +%% chk_PackagesDescriptor([] = D1, D2) -> +%% not_equal('PackagesDescriptor', D1, D2); +%% chk_PackagesDescriptor(D1, [] = D2) -> +%% not_equal('PackagesDescriptor', D1, D2); +%% chk_PackagesDescriptor([H|T1], [H|T2]) -> +%% case is_PackagesItem(H) of +%% true -> +%% chk_PackagesDescriptor(T1, T2); +%% false -> +%% wrong_type('PackagesDescriptor_val', H) +%% end; +%% chk_PackagesDescriptor([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_PackagesItem(H1, H2) end, +%% 'PackagesDescriptor_val'), +%% chk_PackagesDescriptor(T1, T2); +%% chk_PackagesDescriptor(D1, D2) -> +%% wrong_type('PackagesDescriptor_val', D1, D2). + + +%% %% -- PackagesItem -- + +%% is_PackagesItem(#'PackagesItem'{packageName = N, +%% packageVersion = V}) -> +%% is_Name(N) andalso is_INTEGER(V, {range, 0, 99}); +%% is_PackagesItem(_) -> +%% false. + +%% chk_PackagesItem(I, I) -> +%% chk_type(fun is_PackagesItem/1, 'PackagesItem', I); +%% chk_PackagesItem(#'PackagesItem'{packageName = N1, +%% packageVersion = V1}, +%% #'PackagesItem'{packageName = N2, +%% packageVersion = V2}) -> +%% validate(fun() -> chk_Name(N1, N2) end, 'PackagesItem'), +%% validate(fun() -> chk_INTEGER(V1, V2, {range, 0, 99}) end, 'PackagesItem'), +%% ok; +%% chk_PackagesItem(I1, I2) -> +%% wrong_type('PackagesItem', I1, I2). + + +%% %% -- StatisticsDescriptor -- + +%% is_StatisticsDescriptor([]) -> +%% true; +%% is_StatisticsDescriptor([H|T]) -> +%% is_StatisticsParameter(H) andalso is_StatisticsDescriptor(T); +%% is_StatisticsDescriptor(_) -> +%% false. + +%% chk_StatisticsDescriptor([], []) -> +%% ok; +%% chk_StatisticsDescriptor([] = D1, D2) -> +%% not_equal('StatisticsDescriptor', D1, D2); +%% chk_StatisticsDescriptor(D1, [] = D2) -> +%% not_equal('StatisticsDescriptor', D1, D2); +%% chk_StatisticsDescriptor([H|T1], [H|T2]) -> +%% case is_StatisticsParameter(H) of +%% true -> +%% chk_StatisticsDescriptor(T1, T2); +%% false -> +%% wrong_type('StatisticsDescriptor_val', H) +%% end; +%% chk_StatisticsDescriptor([H1|T1], [H2|T2]) -> +%% validate(fun() -> chk_StatisticsParameter(H1, H2) end, +%% 'StatisticsDescriptor_val'), +%% chk_StatisticsDescriptor(T1, T2); +%% chk_StatisticsDescriptor(D1, D2) -> +%% wrong_type('StatisticsDescriptor_val', D1, D2). + + +%% %% -- StatisticsParameter -- + +%% is_StatisticsParameter(#'StatisticsParameter'{statName = N, +%% statValue = V}) -> +%% is_PkgdName(N) andalso is_opt_Value(V); +%% is_StatisticsParameter(_) -> +%% false. + +%% chk_StatisticsParameter(P, P) -> +%% chk_type(fun is_StatisticsParameter/1, 'StatisticsParameter', P); +%% chk_StatisticsParameter(#'StatisticsParameter'{statName = N1, +%% statValue = V1}, +%% #'StatisticsParameter'{statName = N2, +%% statValue = V2}) -> +%% validate(fun() -> chk_PkgdName(N1, N2) end, 'StatisticsParameter'), +%% validate(fun() -> chk_opt_Value(V1, V2) end, 'StatisticsParameter'), +%% ok; +%% chk_StatisticsParameter(P1, P2) -> +%% wrong_type('StatisticsParameter', P1, P2). + + +%% %% -- NonStandardData -- + +%% is_opt_NonStandardData(asn1_NOVALUE) -> +%% true; +%% is_opt_NonStandardData(NSD) -> +%% is_NonStandardData(NSD). + +%% %% is_NonStandardData(#'NonStandardData'{nonStandardIdentifier = Id, +%% %% data = D}) -> +%% %% is_NonStandardIdentifier(Id) andalso is_OCTET_STRING(D); +%% %% is_NonStandardData(_) -> +%% %% false. + +%% is_NonStandardData(_) -> +%% true. + +%% chk_opt_NonStandardData(asn1_NOVALUE, asn1_NOVALUE) -> +%% true; +%% chk_opt_NonStandardData(NSD1, NSD2) -> +%% chk_NonStandardData(NSD1, NSD2). + +%% chk_NonStandardData(NSD, NSD) -> +%% chk_type(fun is_NonStandardData/1, 'NonStandardData', NSD); +%% %% chk_NonStandardData(#'NonStandardData'{nonStandardIdentifier = Id1, +%% %% data = D1}, +%% %% #'NonStandardData'{nonStandardIdentifier = Id2, +%% %% data = D2}) -> +%% %% validate(fun() -> chk_NonStandardIdentifier(Id1, Id2) end, +%% %% 'NonStandardData'), +%% %% validate(fun() -> chk_OCTET_STRING(D1, D2) end, 'NonStandardData'), +%% %% ok; +%% %% chk_NonStandardData(NSD1, NSD2) -> +%% %% wrong_type('NonStandardData', NSD1, NSD2). +%% chk_NonStandardData(NSD1, NSD2) -> +%% not_equal('NonStandardData', NSD1, NSD2). + + +%% %% -- NonStandardIdentifier -- + +%% %% is_NonStandardIdentifier({Tag, Val}) -> +%% %% is_NonStandardIdentifier_tag(Tag) andalso +%% %% is_NonStandardIdentifier_val(Tag, Val); +%% %% is_NonStandardIdentifier(_) -> +%% %% false. + +%% %% is_NonStandardIdentifier_tag(Tag) -> +%% %% Tags = [object, h221NonStandard, experimental], +%% %% lists:member(Tag, Tags). + +%% %% is_NonStandardIdentifier_val(object, Val) -> +%% %% is_OBJECT_IDENTIFIER(Val); +%% %% is_NonStandardIdentifier_val(h221NonStandard, Val) -> +%% %% is_H221NonStandard(Val); +%% %% is_NonStandardIdentifier_val(experimental, Val) -> +%% %% is_IA5String(Val, {exact, 8}). + +%% %% chk_NonStandardIdentifier(Id, Id) -> +%% %% chk_type(fun is_NonStandardIdentifier/1, 'NonStandardIdentifier', Id); +%% %% chk_NonStandardIdentifier({Tag, Val1} = Id1, {Tag, Val2} = Id2) -> +%% %% case (is_NonStandardIdentifier_tag(Tag) andalso +%% %% is_NonStandardIdentifier_val(Tag, Val1) andalso +%% %% is_NonStandardIdentifier_val(Tag, Val1)) of +%% %% true -> +%% %% chk_NonStandardIdentifier_val(Tag, Val1, Val2); +%% %% false -> +%% %% wrong_type('NonStandardIdentifier', Id1, Id2) +%% %% end; +%% %% chk_NonStandardIdentifier({Tag1, Val1} = Id1, {Tag2, Val2} = Id2) -> +%% %% case ((is_NonStandardIdentifier_tag(Tag1) andalso +%% %% is_NonStandardIdentifier_val(Tag1, Val1)) andalso +%% %% (is_NonStandardIdentifier_tag(Tag2) andalso +%% %% is_NonStandardIdentifier_val(Tag2, Val1))) of +%% %% true -> +%% %% not_equal('NonStandardIdentifier', Id1, Id2); +%% %% false -> +%% %% wrong_type('NonStandardIdentifier', Id1, Id2) +%% %% end; +%% %% chk_NonStandardIdentifier(Id1, Id2) -> +%% %% wrong_type('NonStandardIdentifier', Id1, Id2). + +%% %% chk_NonStandardIdentifier_val(object, Val1, Val2) -> +%% %% chk_OBJECT_IDENTIFIER(Val1, Val2); +%% %% chk_NonStandardIdentifier_val(h221NonStandard, Val1, Val2) -> +%% %% chk_H221NonStandard(Val1, Val2); +%% %% chk_NonStandardIdentifier_val(experimental, Val1, Val2) -> +%% %% chk_IA5String(Val1, Val2, {exact, 8}). + + +%% %% -- H221NonStandard -- + +%% %% is_H221NonStandard(#'H221NonStandard'{t35CountryCode1 = CC1, +%% %% t35CountryCode2 = CC2, +%% %% t35Extension = Ext, +%% %% manufacturerCode = MC}) -> +%% %% is_INTEGER(CC1, {range, 0, 255}) andalso +%% %% is_INTEGER(CC2, {range, 0, 255}) andalso +%% %% is_INTEGER(Ext, {range, 0, 255}) andalso +%% %% is_INTEGER(Ext, {range, 0, 65535}); +%% %% is_H221NonStandard(_) -> +%% %% false. + +%% %% chk_H221NonStandard(NS, NS) -> +%% %% chk_type(fun is_H221NonStandard/1, 'H221NonStandard', NS); +%% %% chk_H221NonStandard(#'H221NonStandard'{t35CountryCode1 = CC11, +%% %% t35CountryCode2 = CC21, +%% %% t35Extension = Ext1, +%% %% manufacturerCode = MC1}, +%% %% #'H221NonStandard'{t35CountryCode1 = CC12, +%% %% t35CountryCode2 = CC22, +%% %% t35Extension = Ext2, +%% %% manufacturerCode = MC2}) -> +%% %% validate(fun() -> chk_INTEGER(CC11, CC12, {range, 0, 255}) end, +%% %% 'H221NonStandard'), +%% %% validate(fun() -> chk_INTEGER(CC21, CC22, {range, 0, 255}) end, +%% %% 'H221NonStandard'), +%% %% validate(fun() -> chk_INTEGER(Ext1, Ext2, {range, 0, 255}) end, +%% %% 'H221NonStandard'), +%% %% validate(fun() -> chk_INTEGER(MC1, MC2, {range, 0, 65535}) end, +%% %% 'H221NonStandard'), +%% %% ok; +%% %% chk_H221NonStandard(NS1, NS2) -> +%% %% wrong_type('H221NonStandard', NS1, NS2). + + +%% %% -- TimeNotation -- + +%% is_opt_TimeNotation(asn1_NOVALUE) -> +%% true; +%% is_opt_TimeNotation(TN) -> +%% is_TimeNotation(TN). + +%% is_TimeNotation(#'TimeNotation'{date = D, time = T}) -> +%% is_IA5String(D, {exact, 8}) andalso is_IA5String(T, {exact, 8}); +%% is_TimeNotation(_) -> +%% false. + +%% chk_opt_TimeNotation(asn1_NOVALUE, asn1_NOVALUE) -> +%% ok; +%% chk_opt_TimeNotation(TN1, TN2) -> +%% chk_TimeNotation(TN1, TN2). + +%% chk_TimeNotation(TN, TN) -> +%% chk_type(fun is_TimeNotation/1, 'TimeNotation', TN); +%% chk_TimeNotation(#'TimeNotation'{date = D1, time = T1}, +%% #'TimeNotation'{date = D2, time = T2}) -> +%% validate(fun() -> chk_IA5String(D1, D2, {exact, 8}) end, 'TimeNotation'), +%% validate(fun() -> chk_IA5String(T1, T2, {exact, 8}) end, 'TimeNotation'), +%% ok; +%% chk_TimeNotation(TN1, TN2) -> +%% wrong_type('TimeNotation', TN1, TN2). + + +%% %% -- Value -- + +%% is_opt_Value(V) -> +%% is_OPTIONAL(fun is_Value/1, V). + +is_Value([]) -> + true; +is_Value([H|T]) -> + is_OCTET_STRING(H) andalso is_Value(T); +is_Value(_) -> + false. + +%% chk_opt_Value(V1, V2) -> +%% chk_OPTIONAL('Value', V1, V2, fun is_Value/1, fun chk_Value/2). + +%% chk_Value(V, V) -> +%% case is_Value(V) of +%% true -> +%% ok; +%% false -> +%% wrong_type('Value', V, V) +%% end; +%% chk_Value(V1, V2) -> +%% case (is_Value(V1) andalso is_Value(V2)) of +%% true -> +%% not_equal('Value', V1, V2); +%% false -> +%% wrong_type('Value', V1, V2) +%% end. + + +%% %% ---------------------------------------------------------------------- +%% %% Basic type check functions +%% %% ---------------------------------------------------------------------- + + +is_opt_BOOLEAN(B) -> + is_OPTIONAL(fun is_BOOLEAN/1, B). + +is_BOOLEAN(B) -> + lists:member(B, [true, false]). + +%% chk_opt_BOOLEAN(B1, B2) -> +%% chk_OPTIONAL('BOOLEAN', B1, B2, fun is_BOOLEAN/1, fun chk_BOOLEAN/2). + +%% chk_BOOLEAN(B, B) -> +%% chk_type(fun is_BOOLEAN/1, 'BOOLEAN', B); +%% chk_BOOLEAN(B1, B2) -> +%% case (is_BOOLEAN(B1) andalso is_BOOLEAN(B2)) of +%% true -> +%% not_equal('BOOLEAN', B1, B2); +%% false -> +%% wrong_type('BOOLEAN', B1, B2) +%% end. + + +%% is_IA5String(S) when list(S) -> +%% true; +%% is_IA5String(_) -> +%% false. + +%% is_IA5String(S, _) when list(S) -> +%% true; +%% is_IA5String(_, _) -> +%% false. + +%% %% chk_IA5String(S, S) -> +%% %% chk_type(fun is_IA5String/1, 'IA5String', S); +%% %% chk_IA5String(S1, S2) -> +%% %% case (is_IA5String(S1) andalso is_IA5String(S2)) of +%% %% true -> +%% %% not_equal('IA5String', S1, S2); +%% %% false -> +%% %% wrong_type('IA5String', S1, S2) +%% %% end. + +%% chk_IA5String(S, S, R) -> +%% chk_type(fun is_IA5String/2, 'IA5String', S, R); +%% chk_IA5String(S1, S2, R) -> +%% case (is_IA5String(S1, R) andalso is_IA5String(S2, R)) of +%% true -> +%% not_equal('IA5String', S1, S2); +%% false -> +%% wrong_type('IA5String', S1, S2) +%% end. + + +is_OCTET_STRING(L) -> is_OCTET_STRING(L, any). + +is_OCTET_STRING(L, any) when is_list(L) -> + true; +is_OCTET_STRING(L, {exact, Len}) when is_list(L) andalso (length(L) =:= Len) -> + true; +is_OCTET_STRING(L, {atleast, Len}) when is_list(L) andalso (Len =< length(L)) -> + true; +is_OCTET_STRING(L, {atmost, Len}) when is_list(L) andalso (length(L) =< Len) -> + true; +is_OCTET_STRING(L, {range, Min, Max}) + when is_list(L) andalso (Min =< length(L)) andalso (length(L) =< Max) -> + true; +is_OCTET_STRING(_, _) -> + false. + +%% %% chk_OCTET_STRING(L1, L2) -> +%% %% chk_OCTET_STRING(L1, L2, any). + +%% chk_OCTET_STRING(L, L, R) -> +%% chk_type(fun is_OCTET_STRING/2, 'OCTET STRING', L, R); +%% chk_OCTET_STRING(L1, L2, R) -> +%% case (is_OCTET_STRING(L1, R) andalso is_OCTET_STRING(L2, R)) of +%% true -> +%% not_equal('OCTET STRING', L1, L2); +%% false -> +%% wrong_type('OCTET STRING', L1, L2) +%% end. + + +%% %% is_OBJECT_IDENTIFIER(_) -> +%% %% true. + +%% %% chk_OBJECT_IDENTIFIER(X, X) -> +%% %% ok; +%% %% chk_OBJECT_IDENTIFIER(X1, X2) -> +%% %% not_equal('OBJECT IDENTIFIER', X1, X2). + + +%% is_opt_NULL(N) -> +%% is_OPTIONAL(fun is_NULL/1, N). + +%% is_NULL('NULL') -> +%% true; +%% is_NULL(_) -> +%% false. + +%% chk_opt_NULL(N1, N2) -> +%% chk_OPTIONAL('NULL', N1, N2, fun is_NULL/1, fun chk_NULL/2). + +%% chk_NULL(N, N) -> +%% chk_type(fun is_NULL/1, 'NULL', N); +%% chk_NULL(N1, N2) -> +%% case (is_NULL(N1) andalso is_NULL(N2)) of +%% true -> +%% not_equal('NULL', N1, N2); +%% false -> +%% wrong_type('NULL', N1, N2) +%% end. + + +is_opt_INTEGER(I, R) -> + is_OPTIONAL(fun(X) -> is_INTEGER(X, R) end, I). + +is_INTEGER(I, any) when is_integer(I) -> + true; +is_INTEGER(I, {exact, I}) when is_integer(I) -> + true; +is_INTEGER(I, {atleast, Min}) when is_integer(I) andalso is_integer(Min) andalso (Min =< I) -> + true; +is_INTEGER(I, {atmost, Max}) when is_integer(I) andalso is_integer(Max) andalso (I =< Max) -> + true; +is_INTEGER(I, {range, Min, Max}) + when is_integer(I) andalso + is_integer(Min) andalso + is_integer(Max) andalso + (Min =< I) andalso + (I =< Max) -> + true; +is_INTEGER(_, _) -> + false. + +%% chk_opt_INTEGER(I1, I2, R) -> +%% chk_OPTIONAL('INTEGER', I1, I2, +%% fun(X) -> is_INTEGER(X, R) end, +%% fun(Y1, Y2) -> chk_INTEGER(Y1, Y2, R) end). + +%% chk_INTEGER(I, I, R) -> +%% chk_type(fun is_INTEGER/2, 'INTEGER', I, R); +%% chk_INTEGER(I1, I2, R) -> +%% case (is_INTEGER(I1, R) andalso is_INTEGER(I2, R)) of +%% true -> +%% not_equal('INTEGER', I1, I2); +%% false -> +%% wrong_type('INTEGER', I1, I2) +%% end. + + +%% %% ---------------------------------------------------------------------- +%% %% Various utility functions +%% %% ---------------------------------------------------------------------- + + +%% to_lower([C|Cs]) when C >= $A, C =< $Z -> +%% [C+($a-$A)|to_lower(Cs)]; +%% to_lower([C|Cs]) -> +%% [C|to_lower(Cs)]; +%% to_lower([]) -> +%% []. + + +%% validate(F, Type) when function(F) -> +%% case (catch F()) of +%% {error, Reason} -> +%% error({Type, Reason}); +%% ok -> +%% ok +%% end. + + +%% chk_type(F, T, V) when function(F), atom(T) -> +%% case F(V) of +%% true -> +%% ok; +%% false -> +%% wrong_type(T, V) +%% end. + +%% chk_type(F, T, V1, V2) when function(F), atom(T) -> +%% case F(V1, V2) of +%% true -> +%% ok; +%% false -> +%% wrong_type(T, V1) +%% end. + + +is_OPTIONAL(_, asn1_NOVALUE) -> + true; +is_OPTIONAL(F, Val) when is_function(F) -> + F(Val). + +%% chk_OPTIONAL(_, asn1_NOVALUE, asn1_NOVALUE, _, _) -> +%% ok; +%% chk_OPTIONAL(Type, asn1_NOVALUE = V1, V2, IS, _CHK) when function(IS) -> +%% case IS(V2) of +%% true -> +%% not_equal(Type, V1, V2); +%% false -> +%% wrong_type(Type, V1, V2) +%% end; +%% chk_OPTIONAL(Type, V1, asn1_NOVALUE = V2, IS, _CHK) when function(IS) -> +%% case IS(V1) of +%% true -> +%% not_equal(Type, V1, V2); +%% false -> +%% wrong_type(Type, V1, V2) +%% end; +%% chk_OPTIONAL(_Type, V1, V2, _IS, CHK) when function(CHK) -> +%% CHK(V1, V2). + + +%% %% ---------------------------------------------------------------------- + +%% compare_strings([] = L1, L2) -> +%% {L1, L2}; +%% compare_strings(L1, [] = L2) -> +%% {L1, L2}; +%% compare_strings([H|T1], [H|T2]) -> +%% compare_strings(T1, T2); +%% compare_strings(L1, L2) -> +%% {L1, L2}. + +%% strip_tab_and_newline([]) -> +%% []; +%% strip_tab_and_newline([$\n|T]) -> +%% strip_tab_and_newline(T); +%% strip_tab_and_newline([$\t|T]) -> +%% strip_tab_and_newline(T); +%% strip_tab_and_newline([H|T]) -> +%% [H|strip_tab_and_newline(T)]. + + +%% ---------------------------------------------------------------------- + +%% atmost_once(Type, Val) -> +%% error({atmost_once, {Type, Val}}). + +%% wrong_type(Type, Val) -> +%% error({wrong_type, {Type, Val}}). + +%% wrong_type(Type, Val1, Val2) -> +%% error({wrong_type, {Type, Val1, Val2}}). + +%% not_equal(What, Val1, Val2) -> +%% error({not_equal, {What, Val1, Val2}}). + +error(Reason) -> + throw({error, Reason}). + + +%% ---------------------------------------------------------------------- + +%% d(F) -> +%% d(F, []). + +d(F, A) -> + d(get(dbg), F, A). + +d(true, F, A) -> + io:format("DBG:" ++ F ++ "~n", A); +d(_, _, _) -> + ok. + diff --git a/lib/megaco/test/megaco_test_msg_v2_lib.erl b/lib/megaco/test/megaco_test_msg_v2_lib.erl new file mode 100644 index 0000000000..b680bc869a --- /dev/null +++ b/lib/megaco/test/megaco_test_msg_v2_lib.erl @@ -0,0 +1,7037 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Utility functions for creating the megaco types +%%---------------------------------------------------------------------- + +-module(megaco_test_msg_v2_lib). + +%% ---- + +-include_lib("megaco/include/megaco_message_v2.hrl"). +-include_lib("megaco/include/megaco.hrl"). + +%% ---- + +-export([chk_MegacoMessage/2, + cre_MegacoMessage/1, cre_MegacoMessage/2, + cre_AuthenticationHeader/3, + cre_Message/3, + cre_ErrorDescriptor/1, cre_ErrorDescriptor/2, + cre_ErrorCode/1, + cre_ErrorText/1, + cre_ContextID/1, + cre_Transaction/1, + cre_TransactionId/1, + cre_TransactionRequest/2, + cre_TransactionPending/1, + cre_TransactionReply/2, cre_TransactionReply/3, + cre_TransactionAck/1, cre_TransactionAck/2, + cre_ActionRequest/2, cre_ActionRequest/3, cre_ActionRequest/4, + cre_ActionReply/2, cre_ActionReply/3, cre_ActionReply/4, + cre_ContextRequest/0, cre_ContextRequest/1, cre_ContextRequest/2, + cre_ContextRequest/3, + cre_ContextAttrAuditRequest/0, cre_ContextAttrAuditRequest/3, + cre_CommandRequest/1, cre_CommandRequest/2, cre_CommandRequest/3, + cre_Command/2, + cre_CommandReply/2, + cre_TopologyRequest/3, cre_TopologyRequest/4, + cre_AmmRequest/2, + cre_AmmDescriptor/1, + cre_AmmsReply/1, cre_AmmsReply/2, + cre_SubtractRequest/1, cre_SubtractRequest/2, + cre_AuditRequest/2, + cre_AuditReply/1, + cre_AuditResult/2, + cre_AuditReturnParameter/1, + cre_AuditDescriptor/0, cre_AuditDescriptor/1, cre_AuditDescriptor/2, + cre_IndAuditParameter/1, + cre_IndAudMediaDescriptor/0, cre_IndAudMediaDescriptor/1, + cre_IndAudMediaDescriptor/2, + cre_IndAudStreamDescriptor/2, + cre_IndAudStreamParms/0, cre_IndAudStreamParms/1, + cre_IndAudStreamParms/3, + cre_IndAudLocalControlDescriptor/0, + cre_IndAudLocalControlDescriptor/4, + cre_IndAudPropertyParm/1, + cre_IndAudLocalRemoteDescriptor/1, + cre_IndAudLocalRemoteDescriptor/2, + cre_IndAudPropertyGroup/1, + cre_IndAudTerminationStateDescriptor/1, + cre_IndAudTerminationStateDescriptor/3, + cre_IndAudEventsDescriptor/1, cre_IndAudEventsDescriptor/2, + cre_IndAudEventsDescriptor/3, + cre_IndAudEventBufferDescriptor/1, + cre_IndAudEventBufferDescriptor/2, + cre_IndAudSignalsDescriptor/1, + cre_IndAudSeqSigList/1, + cre_IndAudSeqSigList/2, + cre_IndAudSignal/1, cre_IndAudSignal/2, + cre_IndAudDigitMapDescriptor/0, cre_IndAudDigitMapDescriptor/1, + cre_IndAudStatisticsDescriptor/1, + cre_IndAudPackagesDescriptor/2, + cre_NotifyRequest/2, cre_NotifyRequest/3, + cre_NotifyReply/1, cre_NotifyReply/2, + cre_ObservedEventsDescriptor/2, + cre_ObservedEvent/2, cre_ObservedEvent/3, cre_ObservedEvent/4, + cre_EventName/1, + cre_EventParameter/2, cre_EventParameter/4, + cre_ServiceChangeRequest/2, + cre_ServiceChangeReply/2, + cre_ServiceChangeResult/1, + %% cre_WildcardField/1, + cre_TerminationID/2, + cre_TerminationIDList/1, + cre_MediaDescriptor/0, cre_MediaDescriptor/1, cre_MediaDescriptor/2, + cre_StreamDescriptor/2, + cre_StreamParms/0, cre_StreamParms/1, cre_StreamParms/2, + cre_StreamParms/3, + cre_LocalControlDescriptor/1, cre_LocalControlDescriptor/2, + cre_LocalControlDescriptor/4, + cre_StreamMode/1, + cre_PropertyParm/2, cre_PropertyParm/4, + cre_Name/1, + cre_PkgdName/1, + cre_PkgdName/2, + cre_Relation/1, + cre_LocalRemoteDescriptor/1, + cre_PropertyGroup/1, + cre_TerminationStateDescriptor/1, + cre_TerminationStateDescriptor/2, + cre_TerminationStateDescriptor/3, + cre_EventBufferControl/1, + cre_ServiceState/1, + cre_MuxDescriptor/2, %% cre_MuxDescriptor/3, + cre_MuxType/1, + cre_StreamID/1, + cre_EventsDescriptor/0, cre_EventsDescriptor/2, + cre_RequestedEvent/1, + cre_RequestedEvent/2, cre_RequestedEvent/3, cre_RequestedEvent/4, + cre_RequestedActions/0, + cre_RequestedActions/1, cre_RequestedActions/4, + cre_EventDM/1, + cre_SecondEventsDescriptor/1, cre_SecondEventsDescriptor/2, + cre_SecondRequestedEvent/2, cre_SecondRequestedEvent/3, + cre_SecondRequestedEvent/4, + cre_SecondRequestedActions/0, cre_SecondRequestedActions/1, + cre_SecondRequestedActions/2, cre_SecondRequestedActions/3, + cre_EventBufferDescriptor/1, + cre_EventSpec/2, + cre_EventSpec/3, + cre_SignalsDescriptor/1, + cre_SignalRequest/1, + cre_SeqSigList/2, + cre_Signal/1, cre_Signal/2, cre_Signal/7, + cre_SignalType/1, + cre_SignalName/1, + cre_NotifyCompletion/1, + cre_SigParameter/2, cre_SigParameter/4, + cre_RequestID/1, + cre_ModemDescriptor/2, %% cre_ModemDescriptor/3, + cre_ModemType/1, + cre_DigitMapDescriptor/0, cre_DigitMapDescriptor/1, + cre_DigitMapDescriptor/2, + cre_DigitMapName/1, + cre_DigitMapValue/1, cre_DigitMapValue/4, cre_DigitMapValue/5, + cre_ServiceChangeParm/2, cre_ServiceChangeParm/4, + cre_ServiceChangeParm/9, + cre_ServiceChangeAddress/2, + cre_ServiceChangeResParm/0, cre_ServiceChangeResParm/2, + cre_ServiceChangeResParm/5, + cre_ServiceChangeMethod/1, + cre_ServiceChangeProfile/1, cre_ServiceChangeProfile/2, + cre_PackagesDescriptor/1, + cre_PackagesItem/2, + cre_StatisticsDescriptor/1, + cre_StatisticsParameter/1, cre_StatisticsParameter/2, +%% cre_NonStandardData/2, +%% cre_NonStandardIdentifier/1, +%% cre_H221NonStandard/4, + cre_TimeNotation/2, + cre_Value/1, + cre_BOOLEAN/1 + ]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +cre_MegacoMessage(M) when is_record(M, 'Message') -> + #'MegacoMessage'{mess = M}. + +cre_MegacoMessage(AH, M) + when is_record(AH, 'AuthenticationHeader') andalso + is_record(M, 'Message') -> + #'MegacoMessage'{authHeader = AH, + mess = M}. + +cre_AuthenticationHeader(SPI, SN, AD) -> + #'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AD}. + +cre_Message(V, Mid, ED) when is_record(ED, 'ErrorDescriptor') -> + Body = {errorDescriptor, ED}, + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, Transactions) when is_list(Transactions) -> + Body = {transactions, Transactions}, + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, {transactions, T} = Body) when is_list(T) -> + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, {errorDescriptor, ED} = Body) + when is_record(ED, 'ErrorDescriptor') -> + #'Message'{version = V, + mId = Mid, + messageBody = Body}. + + +cre_ErrorDescriptor(EC) when is_integer(EC) -> + #'ErrorDescriptor'{errorCode = EC}. + +cre_ErrorDescriptor(EC, ET) when is_integer(EC) andalso is_list(ET) -> + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + +cre_ErrorCode(C) when is_integer(C) andalso (0 =< C) andalso (C =< 65535) -> + C; +cre_ErrorCode(C) -> + exit({invalid_ErrorCode, C}). + +cre_ErrorText(T) when is_list(T) -> + T. + +cre_ContextID(Val) when 0 =< Val, Val =< 4294967295 -> + Val; +cre_ContextID(Val) -> + exit({invalid_ContextID, Val}). + +cre_Transaction(TR) when is_record(TR, 'TransactionRequest') -> + {transactionRequest, TR}; +cre_Transaction(TP) when is_record(TP, 'TransactionPending') -> + {transactionPending, TP}; +cre_Transaction(TR) when is_record(TR, 'TransactionReply') -> + {transactionReply, TR}; +cre_Transaction(TRA) when is_list(TRA) -> + {transactionResponseAck, TRA}. + +cre_TransactionId(Val) when (0 =< Val) andalso (Val =< 4294967295) -> + Val; +cre_TransactionId(Val) -> + exit({invalid_TransactionId, Val}). + +cre_TransactionRequest(TransID, ARs) when is_integer(TransID) andalso is_list(ARs) -> + #'TransactionRequest'{transactionId = TransID, + actions = ARs}. + +cre_TransactionPending(TransID) when is_integer(TransID) -> + #'TransactionPending'{transactionId = TransID}. + +cre_TransactionReply(TransID, ED) + when is_integer(TransID) andalso is_record(ED, 'ErrorDescriptor') -> + Res = {transactionError, ED}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}; +cre_TransactionReply(TransID, ARs) + when is_integer(TransID) andalso is_list(ARs) -> + Res = {actionReplies, ARs}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}. + +cre_TransactionReply(TransID, IAR, ED) + when is_integer(TransID) and + ((IAR == 'NULL') or (IAR == asn1_NOVALUE)) and + is_record(ED, 'ErrorDescriptor') -> + Res = {transactionError, ED}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}; +cre_TransactionReply(TransID, IAR, ARs) + when is_integer(TransID) and + ((IAR == 'NULL') or (IAR == asn1_NOVALUE)) and + is_list(ARs) -> + Res = {actionReplies, ARs}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}. + +cre_TransactionAck(FirstAck) -> + #'TransactionAck'{firstAck = FirstAck}. + +cre_TransactionAck(FirstAck, FirstAck) -> + #'TransactionAck'{firstAck = FirstAck}; +cre_TransactionAck(FirstAck, LastAck) -> + #'TransactionAck'{firstAck = FirstAck, + lastAck = LastAck}. + +cre_ActionRequest(CtxID, CmdReqs) + when is_integer(CtxID) andalso is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + commandRequests = CmdReqs}. + +cre_ActionRequest(CtxID, CtxReq, CmdReqs) + when is_integer(CtxID) andalso + is_record(CtxReq, 'ContextRequest') andalso + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextRequest = CtxReq, + commandRequests = CmdReqs}; +cre_ActionRequest(CtxID, CAAR, CmdReqs) + when is_integer(CtxID) andalso + is_record(CAAR, 'ContextAttrAuditRequest') andalso + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextAttrAuditReq = CAAR, + commandRequests = CmdReqs}. + +cre_ActionRequest(CtxID, CtxReq, CAAR, CmdReqs) + when is_integer(CtxID) andalso + is_record(CtxReq, 'ContextRequest') andalso + is_record(CAAR, 'ContextAttrAuditRequest') andalso + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextRequest = CtxReq, + contextAttrAuditReq = CAAR, + commandRequests = CmdReqs}. + +cre_ActionReply(CtxID, CmdReps) + when is_integer(CtxID) andalso + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + commandReply = CmdReps}. + +cre_ActionReply(CtxID, ED, CmdReps) + when is_integer(CtxID) andalso + is_record(ED, 'ErrorDescriptor') andalso + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + errorDescriptor = ED, + commandReply = CmdReps}; +cre_ActionReply(CtxID, CtxReq, CmdReps) + when is_integer(CtxID) andalso + is_record(CtxReq, 'ContextRequest') andalso + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + contextReply = CtxReq, + commandReply = CmdReps}. + +cre_ActionReply(CtxID, ED, CtxReq, CmdReps) + when is_integer(CtxID) andalso + is_record(ED, 'ErrorDescriptor') andalso + is_record(CtxReq, 'ContextRequest') andalso + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + errorDescriptor = ED, + contextReply = CtxReq, + commandReply = CmdReps}. + +cre_ContextRequest() -> + #'ContextRequest'{}. + +cre_ContextRequest(Prio) when is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15) -> + #'ContextRequest'{priority = Prio}; +cre_ContextRequest(Em) when (Em =:= true) andalso (Em =:= false) andalso (Em =:= asn1_NOVALUE) -> + #'ContextRequest'{emergency = Em}; +cre_ContextRequest(Top) when is_list(Top) -> + #'ContextRequest'{topologyReq = Top}. + +cre_ContextRequest(Prio, Em) + when (is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) -> + #'ContextRequest'{priority = Prio, + emergency = Em}; +cre_ContextRequest(Prio, Top) + when is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15) andalso is_list(Top) -> + #'ContextRequest'{priority = Prio, + topologyReq = Top}. + +cre_ContextRequest(Prio, Em, Top) + when (is_integer(Prio) and (0 =< Prio) and (Prio =< 15)) and + ((Em == true) or (Em == false) or (Em == asn1_NOVALUE)) and + is_list(Top) -> + #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top}. + +cre_ContextAttrAuditRequest() -> + #'ContextAttrAuditRequest'{}. + +cre_ContextAttrAuditRequest(Top, Em, Prio) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) -> + #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio}. + +cre_CommandRequest(Cmd) -> + #'CommandRequest'{command = Cmd}. + +cre_CommandRequest(Cmd, Opt) + when ((Opt == 'NULL') or (Opt == asn1_NOVALUE)) -> + #'CommandRequest'{command = Cmd, + optional = Opt}. + +cre_CommandRequest(Cmd, Opt, WR) + when ((Opt == 'NULL') or (Opt == asn1_NOVALUE)) and + ((WR == 'NULL') or (WR == asn1_NOVALUE)) -> + #'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = WR}. + +cre_Command(addReq = Tag, Req) + when is_record(Req, 'AmmRequest') -> + {Tag, Req}; +cre_Command(moveReq = Tag, Req) + when is_record(Req, 'AmmRequest') -> + {Tag, Req}; +cre_Command(modReq = Tag, Req) + when is_record(Req, 'AmmRequest') -> + {Tag, Req}; +cre_Command(subtractReq = Tag, Req) + when is_record(Req, 'SubtractRequest') -> + {Tag, Req}; +cre_Command(auditCapRequest = Tag, Req) + when is_record(Req, 'AuditRequest') -> + {Tag, Req}; +cre_Command(auditValueRequest = Tag, Req) + when is_record(Req, 'AuditRequest') -> + {Tag, Req}; +cre_Command(notifyReq = Tag, Req) + when is_record(Req, 'NotifyRequest') -> + {Tag, Req}; +cre_Command(serviceChangeReq = Tag, Req) + when is_record(Req, 'ServiceChangeRequest') -> + {Tag, Req}. + +cre_CommandReply(addReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(moveReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(modReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(subtractReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(auditCapReply = Tag, Rep) + when is_tuple(Rep) -> + {Tag, Rep}; +cre_CommandReply(auditValueReply = Tag, Rep) + when is_tuple(Rep) -> + {Tag, Rep}; +cre_CommandReply(notifyReply = Tag, Rep) + when is_record(Rep, 'NotifyReply') -> + {Tag, Rep}; +cre_CommandReply(serviceChangeReply = Tag, Rep) + when is_record(Rep, 'ServiceChangeReply') -> + {Tag, Rep}. + +cre_TopologyRequest(From, To, Dir) + when is_record(From, 'TerminationID') and + is_record(To, 'TerminationID') and + ((Dir == bothway) or (Dir == isolate) or (Dir == oneway)) -> + #'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = Dir}. + +cre_TopologyRequest(From, To, Dir, SID) + when is_record(From, 'TerminationID') and + is_record(To, 'TerminationID') and + ((Dir == bothway) or (Dir == isolate) or (Dir == oneway)) and + (is_integer(SID) or (SID == asn1_NOVALUE)) -> + #'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = Dir, + streamID = SID}. + +cre_AmmRequest(TermIDs, Descs) when is_list(TermIDs) andalso is_list(Descs) -> + #'AmmRequest'{terminationID = TermIDs, + descriptors = Descs}. + +cre_AmmDescriptor(D) when is_record(D, 'MediaDescriptor') -> + {mediaDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'ModemDescriptor') -> + {modemDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'MuxDescriptor') -> + {muxDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'EventsDescriptor') -> + {eventsDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'DigitMapDescriptor') -> + {digitMapDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'AuditDescriptor') -> + {auditDescriptor, D}; +cre_AmmDescriptor(D) when is_list(D) -> + case is_EventBufferDescriptor(D) of + true -> + {eventBufferDescriptor, D}; + false -> + case is_SignalsDescriptor(D) of + true -> + {signalsDescriptor, D}; + false -> + error({invalid_AmmDescriptor, D}) + end + end. + +cre_AmmsReply(TermIDs) when is_list(TermIDs) -> + #'AmmsReply'{terminationID = TermIDs}. + +cre_AmmsReply(TermIDs, TAs) when is_list(TermIDs) andalso is_list(TAs) -> + #'AmmsReply'{terminationID = TermIDs, + terminationAudit = TAs}. + +cre_SubtractRequest(TermIDs) when is_list(TermIDs) -> + #'SubtractRequest'{terminationID = TermIDs}. + +cre_SubtractRequest(TermIDs, Audit) + when is_list(TermIDs) andalso is_record(Audit, 'AuditDescriptor') -> + #'SubtractRequest'{terminationID = TermIDs, + auditDescriptor = Audit}. + +cre_AuditRequest(TermID, Audit) + when is_record(TermID, megaco_term_id) andalso is_record(Audit, 'AuditDescriptor') -> + #'AuditRequest'{terminationID = TermID, + auditDescriptor = Audit}. + +cre_AuditReply(TermIDs) when is_list(TermIDs) -> + {contextAuditResult, TermIDs}; +cre_AuditReply(ED) when is_record(ED, 'ErrorDescriptor') -> + {error, ED}; +cre_AuditReply(Audit) when is_record(Audit, 'AuditResult') -> + {auditResult, Audit}. + +cre_AuditResult(TermID, TAs) + when is_record(TermID, megaco_term_id) andalso is_list(TAs) -> + #'AuditResult'{terminationID = TermID, + terminationAuditResult = TAs}. + +cre_AuditReturnParameter(D) when is_record(D, 'ErrorDescriptor') -> + {errorDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'MediaDescriptor') -> + {mediaDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'ModemDescriptor') -> + {modemDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'MuxDescriptor') -> + {muxDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'EventsDescriptor') -> + {eventsDescriptor, D}; +cre_AuditReturnParameter([H|_] = D) when is_record(H, 'EventSpec') -> + {eventBufferDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'DigitMapDescriptor') -> + {digitMapDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'ObservedEventsDescriptor') -> + {observedEventsDescriptor, D}; +cre_AuditReturnParameter([H|_] = D) when is_record(H, 'StatisticsParameter') -> + {statisticsDescriptor, D}; +cre_AuditReturnParameter([H|_] = D) when is_record(H, 'PackagesItem') -> + {packagesDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'AuditDescriptor') -> + {emptyDescriptors, D}; +cre_AuditReturnParameter([H|_] = D) when is_tuple(H) -> + {signalsDescriptor, D}. + +cre_AuditDescriptor() -> + #'AuditDescriptor'{}. + +cre_AuditDescriptor([H|_] = AT) when is_atom(H) -> + #'AuditDescriptor'{auditToken = AT}; +cre_AuditDescriptor(APT) -> + #'AuditDescriptor'{auditPropertyToken = APT}. + +cre_AuditDescriptor(AT, APT) -> + #'AuditDescriptor'{auditToken = AT, + auditPropertyToken = APT}. + +cre_IndAuditParameter(D) when is_record(D, 'IndAudMediaDescriptor') -> + {indAudMediaDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudEventsDescriptor') -> + {indAudEventsDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudEventBufferDescriptor') -> + {indAudEventBufferDescriptor, D}; +cre_IndAuditParameter({signal, _} = D) -> + {indAudSignalsDescriptor, D}; +cre_IndAuditParameter({seqSigList, _} = D) -> + {indAudSignalsDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudDigitMapDescriptor') -> + {indAudDigitMapDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudStatisticsDescriptor') -> + {indAudStatisticsDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudPackagesDescriptor') -> + {indAudPackagesDescriptor, D}. + +cre_IndAudMediaDescriptor() -> + #'IndAudMediaDescriptor'{}. + +cre_IndAudMediaDescriptor(TSD) + when is_record(TSD, 'IndAudTerminationStateDescriptor') -> + #'IndAudMediaDescriptor'{termStateDescr = TSD}; +cre_IndAudMediaDescriptor(Parms) when is_record(Parms, 'IndAudStreamParms') -> + Streams = {oneStream, Parms}, + #'IndAudMediaDescriptor'{streams = Streams}; +cre_IndAudMediaDescriptor(Descs) when is_list(Descs) -> + Streams = {multiStream, Descs}, + #'IndAudMediaDescriptor'{streams = Streams}. + +cre_IndAudMediaDescriptor(TSD, Parms) + when is_record(TSD, 'IndAudTerminationStateDescriptor') andalso + is_record(Parms, 'IndAudStreamParms') -> + Streams = {oneStream, Parms}, + #'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = Streams}; +cre_IndAudMediaDescriptor(TSD, Descs) + when is_record(TSD, 'IndAudTerminationStateDescriptor') andalso is_list(Descs) -> + Streams = {multiStream, Descs}, + #'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = Streams}. + +cre_IndAudStreamDescriptor(SID, Parms) + when is_integer(SID) andalso is_record(Parms, 'IndAudStreamParms') -> + #'IndAudStreamDescriptor'{streamID = SID, + streamParms = Parms}. + +cre_IndAudStreamParms() -> + #'IndAudStreamParms'{}. + +cre_IndAudStreamParms(LCD) when is_record(LCD, 'IndAudLocalControlDescriptor') -> + #'IndAudStreamParms'{localControlDescriptor = LCD}. + +cre_IndAudStreamParms(LCD, L, R) + when is_record(LCD, 'IndAudLocalControlDescriptor') andalso + is_record(L, 'IndAudLocalRemoteDescriptor') andalso + is_record(R, 'IndAudLocalRemoteDescriptor') -> + #'IndAudStreamParms'{localControlDescriptor = LCD, + localDescriptor = L, + remoteDescriptor = R}. + +cre_IndAudLocalControlDescriptor() -> + #'IndAudLocalControlDescriptor'{}. + +cre_IndAudLocalControlDescriptor(SM, RV, RG, PP) + when ((SM == 'NULL') or (SM == asn1_NOVALUE)) and + ((RV == 'NULL') or (RV == asn1_NOVALUE)) and + ((RG == 'NULL') or (RG == asn1_NOVALUE)) and + (is_list(PP) or (PP == asn1_NOVALUE)) -> + #'IndAudLocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP}. + +cre_IndAudPropertyParm(PkgdName) when is_list(PkgdName) -> + #'IndAudPropertyParm'{name = PkgdName}. + +cre_IndAudLocalRemoteDescriptor(Grps) + when is_list(Grps) -> + #'IndAudLocalRemoteDescriptor'{propGrps = Grps}. + +cre_IndAudLocalRemoteDescriptor(GrpID, Grps) + when is_integer(GrpID) andalso (0 =< GrpID) andalso (GrpID =< 65535) andalso is_list(Grps) -> + #'IndAudLocalRemoteDescriptor'{propGroupID = GrpID, + propGrps = Grps}. + +cre_IndAudPropertyGroup([]) -> + []; +cre_IndAudPropertyGroup([H|_] = PG) + when is_record(H, 'IndAudPropertyParm') -> + PG. + +cre_IndAudTerminationStateDescriptor([] = PP) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP}; +cre_IndAudTerminationStateDescriptor([H|_] = PP) + when is_record(H, 'IndAudPropertyParm') -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP}. + +cre_IndAudTerminationStateDescriptor([] = PP, EBC, SS) + when ((EBC == 'NULL') or (EBC == asn1_NOVALUE)) and + ((SS == 'NULL') or (SS == asn1_NOVALUE)) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS}; +cre_IndAudTerminationStateDescriptor([H|_] = PP, EBC, SS) + when is_record(H, 'IndAudPropertyParm') and + ((EBC == 'NULL') or (EBC == asn1_NOVALUE)) and + ((SS == 'NULL') or (SS == asn1_NOVALUE)) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS}. + +cre_IndAudEventsDescriptor(PkgdName) + when is_list(PkgdName) -> + #'IndAudEventsDescriptor'{pkgdName = PkgdName}. + +cre_IndAudEventsDescriptor(RID, PkgdName) + when is_integer(RID) andalso is_list(PkgdName) -> + #'IndAudEventsDescriptor'{requestID = RID, pkgdName = PkgdName}; +cre_IndAudEventsDescriptor(PkgdName, SID) + when is_list(PkgdName) andalso is_integer(SID) -> + #'IndAudEventsDescriptor'{pkgdName = PkgdName, streamID = SID}. + +cre_IndAudEventsDescriptor(RID, PkgdName, SID) + when is_integer(RID) andalso is_list(PkgdName) andalso is_integer(SID) -> + #'IndAudEventsDescriptor'{requestID = RID, + pkgdName = PkgdName, + streamID = SID}. + +cre_IndAudEventBufferDescriptor(EventName) when is_list(EventName) -> + #'IndAudEventBufferDescriptor'{eventName = EventName}. + +cre_IndAudEventBufferDescriptor(EventName, SID) + when is_list(EventName) andalso is_integer(SID) -> + #'IndAudEventBufferDescriptor'{eventName = EventName, streamID = SID}. + +cre_IndAudSignalsDescriptor(S) when is_record(S, 'IndAudSignal') -> + {signal, S}; +cre_IndAudSignalsDescriptor(S) when is_record(S, 'IndAudSeqSigList') -> + {seqSigList, S}. + +cre_IndAudSeqSigList(ID) when is_integer(ID) andalso (0=< ID) andalso (ID =< 65535) -> + #'IndAudSeqSigList'{id = ID}. + +cre_IndAudSeqSigList(ID, S) + when is_integer(ID) andalso + (0 =< ID) andalso (ID =< 65535) andalso + is_record(S, 'IndAudSignal') -> + #'IndAudSeqSigList'{id = ID, signalList = S}. + +cre_IndAudSignal(SigName) when is_list(SigName) -> + #'IndAudSignal'{signalName = SigName}. + +cre_IndAudSignal(SigName, SID) when is_list(SigName) andalso is_integer(SID) -> + #'IndAudSignal'{signalName = SigName, streamID = SID}. + +cre_IndAudDigitMapDescriptor() -> + #'IndAudDigitMapDescriptor'{}. + +cre_IndAudDigitMapDescriptor(DMN) when is_list(DMN) -> + #'IndAudDigitMapDescriptor'{digitMapName = DMN}. + +cre_IndAudStatisticsDescriptor(StatName) when is_list(StatName) -> + #'IndAudStatisticsDescriptor'{statName = StatName}. + +cre_IndAudPackagesDescriptor(N, V) + when is_list(N) andalso + is_integer(V) andalso + (0 =< V) andalso + (V =< 99) -> + #'IndAudPackagesDescriptor'{packageName = N, + packageVersion = V}. + +cre_NotifyRequest(TermIDs, D) + when is_list(TermIDs) andalso is_record(D, 'ObservedEventsDescriptor') -> + #'NotifyRequest'{terminationID = TermIDs, + observedEventsDescriptor = D}. + +cre_NotifyRequest(TermIDs, D, ED) + when is_list(TermIDs) andalso + is_record(D, 'ObservedEventsDescriptor') andalso + is_record(ED, 'ErrorDescriptor') -> + #'NotifyRequest'{terminationID = TermIDs, + observedEventsDescriptor = D, + errorDescriptor = ED}. + +cre_NotifyReply(TermIDs) when is_list(TermIDs) -> + #'NotifyReply'{terminationID = TermIDs}. + +cre_NotifyReply(TermIDs, ED) + when is_list(TermIDs) andalso + is_record(ED, 'ErrorDescriptor') -> + #'NotifyReply'{terminationID = TermIDs, + errorDescriptor = ED}. + +cre_ObservedEventsDescriptor(RID, [H|_] = L) + when is_integer(RID) andalso is_record(H, 'ObservedEvent') -> + #'ObservedEventsDescriptor'{requestId = RID, + observedEventLst = L}. + +cre_ObservedEvent(EN, EPL) + when is_list(EN) andalso is_list(EPL) -> + #'ObservedEvent'{eventName = EN, + eventParList = EPL}; +cre_ObservedEvent(EN, TN) + when is_list(EN) andalso + is_record(TN, 'TimeNotation') -> + #'ObservedEvent'{eventName = EN, + timeNotation = TN}. + +cre_ObservedEvent(EN, SID, EPL) + when is_list(EN) andalso + is_integer(SID) andalso + is_list(EPL) -> + #'ObservedEvent'{eventName = EN, + streamID = SID, + eventParList = EPL}; +cre_ObservedEvent(EN, EPL, TN) + when is_list(EN) andalso + is_list(EPL) andalso + is_record(TN, 'TimeNotation') -> + #'ObservedEvent'{eventName = EN, + eventParList = EPL, + timeNotation = TN}. + +cre_ObservedEvent(EN, SID, EPL, TN) + when is_list(EN) andalso + is_integer(SID) andalso + is_list(EPL) andalso + is_record(TN, 'TimeNotation') -> + #'ObservedEvent'{eventName = EN, + streamID = SID, + eventParList = EPL, + timeNotation = TN}. + +cre_EventName(N) when is_list(N) -> + N. + +cre_EventParameter(N, V) when is_list(N) andalso is_list(V) -> + #'EventParameter'{eventParameterName = N, + value = V}. + +cre_EventParameter(N, V, relation = Tag, R) + when is_list(N) andalso is_list(V) andalso is_atom(R) -> + EI = {Tag, R}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}; +cre_EventParameter(N, V, range = Tag, B) + when is_list(N) andalso is_list(V) andalso is_atom(B) -> + EI = {Tag, B}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}; +cre_EventParameter(N, V, sublist = Tag, B) + when is_list(N) andalso is_list(V) andalso is_atom(B) -> + EI = {Tag, B}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}. + +cre_ServiceChangeRequest(TermIDs, SCP) + when is_list(TermIDs) andalso + is_record(SCP, 'ServiceChangeParm') -> + #'ServiceChangeRequest'{terminationID = TermIDs, + serviceChangeParms = SCP}. + +cre_ServiceChangeReply(TermIDs, {Tag, R} = SCR) + when is_list(TermIDs) andalso is_atom(Tag) andalso is_tuple(R) -> + #'ServiceChangeReply'{terminationID = TermIDs, + serviceChangeResult = SCR}. + +cre_ServiceChangeResult(ED) when is_record(ED, 'ErrorDescriptor') -> + {errorDescriptor, ED}; +cre_ServiceChangeResult(SCRP) when is_record(SCRP, 'ServiceChangeResParm') -> + {serviceChangeResParms, SCRP}. + +%% cre_WildcardField(L) when list(L), length(L) == 1 -> L. + +cre_TerminationID(W, ID) + when is_list(W) andalso + is_list(ID) andalso (1 =< length(ID)) andalso (length(ID) =< 8) -> + #'TerminationID'{wildcard = W, + id = ID}. + +cre_TerminationIDList(L) when is_list(L) -> + L. + +cre_MediaDescriptor() -> + #'MediaDescriptor'{}. + +cre_MediaDescriptor(TSD) when is_record(TSD, 'TerminationStateDescriptor') -> + #'MediaDescriptor'{termStateDescr = TSD}; +cre_MediaDescriptor(SP) when is_record(SP, 'StreamParms') -> + Streams = {oneStream, SP}, + #'MediaDescriptor'{streams = Streams}; +cre_MediaDescriptor([H|_] = SDs) when is_record(H, 'StreamDescriptor') -> + Streams = {multiStream, SDs}, + #'MediaDescriptor'{streams = Streams}. + +cre_MediaDescriptor(TSD, SP) + when is_record(TSD, 'TerminationStateDescriptor') andalso + is_record(SP, 'StreamParms') -> + Streams = {oneStream, SP}, + #'MediaDescriptor'{termStateDescr = TSD, + streams = Streams}; +cre_MediaDescriptor(TSD, [H|_] = SDs) + when is_record(TSD, 'TerminationStateDescriptor') andalso + is_record(H, 'StreamDescriptor') -> + Streams = {multiStream, SDs}, + #'MediaDescriptor'{termStateDescr = TSD, + streams = Streams}. + +cre_StreamDescriptor(SID, SP) when is_integer(SID) andalso is_record(SP, 'StreamParms') -> + #'StreamDescriptor'{streamID = SID, + streamParms = SP}. + +cre_StreamParms() -> + #'StreamParms'{}. + +cre_StreamParms(LCD) when is_record(LCD, 'LocalControlDescriptor') -> + #'StreamParms'{localControlDescriptor = LCD}; +cre_StreamParms(LD) when is_record(LD, 'LocalRemoteDescriptor') -> + #'StreamParms'{localDescriptor = LD}. + +cre_StreamParms(LCD, LD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD}. + +cre_StreamParms(LCD, LD, RD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) and + (is_record(RD, 'LocalRemoteDescriptor') or (RD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD}. + +cre_LocalControlDescriptor(SM) when is_atom(SM) -> + #'LocalControlDescriptor'{streamMode = SM, propertyParms = []}; +cre_LocalControlDescriptor([H|_] = PP) when is_record(H, 'PropertyParm') -> + #'LocalControlDescriptor'{propertyParms = PP}. + +cre_LocalControlDescriptor(SM, [H|_] = PP) + when is_atom(SM) andalso is_record(H, 'PropertyParm') -> + #'LocalControlDescriptor'{streamMode = SM, + propertyParms = PP}. + +cre_LocalControlDescriptor(SM, RV, RG, [H|_] = PP) + when is_atom(SM) and + ((RV == true) or (RV == false) or (RV == asn1_NOVALUE)) and + ((RG == true) or (RG == false) or (RG == asn1_NOVALUE)) and + is_record(H, 'PropertyParm') -> + #'LocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP}. + +cre_StreamMode(sendOnly = M) -> + M; +cre_StreamMode(recvOnly = M) -> + M; +cre_StreamMode(sendRecv = M) -> + M; +cre_StreamMode(inactive = M) -> + M; +cre_StreamMode(loopBack = M) -> + M. + +cre_PropertyParm(N, [H|_] = V) when is_list(N) andalso is_list(H) -> + #'PropertyParm'{name = N, value = V}. + +cre_PropertyParm(N, [H|_] = V, relation = Tag, R) + when is_list(N) andalso is_list(H) andalso is_atom(R) -> + EI = {Tag, R}, + #'PropertyParm'{name = N, value = V, extraInfo = EI}; +cre_PropertyParm(N, [H|_] = V, range = Tag, B) + when is_list(N) andalso is_list(H) andalso is_atom(B) -> + EI = {Tag, B}, + #'PropertyParm'{name = N, value = V, extraInfo = EI}; +cre_PropertyParm(N, [H|_] = V, sublist = Tag, B) + when is_list(N) andalso is_list(H) andalso is_atom(B) -> + EI = {Tag, B}, + #'PropertyParm'{name = N, value = V, extraInfo = EI}. + + +cre_Name(N) when is_list(N) andalso (length(N) =:= 2) -> + N. + +cre_PkgdName(N) when is_list(N) -> + case string:tokens(N, [$\\]) of + [_PkgName, _ItemID] -> + N; + _ -> + error({invalid_PkgdName, N}) + end. +cre_PkgdName(root, root) -> + "*/*"; +cre_PkgdName(PackageName, root) + when is_list(PackageName) and (length(PackageName) =< 64) -> + PackageName ++ "/*"; +cre_PkgdName(PackageName, ItemID) + when ((is_list(PackageName) and (length(PackageName) =< 64)) and + (is_list(ItemID) and (length(ItemID) =< 64))) -> + PackageName ++ "/" ++ ItemID; +cre_PkgdName(PackageName, ItemID) -> + error({invalid_PkgdName, {PackageName, ItemID}}). + +cre_Relation(greaterThan = R) -> + R; +cre_Relation(smallerThan = R) -> + R; +cre_Relation(unequalTo = R) -> + R. + +cre_LocalRemoteDescriptor([H|_] = PGs) when is_list(H) -> + #'LocalRemoteDescriptor'{propGrps = PGs}. + +cre_PropertyGroup([H|_] = PG) when is_record(H, 'PropertyParm') -> + PG. + +cre_TerminationStateDescriptor([H|_] = PPs) when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs}. + +cre_TerminationStateDescriptor([H|_] = PPs, off = EBC) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + eventBufferControl = EBC}; +cre_TerminationStateDescriptor([H|_] = PPs, lockStep = EBC) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + eventBufferControl = EBC}; +cre_TerminationStateDescriptor([H|_] = PPs, test = SS) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + serviceState = SS}; +cre_TerminationStateDescriptor([H|_] = PPs, outOfSvc = SS) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + serviceState = SS}; +cre_TerminationStateDescriptor([H|_] = PPs, inSvc = SS) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + serviceState = SS}. + +cre_TerminationStateDescriptor([H|_] = PPs, EMC, SS) + when is_record(H, 'PropertyParm') andalso + ((EMC == off) or (EMC == lockStep)) and + ((SS == test) or (SS == outOfSvc) or (SS == inSvc)) -> + #'TerminationStateDescriptor'{propertyParms = PPs, + eventBufferControl = EMC, + serviceState = SS}. + +cre_EventBufferControl(off = EBC) -> + EBC; +cre_EventBufferControl(lockStep = EBC) -> + EBC. + +cre_ServiceState(test = SS) -> + SS; +cre_ServiceState(outOfSvc = SS) -> + SS; +cre_ServiceState(inSvc = SS) -> + SS. + +cre_MuxDescriptor(MT, [H|_] = TL) + when is_atom(MT) andalso is_record(H, 'TerminationID') -> + #'MuxDescriptor'{muxType = MT, termList = TL}. + +%% cre_MuxDescriptor(MT, [H|_] = TL, NSD) +%% when atom(MT), record(H, 'TerminationID'), record(NSD, 'NonStandardData') -> +%% #'MuxDescriptor'{muxType = MT, termList = TL, nonStandardData = NSD}. + +cre_MuxType(h221 = MT) -> + MT; +cre_MuxType(h223 = MT) -> + MT; +cre_MuxType(h226 = MT) -> + MT; +cre_MuxType(v76 = MT) -> + MT; +cre_MuxType(nx64k = MT) -> + MT. + +cre_StreamID(Val) when 0 =< Val, Val =< 65535 -> + Val; +cre_StreamID(Val) -> + exit({invalid_ContextID, Val}). + +%% RequestID must be present if eventList is non empty +cre_EventsDescriptor() -> + #'EventsDescriptor'{eventList = []}. + +cre_EventsDescriptor(RID, [H|_] = EL) + when is_integer(RID) andalso is_record(H, 'RequestedEvent') -> + #'EventsDescriptor'{requestID = RID, eventList = EL}. + +cre_RequestedEvent(N) -> + #'RequestedEvent'{pkgdName = N}. + +cre_RequestedEvent(N, [H|_] = EPL) + when is_list(N) andalso + is_record(H, 'EventParameter') -> + #'RequestedEvent'{pkgdName = N, + evParList = EPL}; +cre_RequestedEvent(N, EA) + when is_list(N) andalso + is_record(EA, 'RequestedActions')-> + #'RequestedEvent'{pkgdName = N, + eventAction = EA}. + + +cre_RequestedEvent(N, SID, [H|_] = EPL) + when is_list(N) andalso + is_integer(SID) andalso + is_record(H, 'EventParameter') -> + #'RequestedEvent'{pkgdName = N, + streamID = SID, + evParList = EPL}; +cre_RequestedEvent(N, EA, [H|_] = EPL) + when is_list(N) andalso + is_record(EA, 'RequestedActions') andalso + is_record(H, 'EventParameter') -> + #'RequestedEvent'{pkgdName = N, + eventAction = EA, + evParList = EPL}. + +cre_RequestedEvent(N, SID, EA, [H|_] = EPL) + when is_list(N) andalso + is_integer(SID) andalso + is_record(EA, 'RequestedActions') andalso + is_record(H, 'EventParameter') -> + #'RequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}. + +cre_RequestedActions() -> + #'RequestedActions'{}. + +cre_RequestedActions(KA) + when (KA == true) or (KA == true) or (KA == asn1_NOVALUE) -> + #'RequestedActions'{keepActive = KA}; +cre_RequestedActions(SE) + when is_record(SE, 'SecondEventsDescriptor') or (SE == asn1_NOVALUE) -> + #'RequestedActions'{secondEvent = SE}; +cre_RequestedActions(SD) + when is_list(SD) or (SD == asn1_NOVALUE) -> + #'RequestedActions'{signalsDescriptor = SD}; +cre_RequestedActions({Tag, _} = EDM) + when is_atom(Tag) or (EDM == asn1_NOVALUE) -> + #'RequestedActions'{eventDM = EDM}. + +cre_RequestedActions(KA, {Tag, _} = EDM, SE, SD) + when ((KA == true) or (KA == true) or (KA == asn1_NOVALUE)) and + (is_atom(Tag) or (EDM == asn1_NOVALUE)) and + (is_record(SE, 'SecondEventsDescriptor') or (SE == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) -> + #'RequestedActions'{keepActive = KA, + eventDM = EDM, + secondEvent = SE, + signalsDescriptor = SD}. + +cre_EventDM(N) when is_list(N) -> + {digitMapName, N}; +cre_EventDM(V) when is_record(V, 'DigitMapValue') -> + {digitMapValue, V}. + +cre_SecondEventsDescriptor([H|_] = EL) + when is_record(H, 'SecondRequestedEvent') -> + #'SecondEventsDescriptor'{eventList = EL}. + +cre_SecondEventsDescriptor(RID, [H|_] = EL) + when is_integer(RID) andalso is_record(H, 'SecondRequestedEvent') -> + #'SecondEventsDescriptor'{requestID = RID, eventList = EL}. + +cre_SecondRequestedEvent(N, [H|_] = EPL) + when is_list(N) andalso + is_record(H, 'EventParameter') -> + #'SecondRequestedEvent'{pkgdName = N, + evParList = EPL}. + +cre_SecondRequestedEvent(N, SID, [H|_] = EPL) + when is_list(N) andalso + is_integer(SID) andalso + is_record(H, 'EventParameter') -> + #'SecondRequestedEvent'{pkgdName = N, + streamID = SID, + evParList = EPL}; +cre_SecondRequestedEvent(N, EA, [H|_] = EPL) + when is_list(N) andalso + is_record(EA, 'SecondRequestedActions') andalso + is_record(H, 'EventParameter') -> + #'SecondRequestedEvent'{pkgdName = N, + eventAction = EA, + evParList = EPL}. + +cre_SecondRequestedEvent(N, SID, EA, [H|_] = EPL) + when is_list(N) andalso + is_integer(SID) andalso + is_record(EA, 'SecondRequestedActions') andalso + is_record(H, 'EventParameter') -> + #'SecondRequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}. + +cre_SecondRequestedActions() -> + #'SecondRequestedActions'{}. + +cre_SecondRequestedActions(KA) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) -> + #'SecondRequestedActions'{keepActive = KA}; +cre_SecondRequestedActions(SD) when is_list(SD) -> + #'SecondRequestedActions'{signalsDescriptor = SD}; +cre_SecondRequestedActions({Tag, _} = EDM) when is_atom(Tag) -> + #'SecondRequestedActions'{eventDM = EDM}. + +cre_SecondRequestedActions(KA, SD) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SD) -> + #'SecondRequestedActions'{keepActive = KA, signalsDescriptor = SD}; +cre_SecondRequestedActions(KA, {Tag, _} = EDM) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_atom(Tag) -> + #'SecondRequestedActions'{keepActive = KA, eventDM = EDM}. + +cre_SecondRequestedActions(KA, {Tag, _} = EDM, SD) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_atom(Tag), + is_list(SD) -> + #'SecondRequestedActions'{keepActive = KA, + eventDM = EDM, + signalsDescriptor = SD}. + +cre_EventBufferDescriptor([H|_] = D) when is_record(H, 'EventSpec') -> + D. + +cre_EventSpec(N, [H|_] = EPL) when is_list(N) andalso is_record(H, 'EventParameter') -> + #'EventSpec'{eventName = N, eventParList = EPL}. + +cre_EventSpec(N, SID, [H|_] = EPL) + when is_list(N) andalso is_integer(SID) andalso is_record(H, 'EventParameter') -> + #'EventSpec'{eventName = N, streamID = SID, eventParList = EPL}. + +cre_SignalsDescriptor(D) when is_list(D) -> + D. + +cre_SignalRequest(S) when is_record(S, 'Signal') -> + {signal, S}; +cre_SignalRequest(S) when is_record(S, 'SeqSigList') -> + {seqSigList, S}. + +cre_SeqSigList(ID, [H|_] = SL) + when is_integer(ID) andalso (0 =< ID) andalso (ID =< 65535) andalso is_record(H, 'Signal') -> + #'SeqSigList'{id = ID, signalList = SL}. + +cre_Signal(N) when is_list(N) -> + #'Signal'{signalName = N}. + +cre_Signal(N, [H|_] = SPL) when is_list(N) andalso is_record(H, 'SigParameter') -> + #'Signal'{signalName = N, + sigParList = SPL}. + +cre_Signal(N, SID, ST, Dur, NC, KA, [H|_] = SPL) + when is_list(N) and + (is_integer(SID) or (SID == asn1_NOVALUE)) and + ((ST == brief) or (ST == onOff) or (ST == timeOut) or + (ST == asn1_NOVALUE)) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 65535)) or + (Dur == asm1_NOVALUE)) and + is_list(NC) and + ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_record(H, 'SigParameter') -> + #'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL}. + +cre_SignalType(brief = ST) -> + ST; +cre_SignalType(onOff = ST) -> + ST; +cre_SignalType(timeOut = ST) -> + ST. + +cre_SignalName(N) -> + cre_PkgdName(N). + +cre_NotifyCompletion(L) when is_list(L) -> + Vals = [onTimeOut, onInterruptByEvent, + onInterruptByNewSignalDescr, otherReason], + F = fun(E) -> case lists:member(E, Vals) of + true -> + ok; + false -> + exit({invalid_NotifyCompletion, E}) + end + end, + lists:foreach(F, L), + L. + +cre_SigParameter(N, V) when is_list(N) andalso is_list(V) -> + #'SigParameter'{sigParameterName = N, value = V}. + +cre_SigParameter(N, V, relation = Tag, R) + when is_list(N) andalso is_list(V) andalso is_atom(R) -> + EI = {Tag, R}, + #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}; +cre_SigParameter(N, V, range = Tag, B) + when is_list(N) andalso is_list(V) andalso is_atom(B) -> + EI = {Tag, B}, + #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}; +cre_SigParameter(N, V, sublist = Tag, B) + when is_list(N) andalso is_list(V) andalso is_atom(B) -> + EI = {Tag, B}, + #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}. + +cre_RequestID(Val) when 0 =< Val, Val =< 4294967295 -> + Val; +cre_RequestID(Val) -> + exit({invalid_RequestID, Val}). + +cre_ModemDescriptor(MTL, MPL) when is_list(MTL) andalso is_list(MPL) -> + #'ModemDescriptor'{mtl = MTL, mpl = MPL}. + +%% cre_ModemDescriptor(MTL, MPL, NSD) +%% when list(MTL), list(MPL), record(NSD, 'NonStandardData') -> +%% #'ModemDescriptor'{mtl = MTL, mpl = MPL}. + +cre_ModemType(v18 = MT) -> + MT; +cre_ModemType(v22 = MT) -> + MT; +cre_ModemType(v22bis = MT) -> + MT; +cre_ModemType(v32 = MT) -> + MT; +cre_ModemType(v32bis = MT) -> + MT; +cre_ModemType(v34 = MT) -> + MT; +cre_ModemType(v90 = MT) -> + MT; +cre_ModemType(v91 = MT) -> + MT; +cre_ModemType(synchISDN = MT) -> + MT. + +cre_DigitMapDescriptor() -> + #'DigitMapDescriptor'{}. + +cre_DigitMapDescriptor(N) when is_list(N) -> + #'DigitMapDescriptor'{digitMapName = N}; +cre_DigitMapDescriptor(V) when is_record(V, 'DigitMapValue') -> + #'DigitMapDescriptor'{digitMapValue = V}. + +cre_DigitMapDescriptor(N, V) when is_list(N) andalso is_record(V, 'DigitMapValue') -> + #'DigitMapDescriptor'{digitMapName = N, digitMapValue = V}. + +cre_DigitMapName(N) -> + cre_Name(N). + +cre_DigitMapValue(DMB) when is_list(DMB) -> + #'DigitMapValue'{digitMapBody = DMB}. + +cre_DigitMapValue(Start, Short, Long, DMB) -> + cre_DigitMapValue(Start, Short, Long, DMB, asn1_NOVALUE). + +cre_DigitMapValue(Start, Short, Long, DMB, Dur) + when ((is_integer(Start) and (0 =< Start) and (Start =< 99)) or + (Start == asn1_NOVALUE)) and + ((is_integer(Short) and (0 =< Short) and (Short =< 99)) or + (Short == asn1_NOVALUE)) and + ((is_integer(Long) and (0 =< Long) and (Long =< 99)) or + (Long == asn1_NOVALUE)) and + is_list(DMB) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 99)) or + (Dur == asn1_NOVALUE)) -> + #'DigitMapValue'{startTimer = Start, + shortTimer = Short, + longTimer = Long, + digitMapBody = DMB, + durationTimer = Dur}. + +cre_ServiceChangeParm(M, R) when is_atom(M) andalso is_list(R) -> + #'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeReason = R}. + +cre_ServiceChangeParm(M, Addr, Prof, Reason) -> + cre_ServiceChangeParm(M, Addr, asn1_NOVALUE, Prof, Reason, asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE). + +%% Addr = asn1_NOVALUE | {AddrTag, AddrVal} +cre_ServiceChangeParm(M, Addr, Ver, Prof, R, D, Mid, TS, I) + when is_atom(M) and + ((is_integer(Ver) and (0 =< Ver) and (Ver =< 99)) or + (Ver == asn1_NOVALUE)) and + (is_record(Prof, 'ServiceChangeProfile') or (Prof == asn1_NOVALUE)) and + is_list(R) and + ((is_integer(D) and (0 =< D) and (D =< 4294967295)) or + (D == asn1_NOVALUE)) and + (is_record(TS, 'TimeNotation') or (TS == asn1_NOVALUE)) and + (is_record(I, 'AuditDescriptor') or (I == asn1_NOVALUE)) -> + F = fun(A) -> + (A == asn1_NOVALUE) orelse + (is_tuple(A) + andalso is_atom(element(1, A))) + end, + case (F(Addr) andalso F(Mid)) of + true -> + #'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeAddress = Addr, + serviceChangeVersion = Ver, + serviceChangeProfile = Prof, + serviceChangeReason = R, + serviceChangeDelay = D, + serviceChangeMgcId = Mid, + timeStamp = TS, + serviceChangeInfo = I}; + _ -> + exit({invalid_ServiceChangeParm_args, {Addr, Mid}}) + end. + +cre_ServiceChangeAddress(portNumber = Tag, P) + when is_integer(P) andalso (0 =< P) andalso (P =< 65535) -> + {Tag, P}; +cre_ServiceChangeAddress(ip4Address = Tag, A) when is_record(A, 'IP4Address') -> + {Tag, A}; +cre_ServiceChangeAddress(ip6Address = Tag, A) when is_record(A, 'IP6Address') -> + {Tag, A}; +cre_ServiceChangeAddress(domainName = Tag, N) when is_record(N, 'DomainName') -> + {Tag, N}; +cre_ServiceChangeAddress(deviceName = Tag, N) when is_list(N) -> + {Tag, N}; +cre_ServiceChangeAddress(mtpAddress = Tag, A) when is_list(A) -> + {Tag, A}. + +cre_ServiceChangeResParm() -> + #'ServiceChangeResParm'{}. +cre_ServiceChangeResParm(Addr, Prof) -> + cre_ServiceChangeResParm(asn1_NOVALUE, Addr, asn1_NOVALUE, + Prof, asn1_NOVALUE). +cre_ServiceChangeResParm(Mid, Addr, Ver, Prof, TS) + when ((is_integer(Ver) and (0 =< Ver) and (Ver =< 99)) or + (Ver == asn1_NOVALUE)) and + (is_record(Prof, 'ServiceChangeProfile') or (Prof == asn1_NOVALUE)) and + (is_record(TS, 'TimeNotation') or (TS == asn1_NOVALUE)) -> + F = fun(A) -> + (A == asn1_NOVALUE) orelse + (is_tuple(A) + andalso is_atom(element(1, A))) + end, + case (F(Addr) andalso F(Mid)) of + true -> + #'ServiceChangeResParm'{serviceChangeMgcId = Mid, + serviceChangeAddress = Addr, + serviceChangeVersion = Ver, + serviceChangeProfile = Prof, + timeStamp = TS}; + _ -> + exit({invalid_ServiceChangeResParm_args, {Addr, Mid}}) + end. + +cre_ServiceChangeMethod(failover = M) -> + M; +cre_ServiceChangeMethod(forced = M) -> + M; +cre_ServiceChangeMethod(graceful = M) -> + M; +cre_ServiceChangeMethod(restart = M) -> + M; +cre_ServiceChangeMethod(disconnected = M) -> + M; +cre_ServiceChangeMethod(handOff = M) -> + M. + +%% The version field is added to make it look more like ABNF +cre_ServiceChangeProfile(N) -> + cre_ServiceChangeProfile(N, 1). + +cre_ServiceChangeProfile(N, V) + when is_list(N) andalso is_integer(V) andalso (0 =< V) andalso (V =< 99) -> + #'ServiceChangeProfile'{profileName = N, version = V}. + +cre_PackagesDescriptor([H|_] = D) when is_record(H, 'PackagesItem') -> + D. + +cre_PackagesItem(N, Ver) + when is_list(N) andalso + is_integer(Ver) andalso + (0 =< Ver) andalso (Ver =< 99) -> + #'PackagesItem'{packageName = N, + packageVersion = Ver}. + +cre_StatisticsDescriptor([H|_] = D) when is_record(H, 'StatisticsParameter') -> + D. + +cre_StatisticsParameter(N) when is_list(N) -> + #'StatisticsParameter'{statName = N}. + +cre_StatisticsParameter(N, V) when is_list(N) andalso is_list(V) -> + #'StatisticsParameter'{statName = N, statValue = V}. + +%% cre_NonStandardData({Tag, _} = Id, Data) when atom(Tag), list(Data) -> +%% #'NonStandardData'{nonStandardIdentifier = Id, data = Data}. + +%% cre_NonStandardIdentifier(H221) when record(H221, 'H221NonStandard') -> +%% {h221NonStandard, H221}; +%% cre_NonStandardIdentifier(Obj) when tuple(Obj) -> +%% {object, Obj}; +%% cre_NonStandardIdentifier(Exp) when list(Exp), length(Exp) == 8 -> +%% {experimental, Exp}. + +%% cre_H221NonStandard(CC1, CC2, Ext, MC) +%% when (is_integer(CC1) and (0 =< CC1) and (CC1 =< 255)) and +%% (is_integer(CC2) and (0 =< CC2) and (CC2 =< 255)) and +%% (is_integer(Ext) and (0 =< Ext) and (Ext =< 255)) and +%% (is_integer(MC) and (0 =< MC) and (MC =< 255)) -> +%% #'H221NonStandard'{t35CountryCode1 = CC1, +%% t35CountryCode2 = CC2, +%% t35Extension = Ext, +%% manufacturerCode = MC}. + +cre_TimeNotation(D, T) + when is_list(D) andalso (length(D) =:= 8) andalso is_list(T) andalso (length(T) =:= 8) -> + #'TimeNotation'{date = D, time = T}. + +cre_Value([H|_] = V) when is_list(H) -> + V. + +cre_BOOLEAN(true = B) -> + B; +cre_BOOLEAN(false = B) -> + B. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% -- MegacoMessage -- + +is_MegacoMessage(#'MegacoMessage'{authHeader = Auth, + mess = Mess}) -> + is_opt_AuthenticationHeader(Auth) andalso is_Message(Mess); +is_MegacoMessage(_) -> + false. + + +chk_MegacoMessage(M, M) -> + chk_type(fun is_MegacoMessage/1, 'MegacoMessage', M); +chk_MegacoMessage(#'MegacoMessage'{authHeader = Auth1, + mess = Mess1}, + #'MegacoMessage'{authHeader = Auth2, + mess = Mess2}) -> + chk_opt_AuthenticationHeader(Auth1,Auth2), + chk_Message(Mess1,Mess2), + ok; +chk_MegacoMessage(M1, M2) -> + wrong_type('MegacoMessage', M1, M2). + + +%% -- AuthenticationHeader -- + +is_opt_AuthenticationHeader(AH) -> + is_OPTIONAL(fun is_AuthenticationHeader/1, AH). + +is_AuthenticationHeader(#'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AD}) -> + is_SecurityParmIndex(SPI) andalso + is_SequenceNum(SN) andalso + is_AuthData(AD); +is_AuthenticationHeader(_) -> + false. + +%% This stuff is not really used, so make it simple... +chk_opt_AuthenticationHeader(A1, A2) -> + chk_OPTIONAL('AuthenticationHeader', A1, A2, + fun is_AuthenticationHeader/1, + fun chk_AuthenticationHeader/2). + +chk_AuthenticationHeader(A, A) -> + chk_type(fun is_AuthenticationHeader/1, 'AuthenticationHeader', A); +chk_AuthenticationHeader(A1, A2) -> + case (is_AuthenticationHeader(A1) andalso is_AuthenticationHeader(A2)) of + true -> + not_equal('AuthenticationHeader', A1, A2); + false -> + wrong_type('AuthenticationHeader', A1, A2) + end. + + +%% -- SecurityParmIndex -- + +is_SecurityParmIndex(V) -> is_OCTET_STRING(V, {exact, 4}). + + +%% -- SequenceNum -- + +is_SequenceNum(V) -> is_OCTET_STRING(V, {exact, 4}). + + +%% -- AuthData -- + +is_AuthData(V) -> is_OCTET_STRING(V, {range, 12, 32}). + + +%% -- Message -- + +is_Message(#'Message'{version = V, + mId = MID, + messageBody = Body}) -> + is_INTEGER(V, {range, 0, 99}) andalso + is_MId(MID) andalso + is_Message_messageBody(Body); +is_Message(_) -> + false. + +chk_Message(M,M) when is_record(M,'Message') -> + ok; +chk_Message(#'Message'{version = V1, + mId = MID1, + messageBody = Body1}, + #'Message'{version = V2, + mId = MID2, + messageBody = Body2}) -> + validate(fun() -> chk_INTEGER(V1, V2, {range, 0, 99}) end, 'Message'), + validate(fun() -> chk_MId(MID1, MID2) end, 'Message'), + chk_Message_messageBody(Body1, Body2), + ok; +chk_Message(M1, M2) -> + wrong_type('Message', M1, M2). + + +is_Message_messageBody({Tag, Val}) -> + is_Message_messageBody_tag(Tag) andalso + is_Message_messageBody_val(Tag, Val); +is_Message_messageBody(_) -> + false. + +is_Message_messageBody_tag(Tag) -> + Tags = [messageError, transactions], + lists:member(Tag, Tags). + +is_Message_messageBody_val(messageError, Val) -> + is_ErrorDescriptor(Val); +is_Message_messageBody_val(transactions, Val) -> + is_Message_messageBody_transactions(Val). + +is_Message_messageBody_transactions([]) -> + true; +is_Message_messageBody_transactions([H|T]) -> + is_Transaction(H) andalso is_Message_messageBody_transactions(T); +is_Message_messageBody_transactions(_) -> + false. + +chk_Message_messageBody(B, B) -> + chk_type(fun is_Message_messageBody/1, 'Message_messageBody', B); +chk_Message_messageBody({Tag, Val1} = B1, {Tag, Val2} = B2) -> + case (is_Message_messageBody_tag(Tag) andalso + is_Message_messageBody_val(Tag, Val1) andalso + is_Message_messageBody_val(Tag, Val2)) of + true -> + chk_Message_messageBody_val(Tag, Val1, Val2); + false -> + wrong_type('Message_messageBody', B1, B2) + end; +chk_Message_messageBody({Tag1, Val1} = B1, {Tag2, Val2} = B2) -> + case ((is_Message_messageBody_tag(Tag1) andalso + is_Message_messageBody_val(Tag1, Val1)) andalso + (is_Message_messageBody_tag(Tag2) andalso + is_Message_messageBody_val(Tag2, Val2))) of + true -> + not_equal('Message_messageBody', B1, B2); + false -> + wrong_type('Message_messageBody', B1, B2) + end; +chk_Message_messageBody(B1, B2) -> + wrong_type('Message_messageBody', B1, B2). + +chk_Message_messageBody_val(messageError, Val1, Val2) -> + validate(fun() -> chk_ErrorDescriptor(Val1, Val2) end, + 'Message_messageBody'); +chk_Message_messageBody_val(transactions, Val1, Val2) -> + chk_Message_messageBody_transactions(Val1, Val2). + +chk_Message_messageBody_transactions([], []) -> + ok; +chk_Message_messageBody_transactions([] = T1, T2) -> + not_equal('Message_messageBody_transactions', T1, T2); +chk_Message_messageBody_transactions(T1, [] = T2) -> + not_equal('Message_messageBody_transactions', T1, T2); +chk_Message_messageBody_transactions([H|T1], [H|T2]) -> + case is_Transaction(H) of + true -> + chk_Message_messageBody_transactions(T1, T2); + false -> + wrong_type('Message_messageBody_transactions_val', H) + end; +chk_Message_messageBody_transactions([H1|T1], [H2|T2]) -> + validate(fun() -> chk_Transaction(H1, H2) end, + 'Message_messageBody_transactions_val'), + chk_Message_messageBody_transactions(T1, T2); +chk_Message_messageBody_transactions(T1, T2) -> + wrong_type('Message_messageBody_transactions', T1, T2). + + +%% -- MId -- + +is_opt_MId(M) -> + is_OPTIONAL(fun is_MId/1, M). + +is_MId({Tag, Val}) -> + is_MId_tag(Tag) andalso is_MId_val(Tag, Val); +is_MId(_) -> + false. + +is_MId_tag(Tag) -> + Tags = [ip4Address, ip6Address, domainName, deviceName, mtpAddress], + lists:member(Tag, Tags). + +is_MId_val(ip4Address, Val) -> is_IP4Address(Val); +is_MId_val(ip6Address, Val) -> is_IP6Address(Val); +is_MId_val(domainName, Val) -> is_DomainName(Val); +is_MId_val(deviceName, Val) -> is_PathName(Val); +is_MId_val(mtpAddress, Val) -> is_OCTET_STRING(Val, {range, 2, 4}). + +chk_opt_MId(M1, M2) -> + chk_OPTIONAL('MId', M1, M2, fun is_MId/1, fun chk_MId/2). + +chk_MId(M, M) -> + chk_type(fun is_MId/1, 'MId', M); +chk_MId({Tag, Val1} = M1, {Tag, Val2} = M2) -> + case (is_MId_tag(Tag) andalso + is_MId_val(Tag, Val1) andalso + is_MId_val(Tag, Val2)) of + true -> + chk_MId_val(Tag, Val1, Val2); + false -> + wrong_type('MId', M1, M2) + end; +chk_MId({Tag1, Val1} = M1, {Tag2, Val2} = M2) -> + case ((is_MId_tag(Tag1) andalso + is_MId_val(Tag1, Val1)) andalso + (is_MId_tag(Tag2) andalso + is_MId_val(Tag2, Val2))) of + true -> + not_equal('MId', M1, M2); + false -> + wrong_type('MId', M1, M2) + end; +chk_MId(M1, M2) -> + wrong_type('MId', M1, M2). + +chk_MId_val(ip4Address, M1, M2) -> chk_IP4Address(M1, M2); +chk_MId_val(ip6Address, M1, M2) -> chk_IP6Address(M1, M2); +chk_MId_val(domainName, M1, M2) -> chk_DomainName(M1, M2); +chk_MId_val(deviceName, M1, M2) -> chk_PathName(M1, M2); +chk_MId_val(mtpAddress, M1, M2) -> chk_OCTET_STRING(M1, M2, {range, 2, 4}). + + +%% -- DomainName -- + +is_DomainName(#'DomainName'{name = N, portNumber = PN}) -> + is_IA5String(N) andalso is_opt_INTEGER(PN, {range, 0, 65535}); +is_DomainName(_) -> + false. + +chk_DomainName(N, N) -> + ok; +chk_DomainName(N1, N2) -> + not_equal('DomainName', N1, N2). + + +%% -- IP4Address -- + +is_IP4Address(#'IP4Address'{address = A, portNumber = PN}) -> + is_OCTET_STRING(A, {exact, 4}) andalso + is_opt_INTEGER(PN, {range, 0, 65535}); +is_IP4Address(_) -> + false. + +chk_IP4Address(A, A) -> + ok; +chk_IP4Address(A1, A2) -> + not_equal('IP4Address', A1, A2). + + +%% -- IP6Address -- + +is_IP6Address(#'IP6Address'{address = A, portNumber = PN}) -> + is_OCTET_STRING(A, {exact, 16}) andalso + is_opt_INTEGER(PN, {range, 0, 65535}); +is_IP6Address(_) -> + false. + +chk_IP6Address(A, A) -> + ok; +chk_IP6Address(A1, A2) -> + not_equal('IP6Address', A1, A2). + + +%% -- PathName -- + +is_PathName(N) -> is_IA5String(N, {range, 1, 64}). + +chk_PathName(N, N) -> + ok; +chk_PathName(N1, N2) -> + not_equal('PathName', N1, N2). + + +%% -- Transaction -- + +is_Transaction({Tag, Val}) -> + is_Transaction_tag(Tag) andalso is_Transaction_val(Tag, Val); +is_Transaction(_) -> + false. + +is_Transaction_tag(Tag) -> + Tags = [transactionRequest, + transactionPending, + transactionReply, + transactionResponseAck], + lists:member(Tag, Tags). + +is_Transaction_val(transactionRequest, V) -> is_TransactionRequest(V); +is_Transaction_val(transactionPending, V) -> is_TransactionPending(V); +is_Transaction_val(transactionReply, V) -> is_TransactionReply(V); +is_Transaction_val(transactionResponseAck, V) -> is_TransactionResponseAck(V). + + +chk_Transaction({Tag, Val} = Trans, {Tag, Val}) -> + case (is_Transaction_tag(Tag) andalso is_Transaction_val(Tag, Val)) of + true -> + ok; + false -> + wrong_type('Transaction', Trans, Trans) + end; +chk_Transaction({Tag, Val1} = Trans1, {Tag, Val2} = Trans2) -> + case (is_Transaction_tag(Tag) and + is_Transaction_val(Tag, Val1) and + is_Transaction_val(Tag, Val2)) of + true -> + chk_Transaction_val(Tag, Val1, Val2); + false -> + wrong_type('Transaction', Trans1, Trans2) + end; +chk_Transaction({Tag1, Val1} = Trans1, {Tag2, Val2} = Trans2) -> + case ((is_Transaction_tag(Tag1) andalso + is_Transaction_val(Tag1, Val1)) andalso + (is_Transaction_tag(Tag2) andalso + is_Transaction_val(Tag2, Val2))) of + true -> + not_equal('Transaction', Trans1, Trans2); + false -> + wrong_type('Transaction', Trans1, Trans2) + end; +chk_Transaction(Trans1, Trans2) -> + wrong_type('Transaction', Trans1, Trans2). + +chk_Transaction_val(transactionRequest, T1, T2) -> + chk_TransactionRequest(T1, T2); +chk_Transaction_val(transactionPending, T1, T2) -> + chk_TransactionPending(T1, T2); +chk_Transaction_val(transactionReply, T1, T2) -> + chk_TransactionReply(T1,T2); +chk_Transaction_val(transactionResponseAck, T1, T2) -> + chk_TransactionResponseAck(T1, T2). + + +%% -- TransactionId -- + +is_opt_TransactionId(TID) -> + is_OPTIONAL(fun is_TransactionId/1, TID). + +is_TransactionId(TID) -> is_INTEGER(TID, {range, 0, 4294967295}). + +chk_opt_TransactionId(TID1, TID2) -> + chk_OPTIONAL('TransactionId', TID1, TID2, + fun is_TransactionId/1, fun chk_TransactionId/2). + +chk_TransactionId(TID, TID) -> + chk_type(fun is_TransactionId/1, 'TransactionId', TID); +chk_TransactionId(TID1, TID2) -> + case (is_TransactionId(TID1) andalso is_TransactionId(TID2)) of + true -> + not_equal('TransactionId', TID1, TID2); + false -> + wrong_type('TransactionId', TID1, TID2) + end. + + +%% -- TransactionRequest -- + +is_TransactionRequest(#'TransactionRequest'{transactionId = TID, + actions = Acts}) -> + is_TransactionId(TID) andalso is_TransactionRequest_actions(Acts); +is_TransactionRequest(_) -> + false. + +chk_TransactionRequest(T, T) -> + chk_type(fun is_TransactionRequest/1, 'TransactionRequest', T); +chk_TransactionRequest(#'TransactionRequest'{transactionId = TID1, + actions = Acts1}, + #'TransactionRequest'{transactionId = TID2, + actions = Acts2}) -> + validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionRequest'), + chk_TransactionRequest_actions(Acts1, Acts2), + ok; +chk_TransactionRequest(T1, T2) -> + wrong_type('TransactionRequest', T1, T2). + +is_TransactionRequest_actions([]) -> + true; +is_TransactionRequest_actions([H|T]) -> + is_ActionRequest(H) andalso is_TransactionRequest_actions(T); +is_TransactionRequest_actions(_) -> + false. + +chk_TransactionRequest_actions([], []) -> + ok; +chk_TransactionRequest_actions([] = Acts1, Acts2) -> + not_equal('TransactionRequest_actions', Acts1, Acts2); +chk_TransactionRequest_actions(Acts1, [] = Acts2) -> + not_equal('TransactionRequest_actions', Acts1, Acts2); +chk_TransactionRequest_actions([H|T1], [H|T2]) -> + case is_ActionRequest(H) of + true -> + chk_TransactionRequest_actions(T1, T2); + false -> + wrong_type('TransactionRequest_actions_val', H) + end; +chk_TransactionRequest_actions([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ActionRequest(H1, H2) end, + 'TransactionRequest_actions_val'), + chk_TransactionRequest_actions(T1, T2); +chk_TransactionRequest_actions(Acts1, Acts2) -> + wrong_type('TransactionRequest_actions', Acts1, Acts2). + + +%% -- TransactionPending -- + +is_TransactionPending(#'TransactionPending'{transactionId = TID}) -> + is_TransactionId(TID); +is_TransactionPending(_) -> + false. + +chk_TransactionPending(T, T) -> + chk_type(fun is_TransactionPending/1, 'TransactionPending', T); +chk_TransactionPending(#'TransactionPending'{transactionId = TID1}, + #'TransactionPending'{transactionId = TID2}) -> + validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionPending'), + ok; +chk_TransactionPending(T1, T2) -> + wrong_type('TransactionPending', T1, T2). + + +%% -- TransactionReply -- + +is_TransactionReply(#'TransactionReply'{transactionId = TID, + immAckRequired = IAR, + transactionResult = TR}) -> + is_TransactionId(TID) andalso + is_opt_NULL(IAR) andalso + is_TransactionReply_transactionResult(TR); +is_TransactionReply(_) -> + false. + +chk_TransactionReply(T, T) -> + chk_type(fun is_TransactionReply/1, 'TransactionReply', T); +chk_TransactionReply(#'TransactionReply'{transactionId = TID1, + immAckRequired = IAR1, + transactionResult = TR1}, + #'TransactionReply'{transactionId = TID2, + immAckRequired = IAR2, + transactionResult = TR2}) -> + validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionReply'), + validate(fun() -> chk_opt_NULL(IAR1, IAR2) end, 'TransactionReply'), + chk_TransactionReply_transactionResult(TR1, TR2), + ok; +chk_TransactionReply(T1, T2) -> + wrong_type('TransactionReply', T1, T2). + +is_TransactionReply_transactionResult({Tag, Val}) -> + is_TransactionReply_transactionResult_tag(Tag) andalso + is_TransactionReply_transactionResult_val(Tag, Val); +is_TransactionReply_transactionResult(_) -> + false. + +is_TransactionReply_transactionResult_tag(T) -> + lists:member(T, [transactionError, actionReplies]). + +is_TransactionReply_transactionResult_val(transactionError, V) -> + is_ErrorDescriptor(V); +is_TransactionReply_transactionResult_val(actionReplies, V) -> + is_TransactionReply_actionReplies(V). + +chk_TransactionReply_transactionResult(Res, Res) -> + chk_type(fun is_TransactionReply_transactionResult/1, + 'TransactionReply_transactionResult', Res); +chk_TransactionReply_transactionResult({Tag, Val1} = Res1, + {Tag, Val2} = Res2) -> + case (is_TransactionReply_transactionResult_tag(Tag) and + is_TransactionReply_transactionResult_val(Tag, Val1) and + is_TransactionReply_transactionResult_val(Tag, Val2)) of + true -> + chk_TransactionReply_transactionResult_val(Tag, Val1, Val2); + false -> + wrong_type('TransactionReply_transactionResult', Res1, Res2) + end; +chk_TransactionReply_transactionResult({Tag1, Val1} = Res1, + {Tag2, Val2} = Res2) -> + case ((is_TransactionReply_transactionResult_tag(Tag1) and + is_TransactionReply_transactionResult_val(Tag1, Val1)) and + (is_TransactionReply_transactionResult_tag(Tag2) and + is_TransactionReply_transactionResult_val(Tag2, Val2))) of + true -> + not_equal('TransactionReply_transactionResult', Res1, Res2); + false -> + wrong_type('TransactionReply_transactionResult', Res1, Res2) + end; +chk_TransactionReply_transactionResult(Res1, Res2) -> + wrong_type('TransactionReply_transactionResult', Res1, Res2). + +chk_TransactionReply_transactionResult_val(transactionError, E1, E2) -> + validate(fun() -> chk_ErrorDescriptor(E1, E2) end, + 'TransactionReply_transactionResult'); +chk_TransactionReply_transactionResult_val(actionReplies, R1, R2) -> + validate(fun() -> chk_TransactionReply_actionReplies(R1, R2) end, + 'TransactionReply_transactionResult'). + +is_TransactionReply_actionReplies([]) -> + true; +is_TransactionReply_actionReplies([H|T]) -> + is_ActionReply(H) andalso is_TransactionReply_actionReplies(T); +is_TransactionReply_actionReplies(_) -> + false. + +chk_TransactionReply_actionReplies([], []) -> + ok; +chk_TransactionReply_actionReplies([] = AR1, AR2) -> + not_equal('TransactionReply_actionReplies', AR1, AR2); +chk_TransactionReply_actionReplies(AR1, [] = AR2) -> + not_equal('TransactionReply_actionReplies', AR1, AR2); +chk_TransactionReply_actionReplies([H|T1], [H|T2]) -> + case is_ActionReply(H) of + true -> + chk_TransactionReply_actionReplies(T1, T2); + false -> + wrong_type('TransactionReply_actionReplies_val', H) + end; +chk_TransactionReply_actionReplies([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ActionReply(H1, H2) end, + 'TransactionReply_actionReplies_val'), + chk_TransactionReply_actionReplies(T1, T2); +chk_TransactionReply_actionReplies(AR1, AR2) -> + wrong_type('TransactionReply_actionReplies', AR1, AR2). + + +%% -- TransactionResponseAck -- + +is_TransactionResponseAck([]) -> + true; +is_TransactionResponseAck([H|T]) -> + is_TransactionAck(H) andalso is_TransactionResponseAck(T); +is_TransactionResponseAck(_) -> + false. + +chk_TransactionResponseAck([], []) -> + ok; +chk_TransactionResponseAck([] = AR1, AR2) -> + not_equal('TransactionResponseAck', AR1, AR2); +chk_TransactionResponseAck(AR1, [] = AR2) -> + not_equal('TransactionResponseAck', AR1, AR2); +chk_TransactionResponseAck([H|T1], [H|T2]) -> + case is_TransactionAck(H) of + true -> + chk_TransactionResponseAck(T1, T2); + false -> + wrong_type('TransactionResponseAck_val', H) + end; +chk_TransactionResponseAck([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TransactionAck(H1, H2) end, + 'TransactionResponseAck'), + chk_TransactionResponseAck(T1, T2); +chk_TransactionResponseAck(AR1, AR2) -> + wrong_type('TransactionResponseAck', AR1, AR2). + + +%% -- TransactionAck -- + +is_TransactionAck(#'TransactionAck'{firstAck = F, + lastAck = L}) -> + is_TransactionId(F) andalso is_opt_TransactionId(L); +is_TransactionAck(_) -> + false. + +chk_TransactionAck(T, T) -> + chk_type(fun is_TransactionAck/1, 'TransactionAck', T); +chk_TransactionAck(#'TransactionAck'{firstAck = F1, + lastAck = L1}, + #'TransactionAck'{firstAck = F2, + lastAck = L2}) -> + validate(fun() -> chk_TransactionId(F1, F2) end, 'TransactionAck'), + validate(fun() -> chk_opt_TransactionId(L1, L2) end, 'TransactionAck'), + ok; +chk_TransactionAck(T1, T2) -> + wrong_type('TransactionAck', T1, T2). + + +%% -- ErrorDescriptor -- + +is_opt_ErrorDescriptor(V) -> + is_OPTIONAL(fun is_ErrorDescriptor/1, V). + +is_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code, + errorText = Text}) -> + is_ErrorCode(Code) andalso is_opt_ErrorText(Text); +is_ErrorDescriptor(_) -> + false. + +chk_opt_ErrorDescriptor(E1, E2) -> + chk_OPTIONAL('ErrorDescriptor', E1, E2, + fun is_ErrorDescriptor/1, fun chk_ErrorDescriptor/2). + +chk_ErrorDescriptor(E, E) -> + chk_type(fun is_ErrorDescriptor/1, 'ErrorDescriptor', E); +chk_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code1, + errorText = Text1}, + #'ErrorDescriptor'{errorCode = Code2, + errorText = Text2}) -> + chk_ErrorCode(Code1, Code2), + chk_opt_ErrorText(Text1, Text2), + ok; +chk_ErrorDescriptor(E1, E2) -> + wrong_type('ErrorDescriptor', E1, E2). + + +%% -- ErrorCode -- + +is_ErrorCode(C) -> is_INTEGER(C, {range, 0, 65535}). + +chk_ErrorCode(C, C) -> + case is_ErrorCode(C) of + true -> + ok; + false -> + wrong_type(errorCode, C, C) + end; +chk_ErrorCode(C1, C2) -> + case (is_ErrorCode(C1) andalso is_ErrorCode(C2)) of + true -> + not_equal(errorCode, C1, C2); + false -> + wrong_type(errorCode, C1, C2) + end. + + +%% -- ErrorText -- + +is_opt_ErrorText(V) -> + is_OPTIONAL(fun is_ErrorText/1, V). + +is_ErrorText(V) -> is_IA5String(V). + +chk_opt_ErrorText(T1, T2) -> + chk_OPTIONAL('ErrorText', T1, T2, fun is_ErrorText/1, fun chk_ErrorText/2). + +chk_ErrorText(T, T) -> + chk_type(fun is_ErrorText/1, 'ErrorText', T); +chk_ErrorText(T1, T2) -> + case (is_ErrorText(T1) andalso is_ErrorText(T2)) of + true -> + case {to_lower(T1), to_lower(T2)} of + {T, T} -> + ok; + _ -> + not_equal('ErrorText', T1, T2) + end; + false -> + wrong_type('ErrorText', T1, T2) + end. + + +%% -- ContextID -- + +is_ContextID(Id) -> is_INTEGER(Id, {range, 0, 4294967295}). + +chk_ContextID(Id, Id) -> + chk_type(fun is_ContextID/1, 'ContextID', Id); +chk_ContextID(Id1, Id2) -> + case (is_ContextID(Id1) andalso is_ContextID(Id2)) of + true -> + not_equal('ContextID', Id1, Id2); + false -> + wrong_type('ContextID', Id1, Id2) + end. + + +%% -- ActionRequest -- + +is_ActionRequest(#'ActionRequest'{contextId = Id, + contextRequest = CtxReq, + contextAttrAuditReq = AuditReq, + commandRequests = CmdReqs}) -> + is_ContextID(Id) andalso + is_opt_ContextRequest(CtxReq) andalso + is_opt_ContextAttrAuditRequest(AuditReq) andalso + is_ActionRequest_commandRequests(CmdReqs); +is_ActionRequest(_) -> + false. + +chk_ActionRequest(A, A) -> + chk_type(fun is_ActionRequest/1, 'ActionRequest', A); +chk_ActionRequest(#'ActionRequest'{contextId = Id1, + contextRequest = Req1, + contextAttrAuditReq = AuditReq1, + commandRequests = CmdReqs1}, + #'ActionRequest'{contextId = Id2, + contextRequest = Req2, + contextAttrAuditReq = AuditReq2, + commandRequests = CmdReqs2}) -> + validate(fun() -> chk_ContextID(Id1, Id2) end, 'ActionRequest'), + validate(fun() -> chk_opt_ContextRequest(Req1, Req2) end, 'ActionRequest'), + validate(fun() -> + chk_opt_ContextAttrAuditRequest(AuditReq1, AuditReq2) + end, + 'ActionRequest'), + chk_ActionRequest_commandRequests(CmdReqs1, CmdReqs2), + ok. + + +is_ActionRequest_commandRequests([]) -> + true; +is_ActionRequest_commandRequests([H|T]) -> + is_CommandRequest(H) andalso is_ActionRequest_commandRequests(T); +is_ActionRequest_commandRequests(_) -> + false. + +chk_ActionRequest_commandRequests([], []) -> + ok; +chk_ActionRequest_commandRequests([] = CmdReqs1, CmdReqs2) -> + not_equal('ActionRequest_commandRequests', CmdReqs1, CmdReqs2); +chk_ActionRequest_commandRequests(CmdReqs1, [] = CmdReqs2) -> + not_equal('ActionRequest_commandRequests', CmdReqs1, CmdReqs2); +chk_ActionRequest_commandRequests([H|T1], [H|T2]) -> + case is_CommandRequest(H) of + true -> + chk_ActionRequest_commandRequests(T1, T2); + false -> + wrong_type('ActionRequest_commandRequest_val', H) + end; +chk_ActionRequest_commandRequests([H1|T1], [H2|T2]) -> + validate(fun() -> chk_CommandRequest(H1, H2) end, + 'ActionRequest_commandRequests_val'), + chk_ActionRequest_commandRequests(T1, T2); +chk_ActionRequest_commandRequests(R1, R2) -> + wrong_type('ActionRequest_commandRequests', R1, R2). + + +%% -- ActionReply -- + +is_ActionReply(#'ActionReply'{contextId = Id, + errorDescriptor = ED, + contextReply = CtxRep, + commandReply = CmdRep}) -> + is_ContextID(Id) andalso + is_opt_ErrorDescriptor(ED) andalso + is_opt_ContextRequest(CtxRep) andalso + is_ActionReply_commandReply(CmdRep); +is_ActionReply(_) -> + false. + +is_ActionReply_commandReply([]) -> + true; +is_ActionReply_commandReply([H|T]) -> + is_CommandReply(H) andalso is_ActionReply_commandReply(T); +is_ActionReply_commandReply(_) -> + false. + +chk_ActionReply(A, A) -> + chk_type(fun is_ActionReply/1, 'ActionReply', A); +chk_ActionReply(#'ActionReply'{contextId = Id1, + errorDescriptor = ED1, + contextReply = CtxRep1, + commandReply = CmdRep1}, + #'ActionReply'{contextId = Id2, + errorDescriptor = ED2, + contextReply = CtxRep2, + commandReply = CmdRep2}) -> + chk_ContextID(Id1, Id2), + chk_opt_ErrorDescriptor(ED1, ED2), + chk_opt_ContextRequest(CtxRep1, CtxRep2), + chk_ActionReply_commandReply(CmdRep1, CmdRep2). + +chk_ActionReply_commandReply([], []) -> + ok; +chk_ActionReply_commandReply([] = Reps1, Reps2) -> + not_equal('ActionReply_commandReply', Reps1, Reps2); +chk_ActionReply_commandReply(Reps1, [] = Reps2) -> + not_equal('ActionReply_commandReply', Reps1, Reps2); +chk_ActionReply_commandReply([H|T1], [H|T2]) -> + case is_CommandReply(H) of + true -> + chk_ActionReply_commandReply(T1, T2); + false -> + wrong_type('ActionReply_commandReply_val', H) + end; +chk_ActionReply_commandReply([H1|T1], [H2|T2]) -> + validate(fun() -> chk_CommandReply(H1, H2) end, + 'ActionReply_commandReply_val'), + chk_ActionReply_commandReply(T1, T2); +chk_ActionReply_commandReply(R1, R2) -> + wrong_type('ActionReply_commandReply', R1, R2). + + +%% -- ContextRequest -- + +is_opt_ContextRequest(asn1_NOVALUE) -> + true; +is_opt_ContextRequest(V) -> + is_ContextRequest(V). + +is_ContextRequest(#'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = TopReq}) -> + is_ContextRequest_priority(Prio) andalso + is_ContextRequest_emergency(Em) andalso + is_ContextRequest_topologyReq(TopReq); +is_ContextRequest(_) -> + false. + +is_ContextRequest_priority(asn1_NOVALUE) -> + true; +is_ContextRequest_priority(V) -> + is_INTEGER(V, {range, 1, 15}). + +is_ContextRequest_emergency(asn1_NOVALUE) -> + true; +is_ContextRequest_emergency(V) -> + is_BOOLEAN(V). + +is_ContextRequest_topologyReq(asn1_NOVALUE) -> + true; +is_ContextRequest_topologyReq([]) -> + true; +is_ContextRequest_topologyReq([H|T]) -> + is_TopologyRequest(H) andalso is_ContextRequest_topologyReq(T); +is_ContextRequest_topologyReq(_) -> + false. + +chk_opt_ContextRequest(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_ContextRequest(R, R) -> + chk_ContextRequest(R, R). + +chk_ContextRequest(R, R) -> + chk_type(fun is_ContextRequest/1, 'ContextRequest', R); +chk_ContextRequest(#'ContextRequest'{priority = Prio1, + emergency = Em1, + topologyReq = TopReq1}, + #'ContextRequest'{priority = Prio2, + emergency = Em2, + topologyReq = TopReq2}) -> + chk_ContextRequest_priority(Prio1, Prio2), + chk_ContextRequest_emergency(Em1, Em2), + chk_ContextRequest_topologyReq(TopReq1, TopReq2), + ok; +chk_ContextRequest(R1, R2) -> + wrong_type('ContextRequest', R1, R2). + + +chk_ContextRequest_priority(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_ContextRequest_priority(P, P) -> + chk_type(fun is_ContextRequest_priority/1, 'ContextRequest_priority', P); +chk_ContextRequest_priority(P1, P2) -> + case (is_ContextRequest_priority(P1) andalso + is_ContextRequest_priority(P2)) of + true -> + not_equal('ContextRequest_priority', P1, P2); + false -> + wrong_type(contextRequest_priority, P1, P2) + end. + + +chk_ContextRequest_emergency(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_emergency(E, E) -> + chk_type(fun is_ContextRequest_emergency/1, 'ContextRequest_emergency', E); +chk_ContextRequest_emergency(E1, E2) -> + case (is_ContextRequest_emergency(E1) andalso + is_ContextRequest_emergency(E2)) of + true -> + not_equal('ContextRequest_emergency', E1, E2); + false -> + wrong_type('ContextRequest_emergency', E1, E2) + end. + +chk_ContextRequest_topologyReq(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_topologyReq([], []) -> + ok; +chk_ContextRequest_topologyReq([] = T1, T2) -> + not_equal('ContextRequest_topologyReq', T1, T2); +chk_ContextRequest_topologyReq(T1, [] = T2) -> + not_equal('ContextRequest_topologyReq', T1, T2); +chk_ContextRequest_topologyReq([H|T1], [H|T2]) -> + case is_TopologyRequest(H) of + true -> + chk_ContextRequest_topologyReq(T1, T2); + false -> + wrong_type('ContextRequest_topologyReq_val', H) + end; +chk_ContextRequest_topologyReq([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TopologyRequest(H1, H2) end, + 'ContextRequest_topologyReq_val'), + chk_ContextRequest_topologyReq(T1, T2); +chk_ContextRequest_topologyReq(T1, T2) -> + wrong_type('ContextRequest_topologyReq', T1, T2). + + +%% -- ContextAttrAuditRequest -- + +is_opt_ContextAttrAuditRequest(asn1_NOVALUE) -> + true; +is_opt_ContextAttrAuditRequest(V) -> + is_ContextAttrAuditRequest(V). + +is_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{topology = T, + emergency = E, + priority = P}) -> + is_opt_NULL(T) andalso is_opt_NULL(E) andalso is_opt_NULL(P); +is_ContextAttrAuditRequest(_) -> + false. + +chk_opt_ContextAttrAuditRequest(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_ContextAttrAuditRequest(R1, R2) -> + chk_ContextAttrAuditRequest(R1, R2). + +chk_ContextAttrAuditRequest(R, R) -> + chk_type(fun is_ContextAttrAuditRequest/1, 'ContextAttrAuditRequest', R); +chk_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{topology = T1, + emergency = E1, + priority = P1}, + #'ContextAttrAuditRequest'{topology = T2, + emergency = E2, + priority = P2}) -> + validate(fun() -> chk_opt_NULL(T1, T2) end, + 'ContextAttrAuditRequest_topology'), + validate(fun() -> chk_opt_NULL(E1, E2) end, + 'ContextAttrAuditRequest_emergency'), + validate(fun() -> chk_opt_NULL(P1, P2) end, + 'ContextAttrAuditRequest_priority'), + ok. + + +%% -- CommandRequest -- + +is_CommandRequest(#'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = WR}) -> + is_Command(Cmd) andalso is_opt_NULL(Opt) andalso is_opt_NULL(WR); +is_CommandRequest(_) -> + false. + +chk_CommandRequest(C, C) -> + chk_type(fun is_CommandRequest/1, 'CommandRequest', C); +chk_CommandRequest(#'CommandRequest'{command = Cmd1, + optional = Opt1, + wildcardReturn = WR1}, + #'CommandRequest'{command = Cmd2, + optional = Opt2, + wildcardReturn = WR2}) -> + validate(fun() -> chk_Command(Cmd1, Cmd2) end, 'CommandRequest'), + validate(fun() -> chk_opt_NULL(Opt1, Opt2) end, 'CommandRequest'), + validate(fun() -> chk_opt_NULL(WR1, WR2) end, 'CommandRequest'), + ok; +chk_CommandRequest(R1, R2) -> + wrong_type('CommandRequest', R1, R2). + + +%% -- Command -- + +is_Command({Tag, Val}) -> + is_Command_tag(Tag) andalso is_Command_val(Tag, Val); +is_Command(_) -> + false. + +is_Command_tag(Tag) -> + Tags = [addReq, moveReq, modReq, subtractReq, auditCapRequest, + auditValueRequest, notifyReq, serviceChangeReq], + lists:member(Tag, Tags). + +is_Command_val(addReq, V) -> is_AmmRequest(V); +is_Command_val(moveReq, V) -> is_AmmRequest(V); +is_Command_val(modReq, V) -> is_AmmRequest(V); +is_Command_val(subtractReq, V) -> is_SubtractRequest(V); +is_Command_val(auditCapRequest, V) -> is_AuditRequest(V); +is_Command_val(auditValueRequest, V) -> is_AuditRequest(V); +is_Command_val(notifyReq, V) -> is_NotifyRequest(V); +is_Command_val(serviceChangeReq, V) -> is_ServiceChangeRequest(V). + +chk_Command(Cmd, Cmd) -> + chk_type(fun is_Command/1, 'Command', Cmd); +chk_Command({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> + case (is_Command_tag(Tag) andalso + is_Command_val(Tag, Val1) andalso + is_Command_val(Tag, Val2)) of + true -> + chk_Command_val(Tag, Val1, Val2); + false -> + wrong_type('Command', Cmd1, Cmd2) + end; +chk_Command({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> + case ((is_Command_tag(Tag1) andalso is_Command_val(Tag1, Val1)) andalso + (is_Command_tag(Tag2) andalso is_Command_val(Tag2, Val2))) of + true -> + not_equal('Command', Cmd1, Cmd2); + false -> + wrong_type('Command', Cmd1, Cmd2) + end; +chk_Command(Cmd1, Cmd2) -> + wrong_type('Command', Cmd1, Cmd2). + + +chk_Command_val(addReq, R1, R2) -> + validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_addReq'); +chk_Command_val(moveReq, R1, R2) -> + validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_moveReq'); +chk_Command_val(modReq, R1, R2) -> + validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_modReq'); +chk_Command_val(subtractReq, R1, R2) -> + validate(fun() -> chk_SubtractRequest(R1, R2) end, 'Command_subtractReq'); +chk_Command_val(auditCapRequest, R1, R2) -> + validate(fun() -> chk_AuditRequest(R1, R2) end, 'Command_auditCapRequest'); +chk_Command_val(auditValueRequest, R1, R2) -> + validate(fun() -> chk_AuditRequest(R1, R2) end, + 'Command_auditValueRequest'); +chk_Command_val(notifyReq, R1, R2) -> + validate(fun() -> chk_NotifyRequest(R1, R2) end, 'Command_notifyReq'); +chk_Command_val(serviceChangeReq, R1, R2) -> + validate(fun() -> chk_ServiceChangeRequest(R1, R2) end, + 'Command_serviceChangeReq'). + + +%% -- CommandReply -- + +is_CommandReply({Tag, Val}) -> + is_CommandReply_tag(Tag) andalso is_CommandReply_val(Tag, Val); +is_CommandReply(_) -> + false. + +is_CommandReply_tag(Tag) -> + Tags = [addReply, moveReply, modReply, subtractReply, + auditCapReply, auditValueReply, notifyReply, serviceChangeReply], + lists:member(Tag, Tags). + +is_CommandReply_val(addReply, V) -> is_AmmsReply(V); +is_CommandReply_val(moveReply, V) -> is_AmmsReply(V); +is_CommandReply_val(modReply, V) -> is_AmmsReply(V); +is_CommandReply_val(subtractReply, V) -> is_AmmsReply(V); +is_CommandReply_val(auditCapReply, V) -> is_AuditReply(V); +is_CommandReply_val(auditValueReply, V) -> is_AuditReply(V); +is_CommandReply_val(notifyReply, V) -> is_NotifyReply(V); +is_CommandReply_val(serviceChangeReply, V) -> is_ServiceChangeReply(V). + +chk_CommandReply({Tag, Val} = Cmd, Cmd) -> + case (is_CommandReply_tag(Tag) andalso is_CommandReply_val(Tag, Val)) of + true -> + ok; + false -> + wrong_type('CommandReply', Cmd) + end; +chk_CommandReply({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> + case (is_CommandReply_tag(Tag) andalso + is_CommandReply_val(Tag, Val1) andalso + is_CommandReply_val(Tag, Val2)) of + true -> + chk_CommandReply_val(Tag, Val1, Val2); + false -> + wrong_type('CommandReply', Cmd1, Cmd2) + end; +chk_CommandReply({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> + case ((is_CommandReply_tag(Tag1) andalso + is_CommandReply_val(Tag1, Val1)) andalso + (is_CommandReply_tag(Tag2) andalso + is_CommandReply_val(Tag2, Val2))) of + true -> + not_equal('CommandReply', Cmd1, Cmd2); + false -> + wrong_type('CommandReply', Cmd1, Cmd2) + end; +chk_CommandReply(Cmd1, Cmd2) -> + wrong_type('CommandReply', Cmd1, Cmd2). + +chk_CommandReply_val(addReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_addReply'); +chk_CommandReply_val(moveReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_moveReply'); +chk_CommandReply_val(modReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_modReply'); +chk_CommandReply_val(subtractReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_subtractReply'); +chk_CommandReply_val(auditCapReply, V1, V2) -> + validate(fun() -> chk_AuditReply(V1, V2) end, + 'CommandReply_auditCapReply'); +chk_CommandReply_val(auditValueReply, V1, V2) -> + validate(fun() -> chk_AuditReply(V1, V2) end, + 'CommandReply_auditValueReply'); +chk_CommandReply_val(notifyReply, V1, V2) -> + validate(fun() -> chk_NotifyReply(V1, V2) end, 'CommandReply_notifyReply'); +chk_CommandReply_val(serviceChangeReply, V1, V2) -> + validate(fun() -> chk_ServiceChangeReply(V1, V2) end, + 'CommandReply_serviceChangeReply'). + + +%% -- TopologyRequest -- + +is_TopologyRequest(#'TopologyRequest'{terminationFrom = F, + terminationTo = T, + topologyDirection = D, + streamID = S}) -> + is_TerminationID(F) andalso + is_TerminationID(T) andalso + is_TopologyRequest_topologyDirection(D) andalso + is_opt_StreamID(S); +is_TopologyRequest(_) -> + false. + +is_TopologyRequest_topologyDirection(D) -> + lists:member(D, [bothway, isolate, oneway]). + + +chk_TopologyRequest(T, T) when is_record(T,'TopologyRequest') -> + ok; +chk_TopologyRequest(#'TopologyRequest'{terminationFrom = F1, + terminationTo = T1, + topologyDirection = D1, + streamID = S1}, + #'TopologyRequest'{terminationFrom = F2, + terminationTo = T2, + topologyDirection = D2, + streamID = S2}) -> + validate(fun() -> chk_TerminationID(F1, F2) end, + 'TopologyRequest_terminationFrom'), + validate(fun() -> chk_TerminationID(T1, T2) end, + 'TopologyRequest_terminationTo'), + chk_TopologyRequest_topologyDirection(D1,D2), + validate(fun() -> chk_StreamID(S1, S2) end, 'TopologyRequest_streamID'), + ok. + +chk_TopologyRequest_topologyDirection(D, D) -> + case is_TopologyRequest_topologyDirection(D) of + true -> + ok; + false -> + wrong_type('TopologyRequest_topologyDirection', D) + end; +chk_TopologyRequest_topologyDirection(D1, D2) -> + case (is_TopologyRequest_topologyDirection(D1) andalso + is_TopologyRequest_topologyDirection(D1)) of + true -> + not_equal('TopologyRequest_topologyDirection', D1, D2); + false -> + wrong_type('TopologyRequest_topologyDirection', D1, D2) + end. + + +%% -- AmmRequest -- + +is_AmmRequest(#'AmmRequest'{terminationID = Tids, + descriptors = Descs}) -> + d("is_AmmRequest -> entry with" + "~n Tids: ~p", [Tids]), + is_TerminationIDList(Tids) andalso is_AmmRequest_descriptors(Descs); +is_AmmRequest(_) -> + false. + +is_AmmRequest_descriptors(Descs) -> + is_AmmRequest_descriptors(Descs, []). + +is_AmmRequest_descriptors([], _) -> + true; +is_AmmRequest_descriptors([{Tag, _} = Desc|Descs], FoundDescs) -> + d("is_AmmRequest_descriptors -> entry with" + "~n Tag: ~p" + "~n FoundDescs: ~p", [Tag, FoundDescs]), + case lists:member(Tag, FoundDescs) of + true -> + atmost_once('AmmRequest_descriptors', Tag); + false -> + case is_AmmDescriptor(Desc) of + true -> + is_AmmRequest_descriptors(Descs, [Tag|FoundDescs]); + false -> + wrong_type('AmmRequest_descriptors', Desc) + end + end; +is_AmmRequest_descriptors(Descs, _) -> + d("is_AmmRequest_descriptors -> entry with WRONG TYPE" + "~n Descs: ~p", [Descs]), + wrong_type('AmmRequest_descriptors', Descs). + + +chk_AmmRequest(R, R) when is_record(R, 'AmmRequest') -> + d("chk_AmmRequest -> entry when equal"), + chk_type(fun is_AmmRequest/1, 'AmmRequest', R); +chk_AmmRequest(#'AmmRequest'{terminationID = Tids1, + descriptors = Descs1}, + #'AmmRequest'{terminationID = Tids2, + descriptors = Descs2}) -> + d("chk_AmmRequest -> entry with not equal" + "~n Tids1: ~p" + "~n Tids2: ~p", [Tids1, Tids2]), + validate( + fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'AmmRequest'), + validate( + fun() -> chk_AmmRequest_descriptors(Descs1, Descs2) end, + 'AmmRequest'), + ok. + + +chk_AmmRequest_descriptors([], []) -> + d("chk_AmmRequest_descriptors -> done when OK"), + ok; +chk_AmmRequest_descriptors([] = Descs1, Descs2) -> + d("chk_AmmRequest_descriptors -> done when NOT EQUAL:" + "~n Descs1: ~p" + "~n Descs1: ~p", [Descs1, Descs2]), + not_equal('AmmRequest_descriptors', Descs1, Descs2); +chk_AmmRequest_descriptors(Descs1, [] = Descs2) -> + d("chk_AmmRequest_descriptors -> done when NOT EQUAL:" + "~n Descs1: ~p" + "~n Descs1: ~p", [Descs1, Descs2]), + not_equal('AmmRequest_descriptors', Descs1, Descs2); +chk_AmmRequest_descriptors([H|T1], [H|T2]) -> + d("chk_AmmRequest_descriptors -> entry when equal"), + case is_AmmDescriptor(H) of + true -> + chk_AmmRequest_descriptors(T1, T2); + false -> + wrong_type('AmmRequest_descriptors_val', H) + end; +chk_AmmRequest_descriptors([H1|T1], [H2|T2]) -> + d("chk_AmmRequest_descriptors -> entry when not equal"), + validate(fun() -> chk_AmmDescriptor(H1, H2) end, + 'AmmRequest_descriptors_val'), + chk_AmmRequest_descriptors(T1, T2); +chk_AmmRequest_descriptors(Descs1, Descs2) -> + d("chk_AmmRequest_descriptors -> done when WRONG TYPE:" + "~n Descs1: ~p" + "~n Descs1: ~p", [Descs1, Descs2]), + wrong_type('AmmRequest_descriptors', Descs1, Descs2). + + +%% -- AmmDescriptor -- + +is_AmmDescriptor({Tag, Val}) -> + d("is_AmmDescriptor -> entry with" + "~n Tag: ~p" + "~n Val: ~p",[Tag, Val]), + is_AmmDescriptor_tag(Tag) andalso is_AmmDescriptor_val(Tag, Val); +is_AmmDescriptor(_) -> + false. + +is_AmmDescriptor_tag(Tag) -> + Tags = [mediaDescriptor, modemDescriptor, muxDescriptor, eventsDescriptor, + eventBufferDescriptor, signalsDescriptor, digitMapDescriptor, + auditDescriptor], + lists:member(Tag, Tags). + +is_AmmDescriptor_val(mediaDescriptor, D) -> + is_MediaDescriptor(D); +is_AmmDescriptor_val(modemDescriptor, D) -> + is_ModemDescriptor(D); +is_AmmDescriptor_val(muxDescriptor, D) -> + is_MuxDescriptor(D); +is_AmmDescriptor_val(eventsDescriptor, D) -> + is_EventsDescriptor(D); +is_AmmDescriptor_val(eventBufferDescriptor, D) -> + is_EventBufferDescriptor(D); +is_AmmDescriptor_val(signalsDescriptor, D) -> + is_SignalsDescriptor(D); +is_AmmDescriptor_val(digitMapDescriptor, D) -> + is_DigitMapDescriptor(D); +is_AmmDescriptor_val(auditDescriptor, D) -> + is_AuditDescriptor(D). + +chk_AmmDescriptor(D, D) -> + chk_type(fun is_AmmDescriptor_tag/1, 'AmmDescriptor', D); +chk_AmmDescriptor({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> + case (is_AmmDescriptor_tag(Tag) andalso + is_AmmDescriptor_val(Tag, Val1) andalso + is_AmmDescriptor_val(Tag, Val2)) of + true -> + chk_AmmDescriptor_val(Tag, Val1, Val2); + false -> + wrong_type('AmmDescriptor', Cmd1, Cmd2) + end; +chk_AmmDescriptor({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> + case ((is_AmmDescriptor_tag(Tag1) andalso + is_AmmDescriptor_val(Tag1, Val1)) andalso + (is_AmmDescriptor_tag(Tag2) andalso + is_AmmDescriptor_val(Tag2, Val2))) of + true -> + not_equal('AmmDescriptor', Cmd1, Cmd2); + false -> + wrong_type('AmmDescriptor', Cmd1, Cmd2) + end; +chk_AmmDescriptor(Cmd1, Cmd2) -> + wrong_type('AmmDescriptor', Cmd1, Cmd2). + +chk_AmmDescriptor_val(mediaDescriptor, D1, D2) -> + validate(fun() -> chk_MediaDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(modemDescriptor, D1, D2) -> + validate(fun() -> chk_ModemDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(muxDescriptor, D1, D2) -> + validate(fun() -> chk_MuxDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(eventsDescriptor, D1, D2) -> + validate(fun() -> chk_EventsDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(eventBufferDescriptor, D1, D2) -> + validate(fun() -> chk_EventBufferDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(signalsDescriptor, D1, D2) -> + validate(fun() -> chk_SignalsDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(digitMapDescriptor, D1, D2) -> + validate(fun() -> chk_DigitMapDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(auditDescriptor, D1, D2) -> + validate(fun() -> chk_AuditDescriptor(D1, D2) end, 'AmmDescriptor'). + + +%% -- AmmsReply -- + +is_AmmsReply(#'AmmsReply'{terminationID = Tids, + terminationAudit = TA}) -> + is_TerminationIDList(Tids) andalso is_opt_TerminationAudit(TA); +is_AmmsReply(_) -> + false. + +chk_AmmsReply(R, R) -> + is_AmmsReply(R); +chk_AmmsReply(#'AmmsReply'{terminationID = TID1, + terminationAudit = TA1}, + #'AmmsReply'{terminationID = TID2, + terminationAudit = TA2}) -> + validate(fun() -> chk_TerminationIDList(TID1, TID2) end, 'AmmsReply'), + validate(fun() -> chk_opt_TerminationAudit(TA1, TA2) end, 'AmmsReply'), + ok; +chk_AmmsReply(R1, R2) -> + wrong_type('AmmsReply', R1, R2). + + +%% -- SubtractRequest -- + +is_SubtractRequest(#'SubtractRequest'{terminationID = Tids, + auditDescriptor = AD}) -> + is_TerminationIDList(Tids) andalso is_opt_AuditDescriptor(AD); +is_SubtractRequest(_) -> + false. + +chk_SubtractRequest(R, R) -> + chk_type(fun is_SubtractRequest/1, 'SubtractRequest', R); +chk_SubtractRequest(#'SubtractRequest'{terminationID = Tids1, + auditDescriptor = AD1}, + #'SubtractRequest'{terminationID = Tids2, + auditDescriptor = AD2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'SubtractRequest'), + validate(fun() -> chk_opt_AuditDescriptor(AD1, AD2) end, + 'SubtractRequest'), + ok; +chk_SubtractRequest(SR1, SR2) -> + wrong_type('SubtractRequest', SR1, SR2). + + +%% -- AuditRequest -- + +is_AuditRequest(#'AuditRequest'{terminationID = Tid, + auditDescriptor = AD}) -> + is_TerminationID(Tid) andalso is_AuditDescriptor(AD); +is_AuditRequest(_) -> + false. + +chk_AuditRequest(R, R) -> + chk_type(fun is_AuditRequest/1, 'AuditRequest', R); +chk_AuditRequest(#'AuditRequest'{terminationID = Tids1, + auditDescriptor = AD1}, + #'AuditRequest'{terminationID = Tids2, + auditDescriptor = AD2}) -> + validate(fun() -> chk_TerminationID(Tids1, Tids2) end, + 'AuditRequest'), + validate(fun() -> chk_AuditDescriptor(AD1, AD2) end, + 'AuditRequest'), + ok; +chk_AuditRequest(AR1, AR2) -> + wrong_type('AuditRequest', AR1, AR2). + + +%% -- AuditReply -- + +is_AuditReply({Tag, Val}) -> + is_AuditReply_tag(Tag) andalso is_AuditReply_val(Tag, Val); +is_AuditReply(_) -> + false. + +is_AuditReply_tag(Tag) -> + Tags = [contextAuditResult, error, auditResult], + lists:member(Tag, Tags). + +is_AuditReply_val(contextAuditResult, Val) -> + is_TerminationIDList(Val); +is_AuditReply_val(error, Val) -> + is_ErrorDescriptor(Val); +is_AuditReply_val(auditResult, Val) -> + is_AuditResult(Val). + +chk_AuditReply(R, R) -> + chk_type(fun is_AuditReply/1, 'AuditReply', R); +chk_AuditReply({Tag, Val1} = R1, {Tag, Val2} = R2) -> + case (is_AuditReply_tag(Tag) andalso + is_AuditReply_val(Tag, Val1)andalso + is_AuditReply_val(Tag, Val2)) of + true -> + chk_AuditReply_val(Tag, Val1, Val2); + false -> + wrong_type('AuditReply', R1, R2) + end; +chk_AuditReply({Tag1, Val1} = R1, {Tag2, Val2} = R2) -> + case ((is_AuditReply_tag(Tag1) andalso + is_AuditReply_val(Tag1, Val1)) andalso + (is_AuditReply_tag(Tag2) andalso + is_AuditReply_val(Tag2, Val2))) of + true -> + not_equal('AuditReply', R1, R2); + false -> + wrong_type('AuditReply', R1, R2) + end; +chk_AuditReply(AR1, AR2) -> + wrong_type('AuditReply', AR1, AR2). + +chk_AuditReply_val(contextAuditResult, Val1, Val2) -> + chk_TerminationIDList(Val1, Val2); +chk_AuditReply_val(error, Val1, Val2) -> + chk_ErrorDescriptor(Val1, Val2); +chk_AuditReply_val(auditResult, Val1, Val2) -> + chk_AuditResult(Val1, Val2). + + +%% -- AuditResult -- + +is_AuditResult(#'AuditResult'{terminationID = TID, + terminationAuditResult = TAR}) -> + is_TerminationID(TID) andalso is_TerminationAudit(TAR); +is_AuditResult(_) -> + false. + +chk_AuditResult(R, R) -> + chk_type(fun is_AuditResult/1, 'AuditResult', R); +chk_AuditResult(#'AuditResult'{terminationID = TID1, + terminationAuditResult = TAR1}, + #'AuditResult'{terminationID = TID2, + terminationAuditResult = TAR2}) -> + validate(fun() -> chk_TerminationID(TID1, TID2) end, 'AuditResult'), + validate(fun() -> chk_TerminationAudit(TAR1, TAR2) end, 'AuditResult'), + ok; +chk_AuditResult(AR1, AR2) -> + wrong_type('AuditResult', AR1, AR2). + + +%% -- TerminationAudit -- + +is_opt_TerminationAudit(TA) -> + is_OPTIONAL(fun is_TerminationAudit/1, TA). + +is_TerminationAudit([]) -> + true; +is_TerminationAudit([H|T]) -> + is_AuditReturnParameter(H) andalso is_TerminationAudit(T); +is_TerminationAudit(_) -> + false. + +chk_opt_TerminationAudit(TA1, TA2) -> + chk_OPTIONAL('TerminationAudit', TA1, TA2, + fun is_TerminationAudit/1, fun chk_TerminationAudit/2). + +chk_TerminationAudit([], []) -> + ok; +chk_TerminationAudit([] = TA1, TA2) -> + not_equal('TerminationAudit', TA1, TA2); +chk_TerminationAudit(TA1, [] = TA2) -> + not_equal('TerminationAudit', TA1, TA2); +chk_TerminationAudit([H|T1], [H|T2]) -> + case is_AuditReturnParameter(H) of + true -> + chk_TerminationAudit(T1, T2); + false -> + wrong_type('TerminationAudit', H) + end; +chk_TerminationAudit([H1|_], [H2|_]) -> + chk_AuditReturnParameter(H1, H2), + not_equal('TerminationAudit_val', H1, H2); +chk_TerminationAudit(TA1, TA2) -> + not_equal('TerminationAudit', TA1, TA2). + + +%% -- AuditReturnParameter -- + +is_AuditReturnParameter({Tag, Val}) -> + is_AuditReturnParameter_tag(Tag) andalso + is_AuditReturnParameter_val(Tag, Val); +is_AuditReturnParameter(_) -> + false. + +is_AuditReturnParameter_tag(Tag) -> + Tags = [errorDescriptor, + mediaDescriptor, + modemDescriptor, + muxDescriptor, + eventsDescriptor, + eventBufferDescriptor, + signalsDescriptor, + digitMapDescriptor, + observedEventsDescriptor, + statisticsDescriptor, + packagesDescriptor, + emptyDescriptors], + lists:member(Tag, Tags). + +is_AuditReturnParameter_val(errorDescriptor, V) -> + is_ErrorDescriptor(V); +is_AuditReturnParameter_val(mediaDescriptor, V) -> + is_MediaDescriptor(V); +is_AuditReturnParameter_val(modemDescriptor, V) -> + is_ModemDescriptor(V); +is_AuditReturnParameter_val(muxDescriptor, V) -> + is_MuxDescriptor(V); +is_AuditReturnParameter_val(eventsDescriptor, V) -> + is_EventsDescriptor(V); +is_AuditReturnParameter_val(eventBufferDescriptor, V) -> + is_EventBufferDescriptor(V); +is_AuditReturnParameter_val(signalsDescriptor, V) -> + is_SignalsDescriptor(V); +is_AuditReturnParameter_val(digitMapDescriptor, V) -> + is_DigitMapDescriptor(V); +is_AuditReturnParameter_val(observedEventsDescriptor, V) -> + is_ObservedEventsDescriptor(V); +is_AuditReturnParameter_val(statisticsDescriptor, V) -> + is_StatisticsDescriptor(V); +is_AuditReturnParameter_val(packagesDescriptor, V) -> + is_PackagesDescriptor(V); +is_AuditReturnParameter_val(emptyDescriptors, V) -> + is_AuditDescriptor(V). + +chk_AuditReturnParameter(ARP, ARP) -> + chk_type(fun is_AuditReturnParameter/1, 'AuditReturnParameter', ARP); +chk_AuditReturnParameter({Tag, Val1} = ARP1, {Tag, Val2} = ARP2) -> + case (is_AuditReturnParameter_tag(Tag) andalso + is_AuditReturnParameter_val(Tag, Val1) andalso + is_AuditReturnParameter_val(Tag, Val2)) of + true -> + chk_AuditReturnParameter_val(Tag, Val1, Val2); + false -> + wrong_type('AuditReturnParameter', ARP1, ARP2) + end; +chk_AuditReturnParameter({Tag1, Val1} = ARP1, {Tag2, Val2} = ARP2) -> + case ((is_AuditReturnParameter_tag(Tag1) andalso + is_AuditReturnParameter_val(Tag1, Val1)) andalso + (is_AuditReturnParameter_tag(Tag2) andalso + is_AuditReturnParameter_val(Tag2, Val2))) of + true -> + not_equal('AuditReturnParameter', ARP1, ARP2); + false -> + wrong_type('AuditReturnParameter', ARP1, ARP2) + end; +chk_AuditReturnParameter(ARP1, ARP2) -> + wrong_type('AuditReturnParameter', ARP1, ARP2). + +chk_AuditReturnParameter_val(errorDescriptor, V1, V2) -> + validate(fun() -> chk_ErrorDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(mediaDescriptor, V1, V2) -> + validate(fun() -> chk_MediaDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(modemDescriptor, V1, V2) -> + validate(fun() -> chk_ModemDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(muxDescriptor, V1, V2) -> + validate(fun() -> chk_MuxDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(eventsDescriptor, V1, V2) -> + validate(fun() -> chk_EventsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(eventBufferDescriptor, V1, V2) -> + validate(fun() -> chk_EventBufferDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(signalsDescriptor, V1, V2) -> + validate(fun() -> chk_SignalsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(digitMapDescriptor, V1, V2) -> + validate(fun() -> chk_DigitMapDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(observedEventsDescriptor, V1, V2) -> + validate(fun() -> chk_ObservedEventsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(statisticsDescriptor, V1, V2) -> + validate(fun() -> chk_StatisticsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(packagesDescriptor, V1, V2) -> + validate(fun() -> chk_PackagesDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(emptyDescriptors, V1, V2) -> + validate(fun() -> chk_AuditDescriptor(V1, V2) end, + 'AuditReturnParameter'). + + +%% -- AuditDescriptor -- + +is_opt_AuditDescriptor(asn1_NOVALUE) -> + true; +is_opt_AuditDescriptor(V) -> + is_AuditDescriptor(V). + +is_AuditDescriptor(#'AuditDescriptor'{auditToken = AT, + auditPropertyToken = APT}) -> + is_AuditDescriptor_auditToken(AT) andalso + is_AuditDescriptor_auditPropertyToken(APT); +is_AuditDescriptor(_) -> + false. + +is_AuditDescriptor_auditToken(asn1_NOVALUE) -> + true; +is_AuditDescriptor_auditToken([]) -> + true; +is_AuditDescriptor_auditToken([H|T]) -> + is_AuditDescriptor_auditToken_val(H) andalso + is_AuditDescriptor_auditToken(T); +is_AuditDescriptor_auditToken(_) -> + false. + +is_AuditDescriptor_auditToken_val(V) -> + Toks = [muxToken, modemToken, mediaToken, eventsToken, signalsToken, + digitMapToken, statsToken, observedEventsToken, + packagesToken, eventBufferToken], + lists:member(V, Toks). + +is_AuditDescriptor_auditPropertyToken(asn1_NOVALUE) -> + true; +is_AuditDescriptor_auditPropertyToken([]) -> + true; +is_AuditDescriptor_auditPropertyToken([H|T]) -> + is_IndAuditParameter(H) andalso is_AuditDescriptor_auditPropertyToken(T); +is_AuditDescriptor_auditPropertyToken(_) -> + false. + +chk_opt_AuditDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_AuditDescriptor(AD1, AD2) -> + chk_AuditDescriptor(AD1, AD2). + +chk_AuditDescriptor(AD, AD) -> + chk_type(fun is_AuditDescriptor/1, 'AuditDescriptor', AD); +chk_AuditDescriptor(#'AuditDescriptor'{auditToken = AT1, + auditPropertyToken = APT1}, + #'AuditDescriptor'{auditToken = AT2, + auditPropertyToken = APT2}) -> + chk_AuditDescriptor_auditToken(AT1, AT2), + chk_AuditDescriptor_auditPropertyToken(APT1, APT2), + ok; +chk_AuditDescriptor(AD1, AD2) -> + wrong_type('AuditDescriptor', AD1, AD2). + +chk_AuditDescriptor_auditToken(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_AuditDescriptor_auditToken([], []) -> + ok; +chk_AuditDescriptor_auditToken([] = AT1, AT2) -> + not_equal('AuditDescriptor_auditToken', AT1, AT2); +chk_AuditDescriptor_auditToken(AT1, [] = AT2) -> + not_equal('AuditDescriptor_auditToken', AT1, AT2); +chk_AuditDescriptor_auditToken([H|T1], [H|T2]) -> + case is_AuditDescriptor_auditToken_val(H) of + true -> + chk_AuditDescriptor_auditToken(T1, T2); + false -> + wrong_type('AuditDescriptor_auditToken_val', H) + end; +chk_AuditDescriptor_auditToken([H1|_T1], [H2|_T2]) -> + case (is_AuditDescriptor_auditToken_val(H1) andalso + is_AuditDescriptor_auditToken_val(H2)) of + true -> + not_equal('AuditDescriptor_auditToken_val', H1, H2); + false -> + wrong_type('AuditDescriptor_auditToken_val', H1, H2) + end; +chk_AuditDescriptor_auditToken(AT1, AT2) -> + wrong_type('AuditDescriptor_auditToken', AT1, AT2). + +chk_AuditDescriptor_auditPropertyToken(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_AuditDescriptor_auditPropertyToken([], []) -> + ok; +chk_AuditDescriptor_auditPropertyToken([] = AT1, AT2) -> + not_equal('AuditDescriptor_auditPropertyToken', AT1, AT2); +chk_AuditDescriptor_auditPropertyToken(AT1, [] = AT2) -> + not_equal('AuditDescriptor_auditPropertyToken', AT1, AT2); +chk_AuditDescriptor_auditPropertyToken([H|T1], [H|T2]) -> + case is_IndAuditParameter(H) of + true -> + chk_AuditDescriptor_auditPropertyToken(T1, T2); + false -> + wrong_type('AuditDescriptor_auditPropertyToken_val', H) + end; +chk_AuditDescriptor_auditPropertyToken([H1|_], [H2|_]) -> + chk_IndAuditParameter(H1, H2), + not_equal('AuditDescriptor_auditPropertyToken_val', H1, H2); +chk_AuditDescriptor_auditPropertyToken(AT1, AT2) -> + wrong_type('AuditDescriptor_auditPropertyToken', AT1, AT2). + + +%% -- IndAuditParameter -- + +is_IndAuditParameter({Tag, Val}) -> + is_IndAuditParameter_tag(Tag) andalso is_IndAuditParameter_val(Tag, Val); +is_IndAuditParameter(_) -> + false. + +is_IndAuditParameter_tag(Tag) -> + Tags = [indAudMediaDescriptor, + indAudEventsDescriptor, + indAudEventBufferDescriptor, + indAudSignalsDescriptor, + indAudDigitMapDescriptor, + indAudStatisticsDescriptor, + indAudPackagesDescriptor], + lists:member(Tag, Tags). + +is_IndAuditParameter_val(indAudMediaDescriptor, Val) -> + is_IndAudMediaDescriptor(Val); +is_IndAuditParameter_val(indAudEventsDescriptor, Val) -> + is_IndAudEventsDescriptor(Val); +is_IndAuditParameter_val(indAudEventBufferDescriptor, Val) -> + is_IndAudEventBufferDescriptor(Val); +is_IndAuditParameter_val(indAudSignalsDescriptor, Val) -> + is_IndAudSignalsDescriptor(Val); +is_IndAuditParameter_val(indAudDigitMapDescriptor, Val) -> + is_IndAudDigitMapDescriptor(Val); +is_IndAuditParameter_val(indAudStatisticsDescriptor, Val) -> + is_IndAudStatisticsDescriptor(Val); +is_IndAuditParameter_val(indAudPackagesDescriptor, Val) -> + is_IndAudPackagesDescriptor(Val). + +chk_IndAuditParameter(IAP, IAP) -> + chk_type(fun is_IndAuditParameter/1, 'IndAuditParameter', IAP); +chk_IndAuditParameter({Tag, Val1} = IAP1, {Tag, Val2} = IAP2) -> + case (is_IndAuditParameter_tag(Tag) andalso + is_IndAuditParameter_val(Tag, Val1) andalso + is_IndAuditParameter_val(Tag, Val2)) of + true -> + chk_IndAuditParameter_val(Tag, Val1, Val2); + false -> + wrong_type('IndAuditParameter', IAP1, IAP2) + end; +chk_IndAuditParameter({Tag1, Val1} = IAP1, {Tag2, Val2} = IAP2) -> + case ((is_IndAuditParameter_tag(Tag1) andalso + is_IndAuditParameter_val(Tag1, Val1)) andalso + (is_IndAuditParameter_tag(Tag2) andalso + is_IndAuditParameter_val(Tag2, Val2))) of + true -> + not_equal('IndAuditParameter', IAP1, IAP2); + false -> + wrong_type('IndAuditParameter', IAP1, IAP2) + end; +chk_IndAuditParameter(IAP1, IAP2) -> + wrong_type('IndAuditParameter', IAP1, IAP2). + +chk_IndAuditParameter_val(indAudMediaDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudMediaDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudEventsDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudEventsDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudEventBufferDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudEventBufferDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudSignalsDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudSignalsDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudDigitMapDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudDigitMapDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudStatisticsDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudStatisticsDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudPackagesDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudPackagesDescriptor(Val1, Val2) end, + 'IndAuditParameter'). + + +%% -- IndAudMediaDescriptor -- + +is_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = S}) -> + is_opt_IndAudTerminationStateDescriptor(TSD) andalso + is_IndAudMediaDescriptor_streams(S); +is_IndAudMediaDescriptor(_) -> + false. + +is_IndAudMediaDescriptor_streams(asn1_NOVALUE) -> + true; +is_IndAudMediaDescriptor_streams({Tag, Val}) -> + is_IndAudMediaDescriptor_streams_tag(Tag) andalso + is_IndAudMediaDescriptor_streams_val(Tag, Val); +is_IndAudMediaDescriptor_streams(_) -> + false. + +is_IndAudMediaDescriptor_streams_tag(Tag) -> + Tags = [oneStream, multiStream], + lists:member(Tag, Tags). + +is_IndAudMediaDescriptor_streams_val(oneStream, Val) -> + is_IndAudStreamParms(Val); +is_IndAudMediaDescriptor_streams_val(multiStream, Val) -> + is_IndAudMediaDescriptor_multiStream(Val). + +is_IndAudMediaDescriptor_multiStream([]) -> + true; +is_IndAudMediaDescriptor_multiStream([H|T]) -> + is_IndAudStreamDescriptor(H) andalso + is_IndAudMediaDescriptor_multiStream(T); +is_IndAudMediaDescriptor_multiStream(_) -> + false. + +chk_IndAudMediaDescriptor(IAMD, IAMD) -> + chk_type(fun is_IndAudMediaDescriptor/1, 'IndAudMediaDescriptor', IAMD); +chk_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD1, + streams = S1}, + #'IndAudMediaDescriptor'{termStateDescr = TSD2, + streams = S2}) -> + validate(fun() -> chk_opt_IndAudTerminationStateDescriptor(TSD1, TSD2) end, + 'IndAudMediaDescriptor'), + validate(fun() -> chk_IndAudMediaDescriptor_streams(S1, S2) end, + 'IndAudMediaDescriptor'), + ok; +chk_IndAudMediaDescriptor(IAMD1, IAMD2) -> + wrong_type('IndAudMediaDescriptor', IAMD1, IAMD2). + +chk_IndAudMediaDescriptor_streams(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_IndAudMediaDescriptor_streams({Tag, Val1} = S1, + {Tag, Val2} = S2) -> + case (is_IndAudMediaDescriptor_streams_tag(Tag) andalso + is_IndAudMediaDescriptor_streams_val(Tag, Val1) andalso + is_IndAudMediaDescriptor_streams_val(Tag, Val2)) of + true -> + chk_IndAudMediaDescriptor_streams_val(Tag, Val1, Val2); + false -> + wrong_type('IndAudMediaDescriptor_streams', S1, S2) + end; +chk_IndAudMediaDescriptor_streams({Tag1, Val1} = S1, + {Tag2, Val2} = S2) -> + case ((is_IndAudMediaDescriptor_streams_tag(Tag1) andalso + is_IndAudMediaDescriptor_streams_val(Tag1, Val1)) andalso + (is_IndAudMediaDescriptor_streams_tag(Tag2) andalso + is_IndAudMediaDescriptor_streams_val(Tag2, Val2))) of + true -> + not_equal('IndAudMediaDescriptor_streams', S1, S2); + false -> + wrong_type('IndAudMediaDescriptor_streams', S1, S2) + end; +chk_IndAudMediaDescriptor_streams(S1, S2) -> + wrong_type('IndAudMediaDescriptor_streams', S1, S2). + +chk_IndAudMediaDescriptor_streams_val(oneStream, Val1, Val2) -> + validate(fun() -> chk_IndAudStreamParms(Val1, Val2) end, + 'IndAudMediaDescriptor_streams'); +chk_IndAudMediaDescriptor_streams_val(multiStream, Val1, Val2) -> + validate(fun() -> chk_IndAudMediaDescriptor_multiStream(Val1, Val2) end, + 'IndAudMediaDescriptor_streams'). + +chk_IndAudMediaDescriptor_multiStream([], []) -> + ok; +chk_IndAudMediaDescriptor_multiStream([] = MS1, MS2) -> + not_equal('IndAudMediaDescriptor_multiStream', MS1, MS2); +chk_IndAudMediaDescriptor_multiStream(MS1, [] = MS2) -> + not_equal('IndAudMediaDescriptor_multiStream', MS1, MS2); +chk_IndAudMediaDescriptor_multiStream([H|T1], [H|T2]) -> + case is_IndAudStreamDescriptor(H) of + true -> + chk_IndAudMediaDescriptor_multiStream(T1, T2); + false -> + wrong_type('IndAudMediaDescriptor_multiStream_val', H) + end; +chk_IndAudMediaDescriptor_multiStream([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudStreamDescriptor(H1, H2) end, + 'IndAudMediaDescriptor_multiStream_val'), + chk_IndAudMediaDescriptor_multiStream(T1, T2); +chk_IndAudMediaDescriptor_multiStream(MS1, MS2) -> + wrong_type('IndAudMediaDescriptor_multiStream', MS1, MS2). + + +%% -- IndAudStreamDescriptor -- + +is_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID, + streamParms = Parms}) -> + is_StreamID(SID) andalso is_IndAudStreamParms(Parms); +is_IndAudStreamDescriptor(_) -> + false. + +chk_IndAudStreamDescriptor(D, D) -> + chk_type(fun is_IndAudStreamDescriptor/1, 'IndAudStreamDescriptor', D); +chk_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID1, + streamParms = Parms1}, + #'IndAudStreamDescriptor'{streamID = SID2, + streamParms = Parms2}) -> + validate(fun() -> chk_StreamID(SID1, SID2) end, 'IndAudStreamDescriptor'), + validate(fun() -> chk_IndAudStreamParms(Parms1, Parms2) end, + 'IndAudStreamDescriptor'), + ok; +chk_IndAudStreamDescriptor(D1, D2) -> + wrong_type('IndAudStreamDescriptor', D1, D2). + + +%% -- IndAudStreamParms -- + +is_IndAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD}) -> + is_opt_IndAudLocalControlDescriptor(LCD) andalso + is_opt_IndAudLocalRemoteDescriptor(LD) andalso + is_opt_IndAudLocalRemoteDescriptor(RD); +is_IndAudStreamParms(_) -> + false. + +chk_IndAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD1, + localDescriptor = LD1, + remoteDescriptor = RD1}, + #'IndAudStreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2}) -> + validate(fun() -> chk_opt_IndAudLocalControlDescriptor(LCD1, LCD2) end, + 'IndAudStreamParms'), + validate(fun() -> chk_opt_IndAudLocalRemoteDescriptor(LD1, LD2) end, + 'IndAudStreamParms'), + validate(fun() -> chk_opt_IndAudLocalRemoteDescriptor(RD1, RD2) end, + 'IndAudStreamParms'), + ok; +chk_IndAudStreamParms(D1, D2) -> + wrong_type('IndAudStreamParms', D1, D2). + + +%% -- IndAudLocalControlDescriptor -- + +is_opt_IndAudLocalControlDescriptor(asn1_NOVALUE) -> + true; +is_opt_IndAudLocalControlDescriptor(D) -> + is_IndAudLocalControlDescriptor(D). + +is_IndAudLocalControlDescriptor( + #'IndAudLocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PPs}) -> + is_opt_NULL(SM) andalso is_opt_NULL(RV) andalso is_opt_NULL(RG) andalso + is_IndAudLocalControlDescriptor_propertyParms(PPs); +is_IndAudLocalControlDescriptor(_) -> + false. + +is_IndAudLocalControlDescriptor_propertyParms(asn1_NOVALUE) -> + true; +is_IndAudLocalControlDescriptor_propertyParms([]) -> + true; +is_IndAudLocalControlDescriptor_propertyParms([H|T]) -> + is_IndAudPropertyParm(H) andalso + is_IndAudLocalControlDescriptor_propertyParms(T); +is_IndAudLocalControlDescriptor_propertyParms(_) -> + false. + +chk_opt_IndAudLocalControlDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudLocalControlDescriptor( + #'IndAudLocalControlDescriptor'{streamMode = SM1, + reserveValue = RV1, + reserveGroup = RG1, + propertyParms = PPs1}, + #'IndAudLocalControlDescriptor'{streamMode = SM2, + reserveValue = RV2, + reserveGroup = RG2, + propertyParms = PPs2}) -> + chk_opt_NULL(SM1, SM2), + chk_opt_NULL(RV1, RV2), + chk_opt_NULL(RG1, RG2), + chk_IndAudLocalControlDescriptor_propertyParms(PPs1, PPs2), + ok; +chk_opt_IndAudLocalControlDescriptor(D1, D2) -> + wrong_type('IndAudLocalControlDescriptor', D1, D2). + +chk_IndAudLocalControlDescriptor_propertyParms(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_IndAudLocalControlDescriptor_propertyParms([], []) -> + ok; +chk_IndAudLocalControlDescriptor_propertyParms([] = PPs1, PPs2) -> + not_equal('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2); +chk_IndAudLocalControlDescriptor_propertyParms(PPs1, [] = PPs2) -> + not_equal('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2); +chk_IndAudLocalControlDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_IndAudLocalControlDescriptor_propertyParms(T1, T2); + false -> + wrong_type('IndAudLocalControlDescriptor_propertyParms_val', H) + end; +chk_IndAudLocalControlDescriptor_propertyParms([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, + 'IndAudLocalControlDescriptor_propertyParms_val'), + chk_IndAudLocalControlDescriptor_propertyParms(T1, T2); +chk_IndAudLocalControlDescriptor_propertyParms(PPs1, PPs2) -> + wrong_type('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2). + + +%% -- IndAudPropertyParm -- + +is_IndAudPropertyParm(#'IndAudPropertyParm'{name = Name}) -> + is_PkgdName(Name); +is_IndAudPropertyParm(_) -> + false. + +chk_IndAudPropertyParm(#'IndAudPropertyParm'{name = Name1}, + #'IndAudPropertyParm'{name = Name2}) -> + chk_PkgdName(Name1, Name2), + ok; +chk_IndAudPropertyParm(P1, P2) -> + wrong_type('IndAudPropertyParm', P1, P2). + + +%% -- IndAudLocalRemoteDescriptor -- + +is_opt_IndAudLocalRemoteDescriptor(asn1_NOVALUE) -> + true; +is_opt_IndAudLocalRemoteDescriptor(D) -> + is_IndAudLocalRemoteDescriptor(D). + +is_IndAudLocalRemoteDescriptor( + #'IndAudLocalRemoteDescriptor'{propGroupID = ID, + propGrps = Grps}) -> + is_IndAudLocalRemoteDescriptor_propGroupID(ID) andalso + is_IndAudPropertyGroup(Grps); +is_IndAudLocalRemoteDescriptor(_) -> + false. + +is_IndAudLocalRemoteDescriptor_propGroupID(asn1_NOVALUE) -> + true; +is_IndAudLocalRemoteDescriptor_propGroupID(V) -> + is_INTEGER(V, {range, 0, 65535}). + +chk_opt_IndAudLocalRemoteDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudLocalRemoteDescriptor(D1, D2) -> + chk_IndAudLocalRemoteDescriptor(D1, D2). + +chk_IndAudLocalRemoteDescriptor(D, D) -> + chk_type(fun is_IndAudLocalRemoteDescriptor/1, + 'IndAudLocalRemoteDescriptor', D); +chk_IndAudLocalRemoteDescriptor( + #'IndAudLocalRemoteDescriptor'{propGroupID = ID1, + propGrps = Grps1}, + #'IndAudLocalRemoteDescriptor'{propGroupID = ID2, + propGrps = Grps2}) -> + chk_IndAudLocalRemoteDescriptor_propGroupID(ID1, ID2), + chk_IndAudPropertyGroup(Grps1, Grps2), + ok; +chk_IndAudLocalRemoteDescriptor(D1, D2) -> + wrong_type('IndAudLocalRemoteDescriptor', D1, D2). + +chk_IndAudLocalRemoteDescriptor_propGroupID(ID, ID) -> + chk_type(fun is_IndAudLocalRemoteDescriptor_propGroupID/1, + 'IndAudLocalRemoteDescriptor_propGroupID', ID); +chk_IndAudLocalRemoteDescriptor_propGroupID(ID1, ID2) -> + case (is_IndAudLocalRemoteDescriptor_propGroupID(ID1) andalso + is_IndAudLocalRemoteDescriptor_propGroupID(ID2)) of + true -> + not_equal('IndAudLocalRemoteDescriptor_propGroupID', ID1, ID2); + false -> + wrong_type('IndAudLocalRemoteDescriptor_propGroupID', ID1, ID2) + end. + + +%% -- IndAudPropertyGroup -- + +is_IndAudPropertyGroup([]) -> + true; +is_IndAudPropertyGroup([H|T]) -> + is_IndAudPropertyParm(H) andalso is_IndAudPropertyGroup(T); +is_IndAudPropertyGroup(_) -> + false. + +chk_IndAudPropertyGroup([], []) -> + ok; +chk_IndAudPropertyGroup([] = PG1, PG2) -> + not_equal('IndAudPropertyGroup', PG1, PG2); +chk_IndAudPropertyGroup(PG1, [] = PG2) -> + not_equal('IndAudPropertyGroup', PG1, PG2); +chk_IndAudPropertyGroup([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_IndAudPropertyGroup(T1, T2); + false -> + wrong_type('IndAudPropertyGroup_val', H) + end; +chk_IndAudPropertyGroup([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, + 'IndAudPropertyGroup_val'), + chk_IndAudPropertyGroup(T1, T2); +chk_IndAudPropertyGroup(P1, P2) -> + wrong_type('IndAudPropertyGroup', P1, P2). + + +%% -- IndAudTerminationStateDescriptor -- + +is_opt_IndAudTerminationStateDescriptor(asn1_NOVALUE) -> + true; +is_opt_IndAudTerminationStateDescriptor(D) -> + is_IndAudTerminationStateDescriptor(D). + +is_IndAudTerminationStateDescriptor( + #'IndAudTerminationStateDescriptor'{propertyParms = Parms, + eventBufferControl = EBC, + serviceState = SS}) -> + is_IndAudTerminationStateDescriptor_propertyParms(Parms) andalso + is_opt_NULL(EBC) andalso is_opt_NULL(SS); +is_IndAudTerminationStateDescriptor(_) -> + false. + +is_IndAudTerminationStateDescriptor_propertyParms([]) -> + true; +is_IndAudTerminationStateDescriptor_propertyParms([H|T]) -> + is_IndAudPropertyParm(H) andalso + is_IndAudTerminationStateDescriptor_propertyParms(T); +is_IndAudTerminationStateDescriptor_propertyParms(_) -> + false. + +chk_opt_IndAudTerminationStateDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudTerminationStateDescriptor(D1, D2) -> + chk_IndAudTerminationStateDescriptor(D1, D2). + +chk_IndAudTerminationStateDescriptor( + #'IndAudTerminationStateDescriptor'{propertyParms = Parms1, + eventBufferControl = EBC1, + serviceState = SS1}, + #'IndAudTerminationStateDescriptor'{propertyParms = Parms2, + eventBufferControl = EBC2, + serviceState = SS2}) -> + chk_IndAudTerminationStateDescriptor_propertyParms(Parms1, Parms2), + validate(fun() -> chk_opt_NULL(EBC1, EBC2) end, + 'IndAudTerminationStateDescriptor'), + validate(fun() -> chk_opt_NULL(SS1, SS2) end, + 'IndAudTerminationStateDescriptor'), + ok; +chk_IndAudTerminationStateDescriptor(D1, D2) -> + wrong_type('IndAudTerminationStateDescriptor', D1, D2). + +chk_IndAudTerminationStateDescriptor_propertyParms([], []) -> + ok; +chk_IndAudTerminationStateDescriptor_propertyParms([] = PP1, PP2) -> + not_equal('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2); +chk_IndAudTerminationStateDescriptor_propertyParms(PP1, [] = PP2) -> + not_equal('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2); +chk_IndAudTerminationStateDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_IndAudTerminationStateDescriptor_propertyParms(T1, T2); + false -> + wrong_type('IndAudTerminationStateDescriptor_propertyParms', H) + end; +chk_IndAudTerminationStateDescriptor_propertyParms([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, + 'IndAudTerminationStateDescriptor_propertyParms'), + chk_IndAudTerminationStateDescriptor_propertyParms(T1, T2); +chk_IndAudTerminationStateDescriptor_propertyParms(PP1, PP2) -> + wrong_type('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2). + + +%% -- IndAudEventsDescriptor -- + +is_IndAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID, + pkgdName = Name, + streamID = SID}) -> + is_opt_RequestID(RID) andalso + is_PkgdName(Name) andalso + is_opt_StreamID(SID); +is_IndAudEventsDescriptor(_) -> + false. + +chk_IndAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID1, + pkgdName = Name1, + streamID = SID1}, + #'IndAudEventsDescriptor'{requestID = RID2, + pkgdName = Name2, + streamID = SID2}) -> + chk_opt_RequestID(RID1, RID2), + chk_PkgdName(Name1, Name2), + chk_opt_StreamID(SID1, SID2), + ok; +chk_IndAudEventsDescriptor(D1, D2) -> + wrong_type('IndAudEventsDescriptor', D1, D2). + + +%% -- IndAudEventBufferDescriptor -- + +is_IndAudEventBufferDescriptor( + #'IndAudEventBufferDescriptor'{eventName = Name, + streamID = SID}) -> + is_PkgdName(Name) andalso is_opt_StreamID(SID); +is_IndAudEventBufferDescriptor(_) -> + false. + +chk_IndAudEventBufferDescriptor( + #'IndAudEventBufferDescriptor'{eventName = Name1, + streamID = SID1}, + #'IndAudEventBufferDescriptor'{eventName = Name2, + streamID = SID2}) -> + chk_PkgdName(Name1, Name2), + chk_opt_StreamID(SID1, SID2), + ok; +chk_IndAudEventBufferDescriptor(D1, D2) -> + wrong_type('IndAudEventBufferDescriptor', D1, D2). + + +%% -- IndAudSignalsDescriptor -- + +is_IndAudSignalsDescriptor({Tag, Val}) -> + is_IndAudSignalsDescriptor_tag(Tag) andalso + is_IndAudSignalsDescriptor_val(Tag, Val); +is_IndAudSignalsDescriptor(_) -> + false. + +is_IndAudSignalsDescriptor_tag(Tag) -> + Tags = [signal, seqSigList], + lists:member(Tag, Tags). + +is_IndAudSignalsDescriptor_val(signal, Val) -> + is_IndAudSignal(Val); +is_IndAudSignalsDescriptor_val(seqSigList, Val) -> + is_IndAudSeqSigList(Val). + +chk_IndAudSignalsDescriptor(D, D) -> + chk_type(fun is_IndAudSignalsDescriptor/1, 'IndAudSignalsDescriptor', D); +chk_IndAudSignalsDescriptor({Tag, Val1} = D1, {Tag, Val2} = D2) -> + case (is_IndAudSignalsDescriptor_tag(Tag) andalso + is_IndAudSignalsDescriptor_val(Tag, Val1) andalso + is_IndAudSignalsDescriptor_val(Tag, Val2)) of + true -> + chk_IndAudSignalsDescriptor_val(Tag, Val1, Val2); + false -> + wrong_type('IndAudSignalsDescriptor', D1, D2) + end; +chk_IndAudSignalsDescriptor({Tag1, Val1} = D1, {Tag2, Val2} = D2) -> + case ((is_IndAudSignalsDescriptor_tag(Tag1) andalso + is_IndAudSignalsDescriptor_val(Tag1, Val1)) andalso + (is_IndAudSignalsDescriptor_tag(Tag2) andalso + is_IndAudSignalsDescriptor_val(Tag2, Val2))) of + true -> + not_equal('IndAudSignalsDescriptor', D1, D2); + false -> + wrong_type('IndAudSignalsDescriptor', D1, D2) + end; +chk_IndAudSignalsDescriptor(D1, D2) -> + wrong_type('IndAudSignalsDescriptor', D1, D2). + +chk_IndAudSignalsDescriptor_val(signal, Val1, Val2) -> + chk_IndAudSignal(Val1, Val2); +chk_IndAudSignalsDescriptor_val(seqSigList, Val1, Val2) -> + chk_IndAudSeqSigList(Val1, Val2). + + +%% -- IndAudSeqSigList -- + +is_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID, + signalList = SL}) -> + is_IndAudSeqSigList_id(ID) andalso is_opt_IndAudSignal(SL); +is_IndAudSeqSigList(_) -> + false. + +is_IndAudSeqSigList_id(ID) -> is_INTEGER(ID, {range, 0, 65535}). + +chk_IndAudSeqSigList(L, L) -> + chk_type(fun is_IndAudSeqSigList/1, 'IndAudSeqSigList', L); +chk_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID1, + signalList = SL1}, + #'IndAudSeqSigList'{id = ID2, + signalList = SL2}) -> + chk_IndAudSeqSigList_id(ID1, ID2), + chk_opt_IndAudSignal(SL1, SL2), + ok; +chk_IndAudSeqSigList(L1, L2) -> + wrong_type('IndAudSeqSigList', L1, L2). + +chk_IndAudSeqSigList_id(ID, ID) -> + chk_type(fun is_IndAudSeqSigList_id/1, 'IndAudSeqSigList_id', ID); +chk_IndAudSeqSigList_id(ID1, ID2) -> + case (is_IndAudSeqSigList_id(ID1) andalso + is_IndAudSeqSigList_id(ID2)) of + true -> + not_equal('IndAudSeqSigList_id', ID1, ID2); + false -> + wrong_type('IndAudSeqSigList_id', ID1, ID2) + end. + + +%% -- IndAudSignal -- + +is_opt_IndAudSignal(asn1_NOVALUE) -> + true; +is_opt_IndAudSignal(V) -> + is_IndAudSignal(V). + +is_IndAudSignal(#'IndAudSignal'{signalName = Name, + streamID = SID}) -> + is_PkgdName(Name) andalso is_opt_StreamID(SID); +is_IndAudSignal(_) -> + false. + +chk_opt_IndAudSignal(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudSignal(S1, S2) -> + chk_IndAudSignal(S1, S2). + +chk_IndAudSignal(S, S) -> + chk_type(fun is_IndAudSignal/1, 'IndAudSignal', S); +chk_IndAudSignal(#'IndAudSignal'{signalName = Name1, + streamID = SID1}, + #'IndAudSignal'{signalName = Name2, + streamID = SID2}) -> + chk_PkgdName(Name1, Name2), + chk_opt_StreamID(SID1, SID2), + ok; +chk_IndAudSignal(S1, S2) -> + wrong_type('IndAudSignal', S1, S2). + + +%% -- IndAudDigitMapDescriptor -- + +is_IndAudDigitMapDescriptor( + #'IndAudDigitMapDescriptor'{digitMapName = Name}) -> + is_opt_DigitMapName(Name); +is_IndAudDigitMapDescriptor(_) -> + false. + +chk_IndAudDigitMapDescriptor(D, D) -> + chk_type(fun is_IndAudDigitMapDescriptor/1, 'IndAudDigitMapDescriptor', D); +chk_IndAudDigitMapDescriptor( + #'IndAudDigitMapDescriptor'{digitMapName = Name1}, + #'IndAudDigitMapDescriptor'{digitMapName = Name2}) -> + validate(fun() -> chk_opt_DigitMapName(Name1, Name2) end, + 'IndAudDigitMapDescriptor'), + ok; +chk_IndAudDigitMapDescriptor(D1, D2) -> + wrong_type('IndAudDigitMapDescriptor', D1, D2). + + +%% -- IndAudStatisticsDescriptor -- + +is_IndAudStatisticsDescriptor( + #'IndAudStatisticsDescriptor'{statName = Name}) -> + is_PkgdName(Name); +is_IndAudStatisticsDescriptor(_) -> + false. + +chk_IndAudStatisticsDescriptor(D, D) -> + chk_type(fun is_IndAudStatisticsDescriptor/1, + 'IndAudStatisticsDescriptor', D); +chk_IndAudStatisticsDescriptor( + #'IndAudStatisticsDescriptor'{statName = Name1}, + #'IndAudStatisticsDescriptor'{statName = Name2}) -> + validate(fun() -> chk_PkgdName(Name1, Name2) end, + 'IndAudStatisticsDescriptor'), + ok; +chk_IndAudStatisticsDescriptor(D1, D2) -> + wrong_type('IndAudStatisticsDescriptor', D1, D2). + + +%% -- IndAudPackagesDescriptor -- + +is_IndAudPackagesDescriptor( + #'IndAudPackagesDescriptor'{packageName = Name, + packageVersion = Ver}) -> + is_Name(Name) andalso is_IndAudPackagesDescriptor_packageVersion(Ver); +is_IndAudPackagesDescriptor(_) -> + false. + +is_IndAudPackagesDescriptor_packageVersion(V) -> + is_INTEGER(V, {range, 0, 99}). + +chk_IndAudPackagesDescriptor( + #'IndAudPackagesDescriptor'{packageName = Name1, + packageVersion = Ver1}, + #'IndAudPackagesDescriptor'{packageName = Name2, + packageVersion = Ver2}) -> + validate(fun() -> chk_Name(Name1, Name2) end, 'IndAudPackagesDescriptor'), + chk_IndAudPackagesDescriptor_packageVersion(Ver1, Ver2), + ok; +chk_IndAudPackagesDescriptor(D1, D2) -> + wrong_type('IndAudPackagesDescriptor', D1, D2). + +chk_IndAudPackagesDescriptor_packageVersion(V, V) -> + chk_type(fun is_IndAudPackagesDescriptor_packageVersion/1, + 'IndAudPackagesDescriptor_packageVersion', V); +chk_IndAudPackagesDescriptor_packageVersion(V1, V2) -> + case (is_IndAudPackagesDescriptor_packageVersion(V1) andalso + is_IndAudPackagesDescriptor_packageVersion(V2)) of + true -> + not_equal('IndAudPackagesDescriptor_packageVersion', V1, V2); + false -> + wrong_type('IndAudPackagesDescriptor_packageVersion', V1, V2) + end. + + +%% -- NotifyRequest -- + +is_NotifyRequest(#'NotifyRequest'{terminationID = Tids, + observedEventsDescriptor = OED, + errorDescriptor = ED}) -> + is_TerminationIDList(Tids) andalso + is_ObservedEventsDescriptor(OED) andalso + is_opt_ErrorDescriptor(ED); +is_NotifyRequest(_) -> + false. + +chk_NotifyRequest(#'NotifyRequest'{terminationID = Tids1, + observedEventsDescriptor = OED1, + errorDescriptor = ED1}, + #'NotifyRequest'{terminationID = Tids2, + observedEventsDescriptor = OED2, + errorDescriptor = ED2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'NotifyRequest'), + validate(fun() -> chk_ObservedEventsDescriptor(OED1, OED2) end, + 'NotifyRequest'), + validate(fun() -> chk_opt_ErrorDescriptor(ED1, ED2) end, + 'NotifyRequest'), + ok; +chk_NotifyRequest(NR1, NR2) -> + wrong_type('NotifyRequest', NR1, NR2). + + +%% -- NotifyReply -- + +is_NotifyReply(#'NotifyReply'{terminationID = Tids, + errorDescriptor = ED}) -> + is_TerminationIDList(Tids) andalso is_opt_ErrorDescriptor(ED); +is_NotifyReply(_) -> + false. + +chk_NotifyReply(#'NotifyReply'{terminationID = Tids1, + errorDescriptor = ED1}, + #'NotifyReply'{terminationID = Tids2, + errorDescriptor = ED2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, 'NotifyReply'), + validate(fun() -> chk_opt_ErrorDescriptor(ED1, ED2) end, 'NotifyReply'), + ok; +chk_NotifyReply(NR1, NR2) -> + wrong_type('NotifyReply', NR1, NR2). + + +%% -- ObservedEventsDescriptor -- + +is_ObservedEventsDescriptor( + #'ObservedEventsDescriptor'{requestId = RID, + observedEventLst = OEL}) -> + is_RequestID(RID) andalso + is_ObservedEventsDescriptor_observedEventLst(OEL); +is_ObservedEventsDescriptor(_) -> + false. + +is_ObservedEventsDescriptor_observedEventLst([]) -> + true; +is_ObservedEventsDescriptor_observedEventLst([H|T]) -> + is_ObservedEvent(H) andalso + is_ObservedEventsDescriptor_observedEventLst(T); +is_ObservedEventsDescriptor_observedEventLst(_) -> + false. + +chk_ObservedEventsDescriptor( + #'ObservedEventsDescriptor'{requestId = RID1, + observedEventLst = OEL1}, + #'ObservedEventsDescriptor'{requestId = RID2, + observedEventLst = OEL2}) -> + validate(fun() -> chk_RequestID(RID1, RID2) end, + 'ObservedEventsDescriptor'), + validate( + fun() -> + chk_ObservedEventsDescriptor_observedEventLst(OEL1, OEL2) + end, + 'ObservedEventsDescriptor'), + ok; +chk_ObservedEventsDescriptor(D1, D2) -> + wrong_type('ObservedEventsDescriptor', D1, D2). + +chk_ObservedEventsDescriptor_observedEventLst([], []) -> + ok; +chk_ObservedEventsDescriptor_observedEventLst([] = L1, L2) -> + not_equal('ObservedEventsDescriptor_observedEventLst', L1, L2); +chk_ObservedEventsDescriptor_observedEventLst(L1, [] = L2) -> + not_equal('ObservedEventsDescriptor_observedEventLst', L1, L2); +chk_ObservedEventsDescriptor_observedEventLst([H|T1], [H|T2]) -> + case is_ObservedEvent(H) of + true -> + chk_ObservedEventsDescriptor_observedEventLst(T1, T2); + false -> + wrong_type('ObservedEventsDescriptor_observedEventLst_val', H) + end; +chk_ObservedEventsDescriptor_observedEventLst([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ObservedEvent(H1, H2) end, + 'ObservedEventsDescriptor_observedEventLst_val'), + chk_ObservedEventsDescriptor_observedEventLst(T1, T2); +chk_ObservedEventsDescriptor_observedEventLst(L1, L2) -> + wrong_type('ObservedEventsDescriptor_observedEventLst', L1, L2). + + +%% -- ObservedEvent -- + +is_ObservedEvent(#'ObservedEvent'{eventName = Name, + streamID = SID, + eventParList = EPL, + timeNotation = TN}) -> + is_EventName(Name) andalso + is_opt_StreamID(SID) andalso + is_ObservedEvent_eventParList(EPL) andalso + is_opt_TimeNotation(TN); +is_ObservedEvent(_) -> + false. + +is_ObservedEvent_eventParList([]) -> + true; +is_ObservedEvent_eventParList([H|T]) -> + is_EventParameter(H) andalso is_ObservedEvent_eventParList(T); +is_ObservedEvent_eventParList(_) -> + false. + +chk_ObservedEvent(E, E) -> + chk_type(fun is_ObservedEvent/1, 'ObservedEvent', E); +chk_ObservedEvent(#'ObservedEvent'{eventName = Name1, + streamID = SID1, + eventParList = EPL1, + timeNotation = TN1}, + #'ObservedEvent'{eventName = Name2, + streamID = SID2, + eventParList = EPL2, + timeNotation = TN2}) -> + validate(fun() -> chk_EventName(Name1, Name2) end, 'ObservedEvent'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'ObservedEvent'), + chk_ObservedEvent_eventParList(EPL1, EPL2), + validate(fun() -> chk_opt_TimeNotation(TN1, TN2) end, 'ObservedEvent'), + ok; +chk_ObservedEvent(E1, E2) -> + wrong_type('ObservedEvent', E1, E2). + +chk_ObservedEvent_eventParList([], []) -> + ok; +chk_ObservedEvent_eventParList([] = EPL1, EPL2) -> + not_equal('ObservedEvent_eventParList', EPL1, EPL2); +chk_ObservedEvent_eventParList(EPL1, [] = EPL2) -> + not_equal('ObservedEvent_eventParList', EPL1, EPL2); +chk_ObservedEvent_eventParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_ObservedEvent_eventParList(T1, T2); + false -> + wrong_type('ObservedEvent_eventParList_val', H) + end; +chk_ObservedEvent_eventParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'ObservedEvent_eventParList'), + chk_ObservedEvent_eventParList(T1, T2); +chk_ObservedEvent_eventParList(L1, L2) -> + wrong_type('ObservedEvent_eventParList', L1, L2). + + +%% -- EventName -- + +is_EventName(N) -> is_PkgdName(N). + +chk_EventName(N, N) -> + chk_type(fun is_EventName/1, 'EventName', N); +chk_EventName(N1, N2) -> + case (is_EventName(N1) andalso is_EventName(N2)) of + true -> + not_equal('EventName', N1, N2); + false -> + wrong_type('EventName', N1, N2) + end. + + +%% -- EventParameter -- + +is_EventParameter(#'EventParameter'{eventParameterName = Name, + value = Val, + extraInfo = EI}) -> + d("is_EventParameter -> entery with" + "~n Name: ~p" + "~n Val: ~p" + "~n EI: ~p", [Name, Val, EI]), + is_Name(Name) andalso + is_Value(Val) andalso + is_EventParameter_extraInfo(EI); +is_EventParameter(_) -> + false. + +is_EventParameter_extraInfo(asn1_NOVALUE) -> + true; +is_EventParameter_extraInfo({Tag, Val}) -> + is_EventParameter_extraInfo_tag(Tag) andalso + is_EventParameter_extraInfo_val(Tag, Val); +is_EventParameter_extraInfo(_) -> + false. + +is_EventParameter_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_EventParameter_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_EventParameter_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_EventParameter_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + +chk_EventParameter(#'EventParameter'{eventParameterName = Name1, + value = Val1, + extraInfo = EI1}, + #'EventParameter'{eventParameterName = Name2, + value = Val2, + extraInfo = EI2}) -> + validate(fun() -> chk_Name(Name1, Name2) end, 'EventParameter'), + validate(fun() -> chk_Value(Val1, Val2) end, 'EventParameter'), + chk_EventParameter_extraInfo(EI1, EI2), + ok; +chk_EventParameter(P1, P2) -> + wrong_type('EventParameter', P1, P2). + +chk_EventParameter_extraInfo(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_EventParameter_extraInfo(EI, EI) -> + chk_type(fun is_EventParameter_extraInfo/1, + 'EventParameter_extraInfo', EI); +chk_EventParameter_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> + case (is_EventParameter_extraInfo_tag(Tag) andalso + is_EventParameter_extraInfo_val(Tag, Val1) andalso + is_EventParameter_extraInfo_val(Tag, Val2)) of + true -> + chk_EventParameter_extraInfo_val(Tag, Val1, Val2); + false -> + wrong_type('EventParameter_extraInfo', EI1, EI2) + end; +chk_EventParameter_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> + case ((is_EventParameter_extraInfo_tag(Tag1) andalso + is_EventParameter_extraInfo_val(Tag1, Val1)) andalso + (is_EventParameter_extraInfo_tag(Tag2) andalso + is_EventParameter_extraInfo_val(Tag2, Val2))) of + true -> + not_equal('EventParameter_extraInfo', EI1, EI2); + false -> + wrong_type('EventParameter_extraInfo', EI1, EI2) + end; +chk_EventParameter_extraInfo(EI1, EI2) -> + wrong_type('EventParameter_extraInfo', EI1, EI2). + +chk_EventParameter_extraInfo_val(relation, Val1, Val2) -> + validate(fun() -> chk_Relation(Val1, Val2) end, + 'EventParameter_extraInfo_val'); +chk_EventParameter_extraInfo_val(range, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, + 'EventParameter_extraInfo_val'); +chk_EventParameter_extraInfo_val(sublist, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, + 'EventParameter_extraInfo_val'). + + +%% -- ServiceChangeRequest -- + +is_ServiceChangeRequest(#'ServiceChangeRequest'{terminationID = Tids, + serviceChangeParms = Parms}) -> + is_TerminationIDList(Tids) andalso is_ServiceChangeParm(Parms); +is_ServiceChangeRequest(_) -> + false. + +chk_ServiceChangeRequest(R, R) -> + chk_type(fun is_ServiceChangeRequest/1, 'ServiceChangeRequest', R); +chk_ServiceChangeRequest( + #'ServiceChangeRequest'{terminationID = Tids1, + serviceChangeParms = Parms1}, + #'ServiceChangeRequest'{terminationID = Tids2, + serviceChangeParms = Parms2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'ServiceChangeRequest'), + validate(fun() -> chk_ServiceChangeParm(Parms1, Parms2) end, + 'ServiceChangeRequest'), + ok; +chk_ServiceChangeRequest(R1, R2) -> + wrong_type('ServiceChangeRequest', R1, R2). + + +%% -- ServiceChangeReply -- + +is_ServiceChangeReply(#'ServiceChangeReply'{terminationID = Tids, + serviceChangeResult = Res}) -> + is_TerminationIDList(Tids) andalso is_ServiceChangeResult(Res); +is_ServiceChangeReply(_) -> + false. + +chk_ServiceChangeReply(R, R) -> + chk_type(fun is_ServiceChangeReply/1, 'ServiceChangeReply', R); +chk_ServiceChangeReply( + #'ServiceChangeReply'{terminationID = Tids1, + serviceChangeResult = Res1}, + #'ServiceChangeReply'{terminationID = Tids2, + serviceChangeResult = Res2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'ServiceChangeReply'), + validate(fun() -> chk_ServiceChangeResult(Res1, Res2) end, + 'ServiceChangeReply'), + ok; +chk_ServiceChangeReply(R1, R2) -> + wrong_type('ServiceChangeReply', R1, R2). + + +%% -- ServiceChangeResult -- + +is_ServiceChangeResult({Tag, Val}) -> + is_ServiceChangeResult_tag(Tag) andalso + is_ServiceChangeResult_val(Tag, Val); +is_ServiceChangeResult(_) -> + false. + +is_ServiceChangeResult_tag(Tag) -> + Tags = [errorDescriptor, serviceChangeResParms], + lists:member(Tag, Tags). + +is_ServiceChangeResult_val(errorDescriptor, Val) -> + is_ErrorDescriptor(Val); +is_ServiceChangeResult_val(serviceChangeResParms, Val) -> + is_ServiceChangeResParm(Val). + +chk_ServiceChangeResult(Res, Res) -> + chk_type(fun is_ServiceChangeResult/1, 'ServiceChangeResult', Res); +chk_ServiceChangeResult({Tag, Val1} = Res1, {Tag, Val2} = Res2) -> + case (is_ServiceChangeResult_tag(Tag) andalso + is_ServiceChangeResult_val(Tag, Val1) andalso + is_ServiceChangeResult_val(Tag, Val2)) of + true -> + chk_ServiceChangeResult_val(Tag, Val1, Val2); + false -> + wrong_type('ServiceChangeResult', Res1, Res2) + end; +chk_ServiceChangeResult({Tag1, Val1} = Res1, {Tag2, Val2} = Res2) -> + case ((is_ServiceChangeResult_tag(Tag1) andalso + is_ServiceChangeResult_val(Tag1, Val1)) andalso + (is_ServiceChangeResult_tag(Tag2) andalso + is_ServiceChangeResult_val(Tag2, Val2))) of + true -> + not_equal('ServiceChangeResult', Res1, Res2); + false -> + wrong_type('ServiceChangeResult', Res1, Res2) + end; +chk_ServiceChangeResult(Res1, Res2) -> + wrong_type('ServiceChangeResult', Res1, Res2). + +chk_ServiceChangeResult_val(errorDescriptor, Val1, Val2) -> + validate(fun() -> chk_ErrorDescriptor(Val1, Val2) end, + 'ServiceChangeResult'); +chk_ServiceChangeResult_val(serviceChangeResParms, Val1, Val2) -> + validate(fun() -> chk_ServiceChangeResParm(Val1, Val2) end, + 'ServiceChangeResult'). + + +%% -- WildcardField -- + +is_WildcardField(WF) -> is_OCTET_STRING(WF, {exact, 1}). + +chk_WildcardField(WF, WF) -> + case is_WildcardField(WF) of + true -> + ok; + false -> + wrong_type('WildcardField', WF) + end; +chk_WildcardField(WF1, WF2) -> + case (is_WildcardField(WF1) andalso is_WildcardField(WF2)) of + true -> + not_equal('WildcardField', WF1, WF2); + false -> + wrong_type('WildcardField', WF1, WF2) + end. + + +%% -- TerminationID -- + +is_TerminationID(#'TerminationID'{wildcard = W, + id = ID}) -> + is_TerminationID_wildcard(W) andalso is_TerminationID_id(ID); +is_TerminationID(#megaco_term_id{contains_wildcards = _W, + id = _ID}) -> + true; % What are the types? +is_TerminationID(_) -> + false. + +is_TerminationID_wildcard([]) -> + true; +is_TerminationID_wildcard([H|T]) -> + is_WildcardField(H) andalso is_TerminationID_wildcard(T); +is_TerminationID_wildcard(_) -> + false. + +is_TerminationID_id(ID) -> is_OCTET_STRING(ID, {range, 1, 8}). + +chk_TerminationID(Id,Id) -> + chk_type(fun is_TerminationID/1, 'TerminationID', Id); +chk_TerminationID(#'TerminationID'{wildcard = W1, + id = I1}, + #'TerminationID'{wildcard = W2, + id = I2}) -> + chk_TerminationID_wildcard(W1, W2), + chk_TerminationID_id(I1, I2), + ok; +chk_TerminationID(#megaco_term_id{contains_wildcards = W1, + id = I1}, + #megaco_term_id{contains_wildcards = W2, + id = I2}) -> + chk_TerminationID_wildcard(W1, W2), + chk_TerminationID_id(I1, I2), + ok; +chk_TerminationID(Tid1, Tid2) -> + wrong_type('TerminationID', Tid1, Tid2). + +chk_TerminationID_wildcard([], []) -> + ok; +chk_TerminationID_wildcard([] = WF1, WF2) -> + not_equal('TerminationID_wildcard', WF1, WF2); +chk_TerminationID_wildcard(WF1, [] = WF2) -> + not_equal('TerminationID_wildcard', WF1, WF2); +chk_TerminationID_wildcard([H|T1], [H|T2]) -> + case is_WildcardField(H) of + true -> + chk_TerminationID_wildcard(T1, T2); + false -> + wrong_type('TerminationID_wildcard_val', H) + end; +chk_TerminationID_wildcard([H1|T1], [H2|T2]) -> + validate(fun() -> chk_WildcardField(H1, H2) end, + 'TerminationID_wildcard_val'), + chk_TerminationID_wildcard(T1, T2); +chk_TerminationID_wildcard(WF1,WF2) -> + not_equal('TerminationId_wildcard', WF1, WF2). + +chk_TerminationID_id(Id, Id) -> + case is_OCTET_STRING(Id, {range, 1, 8}) of + true -> + ok; + false -> + wrong_type('TerminationID_id', Id, Id) + end; +chk_TerminationID_id(Id1, Id2) -> + not_equal(terminationId_id, Id1, Id2). + + +%% -- TerminationIDList -- + +is_TerminationIDList([]) -> + true; +is_TerminationIDList([H|T]) -> + is_TerminationID(H) andalso is_TerminationIDList(T); +is_TerminationIDList(_) -> + false. + +chk_TerminationIDList([], []) -> + ok; +chk_TerminationIDList([] = L1, L2) -> + not_equal('TerminationIDList', L1, L2); +chk_TerminationIDList(L1, [] = L2) -> + not_equal('TerminationIDList', L1, L2); +chk_TerminationIDList([H|T1], [H|T2]) -> + case is_TerminationID(H) of + true -> + chk_TerminationIDList(T1, T2); + false -> + wrong_type('TerminationIDList', H) + end; +chk_TerminationIDList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TerminationID(H1, H2) end, 'TerminationIDList'), + chk_TerminationIDList(T1, T2); +chk_TerminationIDList(L1, L2) -> + wrong_type('TerminationIDList', L1, L2). + + +%% -- MediaDescriptor -- + +is_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TSD, + streams = S}) -> + is_opt_TerminationStateDescriptor(TSD) andalso + is_MediaDescriptor_streams(S); +is_MediaDescriptor(_) -> + false. + +is_MediaDescriptor_streams(asn1_NOVALUE) -> + true; +is_MediaDescriptor_streams({Tag, Val}) -> + is_MediaDescriptor_streams_tag(Tag) andalso + is_MediaDescriptor_streams_val(Tag, Val); +is_MediaDescriptor_streams(_) -> + false. + +is_MediaDescriptor_streams_tag(Tag) -> + Tags = [oneStream, multiStream], + lists:member(Tag, Tags). + +is_MediaDescriptor_streams_val(oneStream, SP) -> + is_StreamParms(SP); +is_MediaDescriptor_streams_val(multiStream, SDL) -> + is_MediaDescriptor_multiStream(SDL). + +is_MediaDescriptor_multiStream([]) -> + true; +is_MediaDescriptor_multiStream([H|T]) -> + is_StreamDescriptor(H) andalso is_MediaDescriptor_multiStream(T); +is_MediaDescriptor_multiStream(_) -> + false. + +chk_MediaDescriptor(D, D) -> + chk_type(fun is_MediaDescriptor/1, 'MediaDescriptor', D); +chk_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TSD1, + streams = S1}, + #'MediaDescriptor'{termStateDescr = TSD2, + streams = S2}) -> + validate( + fun() -> + chk_opt_TerminationStateDescriptor(TSD1, TSD2) + end, + 'MediaDescriptor'), + validate( + fun() -> + chk_MediaDescriptor_streams(S1, S2) + end, + 'MediaDescriptor'), + ok; +chk_MediaDescriptor(D1, D2) -> + wrong_type('MediaDescriptor', D1, D2). + + +chk_MediaDescriptor_streams(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_MediaDescriptor_streams({oneStream, SP1}, {oneStream, SP2}) -> + validate(fun() -> + chk_StreamParms(SP1, SP2) + end, + 'MediaDescriptor_streams'); +chk_MediaDescriptor_streams({multiStream, SDs1}, {multiStream, SDs2}) -> + validate(fun() -> + chk_MediaDescriptor_multiStream(SDs1, SDs2) + end, + 'MediaDescriptor_streams'); +chk_MediaDescriptor_streams(S1, S2) -> + wrong_type('MediaDescriptor_streams', S1, S2). + +chk_MediaDescriptor_multiStream([], []) -> + ok; +chk_MediaDescriptor_multiStream([] = MS1, MS2) -> + not_equal('MediaDescriptor_multiStream', MS1, MS2); +chk_MediaDescriptor_multiStream(MS1, [] = MS2) -> + not_equal('MediaDescriptor_multiStream', MS1, MS2); +chk_MediaDescriptor_multiStream([H|T1], [H|T2]) -> + case is_StreamDescriptor(H) of + true -> + chk_MediaDescriptor_multiStream(T1, T2); + false -> + wrong_type('MediaDescriptor_multiStream_val', H) + end; +chk_MediaDescriptor_multiStream([H1|T1], [H2|T2]) -> + validate(fun() -> chk_StreamDescriptor(H1, H2) end, + 'MediaDescriptor_multiStream_val'), + chk_MediaDescriptor_multiStream(T1, T2); +chk_MediaDescriptor_multiStream(MS1, MS2) -> + wrong_type('MediaDescriptor_multiStream_val', MS1, MS2). + + +%% -- StreamDescriptor -- + +is_StreamDescriptor(#'StreamDescriptor'{streamID = SID, + streamParms = Parms}) -> + is_StreamID(SID) andalso is_StreamParms(Parms); +is_StreamDescriptor(_) -> + false. + +chk_StreamDescriptor(D, D) -> + chk_type(fun is_StreamDescriptor/1, 'StreamDescriptor', D); +chk_StreamDescriptor(#'StreamDescriptor'{streamID = SID1, + streamParms = Parms1}, + #'StreamDescriptor'{streamID = SID2, + streamParms = Parms2}) -> + validate(fun() -> chk_StreamID(SID1, SID2) end, 'StreamDescriptor'), + validate(fun() -> chk_StreamParms(Parms1, Parms2) end, 'StreamDescriptor'), + ok; +chk_StreamDescriptor(D1, D2) -> + wrong_type('StreamDescriptor', D1, D2). + + +%% -- StreamParms -- + +is_StreamParms(#'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD}) -> + is_opt_LocalControlDescriptor(LCD) andalso + is_opt_LocalRemoteDescriptor(LD) andalso + is_opt_LocalRemoteDescriptor(RD); +is_StreamParms(_) -> + false. + +chk_StreamParms(SP, SP) -> + chk_type(fun is_StreamParms/1, 'StreamParms', SP); +chk_StreamParms(#'StreamParms'{localControlDescriptor = LCD1, + localDescriptor = LD1, + remoteDescriptor = RD1}, + #'StreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2}) -> + chk_opt_LocalControlDescriptor(LCD1, LCD2), + validate(fun() -> chk_opt_LocalRemoteDescriptor(LD1, LD2) end, + localDescriptor), + validate(fun() -> chk_opt_LocalRemoteDescriptor(RD1, RD2) end, + remoteDescriptor), + ok; +chk_StreamParms(P1, P2) -> + wrong_type('StreamParms', P1, P2). + + +%% -- LocalControlDescriptor -- + +is_opt_LocalControlDescriptor(asn1_NOVALUE) -> + true; +is_opt_LocalControlDescriptor(D) -> + is_LocalControlDescriptor(D). + +is_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP}) -> + is_opt_StreamMode(SM) andalso + is_opt_BOOLEAN(RV) andalso + is_opt_BOOLEAN(RG) andalso + is_LocalControlDescriptor_propertyParms(PP); +is_LocalControlDescriptor(_) -> + false. + +is_LocalControlDescriptor_propertyParms([]) -> + true; +is_LocalControlDescriptor_propertyParms([H|T]) -> + is_PropertyParm(H) andalso is_LocalControlDescriptor_propertyParms(T); +is_LocalControlDescriptor_propertyParms(_) -> + false. + +chk_opt_LocalControlDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_LocalControlDescriptor(LCD1, LCD2) -> + chk_LocalControlDescriptor(LCD1, LCD2). + +chk_LocalControlDescriptor(LCD, LCD) -> + chk_type(fun is_LocalControlDescriptor/1, 'LocalControlDescriptor', LCD); +chk_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = SM1, + reserveValue = RV1, + reserveGroup = RG1, + propertyParms = PP1}, + #'LocalControlDescriptor'{streamMode = SM2, + reserveValue = RV2, + reserveGroup = RG2, + propertyParms = PP2}) -> + validate( + fun() -> chk_opt_StreamMode(SM1, SM2) end, + 'LocalControlDescriptor'), + validate( + fun() -> chk_opt_BOOLEAN(RV1, RV2) end, + 'LocalControlDescriptor_reserveValue'), + validate( + fun() -> chk_opt_BOOLEAN(RG1, RG2) end, + 'LocalControlDescriptor_reserveGroup'), + chk_LocalControlDescriptor_propertyParms(PP1, PP2), + ok; +chk_LocalControlDescriptor(LCD1, LCD2) -> + wrong_type('LocalControlDescriptor', LCD1, LCD2). + + +chk_LocalControlDescriptor_propertyParms([], []) -> + ok; +chk_LocalControlDescriptor_propertyParms([] = PP1, PP2) -> + not_equal('LocalControlDescriptor_propertyParms', PP1, PP2); +chk_LocalControlDescriptor_propertyParms(PP1, [] = PP2) -> + not_equal('LocalControlDescriptor_propertyParms', PP1, PP2); +chk_LocalControlDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_LocalControlDescriptor_propertyParms(T1, T2); + false -> + wrong_type('LocalControlDescriptor_propertyParms_val', H) + end; +chk_LocalControlDescriptor_propertyParms([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, + 'LocalControlDescriptor_propertyParms_val'), + chk_LocalControlDescriptor_propertyParms(T1, T2); +chk_LocalControlDescriptor_propertyParms(PP1, PP2) -> + wrong_type('LocalControlDescriptor_propertyParms', PP1, PP2). + + +%% -- StreamMode -- + +is_opt_StreamMode(asn1_NOVALUE) -> + true; +is_opt_StreamMode(SM) -> + is_StreamMode(SM). + +is_StreamMode(SM) -> + lists:member(SM, [sendOnly, recvOnly, sendRecv, inactive, loopBack]). + +chk_opt_StreamMode(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_StreamMode(SM1, SM2) -> + chk_StreamMode(SM1, SM2). + +chk_StreamMode(SM, SM) -> + chk_type(fun is_StreamMode/1, 'StreamMode', SM); +chk_StreamMode(SM1, SM2) -> + case (is_StreamMode(SM1) andalso is_StreamMode(SM2)) of + true -> + not_equal('StreamMode', SM1, SM2); + false -> + wrong_type('StreamMode', SM1, SM2) + end. + + +%% -- PropertyParm -- + +is_PropertyParm(#'PropertyParm'{name = N, + value = V, + extraInfo = I}) -> + is_PkgdName(N) andalso + is_PropertyParm_value(V) andalso + is_PropertyParm_extraInfo(I); +is_PropertyParm(_) -> + false. + +is_PropertyParm_value([]) -> + true; +is_PropertyParm_value([H|T]) -> + is_OCTET_STRING(H) andalso is_PropertyParm_value(T); +is_PropertyParm_value(_) -> + false. + +is_PropertyParm_extraInfo(asn1_NOVALUE) -> + true; +is_PropertyParm_extraInfo({Tag, Val}) -> + is_PropertyParm_extraInfo_tag(Tag) andalso + is_PropertyParm_extraInfo_val(Tag, Val); +is_PropertyParm_extraInfo(_) -> + false. + +is_PropertyParm_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_PropertyParm_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_PropertyParm_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_PropertyParm_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + +chk_PropertyParm(P, P) -> + chk_type(fun is_PropertyParm/1, 'PropertyParm', P); +chk_PropertyParm(#'PropertyParm'{name = N1, + value = V1, + extraInfo = I1}, + #'PropertyParm'{name = N2, + value = V2, + extraInfo = I2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'PropertyParm'), + chk_PropertyParm_value(V1, V2), + chk_PropertyParm_extraInfo(I1, I2), + ok; +chk_PropertyParm(P1, P2) -> + wrong_type('PropertyParm', P1, P2). + +chk_PropertyParm_value([], []) -> + ok; +chk_PropertyParm_value([] = V1, V2) -> + not_equal('PropertyParm_value', V1, V2); +chk_PropertyParm_value(V1, [] = V2) -> + not_equal('PropertyParm_value', V1, V2); +chk_PropertyParm_value([H|T1], [H|T2]) -> + case is_OCTET_STRING(H) of + true -> + chk_PropertyParm_value(T1, T2); + false -> + wrong_type('PropertyParm_value_val', H) + end; +chk_PropertyParm_value([H1|_], [H2|_]) -> + case (is_OCTET_STRING(H1) andalso is_OCTET_STRING(H2)) of + true -> + not_equal('PropertyParm_value_val', H1, H2); + false -> + wrong_type('PropertyParm_value_val', H1, H2) + end; +chk_PropertyParm_value(V1, V2) -> + wrong_type('PropertyParm_value', V1, V2). + +chk_PropertyParm_extraInfo(EI, EI) -> + chk_type(fun is_PropertyParm_extraInfo/1, 'PropertyParm_extraInfo', EI); +chk_PropertyParm_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> + case (is_PropertyParm_extraInfo_tag(Tag) and + is_PropertyParm_extraInfo_val(Tag, Val1) and + is_PropertyParm_extraInfo_val(Tag, Val2)) of + true -> + chk_PropertyParm_extraInfo_val(Tag, Val1, Val2); + false -> + wrong_type('PropertyParm_extraInfo', EI1, EI2) + end; +chk_PropertyParm_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> + case ((is_PropertyParm_extraInfo_tag(Tag1) and + is_PropertyParm_extraInfo_val(Tag1, Val1)) and + (is_PropertyParm_extraInfo_tag(Tag2) and + is_PropertyParm_extraInfo_val(Tag2, Val2))) of + true -> + not_equal('PropertyParm_extraInfo', EI1, EI2); + false -> + wrong_type('PropertyParm_extraInfo', EI1, EI2) + end; +chk_PropertyParm_extraInfo(EI1, EI2) -> + wrong_type('PropertyParm_extraInfo', EI1, EI2). + +chk_PropertyParm_extraInfo_val(relation, Val1, Val2) -> + validate(fun() -> chk_Relation(Val1, Val2) end, 'PropertyParm_extraInfo'); +chk_PropertyParm_extraInfo_val(range, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'PropertyParm_extraInfo'); +chk_PropertyParm_extraInfo_val(sublist, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'PropertyParm_extraInfo'). + + +%% -- Name -- + +is_Name(N) -> + %% Binary: is_OCTET_STRING(N, {exact, 2}). + case is_OCTET_STRING(N, {range, 1, 64}) of + true -> + is_NAME(N); + false -> + false + end. + +is_NAME([H|T]) when H =< $z, $a =< H -> + is_NAME2(T); +is_NAME([H|T]) when H =< $Z, $A =< H -> + is_NAME2(T); +is_NAME(_) -> + false. + +is_NAME2([]) -> + true; +is_NAME2([$_|T]) -> + is_NAME2(T); +is_NAME2([H|T]) when H =< $z, $a =< H -> + is_NAME2(T); +is_NAME2([H|T]) when H =< $Z, $A =< H -> + is_NAME2(T); +is_NAME2([H|T]) when H =< $9, $0 =< H -> + is_NAME2(T); +is_NAME2(_) -> + false. + + + +chk_Name(N, N) -> + chk_type(fun is_Name/1, 'Name', N); +chk_Name(N1, N2) -> + case (is_Name(N1) andalso is_Name(N2)) of + true -> + not_equal('Name', N1, N2); + false -> + wrong_type('Name', N1, N2) + end. + + +%% -- PkgdName -- + +%% PkgdName is either "AB/CD" or just plain "ABCD" +%% Note that in ASN.1 the parts is exactly 2 char +%% each, unless you don't use the native config +%% option. In text and in binary without the native +%% option, it is 63 + 1 chars for each. +is_PkgdName(N) -> + d("is_PkgdName -> entry with" + "~n N: ~p", [N]), + case string:tokens(N, "/") of + ["*" = PackageName, "*" = ItemID] -> + d("is_PkgdName -> tokenized (0): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + true; + [PackageName, "*" = ItemID] -> + d("is_PkgdName -> tokenized (1): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + is_Name(PackageName); + [PackageName, ItemID] -> + d("is_PkgdName -> tokenized (2): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + is_Name(PackageName) andalso is_Name(ItemID); + _ -> + is_Name(N) + end. + +chk_PkgdName(N, N) -> + case is_PkgdName(N) of + true -> + ok; + false -> + wrong_type('PkgdName', N, N) + end; +chk_PkgdName(N1, N2) -> + case (is_PkgdName(N1) andalso is_PkgdName(N2)) of + true -> + not_equal('PkgdName', N1, N2); + false -> + wrong_type('PkgdName', N1, N2) + end. + + +%% -- Relation -- + +is_Relation(R) -> + lists:member(R, [greaterThan, smallerThan, unequalTo]). + +chk_Relation(R, R) -> + chk_type(fun is_Relation/1, 'Relation', R); +chk_Relation(R1, R2) -> + case (is_Relation(R1) andalso is_Relation(R2)) of + true -> + not_equal('Relation', R1, R2); + false -> + wrong_type('Relation', R1, R2) + end. + + +%% -- LocalRemoteDescriptor -- + +is_opt_LocalRemoteDescriptor(D) -> + is_OPTIONAL(fun is_LocalRemoteDescriptor/1, D). + +is_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = PGs}) -> + is_LocalRemoteDescriptor_propGrps(PGs); +is_LocalRemoteDescriptor(_) -> + false. + +is_LocalRemoteDescriptor_propGrps([]) -> + true; +is_LocalRemoteDescriptor_propGrps([H|T]) -> + is_PropertyGroup(H) andalso is_LocalRemoteDescriptor_propGrps(T); +is_LocalRemoteDescriptor_propGrps(_) -> + false. + +chk_opt_LocalRemoteDescriptor(D1, D2) -> + chk_OPTIONAL('LocalRemoteDescriptor', D1, D2, + fun is_LocalRemoteDescriptor/1, + fun chk_LocalRemoteDescriptor/2). + +chk_LocalRemoteDescriptor(LRD, LRD) -> + chk_type(fun is_LocalRemoteDescriptor/1, 'LocalRemoteDescriptor', LRD); +chk_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = PG1}, + #'LocalRemoteDescriptor'{propGrps = PG2}) -> + chk_LocalRemoteDescriptor_propGrps(PG1, PG2), + ok; +chk_LocalRemoteDescriptor(LRD1, LRD2) -> + wrong_type('LocalRemoteDescriptor', LRD1, LRD2). + +chk_LocalRemoteDescriptor_propGrps([], []) -> + ok; +chk_LocalRemoteDescriptor_propGrps([] = PG1, PG2) -> + not_equal('LocalRemoteDescriptor_propGrps', PG1, PG2); +chk_LocalRemoteDescriptor_propGrps(PG1, [] = PG2) -> + not_equal('LocalRemoteDescriptor_propGrps', PG1, PG2); +chk_LocalRemoteDescriptor_propGrps([H|T1], [H|T2]) -> + case is_PropertyGroup(H) of + true -> + chk_LocalRemoteDescriptor_propGrps(T1, T2); + false -> + wrong_type('LocalRemoteDescriptor_propGrps_val', H) + end; +chk_LocalRemoteDescriptor_propGrps([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyGroup(H1, H2) end, + 'LocalRemoteDescriptor_propGrps_val'), + chk_LocalRemoteDescriptor_propGrps(T1, T2); +chk_LocalRemoteDescriptor_propGrps(PG1, PG2) -> + wrong_type('LocalRemoteDescriptor_propGrps', PG1, PG2). + + +%% -- PropertyGroup -- + +is_PropertyGroup([]) -> + true; +is_PropertyGroup([H|T]) -> + is_PropertyParm(H) andalso is_PropertyGroup(T); +is_PropertyGroup(_) -> + false. + +chk_PropertyGroup([], []) -> + ok; +chk_PropertyGroup([] = PG1, PG2) -> + not_equal('PropertyGroup', PG1, PG2); +chk_PropertyGroup(PG1, [] = PG2) -> + not_equal('PropertyGroup', PG1, PG2); +chk_PropertyGroup([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_PropertyGroup(T1, T2); + false -> + wrong_type('PropertyGroup_val', H) + end; +chk_PropertyGroup([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, 'PropertyGroup_val'), + chk_PropertyGroup(T1, T2); +chk_PropertyGroup(PG1, PG2) -> + wrong_type('PropertyGroup', PG1, PG2). + + +%% -- TerminationStateDescriptor -- + +is_opt_TerminationStateDescriptor(D) -> + is_OPTIONAL(fun is_TerminationStateDescriptor/1, D). + +is_TerminationStateDescriptor( + #'TerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS}) -> + is_TerminationStateDescriptor_propertyParms(PP) andalso + is_opt_EventBufferControl(EBC) andalso + is_opt_ServiceState(SS); +is_TerminationStateDescriptor(_) -> + false. + +is_TerminationStateDescriptor_propertyParms([]) -> + true; +is_TerminationStateDescriptor_propertyParms([H|T]) -> + is_PropertyParm(H) andalso is_TerminationStateDescriptor_propertyParms(T); +is_TerminationStateDescriptor_propertyParms(_) -> + false. + +chk_opt_TerminationStateDescriptor(D1, D2) -> + chk_OPTIONAL('TerminationStateDescriptor', D1, D2, + fun is_TerminationStateDescriptor/1, + fun chk_TerminationStateDescriptor/2). + +chk_TerminationStateDescriptor(D, D) -> + chk_type(fun is_TerminationStateDescriptor/1, + 'TerminationStateDescriptor', D); +chk_TerminationStateDescriptor( + #'TerminationStateDescriptor'{propertyParms = PP1, + eventBufferControl = EBC1, + serviceState = SS1}, + #'TerminationStateDescriptor'{propertyParms = PP2, + eventBufferControl = EBC2, + serviceState = SS2}) -> + chk_TerminationStateDescriptor_propertyParms(PP1, PP2), + validate( + fun() -> + chk_opt_EventBufferControl(EBC1, EBC2) + end, + 'TerminationStateDescriptor'), + validate( + fun() -> + chk_opt_ServiceState(SS1, SS2) + end, + 'TerminationStateDescriptor'), + ok; +chk_TerminationStateDescriptor(D1, D2) -> + wrong_type('TerminationStateDescriptor', D1, D2). + + +chk_TerminationStateDescriptor_propertyParms([], []) -> + ok; +chk_TerminationStateDescriptor_propertyParms([] = P1, P2) -> + not_equal('TerminationStateDescriptor_propertyParms', P1, P2); +chk_TerminationStateDescriptor_propertyParms(P1, [] = P2) -> + not_equal('TerminationStateDescriptor_propertyParms', P1, P2); +chk_TerminationStateDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_TerminationStateDescriptor_propertyParms(T1, T2); + false -> + wrong_type('TerminationStateDescriptor_propertyParms_val', H) + end; +chk_TerminationStateDescriptor_propertyParms([H1|_], [H2|_]) -> + case (is_PropertyParm(H1) andalso is_PropertyParm(H2)) of + true -> + not_equal('TerminationStateDescriptor_propertyParms_val', H1, H2); + false -> + wrong_type('TerminationStateDescriptor_propertyParms_val', H1, H2) + end; +chk_TerminationStateDescriptor_propertyParms(P1, P2) -> + wrong_type('TerminationStateDescriptor_propertyParms', P1, P2). + + +%% -- EventBufferControl -- + +is_opt_EventBufferControl(asn1_NOVALUE) -> + true; +is_opt_EventBufferControl(EBC) -> + is_EventBufferControl(EBC). + +is_EventBufferControl(EBC) -> + lists:member(EBC, [off, lockStep]). + +chk_opt_EventBufferControl(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_EventBufferControl(EBC1, EBC2) -> + chk_EventBufferControl(EBC1, EBC2). + +chk_EventBufferControl(EBC, EBC) -> + chk_type(fun is_EventBufferControl/1, 'EventBufferControl', EBC); +chk_EventBufferControl(EBC1, EBC2) -> + case (is_EventBufferControl(EBC1) andalso is_EventBufferControl(EBC2)) of + true -> + not_equal('EventBufferControl', EBC1, EBC2); + false -> + wrong_type('EventBufferControl', EBC1, EBC2) + end. + + +%% -- ServiceState -- + +is_opt_ServiceState(asn1_NOVALUE) -> + true; +is_opt_ServiceState(SS) -> + is_ServiceState(SS). + +is_ServiceState(SS) -> + lists:member(SS, [test, outOfSvc, inSvc]). + +chk_opt_ServiceState(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_ServiceState(SS1, SS2) -> + chk_ServiceState(SS1, SS2). + +chk_ServiceState(SS, SS) -> + chk_type(fun is_ServiceState/1, 'ServiceState', SS); +chk_ServiceState(SS1, SS2) -> + case (is_ServiceState(SS1) andalso is_ServiceState(SS2)) of + true -> + not_equal('ServiceState', SS1, SS2); + false -> + wrong_type('ServiceState', SS1, SS2) + end. + + +%% -- MuxDescriptor -- + +is_MuxDescriptor(#'MuxDescriptor'{muxType = MT, + termList = TL, + nonStandardData = NSD}) -> + is_MuxType(MT) andalso + is_MuxDescriptor_termList(TL) andalso + is_NonStandardData(NSD); +is_MuxDescriptor(_) -> + false. + +is_MuxDescriptor_termList([]) -> + true; +is_MuxDescriptor_termList([H|T]) -> + is_TerminationID(H) andalso is_MuxDescriptor_termList(T); +is_MuxDescriptor_termList(_) -> + false. + +chk_MuxDescriptor(D, D) -> + chk_type(fun is_MuxDescriptor/1, 'MuxDescriptor', D); +chk_MuxDescriptor(#'MuxDescriptor'{muxType = MT1, + termList = TL1, + nonStandardData = NSD1}, + #'MuxDescriptor'{muxType = MT2, + termList = TL2, + nonStandardData = NSD2}) -> + validate(fun() -> chk_MuxType(MT1, MT2) end, 'MuxDescriptor'), + chk_MuxDescriptor_termList(TL1, TL2), + validate(fun() -> chk_NonStandardData(NSD1, NSD2) end, 'MuxDescriptor'), + ok; +chk_MuxDescriptor(D1, D2) -> + wrong_type('MuxDescriptor', D1, D2). + +chk_MuxDescriptor_termList([], []) -> + ok; +chk_MuxDescriptor_termList([] = TL1, TL2) -> + not_equal('MuxDescriptor_termList', TL1, TL2); +chk_MuxDescriptor_termList(TL1, [] = TL2) -> + not_equal('MuxDescriptor_termList', TL1, TL2); +chk_MuxDescriptor_termList([H|T1], [H|T2]) -> + case is_TerminationID(H) of + true -> + chk_MuxDescriptor_termList(T1, T2); + false -> + wrong_type('MuxDescriptor_termList_val', H) + end; +chk_MuxDescriptor_termList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TerminationID(H1, H2) end, + 'MuxDescriptor_termList_val'), + chk_MuxDescriptor_termList(T1, T2); +chk_MuxDescriptor_termList(TL1, TL2) -> + wrong_type('MuxDescriptor_termList', TL1, TL2). + + +%% -- MuxType -- + +is_MuxType(MT) -> + lists:member(MT, [h221, h223, h226, v76, nx64k]). + +chk_MuxType(MT, MT) -> + chk_type(fun is_MuxType/1, 'MuxType', MT); +chk_MuxType(MT1, MT2) -> + case (is_MuxType(MT1) andalso is_MuxType(MT2)) of + true -> + not_equal('MuxType', MT1, MT2); + false -> + wrong_type('MuxType', MT1, MT2) + end. + + +%% -- StreamID -- + +is_opt_StreamID(asn1_NOVALUE) -> + true; +is_opt_StreamID(V) -> + is_StreamID(V). + +is_StreamID(V) -> is_INTEGER(V, {range, 0, 65535}). + +chk_opt_StreamID(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_StreamID(V1, V2) -> + chk_StreamID(V1, V2). + +chk_StreamID(ID, ID) -> + chk_type(fun is_StreamID/1, 'StreamID', ID); +chk_StreamID(ID1, ID2) -> + case (is_StreamID(ID1) andalso is_StreamID(ID2)) of + true -> + not_equal('StreamID', ID1, ID2); + false -> + wrong_type('StreamID', ID1, ID2) + end. + + +%% -- EventsDescriptor -- + +is_EventsDescriptor(#'EventsDescriptor'{requestID = RID, + eventList = EVL}) -> + d("is_EventsDescriptor -> entry with" + "~n RID: ~p" + "~n EVL: ~p", [RID, EVL]), + is_opt_RequestID(RID) andalso is_EventsDescriptor_eventList(EVL); +is_EventsDescriptor(_) -> + false. + +is_EventsDescriptor_eventList([]) -> + true; +is_EventsDescriptor_eventList([H|T]) -> + is_RequestedEvent(H) andalso is_EventsDescriptor_eventList(T); +is_EventsDescriptor_eventList(_) -> + false. + +chk_EventsDescriptor(D, D) -> + chk_type(fun is_EventsDescriptor/1, 'EventsDescriptor', D); +chk_EventsDescriptor(#'EventsDescriptor'{requestID = RID1, + eventList = EVL1}, + #'EventsDescriptor'{requestID = RID2, + eventList = EVL2}) -> + validate(fun() -> chk_opt_RequestID(RID1, RID2) end, 'EventsDescriptor'), + chk_EventsDescriptor_eventList(EVL1, EVL2), + ok; +chk_EventsDescriptor(D1, D2) -> + wrong_type('EventsDescriptor', D1, D2). + +chk_EventsDescriptor_eventList([], []) -> + ok; +chk_EventsDescriptor_eventList([] = EVL1, EVL2) -> + not_equal('EventsDescriptor_eventList', EVL1, EVL2); +chk_EventsDescriptor_eventList(EVL1, [] = EVL2) -> + not_equal('EventsDescriptor_eventList', EVL1, EVL2); +chk_EventsDescriptor_eventList([H|T1], [H|T2]) -> + case is_RequestedEvent(H) of + true -> + chk_EventsDescriptor_eventList(T1, T2); + false -> + wrong_type('EventsDescriptor_eventList_val', H) + end; +chk_EventsDescriptor_eventList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_RequestedEvent(H1, H2) end, + 'EventsDescriptor_eventList_val'), + chk_EventsDescriptor_eventList(T1, T2); +chk_EventsDescriptor_eventList(EVL1, EVL2) -> + wrong_type('EventsDescriptor_eventList', EVL1, EVL2). + + +%% -- RequestedEvent -- + +is_RequestedEvent(#'RequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}) -> + d("is_RequestedEvent -> entry with" + "~n N: ~p" + "~n SID: ~p" + "~n EA: ~p" + "~n EPL: ~p", [N, SID, EA, EPL]), + is_PkgdName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_RequestedActions(EA) andalso + is_RequestedEvent_evParList(EPL); +is_RequestedEvent(_) -> + false. + +is_RequestedEvent_evParList([]) -> + true; +is_RequestedEvent_evParList([H|T]) -> + is_EventParameter(H) andalso is_RequestedEvent_evParList(T); +is_RequestedEvent_evParList(_) -> + false. + +chk_RequestedEvent(RE, RE) -> + chk_type(fun is_RequestedEvent/1, 'RequestedEvent', RE); +chk_RequestedEvent(#'RequestedEvent'{pkgdName = N1, + streamID = SID1, + eventAction = EA1, + evParList = EPL1}, + #'RequestedEvent'{pkgdName = N2, + streamID = SID2, + eventAction = EA2, + evParList = EPL2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'RequestedEvent'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'RequestedEvent'), + validate(fun() -> chk_opt_RequestedActions(EA1, EA2) end, + 'RequestedEvent'), + chk_RequestedEvent_evParList(EPL1, EPL2), + ok; +chk_RequestedEvent(RE1, RE2) -> + wrong_type('RequestedEvent', RE1, RE2). + +chk_RequestedEvent_evParList([], []) -> + ok; +chk_RequestedEvent_evParList([] = EPL1, EPL2) -> + not_equal('RequestedEvent_evParList', EPL1, EPL2); +chk_RequestedEvent_evParList(EPL1, [] = EPL2) -> + not_equal('RequestedEvent_evParList', EPL1, EPL2); +chk_RequestedEvent_evParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_RequestedEvent_evParList(T1, T2); + false -> + wrong_type('RequestedEvent_evParList_val', H) + end; +chk_RequestedEvent_evParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'RequestedEvent_evParList_val'), + chk_RequestedEvent_evParList(T1, T2); +chk_RequestedEvent_evParList(EPL1, EPL2) -> + wrong_type('RequestedEvent_evParList', EPL1, EPL2). + + +%% -- RequestedActions -- + +is_opt_RequestedActions(asn1_NOVALUE) -> + true; +is_opt_RequestedActions(RA) -> + is_RequestedActions(RA). + +is_RequestedActions(#'RequestedActions'{keepActive = KA, + eventDM = EDM, + secondEvent = SE, + signalsDescriptor = SD}) -> + d("is_RequestedActions -> entry with" + "~n KA: ~p" + "~n EDM: ~p" + "~n SE: ~p" + "~n SD: ~p", [KA, EDM, SE, SD]), + is_opt_BOOLEAN(KA) andalso + is_opt_EventDM(EDM) andalso + is_opt_SecondEventsDescriptor(SE) andalso + is_opt_SignalsDescriptor(SD); +is_RequestedActions(_) -> + false. + +chk_opt_RequestedActions(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_RequestedActions(RA1, RA2) -> + chk_RequestedActions(RA1, RA2). + +chk_RequestedActions(RA, RA) -> + chk_type(fun is_RequestedActions/1, 'RequestedActions', RA); +chk_RequestedActions(#'RequestedActions'{keepActive = KA1, + eventDM = EDM1, + secondEvent = SA1, + signalsDescriptor = SD1}, + #'RequestedActions'{keepActive = KA2, + eventDM = EDM2, + secondEvent = SA2, + signalsDescriptor = SD2}) -> + validate(fun() -> chk_opt_BOOLEAN(KA1, KA2) end, 'RequestedActions'), + validate(fun() -> chk_opt_EventDM(EDM1, EDM2) end, 'RequestedActions'), + validate(fun() -> chk_opt_SecondEventsDescriptor(SA1, SA2) end, + 'RequestedActions'), + validate(fun() -> chk_opt_SignalsDescriptor(SD1, SD2) end, + 'RequestedActions'), + ok; +chk_RequestedActions(RA1, RA2) -> + wrong_type('RequestedActions', RA1, RA2). + + +%% -- EventDM -- + +is_opt_EventDM(EDM) -> + is_OPTIONAL(fun is_EventDM/1, EDM). + +is_EventDM({Tag, Val}) -> + is_EventDM_tag(Tag) andalso is_EventDM_val(Tag, Val); +is_EventDM(_) -> + false. + +is_EventDM_tag(Tag) -> + Tags = [digitMapName, digitMapValue], + lists:member(Tag, Tags). + +is_EventDM_val(digitMapName, Val) -> + is_DigitMapName(Val); +is_EventDM_val(digitMapValue, Val) -> + is_DigitMapValue(Val). + +chk_opt_EventDM(EDM1, EDM2) -> + chk_OPTIONAL('EventDM', EDM1, EDM2, fun is_EventDM/1, fun chk_EventDM/2). + +chk_EventDM(EDM, EDM) -> + chk_type(fun is_EventDM/1, 'EventDM', EDM); +chk_EventDM({Tag, Val1} = EDM1, {Tag, Val2} = EDM2) -> + case (is_EventDM_tag(Tag) andalso + is_EventDM_val(Tag, Val1) andalso + is_EventDM_val(Tag, Val2)) of + true -> + chk_EventDM_val(Tag, Val1, Val2); + false -> + wrong_type('EventDM', EDM1, EDM2) + end; +chk_EventDM({Tag1, Val1} = EDM1, {Tag2, Val2} = EDM2) -> + case ((is_EventDM_tag(Tag1) andalso + is_EventDM_val(Tag1, Val1)) andalso + (is_EventDM_tag(Tag2) andalso + is_EventDM_val(Tag2, Val2))) of + true -> + not_equal('EventDM', EDM1, EDM2); + false -> + wrong_type('EventDM', EDM1, EDM2) + end; +chk_EventDM(EDM1, EDM2) -> + wrong_type('EventDM', EDM1, EDM2). + +chk_EventDM_val(digitMapName, Val1, Val2) -> + validate(fun() -> chk_DigitMapName(Val1, Val2) end, 'EventDM'); +chk_EventDM_val(digitMapValue, Val1, Val2) -> + validate(fun() -> chk_DigitMapValue(Val1, Val2) end, 'EventDM'). + + +%% -- SecondEventsDescriptor -- + +is_opt_SecondEventsDescriptor(asn1_NOVALUE) -> + true; +is_opt_SecondEventsDescriptor(D) -> + is_SecondEventsDescriptor(D). + +is_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = RID, + eventList = EL}) -> + is_opt_RequestID(RID) andalso is_SecondEventsDescriptor_eventList(EL); +is_SecondEventsDescriptor(_) -> + false. + +is_SecondEventsDescriptor_eventList([]) -> + true; +is_SecondEventsDescriptor_eventList([H|T]) -> + is_SecondRequestedEvent(H) andalso is_SecondEventsDescriptor_eventList(T); +is_SecondEventsDescriptor_eventList(_) -> + false. + +chk_opt_SecondEventsDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SecondEventsDescriptor(D1, D2) -> + chk_SecondEventsDescriptor(D1, D2). + +chk_SecondEventsDescriptor(D, D) -> + chk_type(fun is_SecondEventsDescriptor/1, 'SecondEventsDescriptor', D); +chk_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = RID1, + eventList = EL1}, + #'SecondEventsDescriptor'{requestID = RID2, + eventList = EL2}) -> + validate(fun() -> chk_opt_RequestID(RID1, RID2) end, + 'SecondEventsDescriptor'), + chk_SecondEventsDescriptor_eventList(EL1, EL2), + ok; +chk_SecondEventsDescriptor(D1, D2) -> + wrong_type('SecondEventsDescriptor', D1, D2). + +chk_SecondEventsDescriptor_eventList([], []) -> + ok; +chk_SecondEventsDescriptor_eventList([] = EL1, EL2) -> + not_equal('SecondEventsDescriptor_eventList', EL1, EL2); +chk_SecondEventsDescriptor_eventList(EL1, [] = EL2) -> + not_equal('SecondEventsDescriptor_eventList', EL1, EL2); +chk_SecondEventsDescriptor_eventList([H|T1], [H|T2]) -> + case is_SecondRequestedEvent(H) of + true -> + chk_SecondEventsDescriptor_eventList(T1, T2); + false -> + wrong_type('SecondEventsDescriptor_eventList_val', H) + end; +chk_SecondEventsDescriptor_eventList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_SecondRequestedEvent(H1, H2) end, + 'SecondEventsDescriptor_eventList_val'), + chk_SecondEventsDescriptor_eventList(T1, T2); +chk_SecondEventsDescriptor_eventList(L1, L2) -> + wrong_type('SecondEventsDescriptor_eventList_val', L1, L2). + + +%% -- SecondRequestedEvent -- + +is_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}) -> + is_PkgdName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_SecondRequestedActions(EA) andalso + is_SecondRequestedEvent_evParList(EPL); +is_SecondRequestedEvent(_) -> + false. + +is_SecondRequestedEvent_evParList([]) -> + true; +is_SecondRequestedEvent_evParList([H|T]) -> + is_EventParameter(H) andalso is_SecondRequestedEvent_evParList(T); +is_SecondRequestedEvent_evParList(_) -> + false. + +chk_SecondRequestedEvent(RE, RE) -> + chk_type(fun is_SecondRequestedEvent/1, 'SecondRequestedEvent', RE); +chk_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N1, + streamID = SID1, + eventAction = EA1, + evParList = EPL1}, + #'SecondRequestedEvent'{pkgdName = N2, + streamID = SID2, + eventAction = EA2, + evParList = EPL2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'SecondRequestedEvent'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, + 'SecondRequestedEvent'), + validate(fun() -> chk_opt_SecondRequestedActions(EA1, EA2) end, + 'SecondRequestedEvent'), + chk_SecondRequestedEvent_evParList(EPL1, EPL2), + ok; +chk_SecondRequestedEvent(RE1, RE2) -> + wrong_type('SecondRequestedEvent', RE1, RE2). + +chk_SecondRequestedEvent_evParList([], []) -> + ok; +chk_SecondRequestedEvent_evParList([] = EPL1, EPL2) -> + not_equal('SecondRequestedEvent_evParList', EPL1, EPL2); +chk_SecondRequestedEvent_evParList(EPL1, [] = EPL2) -> + not_equal('SecondRequestedEvent_evParList', EPL1, EPL2); +chk_SecondRequestedEvent_evParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_SecondRequestedEvent_evParList(T1, T2); + false -> + wrong_type('SecondRequestedEvent_evParList_val', H) + end; +chk_SecondRequestedEvent_evParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'SecondRequestedEvent_evParList_val'), + chk_SecondRequestedEvent_evParList(T1, T2); +chk_SecondRequestedEvent_evParList(EPL1, EPL2) -> + wrong_type('SecondRequestedEvent_evParList', EPL1, EPL2). + + +%% -- SecondRequestedActions -- + +is_opt_SecondRequestedActions(asn1_NOVALUE) -> + true; +is_opt_SecondRequestedActions(SRA) -> + is_SecondRequestedActions(SRA). + +is_SecondRequestedActions(#'SecondRequestedActions'{keepActive = KA, + eventDM = EDM, + signalsDescriptor = SD}) -> + is_opt_BOOLEAN(KA) andalso + is_opt_EventDM(EDM) andalso + is_opt_SignalsDescriptor(SD); +is_SecondRequestedActions(_) -> + false. + +chk_opt_SecondRequestedActions(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SecondRequestedActions(SRA1, SRA2) -> + chk_SecondRequestedActions(SRA1, SRA2). + +chk_SecondRequestedActions(SRA, SRA) -> + chk_type(fun is_SecondRequestedActions/1, 'SecondRequestedActions', SRA); +chk_SecondRequestedActions( + #'SecondRequestedActions'{keepActive = KA1, + eventDM = EDM1, + signalsDescriptor = SD1}, + #'SecondRequestedActions'{keepActive = KA2, + eventDM = EDM2, + signalsDescriptor = SD2}) -> + validate(fun() -> chk_opt_BOOLEAN(KA1, KA2) end, + 'SecondRequestedActions'), + validate(fun() -> chk_opt_EventDM(EDM1, EDM2) end, + 'SecondRequestedActions'), + validate(fun() -> chk_opt_SignalsDescriptor(SD1, SD2) end, + 'SecondRequestedActions'), + ok; +chk_SecondRequestedActions(SRA1, SRA2) -> + wrong_type('SecondRequestedActions', SRA1, SRA2). + + +%% -- EventBufferDescriptor -- + +is_EventBufferDescriptor([]) -> + true; +is_EventBufferDescriptor([H|T]) -> + is_EventSpec(H) andalso is_EventBufferDescriptor(T); +is_EventBufferDescriptor(_) -> + false. + +chk_EventBufferDescriptor([], []) -> + ok; +chk_EventBufferDescriptor([] = D1, D2) -> + not_equal('EventBufferDescriptor', D1, D2); +chk_EventBufferDescriptor(D1, [] = D2) -> + not_equal('EventBufferDescriptor', D1, D2); +chk_EventBufferDescriptor([H|T1], [H|T2]) -> + case is_EventSpec(H) of + true -> + chk_EventBufferDescriptor(T1, T2); + false -> + wrong_type('EventBufferDescriptor_val', H) + end; +chk_EventBufferDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventSpec(H1, H2) end, + 'EventBufferDescriptor_val'), + chk_EventBufferDescriptor(T1, T2); +chk_EventBufferDescriptor(D1, D2) -> + wrong_type('EventBufferDescriptor_val', D1, D2). + + +%% -- EventSpec -- + +is_EventSpec(#'EventSpec'{eventName = N, + streamID = SID, + eventParList = EPL}) -> + is_EventName(N) andalso + is_opt_StreamID(SID) andalso + is_EventSpec_eventParList(EPL); +is_EventSpec(_) -> + false. + +is_EventSpec_eventParList([]) -> + true; +is_EventSpec_eventParList([H|T]) -> + is_EventParameter(H) andalso is_EventSpec_eventParList(T); +is_EventSpec_eventParList(_) -> + false. + +chk_EventSpec(ES, ES) -> + chk_type(fun is_EventSpec/1, 'EventSpec', ES); +chk_EventSpec(#'EventSpec'{eventName = N1, + streamID = SID1, + eventParList = EPL1}, + #'EventSpec'{eventName = N2, + streamID = SID2, + eventParList = EPL2}) -> + validate(fun() -> chk_EventName(N1, N2) end, 'EventSpec'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'EventSpec'), + chk_EventSpec_eventParList(EPL1, EPL2), + ok; +chk_EventSpec(ES1, ES2) -> + wrong_type('EventSpec', ES1, ES2). + +chk_EventSpec_eventParList([], []) -> + ok; +chk_EventSpec_eventParList([] = EPL1, EPL2) -> + not_equal('EventSpec_eventParList', EPL1, EPL2); +chk_EventSpec_eventParList(EPL1, [] = EPL2) -> + not_equal('EventSpec_eventParList', EPL1, EPL2); +chk_EventSpec_eventParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_EventSpec_eventParList(T1, T2); + false -> + wrong_type('EventSpec_eventParList_val', H) + end; +chk_EventSpec_eventParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'EventSpec_eventParList_val'), + chk_EventSpec_eventParList(T1, T2); +chk_EventSpec_eventParList(EPL1, EPL2) -> + wrong_type('EventSpec_eventParList', EPL1, EPL2). + + +%% -- SignalsDescriptor -- + +is_opt_SignalsDescriptor(asn1_NOVALUE) -> + true; +is_opt_SignalsDescriptor(D) -> + is_SignalsDescriptor(D). + +is_SignalsDescriptor([]) -> + true; +is_SignalsDescriptor([H|T]) -> + is_SignalRequest(H) andalso is_SignalsDescriptor(T); +is_SignalsDescriptor(_) -> + false. + +chk_opt_SignalsDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SignalsDescriptor(D1, D2) -> + chk_SignalsDescriptor(D1, D2). + +chk_SignalsDescriptor([], []) -> + ok; +chk_SignalsDescriptor([] = D1, D2) -> + not_equal('SignalsDescriptor', D1, D2); +chk_SignalsDescriptor(D1, [] = D2) -> + not_equal('SignalsDescriptor', D1, D2); +chk_SignalsDescriptor([H|T1], [H|T2]) -> + case is_SignalRequest(H) of + true -> + chk_SignalsDescriptor(T1, T2); + false -> + wrong_type('SignalsDescriptor_val', H) + end; +chk_SignalsDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_SignalRequest(H1, H2) end, 'SignalsDescriptor_val'), + chk_SignalsDescriptor(T1, T2); +chk_SignalsDescriptor(D1, D2) -> + wrong_type('SignalsDescriptor', D1, D2). + + +%% -- SignalRequest -- + +is_SignalRequest({Tag, Val}) -> + is_SignalRequest_tag(Tag) andalso is_SignalRequest_val(Tag, Val); +is_SignalRequest(_) -> + false. + +is_SignalRequest_tag(Tag) -> + Tags = [signal, seqSigList], + lists:member(Tag, Tags). + +is_SignalRequest_val(signal, Val) -> + is_Signal(Val); +is_SignalRequest_val(seqSigList, Val) -> + is_SeqSigList(Val). + +chk_SignalRequest(R, R) -> + chk_type(fun is_SignalRequest/1, 'SignalRequest', R); +chk_SignalRequest({Tag, Val1} = R1, {Tag, Val2} = R2) -> + case (is_SignalRequest_tag(Tag) andalso + is_SignalRequest_val(Tag, Val1) andalso + is_SignalRequest_val(Tag, Val2)) of + true -> + chk_SignalRequest_val(Tag, Val1, Val2); + false -> + wrong_type('SignalRequest', R1, R2) + end; +chk_SignalRequest({Tag1, Val1} = R1, {Tag2, Val2} = R2) -> + case ((is_SignalRequest_tag(Tag1) andalso + is_SignalRequest_val(Tag1, Val1)) andalso + (is_SignalRequest_tag(Tag2) andalso + is_SignalRequest_val(Tag2, Val2))) of + true -> + not_equal('SignalRequest', R1, R2); + false -> + wrong_type('SignalRequest', R1, R2) + end; +chk_SignalRequest(R1, R2) -> + wrong_type('SignalRequest', R1, R2). + +chk_SignalRequest_val(signal, Val1, Val2) -> + validate(fun() -> chk_Signal(Val1, Val2) end, 'SignalRequest'); +chk_SignalRequest_val(seqSigList, Val1, Val2) -> + validate(fun() -> chk_SeqSigList(Val1, Val2) end, 'SignalRequest'). + + +%% -- SeqSigList -- + +is_SeqSigList(#'SeqSigList'{id = ID, + signalList = SL}) -> + is_INTEGER(ID, {range, 0, 65535}) andalso + is_SeqSigList_signalList(SL); +is_SeqSigList(_) -> + false. + +is_SeqSigList_signalList([]) -> + true; +is_SeqSigList_signalList([H|T]) -> + is_Signal(H) andalso is_SeqSigList_signalList(T); +is_SeqSigList_signalList(_) -> + false. + +chk_SeqSigList(L, L) -> + chk_type(fun is_SeqSigList/1, 'SeqSigList', L); +chk_SeqSigList(#'SeqSigList'{id = ID1, + signalList = SL1}, + #'SeqSigList'{id = ID2, + signalList = SL2}) -> + validate(fun() -> chk_INTEGER(ID1, ID2, {range, 0, 65535}) end, + 'SeqSigList'), + chk_SeqSigList_signalList(SL1, SL2), + ok; +chk_SeqSigList(L1, L2) -> + wrong_type('SeqSigList', L1, L2). + +chk_SeqSigList_signalList([], []) -> + ok; +chk_SeqSigList_signalList([] = L1, L2) -> + not_equal('SeqSigList_signalList', L1, L2); +chk_SeqSigList_signalList(L1, [] = L2) -> + not_equal('SeqSigList_signalList', L1, L2); +chk_SeqSigList_signalList([H|T1], [H|T2]) -> + case is_Signal(H) of + true -> + chk_SeqSigList_signalList(T1, T2); + false -> + wrong_type('SeqSigList_signalList_val', H) + end; +chk_SeqSigList_signalList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_Signal(H1, H2) end, + 'SeqSigList_signalList_val'), + chk_SeqSigList_signalList(T1, T2); +chk_SeqSigList_signalList(L1, L2) -> + wrong_type('SeqSigList_signalList', L1, L2). + + +%% -- Signal -- + +is_Signal(#'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL}) -> + is_SignalName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_SignalType(ST) andalso + is_opt_INTEGER(Dur, {range, 0, 65535}) andalso + is_opt_NotifyCompletion(NC) andalso + is_opt_BOOLEAN(KA) andalso + is_Signal_sigParList(SPL). + +is_Signal_sigParList([]) -> + true; +is_Signal_sigParList([H|T]) -> + is_SigParameter(H) andalso is_Signal_sigParList(T); +is_Signal_sigParList(_) -> + false. + +chk_Signal(S, S) -> + chk_type(fun is_Signal/1, 'Signal', S); +chk_Signal(#'Signal'{signalName = N1, + streamID = SID1, + sigType = ST1, + duration = Dur1, + notifyCompletion = NC1, + keepActive = KA1, + sigParList = SPL1}, + #'Signal'{signalName = N2, + streamID = SID2, + sigType = ST2, + duration = Dur2, + notifyCompletion = NC2, + keepActive = KA2, + sigParList = SPL2}) -> + validate(fun() -> chk_SignalName(N1, N2) end, 'Signal'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'Signal'), + validate(fun() -> chk_opt_SignalType(ST1, ST2) end, 'Signal'), + validate(fun() -> chk_opt_INTEGER(Dur1, Dur2, {range, 0, 65535}) end, + 'Signal'), + validate(fun() -> chk_opt_NotifyCompletion(NC1, NC2) end, 'Signal'), + validate(fun() -> chk_opt_BOOLEAN(KA1, KA2) end, 'Signal'), + chk_Signal_sigParList(SPL1, SPL2), + ok; +chk_Signal(S1, S2) -> + wrong_type('Signal', S1, S2). + +chk_Signal_sigParList([], []) -> + ok; +chk_Signal_sigParList([] = L1, L2) -> + not_equal('Signal_sigParList', L1, L2); +chk_Signal_sigParList(L1, [] = L2) -> + not_equal('Signal_sigParList', L1, L2); +chk_Signal_sigParList([H|T1], [H|T2]) -> + case is_SigParameter(H) of + true -> + chk_Signal_sigParList(T1, T2); + false -> + wrong_type('Signal_sigParList_val', H) + end; +chk_Signal_sigParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_SigParameter(H1, H2) end, + 'Signal_sigParList_val'), + chk_Signal_sigParList(T1, T2); +chk_Signal_sigParList(L1, L2) -> + wrong_type('Signal_sigParList', L1, L2). + + +%% -- SignalType -- + +is_opt_SignalType(asn1_NOVALUE) -> + true; +is_opt_SignalType(T) -> + is_SignalType(T). + +is_SignalType(T) -> + Types = [brief, onOff, timeOut], + lists:member(T, Types). + +chk_opt_SignalType(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SignalType(T1, T2) -> + chk_SignalType(T1, T2). + +chk_SignalType(T, T) -> + chk_type(fun is_SignalType/1, 'SignalType', T); +chk_SignalType(T1, T2) -> + case (is_SignalType(T1) andalso is_SignalType(T2)) of + true -> + not_equal('SignalType', T1, T2); + false -> + wrong_type('SignalType', T1, T2) + end. + + +%% -- SignalName -- + +is_SignalName(N) -> is_PkgdName(N). + +chk_SignalName(N1, N2) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'SignalName'). + + +%% -- NotifyCompletion -- + +is_opt_NotifyCompletion(NC) -> + is_OPTIONAL(fun is_NotifyCompletion/1, NC). + +is_NotifyCompletion(NC) -> + Valids = [onTimeOut, + onInterruptByEvent, + onInterruptByNewSignalDescr, + otherReason], + lists:member(NC, Valids). + +chk_opt_NotifyCompletion(NC1, NC2) -> + chk_OPTIONAL('NotifyCompletion', NC1, NC2, + fun is_NotifyCompletion/1, + fun chk_NotifyCompletion/2). + +chk_NotifyCompletion(NC, NC) -> + chk_type(fun is_NotifyCompletion/1, 'NotifyCompletion', NC); +chk_NotifyCompletion(NC1, NC2) -> + case (is_NotifyCompletion(NC1) andalso is_NotifyCompletion(NC2)) of + true -> + not_equal('NotifyCompletion', NC1, NC2); + false -> + wrong_type('NotifyCompletion', NC1, NC2) + end. + + +%% -- SigParameter -- + +is_SigParameter(#'SigParameter'{sigParameterName = N, + value = V, + extraInfo = I}) -> + is_Name(N) andalso + is_Value(V) andalso + is_SigParameter_extraInfo(I); +is_SigParameter(_) -> + false. + +is_SigParameter_extraInfo({Tag, Val}) -> + is_SigParameter_extraInfo_tag(Tag) andalso + is_SigParameter_extraInfo_val(Tag, Val); +is_SigParameter_extraInfo(_) -> + false. + +is_SigParameter_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_SigParameter_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_SigParameter_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_SigParameter_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + +chk_SigParameter(P, P) -> + chk_type(fun is_SigParameter/1, 'SigParameter', P); +chk_SigParameter(#'SigParameter'{sigParameterName = N1, + value = V1, + extraInfo = I1}, + #'SigParameter'{sigParameterName = N2, + value = V2, + extraInfo = I2}) -> + validate(fun() -> chk_Name(N1, N2) end, 'SigParameter'), + validate(fun() -> chk_Value(V1, V2) end, 'SigParameter'), + chk_SigParameter_extraInfo(I1, I2), + ok; +chk_SigParameter(P1, P2) -> + wrong_type('SigParameter', P1, P2). + +chk_SigParameter_extraInfo(EI, EI) -> + chk_type(fun is_SigParameter_extraInfo/1, 'SigParameter_extraInfo', EI); +chk_SigParameter_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> + case (is_SigParameter_extraInfo_tag(Tag) and + is_SigParameter_extraInfo_val(Tag, Val1) and + is_SigParameter_extraInfo_val(Tag, Val2)) of + true -> + chk_SigParameter_extraInfo_val(Tag, Val1, Val2); + false -> + wrong_type('SigParameter_extraInfo', EI1, EI2) + end; +chk_SigParameter_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> + case ((is_SigParameter_extraInfo_tag(Tag1) and + is_SigParameter_extraInfo_val(Tag1, Val1)) and + (is_SigParameter_extraInfo_tag(Tag2) and + is_SigParameter_extraInfo_val(Tag2, Val2))) of + true -> + not_equal('SigParameter_extraInfo', EI1, EI2); + false -> + wrong_type('SigParameter_extraInfo', EI1, EI2) + end; +chk_SigParameter_extraInfo(EI1, EI2) -> + wrong_type('SigParameter_extraInfo', EI1, EI2). + +chk_SigParameter_extraInfo_val(relation, Val1, Val2) -> + validate(fun() -> chk_Relation(Val1, Val2) end, 'SigParameter_extraInfo'); +chk_SigParameter_extraInfo_val(range, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'SigParameter_extraInfo'); +chk_SigParameter_extraInfo_val(sublist, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'SigParameter_extraInfo'). + + +%% -- RequestID -- + +is_opt_RequestID(asn1_NOVALUE) -> + true; +is_opt_RequestID(V) -> + is_RequestID(V). + +is_RequestID(V) -> is_INTEGER(V, {range, 0, 4294967295}). + +chk_opt_RequestID(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_RequestID(V1, V2) -> + chk_RequestID(V1, V2). + +chk_RequestID(ID, ID) -> + chk_type(fun is_RequestID/1, 'RequestID', ID); +chk_RequestID(ID1, ID2) -> + case (is_RequestID(ID1) andalso is_RequestID(ID2)) of + true -> + not_equal('RequestID', ID1, ID2); + false -> + wrong_type('RequestID', ID1, ID2) + end. + + +%% -- ModemDescriptor -- + +is_ModemDescriptor(D) when is_record(D, 'ModemDescriptor') -> + true; +is_ModemDescriptor(_) -> + false. + +chk_ModemDescriptor(D, D) when is_record(D, 'ModemDescriptor') -> + ok; +chk_ModemDescriptor(#'ModemDescriptor'{mtl = MTL1, + mpl = MPL1, + nonStandardData = NSD1}, + #'ModemDescriptor'{mtl = MTL2, + mpl = MPL2, + nonStandardData = NSD2}) -> + chk_ModemDescriptor_mtl(MTL1, MTL2), + chk_ModemDescriptor_mpl(MPL1, MPL2), + chk_opt_NonStandardData(NSD1, NSD2), + ok; +chk_ModemDescriptor(D1, D2) -> + wrong_type('ModemDescriptor', D1, D2). + +chk_ModemDescriptor_mtl([], []) -> + ok; +chk_ModemDescriptor_mtl([] = MTL1, MTL2) -> + not_equal('ModemDescriptor_mtl', MTL1, MTL2); +chk_ModemDescriptor_mtl(MTL1, [] = MTL2) -> + not_equal('ModemDescriptor_mtl', MTL1, MTL2); +chk_ModemDescriptor_mtl([H|T1], [H|T2]) -> + case is_ModemType(H) of + true -> + chk_ModemDescriptor_mtl(T1, T2); + false -> + wrong_type('ModemDescriptor_mtl_val', H) + end; +chk_ModemDescriptor_mtl([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ModemType(H1, H2) end, 'ModemDescriptor_mtl_val'), + chk_ModemDescriptor_mtl(T1, T2); +chk_ModemDescriptor_mtl(MTL1, MTL2) -> + wrong_type('ModemDescriptor_mtl', MTL1, MTL2). + + +chk_ModemDescriptor_mpl([], []) -> + ok; +chk_ModemDescriptor_mpl([] = MPL1, MPL2) -> + not_equal('ModemDescriptor_mpl', MPL1, MPL2); +chk_ModemDescriptor_mpl(MPL1, [] = MPL2) -> + not_equal('ModemDescriptor_mpl', MPL1, MPL2); +chk_ModemDescriptor_mpl([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_ModemDescriptor_mpl(T1, T2); + false -> + wrong_type('ModemDescriptor_mpl_val', H) + end; +chk_ModemDescriptor_mpl([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, 'ModemDescriptor_mpl_val'), + chk_ModemDescriptor_mpl(T1, T2); +chk_ModemDescriptor_mpl(MPL1, MPL2) -> + wrong_type('ModemDescriptor_mpl', MPL1, MPL2). + + +%% -- ModemType -- + +chk_ModemType(MT, MT) -> + case is_ModemType(MT) of + true -> + ok; + false -> + wrong_type('ModemType', MT, MT) + end; +chk_ModemType(MT1, MT2) -> + case (is_ModemType(MT1) andalso is_ModemType(MT2)) of + true -> + not_equal('ModemType', MT1, MT2); + false -> + wrong_type('ModemType', MT1, MT2) + end. + +is_ModemType(MT) -> + lists:member(MT, + [v18, v22, v22bis, v32, v32bis, v34, v90, v91, synchISDN]). + + +%% -- DigitMapDescriptor -- + +is_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Val}) -> + is_opt_DigitMapName(Name) andalso is_opt_DigitMapValue(Val); +is_DigitMapDescriptor(_) -> + false. + +chk_DigitMapDescriptor(D, D) -> + chk_type(fun is_DigitMapDescriptor/1, 'DigitMapDescriptor', D); +chk_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name1, + digitMapValue = Val1}, + #'DigitMapDescriptor'{digitMapName = Name2, + digitMapValue = Val2}) -> + d("chk_DigitMapDescriptor -> entry with" + "~n Name1: ~p" + "~n Name2: ~p" + "~n Val1: ~p" + "~n Val2: ~p", [Name1, Name2, Val1, Val2]), + validate(fun() -> chk_opt_DigitMapName(Name1, Name2) end, + 'DigitMapDescriptor'), + validate(fun() -> chk_opt_DigitMapValue(Val1, Val2) end, + 'DigitMapDescriptor'), + ok; +chk_DigitMapDescriptor(D1, D2) -> + wrong_type('DigitMapDescriptor', D1, D2). + + +%% -- DigitMapName -- + +is_opt_DigitMapName(asn1_NOVALUE) -> + true; +is_opt_DigitMapName(N) -> + is_DigitMapName(N). + +is_DigitMapName(N) -> is_Name(N). + +chk_opt_DigitMapName(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_DigitMapName(N1, N2) -> + chk_DigitMapName(N1, N2). + +chk_DigitMapName(N, N) -> + chk_type(fun is_DigitMapName/1, 'DigitMapName', N); +chk_DigitMapName(N1, N2) -> + case (is_DigitMapName(N1) andalso is_DigitMapName(N2)) of + true -> + not_equal('DigitMapName', N1, N2); + false -> + wrong_type('DigitMapName', N1, N2) + end. + + +%% -- DigitMapValue -- + +is_opt_DigitMapValue(V) -> + is_OPTIONAL(fun is_DigitMapValue/1, V). + +is_DigitMapValue(#'DigitMapValue'{startTimer = Start, + shortTimer = Short, + longTimer = Long, + digitMapBody = Body, + durationTimer = Dur}) -> + is_DigitMapValue_startTimer(Start) andalso + is_DigitMapValue_shortTimer(Short) andalso + is_DigitMapValue_longTimer(Long) andalso + is_IA5String(Body) andalso + is_DigitMapValue_durationTimer(Dur); +is_DigitMapValue(_) -> + false. + +is_DigitMapValue_startTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_startTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +is_DigitMapValue_shortTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_shortTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +is_DigitMapValue_longTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_longTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +is_DigitMapValue_durationTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_durationTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +chk_opt_DigitMapValue(V1, V2) -> + chk_OPTIONAL('DigitMapValue', V1, V2, + fun is_DigitMapValue/1, fun chk_DigitMapValue/2). + +chk_DigitMapValue(#'DigitMapValue'{startTimer = Start1, + shortTimer = Short1, + longTimer = Long1, + digitMapBody = Body1, + durationTimer = Dur1}, + #'DigitMapValue'{startTimer = Start2, + shortTimer = Short2, + longTimer = Long2, + digitMapBody = Body2, + durationTimer = Dur2}) -> + d("chk_DigitMapValue -> entry with" + "~n Start1: ~p" + "~n Start2: ~p" + "~n Short1: ~p" + "~n Short2: ~p" + "~n Long1: ~p" + "~n Long2: ~p" + "~n Body1: ~p" + "~n Body2: ~p" + "~n Dur1: ~p" + "~n Dur2: ~p", [Start1, Start2, + Short1, Short2, + Long1, Long2, + Body1, Body2, + Dur1, Dur2]), + chk_DigitMapValue_startTimer(Start1, Start2), + chk_DigitMapValue_shortTimer(Short1, Short2), + chk_DigitMapValue_longTimer(Long1, Long2), + chk_DigitMapValue_digitMapBody(Body1, Body2), + chk_DigitMapValue_durationTimer(Dur1, Dur2), + ok; +chk_DigitMapValue(V1, V2) -> + wrong_type('DigitMapValue', V1, V2). + +chk_DigitMapValue_startTimer(T, T) -> + chk_type(fun is_DigitMapValue_startTimer/1, 'DigitMapValue_startTimer', T); +chk_DigitMapValue_startTimer(T1, T2) -> + case (is_DigitMapValue_startTimer(T1) andalso + is_DigitMapValue_startTimer(T2)) of + true -> + not_equal('DigitMapValue_startTimer', T1, T2); + false -> + wrong_type('DigitMapValue_startTimer', T1, T2) + end. + +chk_DigitMapValue_shortTimer(T, T) -> + chk_type(fun is_DigitMapValue_shortTimer/1, 'DigitMapValue_shortTimer', T); +chk_DigitMapValue_shortTimer(T1, T2) -> + case (is_DigitMapValue_shortTimer(T1) andalso + is_DigitMapValue_shortTimer(T2)) of + true -> + not_equal('DigitMapValue_shortTimer', T1, T2); + false -> + wrong_type('DigitMapValue_shortTimer', T1, T2) + end. + +chk_DigitMapValue_longTimer(T, T) -> + chk_type(fun is_DigitMapValue_longTimer/1, 'DigitMapValue_longTimer', T); +chk_DigitMapValue_longTimer(T1, T2) -> + case (is_DigitMapValue_longTimer(T1) andalso + is_DigitMapValue_longTimer(T2)) of + true -> + not_equal('DigitMapValue_longTimer', T1, T2); + false -> + wrong_type('DigitMapValue_longTimer', T1, T2) + end. + +chk_DigitMapValue_durationTimer(T, T) -> + chk_type(fun is_DigitMapValue_durationTimer/1, + 'DigitMapValue_durationTimer', T); +chk_DigitMapValue_durationTimer(T1, T2) -> + case (is_DigitMapValue_durationTimer(T1) andalso + is_DigitMapValue_durationTimer(T2)) of + true -> + not_equal('DigitMapValue_durationTimer', T1, T2); + false -> + wrong_type('DigitMapValue_durationTimer', T1, T2) + end. + +chk_DigitMapValue_digitMapBody(B, B) -> + d("chk_DigitMapValue_digitMapBody -> entry with" + "~n B: ~p", [B]), + chk_type(fun is_IA5String/1, 'DigitMapValue_digitMapBody', B); +chk_DigitMapValue_digitMapBody(B1, B2) -> + d("chk_DigitMapValue_digitMapBody -> entry with" + "~n B1: ~p" + "~n B2: ~p", [B1, B2]), + case (is_IA5String(B1) andalso is_IA5String(B2)) of + true -> + %% If they are different it could be because + %% of trailing tab's and newline's. + case compare_strings(B1, B2) of + {[], []} -> + ok; + {Str1, []} -> + case strip_tab_and_newline(Str1) of + [] -> + ok; + _ -> + not_equal('DigitMapValue_digitMapBody', B1, B2) + end; + {[], Str2} -> + case strip_tab_and_newline(Str2) of + [] -> + ok; + _ -> + not_equal('DigitMapValue_digitMapBody', B1, B2) + end; + _ -> + not_equal('DigitMapValue_digitMapBody', B1, B2) + end; + false -> + wrong_type('DigitMapValue_digitMapBody', B1, B2) + end. + +%% -- ServiceChangeParm -- + +is_ServiceChangeParm(#'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeAddress = A, + serviceChangeVersion = V, + serviceChangeProfile = P, + serviceChangeReason = R, + serviceChangeDelay = D, + serviceChangeMgcId = Id, + timeStamp = TS, + nonStandardData = NSD, + serviceChangeInfo = I}) -> + is_ServiceChangeMethod(M) andalso + is_opt_ServiceChangeAddress(A) andalso + is_opt_INTEGER(V, {range, 0, 99}) andalso + is_opt_ServiceChangeProfile(P) andalso + is_Value(R) andalso + is_opt_INTEGER(D, {range, 0, 4294967295}) andalso + is_opt_MId(Id) andalso + is_opt_TimeNotation(TS) andalso + is_opt_NonStandardData(NSD) andalso + is_opt_AuditDescriptor(I); +is_ServiceChangeParm(_) -> + false. + +chk_ServiceChangeParm(P, P) -> + chk_type(fun is_ServiceChangeParm/1, 'ServiceChangeParm', P); +chk_ServiceChangeParm(#'ServiceChangeParm'{serviceChangeMethod = M1, + serviceChangeAddress = A1, + serviceChangeVersion = V1, + serviceChangeProfile = P1, + serviceChangeReason = R1, + serviceChangeDelay = D1, + serviceChangeMgcId = Id1, + timeStamp = TS1, + nonStandardData = NSD1, + serviceChangeInfo = I1}, + #'ServiceChangeParm'{serviceChangeMethod = M2, + serviceChangeAddress = A2, + serviceChangeVersion = V2, + serviceChangeProfile = P2, + serviceChangeReason = R2, + serviceChangeDelay = D2, + serviceChangeMgcId = Id2, + timeStamp = TS2, + nonStandardData = NSD2, + serviceChangeInfo = I2}) -> + validate(fun() -> chk_ServiceChangeMethod(M1, M2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_ServiceChangeAddress(A1, A2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_INTEGER(V1, V2, {range, 0, 99}) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_ServiceChangeProfile(P1, P2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_Value(R1, R2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_INTEGER(D1, D2, {range, 0, 4294967295}) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_MId(Id1, Id2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_TimeNotation(TS1, TS2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_NonStandardData(NSD1, NSD2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_AuditDescriptor(I1, I2) end, + 'ServiceChangeParm'), + ok; +chk_ServiceChangeParm(P1, P2) -> + wrong_type('ServiceChangeParm', P1, P2). + + +%% -- ServiceChangeAddress -- + +is_opt_ServiceChangeAddress(A) -> + is_OPTIONAL(fun is_ServiceChangeAddress/1, A). + +is_ServiceChangeAddress({Tag, Val}) -> + is_ServiceChangeAddress_tag(Tag) andalso + is_ServiceChangeAddress_val(Tag, Val); +is_ServiceChangeAddress(_) -> + false. + +is_ServiceChangeAddress_tag(Tag) -> + Tags = [portNumber, ip4Address, ip6Address, domainName, deviceName, + mtpAddress], + lists:member(Tag, Tags). + +is_ServiceChangeAddress_val(portNumber, Val) -> + is_INTEGER(Val, {range, 0, 65535}); +is_ServiceChangeAddress_val(ip4Address, Val) -> + is_IP4Address(Val); +is_ServiceChangeAddress_val(ip6Address, Val) -> + is_IP6Address(Val); +is_ServiceChangeAddress_val(domainName, Val) -> + is_DomainName(Val); +is_ServiceChangeAddress_val(deviceName, Val) -> + is_PathName(Val); +is_ServiceChangeAddress_val(mtpAddress, Val) -> + is_OCTET_STRING(Val, {range, 2, 4}). + + +chk_opt_ServiceChangeAddress(A1, A2) -> + chk_OPTIONAL('ServiceChangeAddress', A1, A2, + fun is_ServiceChangeAddress/1, + fun chk_ServiceChangeAddress/2). + +chk_ServiceChangeAddress(A, A) -> + chk_type(fun is_ServiceChangeAddress/1, 'ServiceChangeAddress', A); +chk_ServiceChangeAddress({Tag, Val1} = A1, {Tag, Val2} = A2) -> + case (is_ServiceChangeAddress_tag(Tag) andalso + is_ServiceChangeAddress_val(Tag, Val1) andalso + is_ServiceChangeAddress_val(Tag, Val2)) of + true -> + chk_ServiceChangeAddress_val(Tag, Val1, Val2); + false -> + wrong_type('ServiceChangeAddress', A1, A2) + end; +chk_ServiceChangeAddress({Tag1, Val1} = A1, {Tag2, Val2} = A2) -> + case ((is_ServiceChangeAddress_tag(Tag1) andalso + is_ServiceChangeAddress_val(Tag1, Val1)) andalso + (is_ServiceChangeAddress_tag(Tag2) andalso + is_ServiceChangeAddress_val(Tag2, Val2))) of + true -> + not_equal('ServiceChangeAddress', A1, A2); + false -> + wrong_type('ServiceChangeAddress', A1, A2) + end; +chk_ServiceChangeAddress(A1, A2) -> + wrong_type('ServiceChangeAddress', A1, A2). + +chk_ServiceChangeAddress_val(portNumber, Val1, Val2) -> + validate(fun() -> chk_INTEGER(Val1, Val2, {range, 0, 99}) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(ip4Address, Val1, Val2) -> + validate(fun() -> chk_IP4Address(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(ip6Address, Val1, Val2) -> + validate(fun() -> chk_IP6Address(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(domainName, Val1, Val2) -> + validate(fun() -> chk_DomainName(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(deviceName, Val1, Val2) -> + validate(fun() -> chk_PathName(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(mtpAddress, Val1, Val2) -> + validate(fun() -> chk_OCTET_STRING(Val1, Val2, {range, 2, 4}) end, + 'ServiceChangeAddress'). + + +%% -- ServiceChangeResParm -- + +is_ServiceChangeResParm(#'ServiceChangeResParm'{serviceChangeMgcId = Id, + serviceChangeAddress = A, + serviceChangeVersion = V, + serviceChangeProfile = P, + timeStamp = TS}) -> + is_opt_MId(Id) andalso + is_opt_ServiceChangeAddress(A) andalso + is_opt_INTEGER(V, {range, 0, 99}) andalso + is_opt_ServiceChangeProfile(P) andalso + is_opt_TimeNotation(TS); +is_ServiceChangeResParm(_) -> + false. + +chk_ServiceChangeResParm(P, P) -> + chk_type(fun is_ServiceChangeResParm/1, 'ServiceChangeResParm', P); +chk_ServiceChangeResParm( + #'ServiceChangeResParm'{serviceChangeMgcId = Id1, + serviceChangeAddress = A1, + serviceChangeVersion = V1, + serviceChangeProfile = P1, + timeStamp = TS1}, + #'ServiceChangeResParm'{serviceChangeMgcId = Id2, + serviceChangeAddress = A2, + serviceChangeVersion = V2, + serviceChangeProfile = P2, + timeStamp = TS2}) -> + validate(fun() -> chk_opt_MId(Id1, Id2) end, 'ServiceChangeResParm'), + validate(fun() -> chk_opt_ServiceChangeAddress(A1, A2) end, + 'ServiceChangeResParm'), + validate(fun() -> chk_opt_INTEGER(V1, V2, {range, 0, 99}) end, + 'ServiceChangeResParm'), + validate(fun() -> chk_opt_ServiceChangeProfile(P1, P2) end, + 'ServiceChangeResParm'), + validate(fun() -> chk_opt_TimeNotation(TS1, TS2) end, + 'ServiceChangeResParm'), + ok; +chk_ServiceChangeResParm(P1, P2) -> + wrong_type('ServiceChangeResParm', P1, P2). + + +%% -- ServiceChangeMethod -- + +is_ServiceChangeMethod(M) -> + Methods = [failover, forced, graceful, restart, disconnected, handOff], + lists:member(M, Methods). + +chk_ServiceChangeMethod(M, M) -> + chk_type(fun is_ServiceChangeMethod/1, 'ServiceChangeMethod', M); +chk_ServiceChangeMethod(M1, M2) -> + case (is_ServiceChangeMethod(M1) andalso is_ServiceChangeMethod(M2)) of + true -> + not_equal('ServiceChangeMethod', M1, M2); + false -> + wrong_type('ServiceChangeMethod', M1, M2) + end. + + +%% -- ServiceChangeProfile -- + +is_opt_ServiceChangeProfile(P) -> + is_OPTIONAL(fun is_ServiceChangeProfile/1, P). + +is_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = N}) -> + is_IA5String(N, {range, 1, 67}); +is_ServiceChangeProfile(_) -> + false. + +chk_opt_ServiceChangeProfile(P1, P2) -> + chk_OPTIONAL('ServiceChangeProfile', P1, P2, + fun is_ServiceChangeProfile/1, + fun chk_ServiceChangeProfile/2). + +chk_ServiceChangeProfile(P, P) -> + chk_type(fun is_ServiceChangeProfile/1, 'ServiceChangeProfile', P); +chk_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = N1}, + #'ServiceChangeProfile'{profileName = N2}) -> + validate(fun() -> chk_IA5String(N1, N2, {range, 1, 67}) end, + 'ServiceChangeProfile'), + ok; +chk_ServiceChangeProfile(P1, P2) -> + wrong_type('ServiceChangeProfile', P1, P2). + + +%% -- PackagesDescriptor -- + +is_PackagesDescriptor([]) -> + true; +is_PackagesDescriptor([H|T]) -> + is_PackagesItem(H) andalso is_PackagesDescriptor(T); +is_PackagesDescriptor(_) -> + false. + +chk_PackagesDescriptor([], []) -> + ok; +chk_PackagesDescriptor([] = D1, D2) -> + not_equal('PackagesDescriptor', D1, D2); +chk_PackagesDescriptor(D1, [] = D2) -> + not_equal('PackagesDescriptor', D1, D2); +chk_PackagesDescriptor([H|T1], [H|T2]) -> + case is_PackagesItem(H) of + true -> + chk_PackagesDescriptor(T1, T2); + false -> + wrong_type('PackagesDescriptor_val', H) + end; +chk_PackagesDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PackagesItem(H1, H2) end, + 'PackagesDescriptor_val'), + chk_PackagesDescriptor(T1, T2); +chk_PackagesDescriptor(D1, D2) -> + wrong_type('PackagesDescriptor_val', D1, D2). + + +%% -- PackagesItem -- + +is_PackagesItem(#'PackagesItem'{packageName = N, + packageVersion = V}) -> + is_Name(N) andalso is_INTEGER(V, {range, 0, 99}); +is_PackagesItem(_) -> + false. + +chk_PackagesItem(I, I) -> + chk_type(fun is_PackagesItem/1, 'PackagesItem', I); +chk_PackagesItem(#'PackagesItem'{packageName = N1, + packageVersion = V1}, + #'PackagesItem'{packageName = N2, + packageVersion = V2}) -> + validate(fun() -> chk_Name(N1, N2) end, 'PackagesItem'), + validate(fun() -> chk_INTEGER(V1, V2, {range, 0, 99}) end, 'PackagesItem'), + ok; +chk_PackagesItem(I1, I2) -> + wrong_type('PackagesItem', I1, I2). + + +%% -- StatisticsDescriptor -- + +is_StatisticsDescriptor([]) -> + true; +is_StatisticsDescriptor([H|T]) -> + is_StatisticsParameter(H) andalso is_StatisticsDescriptor(T); +is_StatisticsDescriptor(_) -> + false. + +chk_StatisticsDescriptor([], []) -> + ok; +chk_StatisticsDescriptor([] = D1, D2) -> + not_equal('StatisticsDescriptor', D1, D2); +chk_StatisticsDescriptor(D1, [] = D2) -> + not_equal('StatisticsDescriptor', D1, D2); +chk_StatisticsDescriptor([H|T1], [H|T2]) -> + case is_StatisticsParameter(H) of + true -> + chk_StatisticsDescriptor(T1, T2); + false -> + wrong_type('StatisticsDescriptor_val', H) + end; +chk_StatisticsDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_StatisticsParameter(H1, H2) end, + 'StatisticsDescriptor_val'), + chk_StatisticsDescriptor(T1, T2); +chk_StatisticsDescriptor(D1, D2) -> + wrong_type('StatisticsDescriptor_val', D1, D2). + + +%% -- StatisticsParameter -- + +is_StatisticsParameter(#'StatisticsParameter'{statName = N, + statValue = V}) -> + is_PkgdName(N) andalso is_opt_Value(V); +is_StatisticsParameter(_) -> + false. + +chk_StatisticsParameter(P, P) -> + chk_type(fun is_StatisticsParameter/1, 'StatisticsParameter', P); +chk_StatisticsParameter(#'StatisticsParameter'{statName = N1, + statValue = V1}, + #'StatisticsParameter'{statName = N2, + statValue = V2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'StatisticsParameter'), + validate(fun() -> chk_opt_Value(V1, V2) end, 'StatisticsParameter'), + ok; +chk_StatisticsParameter(P1, P2) -> + wrong_type('StatisticsParameter', P1, P2). + + +%% -- NonStandardData -- + +is_opt_NonStandardData(asn1_NOVALUE) -> + true; +is_opt_NonStandardData(NSD) -> + is_NonStandardData(NSD). + +%% is_NonStandardData(#'NonStandardData'{nonStandardIdentifier = Id, +%% data = D}) -> +%% is_NonStandardIdentifier(Id) andalso is_OCTET_STRING(D); +%% is_NonStandardData(_) -> +%% false. + +is_NonStandardData(_) -> + true. + +chk_opt_NonStandardData(asn1_NOVALUE, asn1_NOVALUE) -> + true; +chk_opt_NonStandardData(NSD1, NSD2) -> + chk_NonStandardData(NSD1, NSD2). + +chk_NonStandardData(NSD, NSD) -> + chk_type(fun is_NonStandardData/1, 'NonStandardData', NSD); +%% chk_NonStandardData(#'NonStandardData'{nonStandardIdentifier = Id1, +%% data = D1}, +%% #'NonStandardData'{nonStandardIdentifier = Id2, +%% data = D2}) -> +%% validate(fun() -> chk_NonStandardIdentifier(Id1, Id2) end, +%% 'NonStandardData'), +%% validate(fun() -> chk_OCTET_STRING(D1, D2) end, 'NonStandardData'), +%% ok; +%% chk_NonStandardData(NSD1, NSD2) -> +%% wrong_type('NonStandardData', NSD1, NSD2). +chk_NonStandardData(NSD1, NSD2) -> + not_equal('NonStandardData', NSD1, NSD2). + + +%% -- NonStandardIdentifier -- + +%% is_NonStandardIdentifier({Tag, Val}) -> +%% is_NonStandardIdentifier_tag(Tag) andalso +%% is_NonStandardIdentifier_val(Tag, Val); +%% is_NonStandardIdentifier(_) -> +%% false. + +%% is_NonStandardIdentifier_tag(Tag) -> +%% Tags = [object, h221NonStandard, experimental], +%% lists:member(Tag, Tags). + +%% is_NonStandardIdentifier_val(object, Val) -> +%% is_OBJECT_IDENTIFIER(Val); +%% is_NonStandardIdentifier_val(h221NonStandard, Val) -> +%% is_H221NonStandard(Val); +%% is_NonStandardIdentifier_val(experimental, Val) -> +%% is_IA5String(Val, {exact, 8}). + +%% chk_NonStandardIdentifier(Id, Id) -> +%% chk_type(fun is_NonStandardIdentifier/1, 'NonStandardIdentifier', Id); +%% chk_NonStandardIdentifier({Tag, Val1} = Id1, {Tag, Val2} = Id2) -> +%% case (is_NonStandardIdentifier_tag(Tag) andalso +%% is_NonStandardIdentifier_val(Tag, Val1) andalso +%% is_NonStandardIdentifier_val(Tag, Val1)) of +%% true -> +%% chk_NonStandardIdentifier_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('NonStandardIdentifier', Id1, Id2) +%% end; +%% chk_NonStandardIdentifier({Tag1, Val1} = Id1, {Tag2, Val2} = Id2) -> +%% case ((is_NonStandardIdentifier_tag(Tag1) andalso +%% is_NonStandardIdentifier_val(Tag1, Val1)) andalso +%% (is_NonStandardIdentifier_tag(Tag2) andalso +%% is_NonStandardIdentifier_val(Tag2, Val1))) of +%% true -> +%% not_equal('NonStandardIdentifier', Id1, Id2); +%% false -> +%% wrong_type('NonStandardIdentifier', Id1, Id2) +%% end; +%% chk_NonStandardIdentifier(Id1, Id2) -> +%% wrong_type('NonStandardIdentifier', Id1, Id2). + +%% chk_NonStandardIdentifier_val(object, Val1, Val2) -> +%% chk_OBJECT_IDENTIFIER(Val1, Val2); +%% chk_NonStandardIdentifier_val(h221NonStandard, Val1, Val2) -> +%% chk_H221NonStandard(Val1, Val2); +%% chk_NonStandardIdentifier_val(experimental, Val1, Val2) -> +%% chk_IA5String(Val1, Val2, {exact, 8}). + + +%% -- H221NonStandard -- + +%% is_H221NonStandard(#'H221NonStandard'{t35CountryCode1 = CC1, +%% t35CountryCode2 = CC2, +%% t35Extension = Ext, +%% manufacturerCode = MC}) -> +%% is_INTEGER(CC1, {range, 0, 255}) andalso +%% is_INTEGER(CC2, {range, 0, 255}) andalso +%% is_INTEGER(Ext, {range, 0, 255}) andalso +%% is_INTEGER(Ext, {range, 0, 65535}); +%% is_H221NonStandard(_) -> +%% false. + +%% chk_H221NonStandard(NS, NS) -> +%% chk_type(fun is_H221NonStandard/1, 'H221NonStandard', NS); +%% chk_H221NonStandard(#'H221NonStandard'{t35CountryCode1 = CC11, +%% t35CountryCode2 = CC21, +%% t35Extension = Ext1, +%% manufacturerCode = MC1}, +%% #'H221NonStandard'{t35CountryCode1 = CC12, +%% t35CountryCode2 = CC22, +%% t35Extension = Ext2, +%% manufacturerCode = MC2}) -> +%% validate(fun() -> chk_INTEGER(CC11, CC12, {range, 0, 255}) end, +%% 'H221NonStandard'), +%% validate(fun() -> chk_INTEGER(CC21, CC22, {range, 0, 255}) end, +%% 'H221NonStandard'), +%% validate(fun() -> chk_INTEGER(Ext1, Ext2, {range, 0, 255}) end, +%% 'H221NonStandard'), +%% validate(fun() -> chk_INTEGER(MC1, MC2, {range, 0, 65535}) end, +%% 'H221NonStandard'), +%% ok; +%% chk_H221NonStandard(NS1, NS2) -> +%% wrong_type('H221NonStandard', NS1, NS2). + + +%% -- TimeNotation -- + +is_opt_TimeNotation(asn1_NOVALUE) -> + true; +is_opt_TimeNotation(TN) -> + is_TimeNotation(TN). + +is_TimeNotation(#'TimeNotation'{date = D, time = T}) -> + is_IA5String(D, {exact, 8}) andalso is_IA5String(T, {exact, 8}); +is_TimeNotation(_) -> + false. + +chk_opt_TimeNotation(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_TimeNotation(TN1, TN2) -> + chk_TimeNotation(TN1, TN2). + +chk_TimeNotation(TN, TN) -> + chk_type(fun is_TimeNotation/1, 'TimeNotation', TN); +chk_TimeNotation(#'TimeNotation'{date = D1, time = T1}, + #'TimeNotation'{date = D2, time = T2}) -> + validate(fun() -> chk_IA5String(D1, D2, {exact, 8}) end, 'TimeNotation'), + validate(fun() -> chk_IA5String(T1, T2, {exact, 8}) end, 'TimeNotation'), + ok; +chk_TimeNotation(TN1, TN2) -> + wrong_type('TimeNotation', TN1, TN2). + + +%% -- Value -- + +is_opt_Value(V) -> + is_OPTIONAL(fun is_Value/1, V). + +is_Value([]) -> + true; +is_Value([H|T]) -> + is_OCTET_STRING(H) andalso is_Value(T); +is_Value(_) -> + false. + +chk_opt_Value(V1, V2) -> + chk_OPTIONAL('Value', V1, V2, fun is_Value/1, fun chk_Value/2). + +chk_Value(V, V) -> + case is_Value(V) of + true -> + ok; + false -> + wrong_type('Value', V, V) + end; +chk_Value(V1, V2) -> + case (is_Value(V1) andalso is_Value(V2)) of + true -> + not_equal('Value', V1, V2); + false -> + wrong_type('Value', V1, V2) + end. + + +%% ---------------------------------------------------------------------- +%% Basic type check functions +%% ---------------------------------------------------------------------- + + +is_opt_BOOLEAN(B) -> + is_OPTIONAL(fun is_BOOLEAN/1, B). + +is_BOOLEAN(B) -> + lists:member(B, [true, false]). + +chk_opt_BOOLEAN(B1, B2) -> + chk_OPTIONAL('BOOLEAN', B1, B2, fun is_BOOLEAN/1, fun chk_BOOLEAN/2). + +chk_BOOLEAN(B, B) -> + chk_type(fun is_BOOLEAN/1, 'BOOLEAN', B); +chk_BOOLEAN(B1, B2) -> + case (is_BOOLEAN(B1) andalso is_BOOLEAN(B2)) of + true -> + not_equal('BOOLEAN', B1, B2); + false -> + wrong_type('BOOLEAN', B1, B2) + end. + + +is_IA5String(S) when is_list(S) -> + true; +is_IA5String(_) -> + false. + +is_IA5String(S, _) when is_list(S) -> + true; +is_IA5String(_, _) -> + false. + +%% chk_IA5String(S, S) -> +%% chk_type(fun is_IA5String/1, 'IA5String', S); +%% chk_IA5String(S1, S2) -> +%% case (is_IA5String(S1) andalso is_IA5String(S2)) of +%% true -> +%% not_equal('IA5String', S1, S2); +%% false -> +%% wrong_type('IA5String', S1, S2) +%% end. + +chk_IA5String(S, S, R) -> + chk_type(fun is_IA5String/2, 'IA5String', S, R); +chk_IA5String(S1, S2, R) -> + case (is_IA5String(S1, R) andalso is_IA5String(S2, R)) of + true -> + not_equal('IA5String', S1, S2); + false -> + wrong_type('IA5String', S1, S2) + end. + + +is_OCTET_STRING(L) -> is_OCTET_STRING(L, any). + +is_OCTET_STRING(L, any) when is_list(L) -> + true; +is_OCTET_STRING(L, {exact, Len}) when is_list(L) andalso (length(L) =:= Len) -> + true; +is_OCTET_STRING(L, {atleast, Len}) when is_list(L) andalso (Len =< length(L)) -> + true; +is_OCTET_STRING(L, {atmost, Len}) when is_list(L) andalso (length(L) =< Len) -> + true; +is_OCTET_STRING(L, {range, Min, Max}) + when is_list(L) andalso (Min =< length(L)) andalso (length(L) =< Max) -> + true; +is_OCTET_STRING(_, _) -> + false. + +%% chk_OCTET_STRING(L1, L2) -> +%% chk_OCTET_STRING(L1, L2, any). + +chk_OCTET_STRING(L, L, R) -> + chk_type(fun is_OCTET_STRING/2, 'OCTET STRING', L, R); +chk_OCTET_STRING(L1, L2, R) -> + case (is_OCTET_STRING(L1, R) andalso is_OCTET_STRING(L2, R)) of + true -> + not_equal('OCTET STRING', L1, L2); + false -> + wrong_type('OCTET STRING', L1, L2) + end. + + +%% is_OBJECT_IDENTIFIER(_) -> +%% true. + +%% chk_OBJECT_IDENTIFIER(X, X) -> +%% ok; +%% chk_OBJECT_IDENTIFIER(X1, X2) -> +%% not_equal('OBJECT IDENTIFIER', X1, X2). + + +is_opt_NULL(N) -> + is_OPTIONAL(fun is_NULL/1, N). + +is_NULL('NULL') -> + true; +is_NULL(_) -> + false. + +chk_opt_NULL(N1, N2) -> + chk_OPTIONAL('NULL', N1, N2, fun is_NULL/1, fun chk_NULL/2). + +chk_NULL(N, N) -> + chk_type(fun is_NULL/1, 'NULL', N); +chk_NULL(N1, N2) -> + case (is_NULL(N1) andalso is_NULL(N2)) of + true -> + not_equal('NULL', N1, N2); + false -> + wrong_type('NULL', N1, N2) + end. + + +is_opt_INTEGER(I, R) -> + is_OPTIONAL(fun(X) -> is_INTEGER(X, R) end, I). + +is_INTEGER(I, any) when is_integer(I) -> + true; +is_INTEGER(I, {exact, I}) when is_integer(I) -> + true; +is_INTEGER(I, {atleast, Min}) when is_integer(I) andalso is_integer(Min) andalso (Min =< I) -> + true; +is_INTEGER(I, {atmost, Max}) when is_integer(I) andalso is_integer(Max) andalso (I =< Max) -> + true; +is_INTEGER(I, {range, Min, Max}) + when is_integer(I) andalso + is_integer(Min) andalso + is_integer(Max) andalso + (Min =< I) andalso + (I =< Max) -> + true; +is_INTEGER(_, _) -> + false. + +chk_opt_INTEGER(I1, I2, R) -> + chk_OPTIONAL('INTEGER', I1, I2, + fun(X) -> is_INTEGER(X, R) end, + fun(Y1, Y2) -> chk_INTEGER(Y1, Y2, R) end). + +chk_INTEGER(I, I, R) -> + chk_type(fun is_INTEGER/2, 'INTEGER', I, R); +chk_INTEGER(I1, I2, R) -> + case (is_INTEGER(I1, R) andalso is_INTEGER(I2, R)) of + true -> + not_equal('INTEGER', I1, I2); + false -> + wrong_type('INTEGER', I1, I2) + end. + + +%% ---------------------------------------------------------------------- +%% Various utility functions +%% ---------------------------------------------------------------------- + + +to_lower([C|Cs]) when C >= $A, C =< $Z -> + [C+($a-$A)|to_lower(Cs)]; +to_lower([C|Cs]) -> + [C|to_lower(Cs)]; +to_lower([]) -> + []. + + +validate(F, Type) when is_function(F) -> + case (catch F()) of + {error, Reason} -> + error({Type, Reason}); + ok -> + ok + end. + + +chk_type(F, T, V) when is_function(F) andalso is_atom(T) -> + case F(V) of + true -> + ok; + false -> + wrong_type(T, V) + end. + +chk_type(F, T, V1, V2) when is_function(F) andalso is_atom(T) -> + case F(V1, V2) of + true -> + ok; + false -> + wrong_type(T, V1) + end. + + +is_OPTIONAL(_, asn1_NOVALUE) -> + true; +is_OPTIONAL(F, Val) when is_function(F) -> + F(Val). + +chk_OPTIONAL(_, asn1_NOVALUE, asn1_NOVALUE, _, _) -> + ok; +chk_OPTIONAL(Type, asn1_NOVALUE = V1, V2, IS, _CHK) when is_function(IS) -> + case IS(V2) of + true -> + not_equal(Type, V1, V2); + false -> + wrong_type(Type, V1, V2) + end; +chk_OPTIONAL(Type, V1, asn1_NOVALUE = V2, IS, _CHK) when is_function(IS) -> + case IS(V1) of + true -> + not_equal(Type, V1, V2); + false -> + wrong_type(Type, V1, V2) + end; +chk_OPTIONAL(_Type, V1, V2, _IS, CHK) when is_function(CHK) -> + CHK(V1, V2). + + +%% ---------------------------------------------------------------------- + +compare_strings([] = L1, L2) -> + {L1, L2}; +compare_strings(L1, [] = L2) -> + {L1, L2}; +compare_strings([H|T1], [H|T2]) -> + compare_strings(T1, T2); +compare_strings(L1, L2) -> + {L1, L2}. + +strip_tab_and_newline([]) -> + []; +strip_tab_and_newline([$\n|T]) -> + strip_tab_and_newline(T); +strip_tab_and_newline([$\t|T]) -> + strip_tab_and_newline(T); +strip_tab_and_newline([H|T]) -> + [H|strip_tab_and_newline(T)]. + + +%% ---------------------------------------------------------------------- + +atmost_once(Type, Val) -> + error({atmost_once, {Type, Val}}). + +wrong_type(Type, Val) -> + error({wrong_type, {Type, Val}}). + +wrong_type(Type, Val1, Val2) -> + error({wrong_type, {Type, Val1, Val2}}). + +not_equal(What, Val1, Val2) -> + error({not_equal, {What, Val1, Val2}}). + +error(Reason) -> + throw({error, Reason}). + + +%% ---------------------------------------------------------------------- + +d(F) -> + d(F, []). + +d(F, A) -> + d(get(dbg), F, A). + +d(true, F, A) -> + io:format("DBG:" ++ F ++ "~n", A); +d(_, _, _) -> + ok. + diff --git a/lib/megaco/test/megaco_test_msg_v3_lib.erl b/lib/megaco/test/megaco_test_msg_v3_lib.erl new file mode 100644 index 0000000000..7b0d4f7d37 --- /dev/null +++ b/lib/megaco/test/megaco_test_msg_v3_lib.erl @@ -0,0 +1,8724 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Utility functions for creating the megaco types +%%---------------------------------------------------------------------- + +-module(megaco_test_msg_v3_lib). + +%% ---- + +-include_lib("megaco/include/megaco_message_v3.hrl"). +-include_lib("megaco/include/megaco.hrl"). + +%% ---- + +-export([chk_MegacoMessage/2, + + cre_MegacoMessage/1, + cre_MegacoMessage/2, + + cre_ActionReply/2, + cre_ActionReply/3, + cre_ActionReply/4, + cre_ActionRequest/2, + cre_ActionRequest/3, + cre_ActionRequest/4, + cre_AmmDescriptor/1, + cre_AmmRequest/2, + cre_AmmsReply/1, + cre_AmmsReply/2, + cre_AuditDescriptor/0, + cre_AuditDescriptor/1, + cre_AuditDescriptor/2, + cre_AuditReply/1, + cre_AuditRequest/2, + cre_AuditRequest/3, + cre_AuditResult/2, + cre_AuditReturnParameter/1, + cre_AuthenticationHeader/3, + cre_BOOLEAN/1, + cre_Command/2, + cre_CommandReply/2, + cre_CommandRequest/1, + cre_CommandRequest/2, + cre_CommandRequest/3, + cre_ContextAttrAuditRequest/0, + cre_ContextAttrAuditRequest/3, + cre_ContextAttrAuditRequest/4, + cre_ContextAttrAuditRequest/5, + cre_ContextAttrAuditRequest/6, + cre_ContextAttrAuditRequest/7, + cre_ContextAttrAuditRequest/8, + cre_ContextAttrAuditRequest/9, + cre_ContextID/1, + cre_ContextRequest/0, + cre_ContextRequest/1, + cre_ContextRequest/2, + cre_ContextRequest/3, + cre_ContextRequest/4, + cre_ContextRequest/5, + cre_ContextRequest/6, + cre_DigitMapDescriptor/0, + cre_DigitMapDescriptor/1, + cre_DigitMapDescriptor/2, + cre_DigitMapName/1, + cre_DigitMapValue/1, + cre_DigitMapValue/4, + cre_DigitMapValue/5, + cre_ErrorCode/1, + cre_ErrorDescriptor/1, + cre_ErrorDescriptor/2, + cre_ErrorText/1, + cre_EventBufferControl/1, + cre_EventBufferDescriptor/1, + cre_EventDM/1, + cre_EventName/1, + cre_EventParameter/2, + cre_EventParameter/4, + cre_EventsDescriptor/0, + cre_EventsDescriptor/2, + cre_EventSpec/2, + cre_EventSpec/3, + %% cre_H221NonStandard/4, + cre_IndAuditParameter/1, + cre_IndAudLocalControlDescriptor/0, + cre_IndAudLocalControlDescriptor/4, + cre_IndAudLocalControlDescriptor/5, + cre_IndAudLocalRemoteDescriptor/1, + cre_IndAudLocalRemoteDescriptor/2, + cre_IndAudMediaDescriptor/0, + cre_IndAudMediaDescriptor/1, + cre_IndAudMediaDescriptor/2, + cre_IndAudPropertyGroup/1, + cre_IndAudPropertyParm/1, + cre_IndAudPropertyParm/2, + cre_IndAudDigitMapDescriptor/0, + cre_IndAudDigitMapDescriptor/1, + cre_IndAudEventBufferDescriptor/1, + cre_IndAudEventBufferDescriptor/2, + cre_IndAudEventsDescriptor/1, + cre_IndAudEventsDescriptor/2, + cre_IndAudEventsDescriptor/3, + cre_IndAudPackagesDescriptor/2, + cre_IndAudSeqSigList/1, + cre_IndAudSeqSigList/2, + cre_IndAudSignal/1, + cre_IndAudSignal/2, + cre_IndAudSignalsDescriptor/1, + cre_IndAudStatisticsDescriptor/1, + cre_IndAudStreamDescriptor/2, + cre_IndAudStreamParms/0, + cre_IndAudStreamParms/1, + cre_IndAudStreamParms/3, + cre_IndAudStreamParms/4, + cre_IndAudTerminationStateDescriptor/1, + cre_IndAudTerminationStateDescriptor/3, + cre_IndAudTerminationStateDescriptor/4, + cre_LocalControlDescriptor/1, + cre_LocalControlDescriptor/2, + cre_LocalControlDescriptor/4, + cre_LocalRemoteDescriptor/1, + cre_MediaDescriptor/0, + cre_MediaDescriptor/1, + cre_MediaDescriptor/2, + cre_Message/3, + cre_ModemDescriptor/2, + %% cre_ModemDescriptor/3, + cre_ModemType/1, + cre_MuxDescriptor/2, + %% cre_MuxDescriptor/3, + cre_MuxType/1, + cre_Name/1, + %% cre_NonStandardData/2, + %% cre_NonStandardIdentifier/1, + cre_NotifyBehaviour/2, + cre_NotifyCompletion/1, + cre_NotifyReply/1, + cre_NotifyReply/2, + cre_NotifyRequest/2, + cre_NotifyRequest/3, + cre_ObservedEvent/2, + cre_ObservedEvent/3, + cre_ObservedEvent/4, + cre_ObservedEventsDescriptor/2, + cre_PackagesDescriptor/1, + cre_PackagesItem/2, + cre_PkgdName/1, + cre_PkgdName/2, + cre_PropertyGroup/1, + cre_PropertyParm/2, + cre_PropertyParm/4, + cre_RegulatedEmbeddedDescriptor/0, + cre_RegulatedEmbeddedDescriptor/1, + cre_RegulatedEmbeddedDescriptor/2, + cre_Relation/1, + cre_RequestedActions/0, + cre_RequestedActions/1, + cre_RequestedActions/4, + cre_RequestedActions/6, + cre_RequestedEvent/1, + cre_RequestedEvent/2, + cre_RequestedEvent/3, + cre_RequestedEvent/4, + cre_RequestID/1, + cre_SecondEventsDescriptor/1, + cre_SecondEventsDescriptor/2, + cre_SecondRequestedActions/0, + cre_SecondRequestedActions/1, + cre_SecondRequestedActions/2, + cre_SecondRequestedActions/3, + cre_SecondRequestedActions/5, + cre_SecondRequestedEvent/2, + cre_SecondRequestedEvent/3, + cre_SecondRequestedEvent/4, + cre_SegmentReply/2, + cre_SegmentReply/3, + cre_SelectLogic/1, + cre_SeqSigList/2, + cre_ServiceChangeAddress/2, + cre_ServiceChangeRequest/2, + cre_ServiceChangeMethod/1, + cre_ServiceChangeParm/2, + cre_ServiceChangeParm/4, + cre_ServiceChangeParm/9, + cre_ServiceChangeParm/10, + cre_ServiceChangeProfile/1, + cre_ServiceChangeProfile/2, + cre_ServiceChangeReply/2, + cre_ServiceChangeResParm/0, + cre_ServiceChangeResParm/2, + cre_ServiceChangeResParm/5, + cre_ServiceChangeResult/1, + cre_ServiceState/1, + cre_Signal/1, + cre_Signal/2, + cre_Signal/7, + cre_Signal/9, + cre_Signal/10, + cre_SignalDirection/1, + cre_SignalName/1, + cre_SignalRequest/1, + cre_SignalsDescriptor/1, + cre_SignalType/1, + cre_SigParameter/2, + cre_SigParameter/4, + cre_StatisticsDescriptor/1, + cre_StatisticsParameter/1, + cre_StatisticsParameter/2, + cre_StreamDescriptor/2, + cre_StreamID/1, + cre_StreamMode/1, + cre_StreamParms/0, + cre_StreamParms/1, + cre_StreamParms/2, + cre_StreamParms/3, + cre_StreamParms/4, + cre_SubtractRequest/1, + cre_SubtractRequest/2, + cre_TopologyRequest/3, + cre_TopologyRequest/4, + cre_TerminationAudit/1, + cre_TerminationID/2, + cre_TerminationIDList/1, + cre_TerminationStateDescriptor/1, + cre_TerminationStateDescriptor/2, + cre_TerminationStateDescriptor/3, + cre_TermListAuditResult/2, + cre_TimeNotation/2, + cre_Transaction/1, + cre_TransactionAck/1, + cre_TransactionAck/2, + cre_TransactionId/1, + cre_TransactionPending/1, + cre_TransactionReply/2, + cre_TransactionReply/3, + cre_TransactionReply/4, + cre_TransactionReply/5, + cre_TransactionRequest/2, + cre_Value/1 + %% cre_WildcardField/1, + ]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +cre_MegacoMessage(M) when is_record(M, 'Message') -> + #'MegacoMessage'{mess = M}. + +cre_MegacoMessage(AH, M) + when is_record(AH, 'AuthenticationHeader') and + is_record(M, 'Message') -> + #'MegacoMessage'{authHeader = AH, + mess = M}. + +cre_AuthenticationHeader(SPI, SN, AD) -> + #'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AD}. + +cre_Message(V, Mid, ED) when is_record(ED, 'ErrorDescriptor') -> + Body = {errorDescriptor, ED}, + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, Transactions) when is_list(Transactions) -> + Body = {transactions, Transactions}, + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, {transactions, T} = Body) when is_list(T) -> + #'Message'{version = V, + mId = Mid, + messageBody = Body}; +cre_Message(V, Mid, {errorDescriptor, ED} = Body) + when is_record(ED, 'ErrorDescriptor') -> + #'Message'{version = V, + mId = Mid, + messageBody = Body}. + + +cre_ErrorDescriptor(EC) when is_integer(EC) -> + #'ErrorDescriptor'{errorCode = EC}. + +cre_ErrorDescriptor(EC, ET) when is_integer(EC) and is_list(ET) -> + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + +cre_ErrorCode(C) when is_integer(C) and (0 =< C) and (C =< 65535) -> + C; +cre_ErrorCode(C) -> + exit({invalid_ErrorCode, C}). + +cre_ErrorText(T) when is_list(T) -> + T. + +cre_ContextID(Val) when (0 =< Val) and (Val =< 4294967295) -> + Val; +cre_ContextID(Val) -> + exit({invalid_ContextID, Val}). + +cre_Transaction(TR) when is_record(TR, 'TransactionRequest') -> + {transactionRequest, TR}; +cre_Transaction(TP) when is_record(TP, 'TransactionPending') -> + {transactionPending, TP}; +cre_Transaction(TR) when is_record(TR, 'TransactionReply') -> + {transactionReply, TR}; +cre_Transaction(TRA) when is_list(TRA) -> + {transactionResponseAck, TRA}; +cre_Transaction(SR) when is_record(SR, 'SegmentReply') -> + {segmentReply, SR}. + +cre_TransactionId(Val) when (0 =< Val) and (Val =< 4294967295) -> + Val; +cre_TransactionId(Val) -> + exit({invalid_TransactionId, Val}). + +cre_TransactionRequest(TransID, ARs) + when is_integer(TransID) and is_list(ARs) -> + #'TransactionRequest'{transactionId = TransID, + actions = ARs}. + +cre_TransactionPending(TransID) when is_integer(TransID) -> + #'TransactionPending'{transactionId = TransID}. + +cre_TransactionReply(TransID, ED) + when is_integer(TransID) and is_record(ED, 'ErrorDescriptor') -> + Res = {transactionError, ED}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}; +cre_TransactionReply(TransID, ARs) + when is_integer(TransID) and is_list(ARs) -> + Res = {actionReplies, ARs}, + #'TransactionReply'{transactionId = TransID, + transactionResult = Res}; +cre_TransactionReply(TransID, Res) -> + error({invalid_TransactionReply_values, {TransID, Res}}). + +cre_TransactionReply(TransID, IAR, ED) + when is_integer(TransID) and + ((IAR == 'NULL') or (IAR == asn1_NOVALUE)) and + is_record(ED, 'ErrorDescriptor') -> + Res = {transactionError, ED}, + #'TransactionReply'{transactionId = TransID, + immAckRequired = IAR, + transactionResult = Res}; +cre_TransactionReply(TransID, IAR, ARs) + when is_integer(TransID) and + ((IAR == 'NULL') or (IAR == asn1_NOVALUE)) and + is_list(ARs) -> + Res = {actionReplies, ARs}, + #'TransactionReply'{transactionId = TransID, + immAckRequired = IAR, + transactionResult = Res}; +cre_TransactionReply(TransID, Res, SN) + when (is_integer(SN) and (SN > 0) and (SN =< 65535)) or + (SN == asn1_NOVALUE) -> + TR = cre_TransactionReply(TransID, Res), + TR#'TransactionReply'{segmentNumber = SN}; +cre_TransactionReply(TransID, Res, SN) -> + error({invalid_TransactionReply_values, {TransID, Res, SN}}). + +cre_TransactionReply(TransID, Res, SN, SC) + when is_integer(SN) and ((SC == 'NULL') or (SC == asn1_NOVALUE)) -> + TR = cre_TransactionReply(TransID, Res), + TR#'TransactionReply'{segmentNumber = SN, + segmentationComplete = SC}; +cre_TransactionReply(TransID, IAR, Res, SN) -> + cre_TransactionReply(TransID, IAR, Res, SN, asn1_NOVALUE). + +cre_TransactionReply(TransID, IAR, Res, SN, SC) + when (SN == asn1_NOVALUE) and (SC == asn1_NOVALUE) -> + cre_TransactionReply(TransID, IAR, Res); +cre_TransactionReply(TransID, IAR, Res, SN, SC) + when (is_integer(SN) and (SN > 0) and (SN =< 65535)) and + ((SC == asn1_NOVALUE) or (SC == 'NULL')) -> + TR = cre_TransactionReply(TransID, IAR, Res), + TR#'TransactionReply'{segmentNumber = SN, + segmentationComplete = SC}; +cre_TransactionReply(TransID, IAR, Res, SN, SC) -> + error({invalid_TransactionReply_values, {TransID, IAR, Res, SN, SC}}). + + +cre_SegmentReply(TransID, SN) + when is_integer(TransID) and + is_integer(SN) and (SN > 0) and (SN =< 65535) -> + #'SegmentReply'{transactionId = TransID, + segmentNumber = SN}. + +cre_SegmentReply(TransID, SN, SC) + when is_integer(TransID) and + is_integer(SN) and (SN > 0) and (SN =< 65535) and + ((SC == 'NULL') or (SC == asn1_NOVALUE)) -> + #'SegmentReply'{transactionId = TransID, + segmentNumber = SN, + segmentationComplete = SC}. + +cre_TransactionAck(FirstAck) -> + #'TransactionAck'{firstAck = FirstAck}. + +cre_TransactionAck(FirstAck, FirstAck) -> + #'TransactionAck'{firstAck = FirstAck}; +cre_TransactionAck(FirstAck, LastAck) -> + #'TransactionAck'{firstAck = FirstAck, + lastAck = LastAck}. + +cre_ActionRequest(CtxID, CmdReqs) + when is_integer(CtxID) and is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + commandRequests = CmdReqs}. + +cre_ActionRequest(CtxID, CtxReq, CmdReqs) + when is_integer(CtxID) and + is_record(CtxReq, 'ContextRequest') and + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextRequest = CtxReq, + commandRequests = CmdReqs}; +cre_ActionRequest(CtxID, CAAR, CmdReqs) + when is_integer(CtxID) and + is_record(CAAR, 'ContextAttrAuditRequest') and + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextAttrAuditReq = CAAR, + commandRequests = CmdReqs}. + +cre_ActionRequest(CtxID, CtxReq, CAAR, CmdReqs) + when is_integer(CtxID) and + (is_record(CtxReq, 'ContextRequest') or + (CtxReq == asn1_NOVALUE)) and + (is_record(CAAR, 'ContextAttrAuditRequest') or + (CAAR == asn1_NOVALUE)) and + is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxID, + contextRequest = CtxReq, + contextAttrAuditReq = CAAR, + commandRequests = CmdReqs}. + +cre_ActionReply(CtxID, CmdReps) + when is_integer(CtxID) and + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + commandReply = CmdReps}. + +cre_ActionReply(CtxID, ED, CmdReps) + when is_integer(CtxID) and + is_record(ED, 'ErrorDescriptor') and + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + errorDescriptor = ED, + commandReply = CmdReps}; +cre_ActionReply(CtxID, CtxReq, CmdReps) + when is_integer(CtxID) and + is_record(CtxReq, 'ContextRequest') and + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + contextReply = CtxReq, + commandReply = CmdReps}. + +cre_ActionReply(CtxID, ED, CtxReq, CmdReps) + when is_integer(CtxID) andalso + (is_record(ED, 'ErrorDescriptor') orelse (ED =:= asn1_NOVALUE)) andalso + (is_record(CtxReq, 'ContextRequest') orelse (CtxReq =:= asn1_NOVALUE)) andalso + is_list(CmdReps) -> + #'ActionReply'{contextId = CtxID, + errorDescriptor = ED, + contextReply = CtxReq, + commandReply = CmdReps}. + +cre_ContextRequest() -> + strip_ContextRequest(#'ContextRequest'{}). + +cre_ContextRequest(Prio) + when is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15) -> + strip_ContextRequest(#'ContextRequest'{priority = Prio}); +cre_ContextRequest(Em) + when (Em =:= true) orelse (Em =:= false) orelse (Em =:= asn1_NOVALUE) -> + strip_ContextRequest(#'ContextRequest'{emergency = Em}); +cre_ContextRequest(Top) when is_list(Top) -> + strip_ContextRequest(#'ContextRequest'{topologyReq = Top}). + +cre_ContextRequest(Prio, Em) + when (is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15)) andalso + ((Em =:= true) orelse (Em =:= false) orelse (Em =:= asn1_NOVALUE)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em}, + strip_ContextRequest(CR); +cre_ContextRequest(Prio, Top) + when is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15) andalso is_list(Top) -> + CR = #'ContextRequest'{priority = Prio, + topologyReq = Top}, + strip_ContextRequest(CR). + +cre_ContextRequest(Prio, Em, Top) + when (is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15)) andalso + ((Em =:= true) orelse (Em =:= false) orelse (Em =:= asn1_NOVALUE)) andalso + (is_list(Top) orelse (Top == asn1_NOVALUE)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top}, + strip_ContextRequest(CR). + +cre_ContextRequest(Prio, Em, Top, Ieps) + when (is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15)) andalso + ((Em =:= true) orelse (Em =:= false) orelse (Em =:= asn1_NOVALUE)) andalso + (is_list(Top) orelse (Top =:= asn1_NOVALUE)) andalso + ((Ieps =:= true) orelse (Ieps =:= false)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + iepscallind = Ieps}, + strip_ContextRequest(CR); +cre_ContextRequest(Prio, Em, Top, Ctx) + when ((is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15)) or + (Prio =:= asn1_NOVALUE)) andalso + ((Em =:= true) orelse (Em =:= false) orelse (Em =:= asn1_NOVALUE)) andalso + (is_list(Top) orelse (Top =:= asn1_NOVALUE)) andalso + (is_list(Ctx)) -> + CR = + case context_list_or_prop(Ctx) of + contextProp -> + #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + contextProp = Ctx}; + contextList -> + #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + contextList = Ctx} + end, + strip_ContextRequest(CR). + +cre_ContextRequest(Prio, Em, Top, Ieps, Ctx) + when ((is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15)) orelse + (Prio =:= asn1_NOVALUE)) andalso + ((Em =:= true) orelse (Em =:= false) orelse (Em =:= asn1_NOVALUE)) andalso + (is_list(Top) orelse (Top =:= asn1_NOVALUE)) andalso + ((Ieps =:= true) orelse (Ieps =:= false) orelse (Ieps =:= asn1_NOVALUE)) andalso + (is_list(Ctx)) -> + CR = + case context_list_or_prop(Ctx) of + contextProp -> + #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + iepscallind = Ieps, + contextProp = Ctx}; + contextList -> + #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + iepscallind = Ieps, + contextList = Ctx} + end, + strip_ContextRequest(CR). + +cre_ContextRequest(Prio, Em, Top, Ieps, CtxProp, CtxList) + when ((is_integer(Prio) andalso (0 =< Prio) andalso (Prio =< 15)) orelse + (Prio =:= asn1_NOVALUE)) andalso + ((Em =:= true) orelse (Em =:= false) orelse (Em =:= asn1_NOVALUE)) andalso + (is_list(Top) orelse (Top =:= asn1_NOVALUE)) andalso + ((Ieps =:= true) orelse (Ieps =:= false) orelse (Ieps =:= asn1_NOVALUE)) andalso + (is_list(CtxProp) orelse (CtxProp =:= asn1_NOVALUE)) andalso + (is_list(CtxList) orelse (CtxList =:= asn1_NOVALUE)) -> + CR = #'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = Top, + iepscallind = Ieps, + contextProp = CtxProp, + contextList = CtxList}, + strip_ContextRequest(CR). + +context_list_or_prop(asn1_NOVALUE) -> + contextProp; +context_list_or_prop([]) -> + contextProp; +context_list_or_prop([H|T]) -> + case is_ContextID(H) of + true -> + context_list_or_prop(T, contextList); + false -> + context_list_or_prop(T, contextProp) + end. + +context_list_or_prop([], What) -> + What; +context_list_or_prop([H|T], What) -> + case is_ContextID(H) of + true when (What =:= contextList) -> + context_list_or_prop(T, What); + false when (What =:= contextProp) -> + context_list_or_prop(T, What); + _ -> + error({invalid_contextListOrProp, H, What}) + end. + +strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE, + emergency = asn1_NOVALUE, + topologyReq = asn1_NOVALUE, + iepscallind = asn1_NOVALUE, + contextProp = asn1_NOVALUE}) -> + asn1_NOVALUE; +strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE, + emergency = asn1_NOVALUE, + topologyReq = Top, + iepscallind = Ieps, + contextProp = Prop} = CR) -> + case (((Top == []) or (Top == asn1_NOVALUE)) and + ((Ieps == false) or (Ieps == asn1_NOVALUE)) and + ((Prop == []) or (Prop == asn1_NOVALUE))) of + true -> + asn1_NOVALUE; + false -> + CR + end; +strip_ContextRequest(CR) -> + CR. + +cre_ContextAttrAuditRequest() -> + strip_ContextAttrAuditRequest(#'ContextAttrAuditRequest'{}). + +cre_ContextAttrAuditRequest(Top, Em, Prio) + when ((Top =:= 'NULL') orelse (Top =:= asn1_NOVALUE)) andalso + ((Em =:= 'NULL') orelse (Em =:= asn1_NOVALUE)) andalso + ((Prio =:= 'NULL') orelse (Prio =:= asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio}, + strip_ContextAttrAuditRequest(CAAR). + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps) + when ((Top =:= 'NULL') orelse (Top =:= asn1_NOVALUE)) andalso + ((Em =:= 'NULL') orelse (Em =:= asn1_NOVALUE)) andalso + ((Prio =:= 'NULL') orelse (Prio =:= asn1_NOVALUE)) andalso + ((Ieps =:= 'NULL') orelse (Ieps =:= asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ieps}, + strip_ContextAttrAuditRequest(CAAR). + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx) + when ((Top =:= 'NULL') orelse (Top =:= asn1_NOVALUE)) andalso + ((Em =:= 'NULL') orelse (Em =:= asn1_NOVALUE)) andalso + ((Prio =:= 'NULL') orelse (Prio =:= asn1_NOVALUE)) andalso + ((Ieps =:= 'NULL') orelse (Ieps =:= asn1_NOVALUE)) andalso + (is_list(Ctx) orelse (Ctx =:= asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ieps, + contextPropAud = Ctx}, + strip_ContextAttrAuditRequest(CAAR). + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx, SelPrio) + when ((Top =:= 'NULL') orelse (Top =:= asn1_NOVALUE)) andalso + ((Em =:= 'NULL') orelse (Em =:= asn1_NOVALUE)) andalso + ((Prio =:= 'NULL') orelse (Prio =:= asn1_NOVALUE)) andalso + ((Ieps =:= 'NULL') orelse (Ieps =:= asn1_NOVALUE)) andalso + (is_list(Ctx) orelse (Ctx =:= asn1_NOVALUE)) andalso + ((is_integer(SelPrio) andalso ((0 =< SelPrio) and (SelPrio =< 15))) orelse + (SelPrio =:= asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ieps, + contextPropAud = Ctx, + selectpriority = SelPrio}, + strip_ContextAttrAuditRequest(CAAR). + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx, SelPrio, SelLog) + when ((Top =:= 'NULL') orelse (Top =:= asn1_NOVALUE)) andalso + ((Em =:= 'NULL') orelse (Em =:= asn1_NOVALUE)) andalso + ((Prio =:= 'NULL') orelse (Prio =:= asn1_NOVALUE)) andalso + ((Ieps =:= 'NULL') orelse (Ieps =:= asn1_NOVALUE)) andalso + (is_list(Ctx) orelse (Ctx =:= asn1_NOVALUE)) andalso + ((is_integer(SelPrio) andalso ((0 =< SelPrio) andalso (SelPrio =< 15))) orelse + (SelPrio =:= asn1_NOVALUE)) -> + case ((SelLog =:= asn1_NOVALUE) orelse is_SelectLogic(SelLog)) of + true -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ieps, + contextPropAud = Ctx, + selectpriority = SelPrio, + selectLogic = SelLog}, + strip_ContextAttrAuditRequest(CAAR); + false -> + error({invalid_SelectLogic, SelLog, + ['ContextAttrAuditRequest', + Top, Em, Prio, Ieps, Ctx, SelPrio]}) + end. + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx, + SelPrio, SelEm, SelIeps) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) and + ((Ieps == 'NULL') or (Ieps == asn1_NOVALUE)) and + (is_list(Ctx) or (Ctx == asn1_NOVALUE)) and + ((is_integer(SelPrio) and ((0 =< SelPrio) and (SelPrio =< 15))) or + (SelPrio == asn1_NOVALUE)) and + ((SelEm == true) or + (SelEm == false) or + (SelEm == asn1_NOVALUE)) and + ((SelIeps == true) or + (SelIeps == false) or + (SelIeps == asn1_NOVALUE)) -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ieps, + contextPropAud = Ctx, + selectpriority = SelPrio, + selectemergency = SelEm, + selectiepscallind = SelIeps}, + strip_ContextAttrAuditRequest(CAAR). + +cre_ContextAttrAuditRequest(Top, Em, Prio, Ieps, Ctx, + SelPrio, SelEm, SelIeps, SelLog) + when ((Top == 'NULL') or (Top == asn1_NOVALUE)) and + ((Em == 'NULL') or (Em == asn1_NOVALUE)) and + ((Prio == 'NULL') or (Prio == asn1_NOVALUE)) and + ((Ieps == 'NULL') or (Ieps == asn1_NOVALUE)) and + (is_list(Ctx) or (Ctx == asn1_NOVALUE)) and + ((is_integer(SelPrio) and ((0 =< SelPrio) and (SelPrio =< 15))) or + (SelPrio == asn1_NOVALUE)) and + ((SelEm == true) or + (SelEm == false) or + (SelEm == asn1_NOVALUE)) and + ((SelIeps == true) or + (SelIeps == false) or + (SelIeps == asn1_NOVALUE)) -> + case ((SelLog == asn1_NOVALUE) orelse is_SelectLogic(SelLog)) of + true -> + CAAR = #'ContextAttrAuditRequest'{topology = Top, + emergency = Em, + priority = Prio, + iepscallind = Ieps, + contextPropAud = Ctx, + selectpriority = SelPrio, + selectemergency = SelEm, + selectiepscallind = SelIeps, + selectLogic = SelLog}, + strip_ContextAttrAuditRequest(CAAR); + false -> + error({invalid_SelectLogic, SelLog}) + end. + +strip_ContextAttrAuditRequest( + #'ContextAttrAuditRequest'{topology = asn1_NOVALUE, + emergency = asn1_NOVALUE, + priority = asn1_NOVALUE, + iepscallind = asn1_NOVALUE, + contextPropAud = asn1_NOVALUE}) -> + asn1_NOVALUE; +strip_ContextAttrAuditRequest( + #'ContextAttrAuditRequest'{topology = asn1_NOVALUE, + emergency = asn1_NOVALUE, + priority = asn1_NOVALUE, + iepscallind = asn1_NOVALUE, + contextPropAud = []}) -> + asn1_NOVALUE; +strip_ContextAttrAuditRequest(CAAR) -> + CAAR. + + +cre_SelectLogic(andAUDITSelect = SL) -> + {SL, 'NULL'}; +cre_SelectLogic(orAUDITSelect = SL) -> + {SL, 'NULL'}; +cre_SelectLogic(asn1_NOVALUE) -> + asn1_NOVALUE. + + +cre_CommandRequest(Cmd) -> + #'CommandRequest'{command = Cmd}. + +cre_CommandRequest(Cmd, Opt) + when ((Opt == 'NULL') or (Opt == asn1_NOVALUE)) -> + #'CommandRequest'{command = Cmd, + optional = Opt}. + +cre_CommandRequest(Cmd, Opt, WR) + when ((Opt == 'NULL') or (Opt == asn1_NOVALUE)) and + ((WR == 'NULL') or (WR == asn1_NOVALUE)) -> + #'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = WR}. + +cre_Command(addReq = Tag, Req) + when is_record(Req, 'AmmRequest') -> + {Tag, Req}; +cre_Command(moveReq = Tag, Req) + when is_record(Req, 'AmmRequest') -> + {Tag, Req}; +cre_Command(modReq = Tag, Req) + when is_record(Req, 'AmmRequest') -> + {Tag, Req}; +cre_Command(subtractReq = Tag, Req) + when is_record(Req, 'SubtractRequest') -> + {Tag, Req}; +cre_Command(auditCapRequest = Tag, Req) + when is_record(Req, 'AuditRequest') -> + {Tag, Req}; +cre_Command(auditValueRequest = Tag, Req) + when is_record(Req, 'AuditRequest') -> + {Tag, Req}; +cre_Command(notifyReq = Tag, Req) + when is_record(Req, 'NotifyRequest') -> + {Tag, Req}; +cre_Command(serviceChangeReq = Tag, Req) + when is_record(Req, 'ServiceChangeRequest') -> + {Tag, Req}. + +cre_CommandReply(addReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(moveReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(modReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(subtractReply = Tag, Rep) + when is_record(Rep, 'AmmsReply') -> + {Tag, Rep}; +cre_CommandReply(auditCapReply = Tag, Rep) + when is_tuple(Rep) -> + {Tag, Rep}; +cre_CommandReply(auditValueReply = Tag, Rep) + when is_tuple(Rep) -> + {Tag, Rep}; +cre_CommandReply(notifyReply = Tag, Rep) + when is_record(Rep, 'NotifyReply') -> + {Tag, Rep}; +cre_CommandReply(serviceChangeReply = Tag, Rep) + when is_record(Rep, 'ServiceChangeReply') -> + {Tag, Rep}. + + +%% -- TopologyRequest -- + +cre_TopologyRequest(From, To, TD) + when (is_record(From, 'TerminationID') or + is_record(From, megaco_term_id)) and + (is_record(To, 'TerminationID') or + is_record(To, megaco_term_id)) and + ((TD == bothway) or (TD == isolate) or (TD == oneway)) -> + #'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = TD}; +cre_TopologyRequest(From, To, TDE) + when (is_record(From, 'TerminationID') or + is_record(From, megaco_term_id)) and + (is_record(To, 'TerminationID') or + is_record(To, megaco_term_id)) and + ((TDE == onewayexternal) or (TDE == onewayboth)) -> + #'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = oneway, + topologyDirectionExtension = TDE}. + +cre_TopologyRequest(From, To, TD, SID) + when (is_record(From, 'TerminationID') or + is_record(From, megaco_term_id)) and + (is_record(To, 'TerminationID') or + is_record(To, megaco_term_id)) and + ((TD == bothway) or (TD == isolate) or (TD == oneway)) and + (is_integer(SID)) -> + #'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = TD, + streamID = SID}; +cre_TopologyRequest(From, To, SID, TDE) + when (is_record(From, 'TerminationID') or + is_record(From, megaco_term_id)) and + (is_record(To, 'TerminationID') or + is_record(To, megaco_term_id)) and + (is_integer(SID)) and + ((TDE == onewayexternal) or (TDE == onewayboth)) -> + #'TopologyRequest'{terminationFrom = From, + terminationTo = To, + topologyDirection = oneway, + streamID = SID, + topologyDirectionExtension = TDE}. + +cre_AmmRequest(TermIDs, Descs) -> + d("cre_AmmRequest -> entry with" + "~n TermIDs: ~p" + "~n Descs: ~p", [TermIDs, Descs]), + case is_TerminationIDList(TermIDs) andalso + is_AmmRequest_descriptors(Descs) of + true -> + #'AmmRequest'{terminationID = TermIDs, + descriptors = Descs}; + false -> + error({invalid_AmmRequest, {TermIDs, Descs}}) + end. + +cre_AmmDescriptor(D) when is_record(D, 'MediaDescriptor') -> + {mediaDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'ModemDescriptor') -> + {modemDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'MuxDescriptor') -> + {muxDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'EventsDescriptor') -> + {eventsDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'DigitMapDescriptor') -> + {digitMapDescriptor, D}; +cre_AmmDescriptor(D) when is_record(D, 'AuditDescriptor') -> + {auditDescriptor, D}; +cre_AmmDescriptor(D) when is_list(D) -> + case is_EventBufferDescriptor(D) of + true -> + {eventBufferDescriptor, D}; + false -> + case is_SignalsDescriptor(D) of + true -> + {signalsDescriptor, D}; + false -> + case is_StatisticsDescriptor(D) of + true -> + {statisticsDescriptor, D}; + false -> + error({invalid_AmmDescriptor, D}) + end + end + end. + +cre_AmmsReply(TermIDs) when is_list(TermIDs) -> + #'AmmsReply'{terminationID = TermIDs}. + +cre_AmmsReply(TermIDs, TAs) when is_list(TermIDs) and is_list(TAs) -> + #'AmmsReply'{terminationID = TermIDs, + terminationAudit = TAs}. + +cre_SubtractRequest(TermIDs) when is_list(TermIDs) -> + #'SubtractRequest'{terminationID = TermIDs}. + +cre_SubtractRequest(TermIDs, Audit) + when is_list(TermIDs) and is_record(Audit, 'AuditDescriptor') -> + #'SubtractRequest'{terminationID = TermIDs, + auditDescriptor = Audit}. + +cre_AuditRequest(TermID, Audit) + when is_record(TermID, megaco_term_id) and + is_record(Audit, 'AuditDescriptor') -> + #'AuditRequest'{terminationID = TermID, + auditDescriptor = Audit}. + +cre_AuditRequest(TID, Audit, [TID|_] = TIDs) + when is_record(TID, megaco_term_id) and + is_record(Audit, 'AuditDescriptor') -> + #'AuditRequest'{terminationID = TID, + auditDescriptor = Audit, + terminationIDList = TIDs}. + +cre_AuditReply(TermIDs) when is_list(TermIDs) -> + {contextAuditResult, TermIDs}; +cre_AuditReply(ED) when is_record(ED, 'ErrorDescriptor') -> + {error, ED}; +cre_AuditReply(Audit) when is_record(Audit, 'AuditResult') -> + {auditResult, Audit}; +cre_AuditReply(ARTL) when is_record(ARTL, 'TermListAuditResult') -> + {auditResultTermList, ARTL}. + +cre_AuditResult(TID, TAs) + when is_record(TID, megaco_term_id) and is_list(TAs) -> + #'AuditResult'{terminationID = TID, + terminationAuditResult = TAs}. + +cre_TermListAuditResult(TIDs, TA) + when is_list(TIDs) and is_list(TA) -> + #'TermListAuditResult'{terminationIDList = TIDs, + terminationAuditResult = TA}. + +cre_TerminationAudit(D) -> + true = is_TerminationAudit(D), + D. + +cre_AuditReturnParameter(D) when is_record(D, 'ErrorDescriptor') -> + {errorDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'MediaDescriptor') -> + {mediaDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'ModemDescriptor') -> + {modemDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'MuxDescriptor') -> + {muxDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'EventsDescriptor') -> + {eventsDescriptor, D}; +cre_AuditReturnParameter([H|_] = D) when is_record(H, 'EventSpec') -> + {eventBufferDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'DigitMapDescriptor') -> + {digitMapDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'ObservedEventsDescriptor') -> + {observedEventsDescriptor, D}; +cre_AuditReturnParameter([H|_] = D) when is_record(H, 'StatisticsParameter') -> + {statisticsDescriptor, D}; +cre_AuditReturnParameter([H|_] = D) when is_record(H, 'PackagesItem') -> + {packagesDescriptor, D}; +cre_AuditReturnParameter(D) when is_record(D, 'AuditDescriptor') -> + {emptyDescriptors, D}; +cre_AuditReturnParameter([H|_] = D) when is_tuple(H) -> + {signalsDescriptor, D}. + +cre_AuditDescriptor() -> + #'AuditDescriptor'{}. + +cre_AuditDescriptor([H|_] = AT) when is_atom(H) -> + #'AuditDescriptor'{auditToken = AT}; +cre_AuditDescriptor(APT) -> + #'AuditDescriptor'{auditPropertyToken = APT}. + +cre_AuditDescriptor(AT, APT) -> + #'AuditDescriptor'{auditToken = AT, + auditPropertyToken = APT}. + +cre_IndAuditParameter(D) when is_record(D, 'IndAudMediaDescriptor') -> + {indAudMediaDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudEventsDescriptor') -> + {indAudEventsDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudEventBufferDescriptor') -> + {indAudEventBufferDescriptor, D}; +cre_IndAuditParameter({signal, _} = D) -> + {indAudSignalsDescriptor, D}; +cre_IndAuditParameter({seqSigList, _} = D) -> + {indAudSignalsDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudDigitMapDescriptor') -> + {indAudDigitMapDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudStatisticsDescriptor') -> + {indAudStatisticsDescriptor, D}; +cre_IndAuditParameter(D) when is_record(D, 'IndAudPackagesDescriptor') -> + {indAudPackagesDescriptor, D}. + +cre_IndAudMediaDescriptor() -> + #'IndAudMediaDescriptor'{}. + +cre_IndAudMediaDescriptor(TSD) + when is_record(TSD, 'IndAudTerminationStateDescriptor') -> + #'IndAudMediaDescriptor'{termStateDescr = TSD}; +cre_IndAudMediaDescriptor(Parms) when is_record(Parms, 'IndAudStreamParms') -> + Streams = {oneStream, Parms}, + #'IndAudMediaDescriptor'{streams = Streams}; +cre_IndAudMediaDescriptor(Descs) when is_list(Descs) -> + Streams = {multiStream, Descs}, + #'IndAudMediaDescriptor'{streams = Streams}. + +cre_IndAudMediaDescriptor(TSD, Parms) + when is_record(TSD, 'IndAudTerminationStateDescriptor') and + is_record(Parms, 'IndAudStreamParms') -> + Streams = {oneStream, Parms}, + #'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = Streams}; +cre_IndAudMediaDescriptor(TSD, Descs) + when is_record(TSD, 'IndAudTerminationStateDescriptor') and is_list(Descs) -> + Streams = {multiStream, Descs}, + #'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = Streams}. + +cre_IndAudStreamDescriptor(SID, Parms) + when is_integer(SID) and is_record(Parms, 'IndAudStreamParms') -> + #'IndAudStreamDescriptor'{streamID = SID, + streamParms = Parms}; +cre_IndAudStreamDescriptor(SID, Parms) -> + error({invalid_IndAudStreamDescriptor, [SID, Parms]}). + +cre_IndAudStreamParms() -> + #'IndAudStreamParms'{}. + +cre_IndAudStreamParms(LCD) + when is_record(LCD, 'IndAudLocalControlDescriptor') -> + #'IndAudStreamParms'{localControlDescriptor = LCD}; +cre_IndAudStreamParms(SD) when is_record(SD, 'IndAudStatisticsDescriptor') -> + #'IndAudStreamParms'{statisticsDescriptor = SD}. + +cre_IndAudStreamParms(LC, L, R) + when is_record(LC, 'IndAudLocalControlDescriptor') and + is_record(L, 'IndAudLocalRemoteDescriptor') and + is_record(R, 'IndAudLocalRemoteDescriptor') -> + #'IndAudStreamParms'{localControlDescriptor = LC, + localDescriptor = L, + remoteDescriptor = R}. + +cre_IndAudStreamParms(LC, L, R, S) + when is_record(LC, 'IndAudLocalControlDescriptor') and + is_record(L, 'IndAudLocalRemoteDescriptor') and + is_record(R, 'IndAudLocalRemoteDescriptor') and + is_record(S, 'IndAudStatisticsDescriptor') -> + #'IndAudStreamParms'{localControlDescriptor = LC, + localDescriptor = L, + remoteDescriptor = R, + statisticsDescriptor = S}. + +cre_IndAudLocalControlDescriptor() -> + #'IndAudLocalControlDescriptor'{}. + +cre_IndAudLocalControlDescriptor(SM, RV, RG, PP) + when ((SM == 'NULL') or (SM == asn1_NOVALUE)) and + ((RV == 'NULL') or (RV == asn1_NOVALUE)) and + ((RG == 'NULL') or (RG == asn1_NOVALUE)) and + (is_list(PP) or (PP == asn1_NOVALUE)) -> + #'IndAudLocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP}; +cre_IndAudLocalControlDescriptor(RV, RG, PP, SMS) + when ((RV == 'NULL') or (RV == asn1_NOVALUE)) and + ((RG == 'NULL') or (RG == asn1_NOVALUE)) and + (is_list(PP) or (PP == asn1_NOVALUE)) and + is_atom(SMS) -> + #'IndAudLocalControlDescriptor'{reserveValue = RV, + reserveGroup = RG, + propertyParms = PP, + streamModeSel = SMS}. + +cre_IndAudLocalControlDescriptor(SM, RV, RG, PP, SMS) + when (SM == 'NULL') and + (is_atom(SMS) and (SMS =/= asn1_NOVALUE)) -> + error({invalid_IndAudLocalControlDescriptor, [SM, RV, RG, PP, SMS]}); +cre_IndAudLocalControlDescriptor(SM, RV, RG, PP, SMS) + when ((SM == 'NULL') or (SM == asn1_NOVALUE)) and + ((RV == 'NULL') or (RV == asn1_NOVALUE)) and + ((RG == 'NULL') or (RG == asn1_NOVALUE)) and + (is_list(PP) or (PP == asn1_NOVALUE)) and + is_atom(SMS) -> + case is_StreamMode(SMS) of + true -> + #'IndAudLocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP, + streamModeSel = SMS}; + false -> + error({invalid_IndAudLocalControlDescriptor, SMS}) + end. + +cre_IndAudPropertyParm(PkgdName) when is_list(PkgdName) -> + #'IndAudPropertyParm'{name = PkgdName}. + +cre_IndAudPropertyParm(PkgdName, PP) + when is_list(PkgdName) and is_record(PP, 'PropertyParm') -> + #'IndAudPropertyParm'{name = PkgdName, propertyParms = PP}. + +cre_IndAudLocalRemoteDescriptor(Grps) when is_list(Grps) -> + #'IndAudLocalRemoteDescriptor'{propGrps = Grps}. + +cre_IndAudLocalRemoteDescriptor(GID, Grps) + when is_integer(GID) and (0 =< GID) and (GID =< 65535) and is_list(Grps) -> + #'IndAudLocalRemoteDescriptor'{propGroupID = GID, + propGrps = Grps}. + +cre_IndAudPropertyGroup([]) -> + []; +cre_IndAudPropertyGroup([H|_] = PG) when is_record(H, 'IndAudPropertyParm') -> + PG. + +cre_IndAudTerminationStateDescriptor([] = PP) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP}; +cre_IndAudTerminationStateDescriptor([H|_] = PP) + when is_record(H, 'IndAudPropertyParm') -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP}. + +cre_IndAudTerminationStateDescriptor([] = PP, EBC, SS) + when ((EBC == 'NULL') or (EBC == asn1_NOVALUE)) and + ((SS == 'NULL') or (SS == asn1_NOVALUE)) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS}; +cre_IndAudTerminationStateDescriptor([H|_] = PP, EBC, SS) + when is_record(H, 'IndAudPropertyParm') and + ((EBC == 'NULL') or (EBC == asn1_NOVALUE)) and + ((SS == 'NULL') or (SS == asn1_NOVALUE)) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS}. + +cre_IndAudTerminationStateDescriptor(PP, EBC, SS, SSS) + when (SS == 'NULL') and + ((is_atom(SSS) and (SSS =/= asn1_NOVALUE))) -> + error({invalid_IndAudTerminationStateDescriptor, [PP, EBC, SS, SSS]}); +cre_IndAudTerminationStateDescriptor([] = PP, EBC, SS, SSS) + when ((EBC == 'NULL') or (EBC == asn1_NOVALUE)) and + ((SS == 'NULL') or (SS == asn1_NOVALUE)) and + is_atom(SSS) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS, + serviceStateSel = SSS}; +cre_IndAudTerminationStateDescriptor([H|_] = PP, EBC, SS, SSS) + when is_record(H, 'IndAudPropertyParm') and + ((EBC == 'NULL') or (EBC == asn1_NOVALUE)) and + ((SS == 'NULL') or (SS == asn1_NOVALUE)) and + is_atom(SSS) -> + #'IndAudTerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS, + serviceStateSel = SSS}. + +cre_IndAudEventsDescriptor(PkgdName) + when is_list(PkgdName) -> + #'IndAudEventsDescriptor'{pkgdName = PkgdName}. + +cre_IndAudEventsDescriptor(RID, PkgdName) + when is_integer(RID) and is_list(PkgdName) -> + #'IndAudEventsDescriptor'{requestID = RID, pkgdName = PkgdName}; +cre_IndAudEventsDescriptor(PkgdName, SID) + when is_list(PkgdName) and is_integer(SID) -> + #'IndAudEventsDescriptor'{pkgdName = PkgdName, streamID = SID}. + +cre_IndAudEventsDescriptor(RID, PkgdName, SID) + when is_integer(RID) and is_list(PkgdName) and is_integer(SID) -> + #'IndAudEventsDescriptor'{requestID = RID, + pkgdName = PkgdName, + streamID = SID}. + +cre_IndAudEventBufferDescriptor(EventName) when is_list(EventName) -> + #'IndAudEventBufferDescriptor'{eventName = EventName}. + +cre_IndAudEventBufferDescriptor(EventName, SID) + when is_list(EventName) and is_integer(SID) -> + #'IndAudEventBufferDescriptor'{eventName = EventName, streamID = SID}. + +cre_IndAudSignalsDescriptor(S) when is_record(S, 'IndAudSignal') -> + {signal, S}; +cre_IndAudSignalsDescriptor(S) when is_record(S, 'IndAudSeqSigList') -> + {seqSigList, S}. + +cre_IndAudSeqSigList(ID) + when is_integer(ID) and (0=< ID) and (ID =< 65535) -> + #'IndAudSeqSigList'{id = ID}. + +cre_IndAudSeqSigList(ID, S) + when is_integer(ID) and (0=< ID) and (ID =< 65535) and + is_record(S, 'IndAudSignal') -> + #'IndAudSeqSigList'{id = ID, signalList = S}. + +cre_IndAudSignal(SigName) when is_list(SigName) -> + #'IndAudSignal'{signalName = SigName}. + +cre_IndAudSignal(SigName, RID) + when is_list(SigName) and is_integer(RID) -> + #'IndAudSignal'{signalName = SigName, + signalRequestID = RID}. + +cre_IndAudDigitMapDescriptor() -> + #'IndAudDigitMapDescriptor'{}. + +cre_IndAudDigitMapDescriptor(DMN) when is_list(DMN) -> + #'IndAudDigitMapDescriptor'{digitMapName = DMN}. + +cre_IndAudStatisticsDescriptor(StatName) when is_list(StatName) -> + #'IndAudStatisticsDescriptor'{statName = StatName}. + +cre_IndAudPackagesDescriptor(N, V) + when is_list(N) and + is_integer(V) and (0 =< V) and (V =< 99) -> + #'IndAudPackagesDescriptor'{packageName = N, + packageVersion = V}. + +cre_NotifyRequest(TermIDs, D) + when is_list(TermIDs) and is_record(D, 'ObservedEventsDescriptor') -> + #'NotifyRequest'{terminationID = TermIDs, + observedEventsDescriptor = D}. + +cre_NotifyRequest(TermIDs, D, ED) + when is_list(TermIDs) andalso + is_record(D, 'ObservedEventsDescriptor') andalso + is_record(ED, 'ErrorDescriptor') -> + #'NotifyRequest'{terminationID = TermIDs, + observedEventsDescriptor = D, + errorDescriptor = ED}. + +cre_NotifyReply(TermIDs) when is_list(TermIDs) -> + #'NotifyReply'{terminationID = TermIDs}. + +cre_NotifyReply(TermIDs, ED) + when is_list(TermIDs) andalso + is_record(ED, 'ErrorDescriptor') -> + #'NotifyReply'{terminationID = TermIDs, + errorDescriptor = ED}. + +cre_ObservedEventsDescriptor(RID, [H|_] = L) + when is_integer(RID) andalso is_record(H, 'ObservedEvent') -> + #'ObservedEventsDescriptor'{requestId = RID, + observedEventLst = L}. + +cre_ObservedEvent(EN, EPL) + when is_list(EN) and is_list(EPL) -> + #'ObservedEvent'{eventName = EN, + eventParList = EPL}; +cre_ObservedEvent(EN, TN) + when is_list(EN) and is_record(TN, 'TimeNotation') -> + #'ObservedEvent'{eventName = EN, + timeNotation = TN}. + +cre_ObservedEvent(EN, SID, EPL) + when is_list(EN) and is_integer(SID) and is_list(EPL) -> + #'ObservedEvent'{eventName = EN, + streamID = SID, + eventParList = EPL}; +cre_ObservedEvent(EN, EPL, TN) + when is_list(EN) and is_list(EPL) and is_record(TN, 'TimeNotation') -> + #'ObservedEvent'{eventName = EN, + eventParList = EPL, + timeNotation = TN}. + +cre_ObservedEvent(EN, SID, EPL, TN) + when is_list(EN) and + is_integer(SID) and + is_list(EPL) and + is_record(TN, 'TimeNotation') -> + #'ObservedEvent'{eventName = EN, + streamID = SID, + eventParList = EPL, + timeNotation = TN}. + +cre_EventName(N) when is_list(N) -> + N. + +cre_EventParameter(N, V) when is_list(N) and is_list(V) -> + #'EventParameter'{eventParameterName = N, + value = V}. + +cre_EventParameter(N, V, relation = Tag, R) + when is_list(N) and is_list(V) and is_atom(R) -> + EI = {Tag, R}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}; +cre_EventParameter(N, V, range = Tag, B) + when is_list(N) and is_list(V) and is_atom(B) -> + EI = {Tag, B}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}; +cre_EventParameter(N, V, sublist = Tag, B) + when is_list(N) and is_list(V) and is_atom(B) -> + EI = {Tag, B}, + #'EventParameter'{eventParameterName = N, + value = V, + extraInfo = EI}. + +cre_ServiceChangeRequest(TermIDs, SCP) + when is_list(TermIDs) and + is_record(SCP, 'ServiceChangeParm') -> + #'ServiceChangeRequest'{terminationID = TermIDs, + serviceChangeParms = SCP}. + +cre_ServiceChangeReply(TermIDs, {Tag, R} = SCR) + when is_list(TermIDs) and is_atom(Tag) and is_tuple(R) -> + #'ServiceChangeReply'{terminationID = TermIDs, + serviceChangeResult = SCR}. + +cre_ServiceChangeResult(ED) when is_record(ED, 'ErrorDescriptor') -> + {errorDescriptor, ED}; +cre_ServiceChangeResult(SCRP) when is_record(SCRP, 'ServiceChangeResParm') -> + {serviceChangeResParms, SCRP}. + +%% cre_WildcardField(L) when list(L), length(L) == 1 -> L. + +cre_TerminationID(W, ID) + when is_list(W) andalso + is_list(ID) andalso (1 =< length(ID)) andalso (length(ID) =< 8) -> + #'TerminationID'{wildcard = W, + id = ID}. + +cre_TerminationIDList(L) when is_list(L) -> + L. + +cre_MediaDescriptor() -> + #'MediaDescriptor'{}. + +cre_MediaDescriptor(TSD) when is_record(TSD, 'TerminationStateDescriptor') -> + #'MediaDescriptor'{termStateDescr = TSD}; +cre_MediaDescriptor(SP) when is_record(SP, 'StreamParms') -> + Streams = {oneStream, SP}, + #'MediaDescriptor'{streams = Streams}; +cre_MediaDescriptor([H|_] = SDs) when is_record(H, 'StreamDescriptor') -> + Streams = {multiStream, SDs}, + #'MediaDescriptor'{streams = Streams}. + +cre_MediaDescriptor(TSD, SP) + when is_record(TSD, 'TerminationStateDescriptor') and + is_record(SP, 'StreamParms') -> + Streams = {oneStream, SP}, + #'MediaDescriptor'{termStateDescr = TSD, + streams = Streams}; +cre_MediaDescriptor(TSD, [H|_] = SDs) + when is_record(TSD, 'TerminationStateDescriptor') and + is_record(H, 'StreamDescriptor') -> + Streams = {multiStream, SDs}, + #'MediaDescriptor'{termStateDescr = TSD, + streams = Streams}. + +cre_StreamDescriptor(SID, SP) + when is_integer(SID) and is_record(SP, 'StreamParms') -> + #'StreamDescriptor'{streamID = SID, + streamParms = SP}. + +cre_StreamParms() -> + #'StreamParms'{}. + +cre_StreamParms(LCD) when is_record(LCD, 'LocalControlDescriptor') -> + #'StreamParms'{localControlDescriptor = LCD}; +cre_StreamParms(LD) when is_record(LD, 'LocalRemoteDescriptor') -> + #'StreamParms'{localDescriptor = LD}; +cre_StreamParms(SD) when is_list(SD) -> + #'StreamParms'{statisticsDescriptor = SD}. + +cre_StreamParms(LCD, LD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD}. + +cre_StreamParms(LCD, LD, RD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) and + (is_record(RD, 'LocalRemoteDescriptor') or (RD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD}; +cre_StreamParms(LCD, LD, SD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + statisticsDescriptor = SD}. + +cre_StreamParms(LCD, LD, RD, SD) + when (is_record(LCD, 'LocalControlDescriptor') or (LCD == asn1_NOVALUE)) and + (is_record(LD, 'LocalRemoteDescriptor') or (LD == asn1_NOVALUE)) and + (is_record(RD, 'LocalRemoteDescriptor') or (RD == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) -> + #'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}. + +cre_LocalControlDescriptor(SM) when is_atom(SM) -> + #'LocalControlDescriptor'{streamMode = SM, propertyParms = []}; +cre_LocalControlDescriptor([H|_] = PP) when is_record(H, 'PropertyParm') -> + #'LocalControlDescriptor'{propertyParms = PP}. + +cre_LocalControlDescriptor(SM, [H|_] = PP) + when is_atom(SM) and is_record(H, 'PropertyParm') -> + #'LocalControlDescriptor'{streamMode = SM, + propertyParms = PP}. + +cre_LocalControlDescriptor(SM, RV, RG, [H|_] = PP) + when is_atom(SM) and + ((RV == true) or (RV == false) or (RV == asn1_NOVALUE)) and + ((RG == true) or (RG == false) or (RG == asn1_NOVALUE)) and + is_record(H, 'PropertyParm') -> + #'LocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP}. + +cre_StreamMode(sendOnly = M) -> + M; +cre_StreamMode(recvOnly = M) -> + M; +cre_StreamMode(sendRecv = M) -> + M; +cre_StreamMode(inactive = M) -> + M; +cre_StreamMode(loopBack = M) -> + M. + +cre_PropertyParm(N, [H|_] = V) when is_list(N) and is_list(H) -> + #'PropertyParm'{name = N, value = V}. + +cre_PropertyParm(N, [H|_] = V, relation = Tag, R) + when is_list(N) and is_list(H) and is_atom(R) -> + EI = {Tag, R}, + #'PropertyParm'{name = N, value = V, extraInfo = EI}; +cre_PropertyParm(N, [H|_] = V, range = Tag, B) + when is_list(N) and is_list(H) and is_atom(B) -> + EI = {Tag, B}, + #'PropertyParm'{name = N, value = V, extraInfo = EI}; +cre_PropertyParm(N, [H|_] = V, sublist = Tag, B) + when is_list(N) and is_list(H) and is_atom(B) -> + EI = {Tag, B}, + #'PropertyParm'{name = N, value = V, extraInfo = EI}. + + +cre_Name(N) when is_list(N) and (length(N) == 2) -> + N. + +cre_PkgdName(N) when is_list(N) -> + case string:tokens(N, [$\\]) of + [_PkgName, _ItemID] -> + N; + _ -> + error({invalid_PkgdName, N}) + end. +cre_PkgdName(root, root) -> + "*/*"; +cre_PkgdName(PackageName, root) + when is_list(PackageName) and (length(PackageName) =< 64) -> + PackageName ++ "/*"; +cre_PkgdName(PackageName, ItemID) + when ((is_list(PackageName) and (length(PackageName) =< 64)) and + (is_list(ItemID) and (length(ItemID) =< 64))) -> + PackageName ++ "/" ++ ItemID; +cre_PkgdName(PackageName, ItemID) -> + error({invalid_PkgdName, {PackageName, ItemID}}). + +cre_Relation(greaterThan = R) -> + R; +cre_Relation(smallerThan = R) -> + R; +cre_Relation(unequalTo = R) -> + R. + +cre_LocalRemoteDescriptor([H|_] = PGs) when is_list(H) -> + #'LocalRemoteDescriptor'{propGrps = PGs}. + +cre_PropertyGroup([H|_] = PG) when is_record(H, 'PropertyParm') -> + PG. + +cre_TerminationStateDescriptor([H|_] = PPs) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs}. + +cre_TerminationStateDescriptor([H|_] = PPs, off = EBC) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + eventBufferControl = EBC}; +cre_TerminationStateDescriptor([H|_] = PPs, lockStep = EBC) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + eventBufferControl = EBC}; +cre_TerminationStateDescriptor([H|_] = PPs, test = SS) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + serviceState = SS}; +cre_TerminationStateDescriptor([H|_] = PPs, outOfSvc = SS) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + serviceState = SS}; +cre_TerminationStateDescriptor([H|_] = PPs, inSvc = SS) + when is_record(H, 'PropertyParm') -> + #'TerminationStateDescriptor'{propertyParms = PPs, + serviceState = SS}. + +cre_TerminationStateDescriptor([H|_] = PPs, EMC, SS) + when is_record(H, 'PropertyParm') and + ((EMC == off) or (EMC == lockStep)) and + ((SS == test) or (SS == outOfSvc) or (SS == inSvc)) -> + #'TerminationStateDescriptor'{propertyParms = PPs, + eventBufferControl = EMC, + serviceState = SS}. + +cre_EventBufferControl(off = EBC) -> + EBC; +cre_EventBufferControl(lockStep = EBC) -> + EBC. + +cre_ServiceState(test = SS) -> + SS; +cre_ServiceState(outOfSvc = SS) -> + SS; +cre_ServiceState(inSvc = SS) -> + SS. + +cre_MuxDescriptor(MT, [H|_] = TL) + when is_atom(MT) and is_record(H, 'TerminationID') -> + #'MuxDescriptor'{muxType = MT, termList = TL}. + +%% cre_MuxDescriptor(MT, [H|_] = TL, NSD) +%% when atom(MT), record(H, 'TerminationID'), record(NSD, 'NonStandardData') -> +%% #'MuxDescriptor'{muxType = MT, termList = TL, nonStandardData = NSD}. + +cre_MuxType(h221 = MT) -> + MT; +cre_MuxType(h223 = MT) -> + MT; +cre_MuxType(h226 = MT) -> + MT; +cre_MuxType(v76 = MT) -> + MT; +cre_MuxType(nx64k = MT) -> + MT. + +cre_StreamID(Val) when (0 =< Val) and (Val =< 65535) -> + Val; +cre_StreamID(Val) -> + exit({invalid_ContextID, Val}). + +%% RequestID must be present if eventList is non empty +cre_EventsDescriptor() -> + #'EventsDescriptor'{eventList = []}. + +cre_EventsDescriptor(RID, [H|_] = EL) + when is_integer(RID) and is_record(H, 'RequestedEvent') -> + #'EventsDescriptor'{requestID = RID, eventList = EL}. + +cre_RequestedEvent(N) -> + #'RequestedEvent'{pkgdName = N}. + +cre_RequestedEvent(N, EPL) + when is_list(N) and is_list(EPL) -> + #'RequestedEvent'{pkgdName = N, + evParList = EPL}; +cre_RequestedEvent(N, EA) + when is_list(N) and is_record(EA, 'RequestedActions')-> + #'RequestedEvent'{pkgdName = N, + eventAction = EA}. + + +cre_RequestedEvent(N, SID, EPL) + when is_list(N) and is_integer(SID) and is_list(EPL) -> + #'RequestedEvent'{pkgdName = N, + streamID = SID, + evParList = EPL}; +cre_RequestedEvent(N, EA, EPL) + when is_list(N) and is_record(EA, 'RequestedActions') and is_list(EPL) -> + #'RequestedEvent'{pkgdName = N, + eventAction = EA, + evParList = EPL}. + +cre_RequestedEvent(N, SID, EA, EPL) + when is_list(N) and + is_integer(SID) and + is_record(EA, 'RequestedActions') and + is_list(EPL) -> + #'RequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}. + +cre_RegulatedEmbeddedDescriptor() -> + #'RegulatedEmbeddedDescriptor'{}. + +cre_RegulatedEmbeddedDescriptor(D) -> + case is_SecondEventsDescriptor(D) of + true -> + #'RegulatedEmbeddedDescriptor'{secondEvent = D}; + false -> + case is_SignalsDescriptor(D) of + true -> + #'RegulatedEmbeddedDescriptor'{signalsDescriptor = D}; + false -> + error({invalid_RegulatedEmbeddedDescriptor, D}) + end + end. + +cre_RegulatedEmbeddedDescriptor(SED, SD) + when ((SED == asn1_NOVALUE) or is_record(SED, 'SecondEventsDescriptor')) and + ((SD == asn1_NOVALUE) or is_list(SD)) -> + #'RegulatedEmbeddedDescriptor'{secondEvent = SED, + signalsDescriptor = SD}. + +cre_NotifyBehaviour(notifyImmediate = Tag, 'NULL' = Val) -> + {Tag, Val}; +cre_NotifyBehaviour(notifyRegulated = Tag, Val) + when is_record(Val, 'RegulatedEmbeddedDescriptor') -> + {Tag, Val}; +cre_NotifyBehaviour(neverNotify = Tag, 'NULL' = Val) -> + {Tag, Val}; +cre_NotifyBehaviour(Tag, Val) -> + error({invalid_NotifyBehaviour, [Tag, Val]}). + +cre_RequestedActions() -> + #'RequestedActions'{}. + +cre_RequestedActions(KA) + when (KA == true) or (KA == true) -> + #'RequestedActions'{keepActive = KA}; +cre_RequestedActions(SE) + when is_record(SE, 'SecondEventsDescriptor') -> + #'RequestedActions'{secondEvent = SE}; +cre_RequestedActions(SD) + when is_list(SD) -> + #'RequestedActions'{signalsDescriptor = SD}; +cre_RequestedActions({Tag, _} = EDM) + when is_atom(Tag) -> + #'RequestedActions'{eventDM = EDM}. + +cre_RequestedActions(KA, {Tag, _} = EDM, SE, SD) + when ((KA == true) or (KA == true) or (KA == asn1_NOVALUE)) and + (is_atom(Tag) or (EDM == asn1_NOVALUE)) and + (is_record(SE, 'SecondEventsDescriptor') or (SE == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) -> + #'RequestedActions'{keepActive = KA, + eventDM = EDM, + secondEvent = SE, + signalsDescriptor = SD}. + +cre_RequestedActions(KA, {EDMTag, _} = EDM, SE, SD, {NBTag, _} = NB, RED) + when ((KA == true) or (KA == true) or (KA == asn1_NOVALUE)) and + (is_atom(EDMTag) or (EDM == asn1_NOVALUE)) and + (is_record(SE, 'SecondEventsDescriptor') or (SE == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) and + (is_atom(NBTag) or (NB == asn1_NOVALUE)) and + ((RED == 'NULL') or (RED == asn1_NOVALUE)) -> + #'RequestedActions'{keepActive = KA, + eventDM = EDM, + secondEvent = SE, + signalsDescriptor = SD, + notifyBehaviour = NB, + resetEventsDescriptor = RED}. + +cre_EventDM(N) when is_list(N) -> + {digitMapName, N}; +cre_EventDM(V) when is_record(V, 'DigitMapValue') -> + {digitMapValue, V}. + +cre_SecondEventsDescriptor([H|_] = EL) + when is_record(H, 'SecondRequestedEvent') -> + #'SecondEventsDescriptor'{eventList = EL}. + +cre_SecondEventsDescriptor(RID, [H|_] = EL) + when is_integer(RID) and is_record(H, 'SecondRequestedEvent') -> + #'SecondEventsDescriptor'{requestID = RID, eventList = EL}. + +cre_SecondRequestedEvent(N, EPL) + when is_list(N) and is_list(EPL) -> + #'SecondRequestedEvent'{pkgdName = N, + evParList = EPL}; +cre_SecondRequestedEvent(N, EPL) -> + error({invalid_SecondRequestedEvent, [N, EPL]}). + +cre_SecondRequestedEvent(N, SID, EPL) + when is_list(N) and is_integer(SID) and is_list(EPL) -> + #'SecondRequestedEvent'{pkgdName = N, + streamID = SID, + evParList = EPL}; +cre_SecondRequestedEvent(N, EA, EPL) + when is_list(N) and + is_record(EA, 'SecondRequestedActions') and + is_list(EPL) -> + #'SecondRequestedEvent'{pkgdName = N, + eventAction = EA, + evParList = EPL}. + +cre_SecondRequestedEvent(N, SID, EA, EPL) + when is_list(N) and + is_integer(SID) and + is_record(EA, 'SecondRequestedActions') and + is_list(EPL) -> + #'SecondRequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}. + +cre_SecondRequestedActions() -> + #'SecondRequestedActions'{}. + +cre_SecondRequestedActions(KA) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) -> + #'SecondRequestedActions'{keepActive = KA}; +cre_SecondRequestedActions(SD) when is_list(SD) -> + #'SecondRequestedActions'{signalsDescriptor = SD}; +cre_SecondRequestedActions({Tag, _} = Val) when is_atom(Tag) -> + case is_EventDM(Val) of + true -> + #'SecondRequestedActions'{eventDM = Val}; + false -> + case is_NotifyBehaviour(Val) of + true -> + #'SecondRequestedActions'{notifyBehaviour = Val}; + false -> + error({invalid_SecondRequestedActions, Val}) + end + end; +cre_SecondRequestedActions('NULL' = RED) -> + #'SecondRequestedActions'{resetEventsDescriptor = RED}. + +cre_SecondRequestedActions(KA, SD) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SD) -> + #'SecondRequestedActions'{keepActive = KA, signalsDescriptor = SD}; +cre_SecondRequestedActions(KA, {Tag, _} = Val) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_atom(Tag) -> + case is_EventDM(Val) of + true -> + #'SecondRequestedActions'{keepActive = KA, + eventDM = Val}; + false -> + case is_NotifyBehaviour(Val) of + true -> + #'SecondRequestedActions'{keepActive = KA, + notifyBehaviour = Val}; + false -> + error({invalid_SecondRequestedActions, Val}) + end + end; +cre_SecondRequestedActions(KA, 'NULL' = RED) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) -> + #'SecondRequestedActions'{keepActive = KA, + resetEventsDescriptor = RED}. + +cre_SecondRequestedActions(KA, {Tag, _} = EDM, SD) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_atom(Tag) and + is_list(SD) -> + #'SecondRequestedActions'{keepActive = KA, + eventDM = EDM, + signalsDescriptor = SD}; +cre_SecondRequestedActions(KA, SD, {Tag, _} = NB) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SD) and + is_atom(Tag) -> + #'SecondRequestedActions'{keepActive = KA, + signalsDescriptor = SD, + notifyBehaviour = NB}; +cre_SecondRequestedActions(KA, SD, 'NULL' = RED) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SD) -> + #'SecondRequestedActions'{keepActive = KA, + signalsDescriptor = SD, + resetEventsDescriptor = RED}. + +cre_SecondRequestedActions(KA, {EDMTag, _} = EDM, SD, + {NBTag, _} = NB, RED) + when ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + (is_atom(EDMTag) or (EDM == asn1_NOVALUE)) and + (is_list(SD) or (SD == asn1_NOVALUE)) and + (is_atom(NBTag) or (NB == asn1_NOVALUE)) and + ((RED == 'NULL') or (RED == asn1_NOVALUE)) -> + #'SecondRequestedActions'{keepActive = KA, + eventDM = EDM, + signalsDescriptor = SD, + notifyBehaviour = NB, + resetEventsDescriptor = RED}. + +cre_EventBufferDescriptor([H|_] = D) when is_record(H, 'EventSpec') -> + D. + +cre_EventSpec(N, [H|_] = EPL) + when is_list(N) and is_record(H, 'EventParameter') -> + #'EventSpec'{eventName = N, eventParList = EPL}. + +cre_EventSpec(N, SID, [H|_] = EPL) + when is_list(N) and is_integer(SID) and is_record(H, 'EventParameter') -> + #'EventSpec'{eventName = N, streamID = SID, eventParList = EPL}. + +cre_SignalsDescriptor(D) -> + case is_SignalsDescriptor(D) of + true -> + D; + false -> + error({invalid_SignalsDescriptor, D}) + end. + +cre_SignalRequest(S) when is_record(S, 'Signal') -> + {signal, S}; +cre_SignalRequest(S) when is_record(S, 'SeqSigList') -> + {seqSigList, S}. + +cre_SeqSigList(ID, [H|_] = SL) + when is_integer(ID) and (0 =< ID) and (ID =< 65535) and + is_record(H, 'Signal') -> + #'SeqSigList'{id = ID, signalList = SL}. + +cre_Signal(N) when is_list(N) -> + #'Signal'{signalName = N}. + +cre_Signal(N, SPL) when is_list(N) and is_list(SPL) -> + #'Signal'{signalName = N, + sigParList = SPL}. + +cre_Signal(N, SID, ST, Dur, NC, KA, SPL) + when is_list(N) and + (is_integer(SID) or (SID == asn1_NOVALUE)) and + ((ST == brief) or (ST == onOff) or (ST == timeOut) or + (ST == asn1_NOVALUE)) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 65535)) or + (Dur == asn1_NOVALUE)) and + (is_list(NC) or (NC == asn1_NOVALUE)) and + ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SPL) -> + #'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL}. + +cre_Signal(N, SID, ST, Dur, NC, KA, SPL, Dir, RID) + when is_list(N) and + (is_integer(SID) or (SID == asn1_NOVALUE)) and + ((ST == brief) or (ST == onOff) or (ST == timeOut) or + (ST == asn1_NOVALUE)) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 65535)) or + (Dur == asn1_NOVALUE)) and + (is_list(NC) or (NC == asn1_NOVALUE)) and + ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SPL) and + ((Dir == internal) or (Dir == external) or (Dir == both) or + (Dir == asn1_NOVALUE)) and + (is_integer(RID) or (RID == asn1_NOVALUE)) -> + #'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL, + direction = Dir, + requestID = RID}. + +cre_Signal(N, SID, ST, Dur, NC, KA, SPL, Dir, RID, ISIG) + when is_list(N) and + (is_integer(SID) or (SID == asn1_NOVALUE)) and + ((ST == brief) or (ST == onOff) or (ST == timeOut) or + (ST == asn1_NOVALUE)) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 65535)) or + (Dur == asn1_NOVALUE)) and + (is_list(NC) or (NC == asn1_NOVALUE)) and + ((KA == true) or (KA == false) or (KA == asn1_NOVALUE)) and + is_list(SPL) and + ((Dir == internal) or (Dir == external) or (Dir == both) or + (Dir == asn1_NOVALUE)) and + (is_integer(RID) or (RID == asn1_NOVALUE)) and + (is_integer(ISIG) or (ISIG == asn1_NOVALUE)) -> + #'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL, + direction = Dir, + requestID = RID, + intersigDelay = ISIG}. + +cre_SignalType(brief = ST) -> + ST; +cre_SignalType(onOff = ST) -> + ST; +cre_SignalType(timeOut = ST) -> + ST. + +cre_SignalDirection(internal = SD) -> + SD; +cre_SignalDirection(external = SD) -> + SD; +cre_SignalDirection(both = SD) -> + SD. + +cre_SignalName(N) -> + cre_PkgdName(N). + +cre_NotifyCompletion(L) when is_list(L) -> + Vals = [onTimeOut, onInterruptByEvent, + onInterruptByNewSignalDescr, otherReason], + F = fun(E) -> case lists:member(E, Vals) of + true -> + ok; + false -> + exit({invalid_NotifyCompletion, E}) + end + end, + lists:foreach(F, L), + L. + +cre_SigParameter(N, V) when is_list(N) and is_list(V) -> + #'SigParameter'{sigParameterName = N, value = V}. + +cre_SigParameter(N, V, relation = Tag, R) + when is_list(N) and is_list(V) and is_atom(R) -> + EI = {Tag, R}, + #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}; +cre_SigParameter(N, V, range = Tag, B) + when is_list(N) and is_list(V) and is_atom(B) -> + EI = {Tag, B}, + #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}; +cre_SigParameter(N, V, sublist = Tag, B) + when is_list(N) and is_list(V) and is_atom(B) -> + EI = {Tag, B}, + #'SigParameter'{sigParameterName = N, value = V, extraInfo = EI}. + +cre_RequestID(Val) when (0 =< Val) and (Val =< 4294967295) -> + Val; +cre_RequestID(Val) -> + exit({invalid_RequestID, Val}). + +cre_ModemDescriptor(MTL, MPL) when is_list(MTL) and is_list(MPL) -> + #'ModemDescriptor'{mtl = MTL, mpl = MPL}. + +%% cre_ModemDescriptor(MTL, MPL, NSD) +%% when list(MTL), list(MPL), record(NSD, 'NonStandardData') -> +%% #'ModemDescriptor'{mtl = MTL, mpl = MPL}. + +cre_ModemType(v18 = MT) -> + MT; +cre_ModemType(v22 = MT) -> + MT; +cre_ModemType(v22bis = MT) -> + MT; +cre_ModemType(v32 = MT) -> + MT; +cre_ModemType(v32bis = MT) -> + MT; +cre_ModemType(v34 = MT) -> + MT; +cre_ModemType(v90 = MT) -> + MT; +cre_ModemType(v91 = MT) -> + MT; +cre_ModemType(synchISDN = MT) -> + MT. + +cre_DigitMapDescriptor() -> + #'DigitMapDescriptor'{}. + +cre_DigitMapDescriptor(N) when is_list(N) -> + #'DigitMapDescriptor'{digitMapName = N}; +cre_DigitMapDescriptor(V) when is_record(V, 'DigitMapValue') -> + #'DigitMapDescriptor'{digitMapValue = V}. + +cre_DigitMapDescriptor(N, V) + when is_list(N) and is_record(V, 'DigitMapValue') -> + #'DigitMapDescriptor'{digitMapName = N, digitMapValue = V}. + +cre_DigitMapName(N) -> + cre_Name(N). + +cre_DigitMapValue(DMB) when is_list(DMB) -> + #'DigitMapValue'{digitMapBody = DMB}. + +cre_DigitMapValue(Start, Short, Long, DMB) -> + cre_DigitMapValue(Start, Short, Long, DMB, asn1_NOVALUE). + +cre_DigitMapValue(Start, Short, Long, DMB, Dur) + when ((is_integer(Start) and (0 =< Start) and (Start =< 99)) or + (Start == asn1_NOVALUE)) and + ((is_integer(Short) and (0 =< Short) and (Short =< 99)) or + (Short == asn1_NOVALUE)) and + ((is_integer(Long) and (0 =< Long) and (Long =< 99)) or + (Long == asn1_NOVALUE)) and + is_list(DMB) and + ((is_integer(Dur) and (0 =< Dur) and (Dur =< 99)) or + (Dur == asn1_NOVALUE)) -> + #'DigitMapValue'{startTimer = Start, + shortTimer = Short, + longTimer = Long, + digitMapBody = DMB, + durationTimer = Dur}. + +cre_ServiceChangeParm(M, R) when is_atom(M) and is_list(R) -> + #'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeReason = R}. + +cre_ServiceChangeParm(M, Addr, Prof, Reason) -> + cre_ServiceChangeParm(M, Addr, asn1_NOVALUE, Prof, Reason, asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE, + asn1_NOVALUE, asn1_NOVALUE). + +%% Addr = asn1_NOVALUE | {AddrTag, AddrVal} +cre_ServiceChangeParm(M, Addr, Ver, Prof, R, D, Mid, TS, I) -> + cre_ServiceChangeParm(M, Addr, Ver, Prof, R, D, Mid, TS, I, asn1_NOVALUE). + +cre_ServiceChangeParm(M, Addr, Ver, Prof, R, D, Mid, TS, I, IF) + when is_atom(M) and + ((is_integer(Ver) and (0 =< Ver) and (Ver =< 99)) or + (Ver == asn1_NOVALUE)) and + (is_record(Prof, 'ServiceChangeProfile') or (Prof == asn1_NOVALUE)) and + is_list(R) and + ((is_integer(D) and (0 =< D) and (D =< 4294967295)) or + (D == asn1_NOVALUE)) and + (is_record(TS, 'TimeNotation') or (TS == asn1_NOVALUE)) and + (is_record(I, 'AuditDescriptor') or (I == asn1_NOVALUE)) and + ((IF == 'NULL') or (IF == asn1_NOVALUE)) -> + F = fun(A) -> + (A == asn1_NOVALUE) orelse + (is_tuple(A) + andalso is_atom(element(1, A))) + end, + case (F(Addr) andalso F(Mid)) of + true -> + #'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeAddress = Addr, + serviceChangeVersion = Ver, + serviceChangeProfile = Prof, + serviceChangeReason = R, + serviceChangeDelay = D, + serviceChangeMgcId = Mid, + timeStamp = TS, + serviceChangeInfo = I, + serviceChangeIncompleteFlag = IF}; + _ -> + exit({invalid_ServiceChangeParm_args, {Addr, Mid}}) + end. + +cre_ServiceChangeAddress(portNumber = Tag, P) + when is_integer(P) and (0 =< P) and (P =< 65535) -> + {Tag, P}; +cre_ServiceChangeAddress(ip4Address = Tag, A) + when is_record(A, 'IP4Address') -> + {Tag, A}; +cre_ServiceChangeAddress(ip6Address = Tag, A) + when is_record(A, 'IP6Address') -> + {Tag, A}; +cre_ServiceChangeAddress(domainName = Tag, N) + when is_record(N, 'DomainName') -> + {Tag, N}; +cre_ServiceChangeAddress(deviceName = Tag, N) when is_list(N) -> + {Tag, N}; +cre_ServiceChangeAddress(mtpAddress = Tag, A) when is_list(A) -> + {Tag, A}. + +cre_ServiceChangeResParm() -> + #'ServiceChangeResParm'{}. +cre_ServiceChangeResParm(Addr, Prof) -> + cre_ServiceChangeResParm(asn1_NOVALUE, Addr, asn1_NOVALUE, + Prof, asn1_NOVALUE). +cre_ServiceChangeResParm(Mid, Addr, Ver, Prof, TS) + when ((is_integer(Ver) and (0 =< Ver) and (Ver =< 99)) or + (Ver == asn1_NOVALUE)) and + (is_record(Prof, 'ServiceChangeProfile') or (Prof == asn1_NOVALUE)) and + (is_record(TS, 'TimeNotation') or (TS == asn1_NOVALUE)) -> + F = fun(A) -> + (A == asn1_NOVALUE) orelse + (is_tuple(A) + andalso is_atom(element(1, A))) + end, + case (F(Addr) andalso F(Mid)) of + true -> + #'ServiceChangeResParm'{serviceChangeMgcId = Mid, + serviceChangeAddress = Addr, + serviceChangeVersion = Ver, + serviceChangeProfile = Prof, + timeStamp = TS}; + _ -> + exit({invalid_ServiceChangeResParm_args, {Addr, Mid}}) + end. + +cre_ServiceChangeMethod(failover = M) -> + M; +cre_ServiceChangeMethod(forced = M) -> + M; +cre_ServiceChangeMethod(graceful = M) -> + M; +cre_ServiceChangeMethod(restart = M) -> + M; +cre_ServiceChangeMethod(disconnected = M) -> + M; +cre_ServiceChangeMethod(handOff = M) -> + M. + +%% The version field is added to make it look more like ABNF +cre_ServiceChangeProfile(N) -> + cre_ServiceChangeProfile(N, 1). + +cre_ServiceChangeProfile(N, V) + when is_list(N) and is_integer(V) and (0 =< V) and (V =< 99) -> + #'ServiceChangeProfile'{profileName = N, version = V}. + +cre_PackagesDescriptor([H|_] = D) when is_record(H, 'PackagesItem') -> + D. + +cre_PackagesItem(N, Ver) + when is_list(N) and + is_integer(Ver) and (0 =< Ver) and (Ver =< 99) -> + #'PackagesItem'{packageName = N, + packageVersion = Ver}. + +cre_StatisticsDescriptor(D) -> + true = is_StatisticsDescriptor(D), + D. + +cre_StatisticsParameter(N) when is_list(N) -> + #'StatisticsParameter'{statName = N}. + +cre_StatisticsParameter(N, V) when is_list(N) and is_list(V) -> + #'StatisticsParameter'{statName = N, statValue = V}. + +%% cre_NonStandardData({Tag, _} = Id, Data) when atom(Tag), list(Data) -> +%% #'NonStandardData'{nonStandardIdentifier = Id, data = Data}. + +%% cre_NonStandardIdentifier(H221) when record(H221, 'H221NonStandard') -> +%% {h221NonStandard, H221}; +%% cre_NonStandardIdentifier(Obj) when tuple(Obj) -> +%% {object, Obj}; +%% cre_NonStandardIdentifier(Exp) when list(Exp), length(Exp) == 8 -> +%% {experimental, Exp}. + +%% cre_H221NonStandard(CC1, CC2, Ext, MC) +%% when (is_integer(CC1) and (0 =< CC1) and (CC1 =< 255)) and +%% (is_integer(CC2) and (0 =< CC2) and (CC2 =< 255)) and +%% (is_integer(Ext) and (0 =< Ext) and (Ext =< 255)) and +%% (is_integer(MC) and (0 =< MC) and (MC =< 255)) -> +%% #'H221NonStandard'{t35CountryCode1 = CC1, +%% t35CountryCode2 = CC2, +%% t35Extension = Ext, +%% manufacturerCode = MC}. + +cre_TimeNotation(D, T) + when is_list(D) and (length(D) == 8) and + is_list(T) and (length(T) == 8) -> + #'TimeNotation'{date = D, time = T}. + +cre_Value([H|_] = V) when is_list(H) -> + V. + +cre_BOOLEAN(true = B) -> + B; +cre_BOOLEAN(false = B) -> + B. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% -- MegacoMessage -- + +is_MegacoMessage(#'MegacoMessage'{authHeader = Auth, + mess = Mess}) -> + d("is_MegacoMessage -> entry"), + is_opt_AuthenticationHeader(Auth) andalso is_Message(Mess); +is_MegacoMessage(_) -> + false. + + +chk_MegacoMessage(M, M) -> + d("chk_MegacoMessage -> entry (1)"), + chk_type(fun is_MegacoMessage/1, 'MegacoMessage', M); +chk_MegacoMessage(#'MegacoMessage'{authHeader = Auth1, + mess = Mess1}, + #'MegacoMessage'{authHeader = Auth2, + mess = Mess2}) -> + d("chk_MegacoMessage -> entry (2)"), + chk_opt_AuthenticationHeader(Auth1,Auth2), + chk_Message(Mess1,Mess2), + ok; +chk_MegacoMessage(M1, M2) -> + wrong_type('MegacoMessage', M1, M2). + + +%% -- AuthenticationHeader -- + +is_opt_AuthenticationHeader(AH) -> + is_OPTIONAL(fun is_AuthenticationHeader/1, AH). + +is_AuthenticationHeader(#'AuthenticationHeader'{secParmIndex = SPI, + seqNum = SN, + ad = AD}) -> + is_SecurityParmIndex(SPI) andalso + is_SequenceNum(SN) andalso + is_AuthData(AD); +is_AuthenticationHeader(_) -> + false. + +%% This stuff is not really used, so make it simple... +chk_opt_AuthenticationHeader(A1, A2) -> + chk_OPTIONAL('AuthenticationHeader', A1, A2, + fun is_AuthenticationHeader/1, + fun chk_AuthenticationHeader/2). + +chk_AuthenticationHeader(A, A) -> + chk_type(fun is_AuthenticationHeader/1, 'AuthenticationHeader', A); +chk_AuthenticationHeader(A1, A2) -> + case (is_AuthenticationHeader(A1) andalso is_AuthenticationHeader(A2)) of + true -> + not_equal('AuthenticationHeader', A1, A2); + false -> + wrong_type('AuthenticationHeader', A1, A2) + end. + + +%% -- SecurityParmIndex -- + +is_SecurityParmIndex(V) -> is_OCTET_STRING(V, {exact, 4}). + + +%% -- SequenceNum -- + +is_SequenceNum(V) -> is_OCTET_STRING(V, {exact, 4}). + + +%% -- AuthData -- + +is_AuthData(V) -> is_OCTET_STRING(V, {range, 12, 32}). + + +%% -- Message -- + +is_Message(#'Message'{version = V, + mId = MID, + messageBody = Body}) -> + d("is_Message -> entry"), + is_INTEGER(V, {range, 0, 99}) andalso + is_MId(MID) andalso + is_Message_messageBody(Body); +is_Message(_) -> + false. + +chk_Message(M, M) -> + d("chk_Message -> entry (1)"), + chk_type(fun is_Message/1, 'Message', M); +chk_Message(#'Message'{version = V1, + mId = MID1, + messageBody = Body1}, + #'Message'{version = V2, + mId = MID2, + messageBody = Body2}) -> + d("chk_Message -> entry with" + "~n V1: ~p" + "~n V2: ~p" + "~n MID1: ~p" + "~n MID2: ~p" + "~n Body1: ~p" + "~n Body2: ~p", + [V1, V2, MID1, MID2, Body1, Body2]), + validate(fun() -> chk_INTEGER(V1, V2, {range, 0, 99}) end, + 'Message_version'), + validate(fun() -> chk_MId(MID1, MID2) end, 'Message_mId'), + chk_Message_messageBody(Body1, Body2), + ok; +chk_Message(M1, M2) -> + wrong_type('Message', M1, M2). + + +is_Message_messageBody({Tag, Val}) -> + d("is_Message_messageBody -> entry"), + is_Message_messageBody_tag(Tag) andalso + is_Message_messageBody_val(Tag, Val); +is_Message_messageBody(_) -> + false. + +is_Message_messageBody_tag(Tag) -> + Tags = [messageError, transactions], + lists:member(Tag, Tags). + +is_Message_messageBody_val(messageError, Val) -> + is_ErrorDescriptor(Val); +is_Message_messageBody_val(transactions, Val) -> + is_Message_messageBody_transactions(Val). + +is_Message_messageBody_transactions([]) -> + d("is_Message_messageBody_transactions -> entry when done"), + true; +is_Message_messageBody_transactions([H|T]) -> + d("is_Message_messageBody_transactions -> entry"), + is_Transaction(H) andalso is_Message_messageBody_transactions(T); +is_Message_messageBody_transactions(_) -> + false. + +chk_Message_messageBody(B, B) -> + d("chk_Message_messageBody -> entry (1)"), + chk_type(fun is_Message_messageBody/1, 'Message_messageBody', B); +chk_Message_messageBody({Tag, Val1} = B1, {Tag, Val2} = B2) -> + d("chk_Message_messageBody -> entry (2)"), + case (is_Message_messageBody_tag(Tag) andalso + is_Message_messageBody_val(Tag, Val1) andalso + is_Message_messageBody_val(Tag, Val2)) of + true -> + chk_Message_messageBody_val(Tag, Val1, Val2); + false -> + wrong_type('Message_messageBody', B1, B2) + end; +chk_Message_messageBody({Tag1, Val1} = B1, {Tag2, Val2} = B2) -> + d("chk_Message_messageBody -> entry (3)"), + case ((is_Message_messageBody_tag(Tag1) andalso + is_Message_messageBody_val(Tag1, Val1)) andalso + (is_Message_messageBody_tag(Tag2) andalso + is_Message_messageBody_val(Tag2, Val2))) of + true -> + not_equal('Message_messageBody', B1, B2); + false -> + wrong_type('Message_messageBody', B1, B2) + end; +chk_Message_messageBody(B1, B2) -> + wrong_type('Message_messageBody', B1, B2). + +chk_Message_messageBody_val(messageError, Val1, Val2) -> + validate(fun() -> chk_ErrorDescriptor(Val1, Val2) end, + 'Message_messageBody'); +chk_Message_messageBody_val(transactions, Val1, Val2) -> + chk_Message_messageBody_transactions(lists:sort(Val1), + lists:sort(Val2)). + +chk_Message_messageBody_transactions([], []) -> + d("chk_Message_messageBody_transactions -> entry - ok (1)"), + ok; +chk_Message_messageBody_transactions([] = T1, T2) -> + d("chk_Message_messageBody_transactions -> entry - not-equal (2)"), + not_equal('Message_messageBody_transactions', T1, T2); +chk_Message_messageBody_transactions(T1, [] = T2) -> + d("chk_Message_messageBody_transactions -> entry - not-equal (3)"), + not_equal('Message_messageBody_transactions', T1, T2); +chk_Message_messageBody_transactions([H|T1], [H|T2]) -> + d("chk_Message_messageBody_transactions -> entry (4)"), + case is_Transaction(H) of + true -> + chk_Message_messageBody_transactions(T1, T2); + false -> + wrong_type('Message_messageBody_transactions_val', H) + end; +chk_Message_messageBody_transactions([H1|T1], [H2|T2]) -> + d("chk_Message_messageBody_transactions -> entry (5)"), + validate(fun() -> chk_Transaction(H1, H2) end, + 'Message_messageBody_transactions_val'), + chk_Message_messageBody_transactions(T1, T2); +chk_Message_messageBody_transactions(T1, T2) -> + d("chk_Message_messageBody_transactions -> entry - wrong-type (6)"), + wrong_type('Message_messageBody_transactions', T1, T2). + + +%% -- MId -- + +is_opt_MId(M) -> + is_OPTIONAL(fun is_MId/1, M). + +is_MId({Tag, Val}) -> + is_MId_tag(Tag) andalso is_MId_val(Tag, Val); +is_MId(_) -> + false. + +is_MId_tag(Tag) -> + Tags = [ip4Address, ip6Address, domainName, deviceName, mtpAddress], + lists:member(Tag, Tags). + +is_MId_val(ip4Address, Val) -> is_IP4Address(Val); +is_MId_val(ip6Address, Val) -> is_IP6Address(Val); +is_MId_val(domainName, Val) -> is_DomainName(Val); +is_MId_val(deviceName, Val) -> is_PathName(Val); +is_MId_val(mtpAddress, Val) -> is_OCTET_STRING(Val, {range, 2, 4}). + +chk_opt_MId(M1, M2) -> + chk_OPTIONAL('MId', M1, M2, fun is_MId/1, fun chk_MId/2). + +chk_MId(M, M) -> + chk_type(fun is_MId/1, 'MId', M); +chk_MId({Tag, Val1} = M1, {Tag, Val2} = M2) -> + case (is_MId_tag(Tag) andalso + is_MId_val(Tag, Val1) andalso + is_MId_val(Tag, Val2)) of + true -> + chk_MId_val(Tag, Val1, Val2); + false -> + wrong_type('MId', M1, M2) + end; +chk_MId({Tag1, Val1} = M1, {Tag2, Val2} = M2) -> + case ((is_MId_tag(Tag1) andalso + is_MId_val(Tag1, Val1)) andalso + (is_MId_tag(Tag2) andalso + is_MId_val(Tag2, Val2))) of + true -> + not_equal('MId', M1, M2); + false -> + wrong_type('MId', M1, M2) + end; +chk_MId(M1, M2) -> + wrong_type('MId', M1, M2). + +chk_MId_val(ip4Address, M1, M2) -> chk_IP4Address(M1, M2); +chk_MId_val(ip6Address, M1, M2) -> chk_IP6Address(M1, M2); +chk_MId_val(domainName, M1, M2) -> chk_DomainName(M1, M2); +chk_MId_val(deviceName, M1, M2) -> chk_PathName(M1, M2); +chk_MId_val(mtpAddress, M1, M2) -> chk_OCTET_STRING(M1, M2, {range, 2, 4}). + + +%% -- DomainName -- + +is_DomainName(#'DomainName'{name = N, portNumber = PN}) -> + is_IA5String(N) andalso is_opt_INTEGER(PN, {range, 0, 65535}); +is_DomainName(_) -> + false. + +chk_DomainName(N, N) -> + ok; +chk_DomainName(N1, N2) -> + not_equal('DomainName', N1, N2). + + +%% -- IP4Address -- + +is_IP4Address(#'IP4Address'{address = A, portNumber = PN}) -> + is_OCTET_STRING(A, {exact, 4}) andalso + is_opt_INTEGER(PN, {range, 0, 65535}); +is_IP4Address(_) -> + false. + +chk_IP4Address(A, A) -> + ok; +chk_IP4Address(A1, A2) -> + not_equal('IP4Address', A1, A2). + + +%% -- IP6Address -- + +is_IP6Address(#'IP6Address'{address = A, portNumber = PN}) -> + is_OCTET_STRING(A, {exact, 16}) andalso + is_opt_INTEGER(PN, {range, 0, 65535}); +is_IP6Address(_) -> + false. + +chk_IP6Address(A, A) -> + ok; +chk_IP6Address(A1, A2) -> + not_equal('IP6Address', A1, A2). + + +%% -- PathName -- + +is_PathName(N) -> is_IA5String(N, {range, 1, 64}). + +chk_PathName(N, N) -> + ok; +chk_PathName(N1, N2) -> + not_equal('PathName', N1, N2). + + +%% -- Transaction -- + +is_Transaction({Tag, Val}) -> + d("is_Transaction -> entry"), + is_Transaction_tag(Tag) andalso is_Transaction_val(Tag, Val); +is_Transaction(_) -> + false. + +is_Transaction_tag(Tag) -> + Tags = [transactionRequest, + transactionPending, + transactionReply, + transactionResponseAck], + lists:member(Tag, Tags). + +is_Transaction_val(transactionRequest, V) -> is_TransactionRequest(V); +is_Transaction_val(transactionPending, V) -> is_TransactionPending(V); +is_Transaction_val(transactionReply, V) -> is_TransactionReply(V); +is_Transaction_val(transactionResponseAck, V) -> is_TransactionResponseAck(V). + + +chk_Transaction({Tag, Val} = Trans, Trans) -> + d("chk_Transaction -> entry (1)"), + case (is_Transaction_tag(Tag) andalso is_Transaction_val(Tag, Val)) of + true -> + ok; + false -> + wrong_type('Transaction', Trans, Trans) + end; +chk_Transaction({Tag, Val1} = Trans1, {Tag, Val2} = Trans2) -> + d("chk_Transaction -> entry (2)"), + case (is_Transaction_tag(Tag) and + is_Transaction_val(Tag, Val1) and + is_Transaction_val(Tag, Val2)) of + true -> + chk_Transaction_val(Tag, Val1, Val2); + false -> + wrong_type('Transaction', Trans1, Trans2) + end; +chk_Transaction({Tag1, Val1} = Trans1, {Tag2, Val2} = Trans2) -> + d("chk_Transaction -> entry (3)"), + case ((is_Transaction_tag(Tag1) andalso + is_Transaction_val(Tag1, Val1)) andalso + (is_Transaction_tag(Tag2) andalso + is_Transaction_val(Tag2, Val2))) of + true -> + not_equal('Transaction', Trans1, Trans2); + false -> + wrong_type('Transaction', Trans1, Trans2) + end; +chk_Transaction(Trans1, Trans2) -> + d("chk_Transaction -> entry - wrong-type - (4)"), + wrong_type('Transaction', Trans1, Trans2). + +chk_Transaction_val(transactionRequest, T1, T2) -> + chk_TransactionRequest(T1, T2); +chk_Transaction_val(transactionPending, T1, T2) -> + chk_TransactionPending(T1, T2); +chk_Transaction_val(transactionReply, T1, T2) -> + chk_TransactionReply(T1,T2); +chk_Transaction_val(transactionResponseAck, T1, T2) -> + chk_TransactionResponseAck(T1, T2). + + +%% -- TransactionId -- + +is_opt_TransactionId(TID) -> + is_OPTIONAL(fun is_TransactionId/1, TID). + +is_TransactionId(TID) -> + d("is_TransactionId -> entry"), + is_INTEGER(TID, {range, 0, 4294967295}). + +chk_opt_TransactionId(TID1, TID2) -> + chk_OPTIONAL('TransactionId', TID1, TID2, + fun is_TransactionId/1, fun chk_TransactionId/2). + +chk_TransactionId(TID, TID) -> + chk_type(fun is_TransactionId/1, 'TransactionId', TID); +chk_TransactionId(TID1, TID2) -> + case (is_TransactionId(TID1) andalso is_TransactionId(TID2)) of + true -> + not_equal('TransactionId', TID1, TID2); + false -> + wrong_type('TransactionId', TID1, TID2) + end. + + +%% -- TransactionRequest -- + +is_TransactionRequest(#'TransactionRequest'{transactionId = TID, + actions = Acts}) -> + d("is_TransactionRequest -> entry"), + is_TransactionId(TID) andalso is_TransactionRequest_actions(Acts); +is_TransactionRequest(_) -> + false. + +chk_TransactionRequest(T, T) -> + chk_type(fun is_TransactionRequest/1, 'TransactionRequest', T); +chk_TransactionRequest(#'TransactionRequest'{transactionId = TID1, + actions = Acts1}, + #'TransactionRequest'{transactionId = TID2, + actions = Acts2}) -> + validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionRequest'), + chk_TransactionRequest_actions(lists:sort(Acts1), + lists:sort(Acts2)), + ok; +chk_TransactionRequest(T1, T2) -> + wrong_type('TransactionRequest', T1, T2). + +is_TransactionRequest_actions([]) -> + d("is_TransactionRequest_actions -> entry when done"), + true; +is_TransactionRequest_actions([H|T]) -> + d("is_TransactionRequest_actions -> entry"), + is_ActionRequest(H) andalso is_TransactionRequest_actions(T); +is_TransactionRequest_actions(_) -> + false. + +chk_TransactionRequest_actions([], []) -> + ok; +chk_TransactionRequest_actions([] = Acts1, Acts2) -> + not_equal('TransactionRequest_actions', Acts1, Acts2); +chk_TransactionRequest_actions(Acts1, [] = Acts2) -> + not_equal('TransactionRequest_actions', Acts1, Acts2); +chk_TransactionRequest_actions([H|T1], [H|T2]) -> + case is_ActionRequest(H) of + true -> + chk_TransactionRequest_actions(T1, T2); + false -> + wrong_type('TransactionRequest_actions_val', H) + end; +chk_TransactionRequest_actions([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ActionRequest(H1, H2) end, + 'TransactionRequest_actions_val'), + chk_TransactionRequest_actions(T1, T2); +chk_TransactionRequest_actions(Acts1, Acts2) -> + wrong_type('TransactionRequest_actions', Acts1, Acts2). + + +%% -- TransactionPending -- + +is_TransactionPending(#'TransactionPending'{transactionId = TID}) -> + d("is_TransactionPending -> entry"), + is_TransactionId(TID); +is_TransactionPending(_) -> + false. + +chk_TransactionPending(T, T) -> + chk_type(fun is_TransactionPending/1, 'TransactionPending', T); +chk_TransactionPending(#'TransactionPending'{transactionId = TID1}, + #'TransactionPending'{transactionId = TID2}) -> + validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionPending'), + ok; +chk_TransactionPending(T1, T2) -> + wrong_type('TransactionPending', T1, T2). + + +%% -- TransactionReply -- + +is_TransactionReply(#'TransactionReply'{transactionId = TID, + immAckRequired = IAR, + transactionResult = TR}) -> + d("is_TransactionReply -> entry"), + is_TransactionId(TID) andalso + is_opt_NULL(IAR) andalso + is_TransactionReply_transactionResult(TR); +is_TransactionReply(_) -> + false. + +chk_TransactionReply(T, T) -> + d("chk_TransactionReply -> entry (2)"), + chk_type(fun is_TransactionReply/1, 'TransactionReply', T); +chk_TransactionReply(#'TransactionReply'{transactionId = TID1, + immAckRequired = IAR1, + transactionResult = TR1}, + #'TransactionReply'{transactionId = TID2, + immAckRequired = IAR2, + transactionResult = TR2}) -> + d("chk_TransactionReply -> entry (2)"), + validate(fun() -> chk_TransactionId(TID1, TID2) end, 'TransactionReply'), + validate(fun() -> chk_opt_NULL(IAR1, IAR2) end, 'TransactionReply'), + chk_TransactionReply_transactionResult(TR1, TR2), + ok; +chk_TransactionReply(T1, T2) -> + d("chk_TransactionReply -> entry (3)"), + wrong_type('TransactionReply', T1, T2). + +is_TransactionReply_transactionResult({Tag, Val}) -> + d("is_TransactionReply_transactionResult -> entry"), + is_TransactionReply_transactionResult_tag(Tag) andalso + is_TransactionReply_transactionResult_val(Tag, Val); +is_TransactionReply_transactionResult(_) -> + false. + +is_TransactionReply_transactionResult_tag(T) -> + lists:member(T, [transactionError, actionReplies]). + +is_TransactionReply_transactionResult_val(transactionError, V) -> + is_ErrorDescriptor(V); +is_TransactionReply_transactionResult_val(actionReplies, V) -> + is_TransactionReply_actionReplies(V). + +chk_TransactionReply_transactionResult(Res, Res) -> + chk_type(fun is_TransactionReply_transactionResult/1, + 'TransactionReply_transactionResult', Res); +chk_TransactionReply_transactionResult({Tag, Val1} = Res1, + {Tag, Val2} = Res2) -> + case (is_TransactionReply_transactionResult_tag(Tag) and + is_TransactionReply_transactionResult_val(Tag, Val1) and + is_TransactionReply_transactionResult_val(Tag, Val2)) of + true -> + chk_TransactionReply_transactionResult_val(Tag, Val1, Val2); + false -> + wrong_type('TransactionReply_transactionResult', Res1, Res2) + end; +chk_TransactionReply_transactionResult({Tag1, Val1} = Res1, + {Tag2, Val2} = Res2) -> + case ((is_TransactionReply_transactionResult_tag(Tag1) and + is_TransactionReply_transactionResult_val(Tag1, Val1)) and + (is_TransactionReply_transactionResult_tag(Tag2) and + is_TransactionReply_transactionResult_val(Tag2, Val2))) of + true -> + not_equal('TransactionReply_transactionResult', Res1, Res2); + false -> + wrong_type('TransactionReply_transactionResult', Res1, Res2) + end; +chk_TransactionReply_transactionResult(Res1, Res2) -> + wrong_type('TransactionReply_transactionResult', Res1, Res2). + +chk_TransactionReply_transactionResult_val(transactionError, E1, E2) -> + validate(fun() -> chk_ErrorDescriptor(E1, E2) end, + 'TransactionReply_transactionResult'); +chk_TransactionReply_transactionResult_val(actionReplies, R1, R2) -> + validate(fun() -> + chk_TransactionReply_actionReplies(lists:sort(R1), + lists:sort(R2)) + end, + 'TransactionReply_transactionResult'). + +is_TransactionReply_actionReplies([]) -> + d("is_TransactionReply_actionReplies -> entry when done"), + true; +is_TransactionReply_actionReplies([H|T]) -> + d("is_TransactionReply_actionReplies -> entry"), + is_ActionReply(H) andalso is_TransactionReply_actionReplies(T); +is_TransactionReply_actionReplies(_) -> + false. + +chk_TransactionReply_actionReplies([], []) -> + ok; +chk_TransactionReply_actionReplies([] = AR1, AR2) -> + not_equal('TransactionReply_actionReplies', AR1, AR2); +chk_TransactionReply_actionReplies(AR1, [] = AR2) -> + not_equal('TransactionReply_actionReplies', AR1, AR2); +chk_TransactionReply_actionReplies([H|T1], [H|T2]) -> + case is_ActionReply(H) of + true -> + chk_TransactionReply_actionReplies(T1, T2); + false -> + wrong_type('TransactionReply_actionReplies_val', H) + end; +chk_TransactionReply_actionReplies([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ActionReply(H1, H2) end, + 'TransactionReply_actionReplies_val'), + chk_TransactionReply_actionReplies(T1, T2); +chk_TransactionReply_actionReplies(AR1, AR2) -> + wrong_type('TransactionReply_actionReplies', AR1, AR2). + + +%% -- TransactionResponseAck -- + +is_TransactionResponseAck([]) -> + d("is_TransactionResponseAck -> entry when done"), + true; +is_TransactionResponseAck([H|T]) -> + d("is_TransactionResponseAck -> entry"), + is_TransactionAck(H) andalso is_TransactionResponseAck(T); +is_TransactionResponseAck(_) -> + false. + +chk_TransactionResponseAck([], []) -> + ok; +chk_TransactionResponseAck([] = AR1, AR2) -> + not_equal('TransactionResponseAck', AR1, AR2); +chk_TransactionResponseAck(AR1, [] = AR2) -> + not_equal('TransactionResponseAck', AR1, AR2); +chk_TransactionResponseAck([H|T1], [H|T2]) -> + case is_TransactionAck(H) of + true -> + chk_TransactionResponseAck(T1, T2); + false -> + wrong_type('TransactionResponseAck_val', H) + end; +chk_TransactionResponseAck([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TransactionAck(H1, H2) end, + 'TransactionResponseAck'), + chk_TransactionResponseAck(T1, T2); +chk_TransactionResponseAck(AR1, AR2) -> + wrong_type('TransactionResponseAck', AR1, AR2). + + +%% -- TransactionAck -- + +is_TransactionAck(#'TransactionAck'{firstAck = F, + lastAck = L}) -> + d("is_TransactionAck -> entry"), + is_TransactionId(F) andalso is_opt_TransactionId(L); +is_TransactionAck(_) -> + false. + +chk_TransactionAck(T, T) -> + chk_type(fun is_TransactionAck/1, 'TransactionAck', T); +chk_TransactionAck(#'TransactionAck'{firstAck = F1, + lastAck = L1}, + #'TransactionAck'{firstAck = F2, + lastAck = L2}) -> + validate(fun() -> chk_TransactionId(F1, F2) end, 'TransactionAck'), + validate(fun() -> chk_opt_TransactionId(L1, L2) end, 'TransactionAck'), + ok; +chk_TransactionAck(T1, T2) -> + wrong_type('TransactionAck', T1, T2). + + +%% -- ErrorDescriptor -- + +is_opt_ErrorDescriptor(V) -> + is_OPTIONAL(fun is_ErrorDescriptor/1, V). + +is_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code, + errorText = Text}) -> + d("is_ErrorDescriptor -> entry"), + is_ErrorCode(Code) andalso is_opt_ErrorText(Text); +is_ErrorDescriptor(_) -> + false. + +chk_opt_ErrorDescriptor(E1, E2) -> + chk_OPTIONAL('ErrorDescriptor', E1, E2, + fun is_ErrorDescriptor/1, fun chk_ErrorDescriptor/2). + +chk_ErrorDescriptor(E, E) -> + chk_type(fun is_ErrorDescriptor/1, 'ErrorDescriptor', E); +chk_ErrorDescriptor(#'ErrorDescriptor'{errorCode = Code1, + errorText = Text1}, + #'ErrorDescriptor'{errorCode = Code2, + errorText = Text2}) -> + chk_ErrorCode(Code1, Code2), + chk_opt_ErrorText(Text1, Text2), + ok; +chk_ErrorDescriptor(E1, E2) -> + wrong_type('ErrorDescriptor', E1, E2). + + +%% -- ErrorCode -- + +is_ErrorCode(C) -> is_INTEGER(C, {range, 0, 65535}). + +chk_ErrorCode(C, C) -> + case is_ErrorCode(C) of + true -> + ok; + false -> + wrong_type(errorCode, C, C) + end; +chk_ErrorCode(C1, C2) -> + case (is_ErrorCode(C1) andalso is_ErrorCode(C2)) of + true -> + not_equal(errorCode, C1, C2); + false -> + wrong_type(errorCode, C1, C2) + end. + + +%% -- ErrorText -- + +is_opt_ErrorText(V) -> + is_OPTIONAL(fun is_ErrorText/1, V). + +is_ErrorText(V) -> is_IA5String(V). + +chk_opt_ErrorText(T1, T2) -> + chk_OPTIONAL('ErrorText', T1, T2, fun is_ErrorText/1, fun chk_ErrorText/2). + +chk_ErrorText(T, T) -> + chk_type(fun is_ErrorText/1, 'ErrorText', T); +chk_ErrorText(T1, T2) -> + case (is_ErrorText(T1) andalso is_ErrorText(T2)) of + true -> + case {to_lower(T1), to_lower(T2)} of + {T, T} -> + ok; + _ -> + not_equal('ErrorText', T1, T2) + end; + false -> + wrong_type('ErrorText', T1, T2) + end. + + +%% -- ContextID -- + +is_ContextID(Id) -> is_INTEGER(Id, {range, 0, 4294967295}). + +chk_ContextID(Id, Id) -> + chk_type(fun is_ContextID/1, 'ContextID', Id); +chk_ContextID(Id1, Id2) -> + case (is_ContextID(Id1) andalso is_ContextID(Id2)) of + true -> + not_equal('ContextID', Id1, Id2); + false -> + wrong_type('ContextID', Id1, Id2) + end. + + +%% -- ActionRequest -- + +is_ActionRequest(#'ActionRequest'{contextId = Id, + contextRequest = CtxReq, + contextAttrAuditReq = AuditReq, + commandRequests = CmdReqs}) -> + d("is_ActionRequest -> entry"), + is_ContextID(Id) andalso + is_opt_ContextRequest(CtxReq) andalso + is_opt_ContextAttrAuditRequest(AuditReq) andalso + is_ActionRequest_commandRequests(CmdReqs); +is_ActionRequest(_) -> + false. + +chk_ActionRequest(A, A) -> + chk_type(fun is_ActionRequest/1, 'ActionRequest', A); +chk_ActionRequest(#'ActionRequest'{contextId = Id1, + contextRequest = Req1, + contextAttrAuditReq = AuditReq1, + commandRequests = CmdReqs1}, + #'ActionRequest'{contextId = Id2, + contextRequest = Req2, + contextAttrAuditReq = AuditReq2, + commandRequests = CmdReqs2}) -> + validate(fun() -> chk_ContextID(Id1, Id2) end, 'ActionRequest'), + validate(fun() -> chk_opt_ContextRequest(Req1, Req2) end, 'ActionRequest'), + validate(fun() -> + chk_opt_ContextAttrAuditRequest(AuditReq1, AuditReq2) + end, + 'ActionRequest'), + chk_ActionRequest_commandRequests(CmdReqs1, CmdReqs2), + ok. + + +is_ActionRequest_commandRequests([]) -> + d("is_ActionRequest_commandRequests -> entry when done"), + true; +is_ActionRequest_commandRequests([H|T]) -> + d("is_ActionRequest_commandRequests -> entry"), + is_CommandRequest(H) andalso is_ActionRequest_commandRequests(T); +is_ActionRequest_commandRequests(_) -> + false. + +chk_ActionRequest_commandRequests([], []) -> + ok; +chk_ActionRequest_commandRequests([] = CmdReqs1, CmdReqs2) -> + not_equal('ActionRequest_commandRequests', CmdReqs1, CmdReqs2); +chk_ActionRequest_commandRequests(CmdReqs1, [] = CmdReqs2) -> + not_equal('ActionRequest_commandRequests', CmdReqs1, CmdReqs2); +chk_ActionRequest_commandRequests([H|T1], [H|T2]) -> + case is_CommandRequest(H) of + true -> + chk_ActionRequest_commandRequests(T1, T2); + false -> + wrong_type('ActionRequest_commandRequest_val', H) + end; +chk_ActionRequest_commandRequests([H1|T1], [H2|T2]) -> + validate(fun() -> chk_CommandRequest(H1, H2) end, + 'ActionRequest_commandRequests_val'), + chk_ActionRequest_commandRequests(T1, T2); +chk_ActionRequest_commandRequests(R1, R2) -> + wrong_type('ActionRequest_commandRequests', R1, R2). + + +%% -- ActionReply -- + +is_ActionReply(#'ActionReply'{contextId = Id, + errorDescriptor = ED, + contextReply = CtxRep, + commandReply = CmdRep}) -> + d("is_ActionReply -> entry"), + is_ContextID(Id) andalso + is_opt_ErrorDescriptor(ED) andalso + is_opt_ContextRequest(CtxRep) andalso + is_ActionReply_commandReply(CmdRep); +is_ActionReply(_) -> + false. + +is_ActionReply_commandReply([]) -> + d("is_ActionReply_commandReply -> entry when done"), + true; +is_ActionReply_commandReply([H|T]) -> + d("is_ActionReply_commandReply -> entry"), + is_CommandReply(H) andalso is_ActionReply_commandReply(T); +is_ActionReply_commandReply(_) -> + false. + +chk_ActionReply(A, A) -> + d("chk_ActionReply -> entry (1)"), + chk_type(fun is_ActionReply/1, 'ActionReply', A); +chk_ActionReply(#'ActionReply'{contextId = Id1, + errorDescriptor = ED1, + contextReply = CtxRep1, + commandReply = CmdRep1}, + #'ActionReply'{contextId = Id2, + errorDescriptor = ED2, + contextReply = CtxRep2, + commandReply = CmdRep2}) -> + d("chk_ActionReply -> entry (2)"), + chk_ContextID(Id1, Id2), + chk_opt_ErrorDescriptor(ED1, ED2), + chk_opt_ContextRequest(CtxRep1, CtxRep2), + chk_ActionReply_commandReply(CmdRep1, CmdRep2). + +chk_ActionReply_commandReply([], []) -> + ok; +chk_ActionReply_commandReply([] = Reps1, Reps2) -> + not_equal('ActionReply_commandReply', Reps1, Reps2); +chk_ActionReply_commandReply(Reps1, [] = Reps2) -> + not_equal('ActionReply_commandReply', Reps1, Reps2); +chk_ActionReply_commandReply([H|T1], [H|T2]) -> + case is_CommandReply(H) of + true -> + chk_ActionReply_commandReply(T1, T2); + false -> + wrong_type('ActionReply_commandReply_val', H) + end; +chk_ActionReply_commandReply([H1|T1], [H2|T2]) -> + validate(fun() -> chk_CommandReply(H1, H2) end, + 'ActionReply_commandReply_val'), + chk_ActionReply_commandReply(T1, T2); +chk_ActionReply_commandReply(R1, R2) -> + wrong_type('ActionReply_commandReply', R1, R2). + + +%% -- ContextRequest -- + +is_opt_ContextRequest(V) -> + is_OPTIONAL(fun is_ContextRequest/1, V). + +is_ContextRequest(#'ContextRequest'{priority = Prio, + emergency = Em, + topologyReq = TopReq, + iepscallind = Ieps, + contextProp = CtxProp, + contextList = CtxList}) -> + d("is_ContextRequest -> entry"), + is_ContextRequest_priority(Prio) andalso + is_ContextRequest_emergency(Em) andalso + is_ContextRequest_topologyReq(TopReq) andalso + is_ContextRequest_iepscallind(Ieps) andalso + is_ContextRequest_contextProp(CtxProp) andalso + is_ContextRequest_contextList(CtxList); +is_ContextRequest(_) -> + false. + +is_ContextRequest_priority(asn1_NOVALUE) -> + true; +is_ContextRequest_priority(V) -> + is_INTEGER(V, {range, 1, 15}). + +is_ContextRequest_emergency(asn1_NOVALUE) -> + true; +is_ContextRequest_emergency(V) -> + is_BOOLEAN(V). + +is_ContextRequest_topologyReq(asn1_NOVALUE) -> + true; +is_ContextRequest_topologyReq([]) -> + true; +is_ContextRequest_topologyReq([H|T]) -> + is_TopologyRequest(H) andalso is_ContextRequest_topologyReq(T); +is_ContextRequest_topologyReq(_) -> + false. + +is_ContextRequest_iepscallind(asn1_NOVALUE) -> + true; +is_ContextRequest_iepscallind(V) -> + is_BOOLEAN(V). + +is_ContextRequest_contextProp(asn1_NOVALUE) -> + true; +is_ContextRequest_contextProp([]) -> + true; +is_ContextRequest_contextProp([H|T]) -> + is_PropertyParm(H) andalso is_ContextRequest_contextProp(T); +is_ContextRequest_contextProp(_) -> + false. + +is_ContextRequest_contextList(asn1_NOVALUE) -> + true; +is_ContextRequest_contextList([]) -> + true; +is_ContextRequest_contextList([H|T]) -> + is_ContextID(H) andalso is_ContextRequest_contextList(T); +is_ContextRequest_contextList(_) -> + false. + +chk_opt_ContextRequest(R1, R2) -> + chk_OPTIONAL('ContextRequest', R1, R2, + fun is_ContextRequest/1, fun chk_ContextRequest/2). + +chk_ContextRequest(R, R) -> + chk_type(fun is_ContextRequest/1, 'ContextRequest', R); +chk_ContextRequest(#'ContextRequest'{priority = Prio1, + emergency = Em1, + topologyReq = TopReq1, + iepscallind = Ieps1, + contextProp = CtxProp1, + contextList = CtxList1}, + #'ContextRequest'{priority = Prio2, + emergency = Em2, + topologyReq = TopReq2, + iepscallind = Ieps2, + contextProp = CtxProp2, + contextList = CtxList2}) -> + chk_ContextRequest_priority(Prio1, Prio2), + chk_ContextRequest_emergency(Em1, Em2), + chk_ContextRequest_topologyReq(TopReq1, TopReq2), + chk_ContextRequest_iepscallind(Ieps1, Ieps2), + chk_ContextRequest_contextProp(CtxProp1, CtxProp2), + chk_ContextRequest_contextList(CtxList1, CtxList2), + ok; +chk_ContextRequest(R1, R2) -> + wrong_type('ContextRequest', R1, R2). + + +chk_ContextRequest_priority(asn1_NOVALUE,asn1_NOVALUE) -> + ok; +chk_ContextRequest_priority(P, P) -> + chk_type(fun is_ContextRequest_priority/1, 'ContextRequest_priority', P); +chk_ContextRequest_priority(P1, P2) -> + case (is_ContextRequest_priority(P1) andalso + is_ContextRequest_priority(P2)) of + true -> + not_equal('ContextRequest_priority', P1, P2); + false -> + wrong_type(contextRequest_priority, P1, P2) + end. + + +chk_ContextRequest_emergency(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_emergency(E, E) -> + chk_type(fun is_ContextRequest_emergency/1, 'ContextRequest_emergency', E); +chk_ContextRequest_emergency(E1, E2) -> + case (is_ContextRequest_emergency(E1) andalso + is_ContextRequest_emergency(E2)) of + true -> + not_equal('ContextRequest_emergency', E1, E2); + false -> + wrong_type('ContextRequest_emergency', E1, E2) + end. + +chk_ContextRequest_topologyReq(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_topologyReq([], []) -> + ok; +chk_ContextRequest_topologyReq([] = T1, T2) -> + not_equal('ContextRequest_topologyReq', T1, T2); +chk_ContextRequest_topologyReq(T1, [] = T2) -> + not_equal('ContextRequest_topologyReq', T1, T2); +chk_ContextRequest_topologyReq([H|T1], [H|T2]) -> + case is_TopologyRequest(H) of + true -> + chk_ContextRequest_topologyReq(T1, T2); + false -> + wrong_type('ContextRequest_topologyReq_val', H) + end; +chk_ContextRequest_topologyReq([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TopologyRequest(H1, H2) end, + 'ContextRequest_topologyReq_val'), + chk_ContextRequest_topologyReq(T1, T2); +chk_ContextRequest_topologyReq(T1, T2) -> + wrong_type('ContextRequest_topologyReq', T1, T2). + + +chk_ContextRequest_iepscallind(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_iepscallind(E, E) -> + chk_type(fun is_ContextRequest_iepscallind/1, + 'ContextRequest_iepscallind', E); +chk_ContextRequest_iepscallind(E1, E2) -> + case (is_ContextRequest_iepscallind(E1) andalso + is_ContextRequest_iepscallind(E2)) of + true -> + case (((E1 == false) and (E2 == asn1_NOVALUE)) or + ((E1 == asn1_NOVALUE) and (E2 == false))) of + true -> + ok; + false -> + not_equal('ContextRequest_iepscallind', E1, E2) + end; + + false -> + wrong_type('ContextRequest_iepscallind', E1, E2) + end. + +chk_ContextRequest_contextProp(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_contextProp([], []) -> + ok; +chk_ContextRequest_contextProp([] = T1, T2) -> + not_equal('ContextRequest_contextProp', T1, T2); +chk_ContextRequest_contextProp(T1, [] = T2) -> + not_equal('ContextRequest_contextProp', T1, T2); +chk_ContextRequest_contextProp([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_ContextRequest_contextProp(T1, T2); + false -> + wrong_type('ContextRequest_contextProp_val', H) + end; +chk_ContextRequest_contextProp([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, + 'ContextRequest_contextProp_val'), + chk_ContextRequest_contextProp(T1, T2); +chk_ContextRequest_contextProp(T1, T2) -> + wrong_type('ContextRequest_contextProp', T1, T2). + +chk_ContextRequest_contextList(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextRequest_contextList([], []) -> + ok; +chk_ContextRequest_contextList([] = T1, T2) -> + not_equal('ContextRequest_contextList', T1, T2); +chk_ContextRequest_contextList(T1, [] = T2) -> + not_equal('ContextRequest_contextList', T1, T2); +chk_ContextRequest_contextList([H|T1], [H|T2]) -> + case is_ContextID(H) of + true -> + chk_ContextRequest_contextList(T1, T2); + false -> + wrong_type('ContextRequest_contextList_val', H) + end; +chk_ContextRequest_contextList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ContextID(H1, H2) end, + 'ContextRequest_contextList_val'), + chk_ContextRequest_contextList(T1, T2); +chk_ContextRequest_contextList(T1, T2) -> + wrong_type('ContextRequest_contextList', T1, T2). + + +%% -- ContextAttrAuditRequest -- + +is_opt_ContextAttrAuditRequest(asn1_NOVALUE) -> + true; +is_opt_ContextAttrAuditRequest(V) -> + is_ContextAttrAuditRequest(V). + +is_ContextAttrAuditRequest( + #'ContextAttrAuditRequest'{topology = T, + emergency = E, + priority = P, + iepscallind = I, + contextPropAud = A, + selectpriority = SP, + selectemergency = SE, + selectiepscallind = SI, + selectLogic = SL}) -> + d("is_ContextAttrAuditRequest -> entry"), + is_opt_NULL(T) andalso + is_opt_NULL(E) andalso + is_opt_NULL(P) andalso + is_opt_NULL(I) andalso + is_ContextAttrAuditRequest_contextPropAud(A) andalso + is_ContextAttrAuditRequest_selectpriority(SP) andalso + is_ContextAttrAuditRequest_selectemergency(SE) andalso + is_ContextAttrAuditRequest_selectiepscallind(SI) andalso + is_opt_SelectLogic(SL); +is_ContextAttrAuditRequest(_) -> + false. + +is_ContextAttrAuditRequest_contextPropAud(asn1_NOVALUE) -> + true; +is_ContextAttrAuditRequest_contextPropAud([]) -> + true; +is_ContextAttrAuditRequest_contextPropAud([H|T]) -> + d("is_ContextAttrAuditRequest_contextPropAud -> entry"), + is_IndAudPropertyParm(H) andalso + is_ContextAttrAuditRequest_contextPropAud(T). + +is_ContextAttrAuditRequest_selectpriority(asn1_NOVALUE) -> + true; +is_ContextAttrAuditRequest_selectpriority(V) -> + is_INTEGER(V, {range, 1, 15}). + +is_ContextAttrAuditRequest_selectemergency(asn1_NOVALUE) -> + true; +is_ContextAttrAuditRequest_selectemergency(V) -> + is_BOOLEAN(V). + +is_ContextAttrAuditRequest_selectiepscallind(asn1_NOVALUE) -> + true; +is_ContextAttrAuditRequest_selectiepscallind(V) -> + is_BOOLEAN(V). + + +chk_opt_ContextAttrAuditRequest(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_ContextAttrAuditRequest(R1, R2) -> + chk_ContextAttrAuditRequest(R1, R2). + +chk_ContextAttrAuditRequest(R, R) -> + chk_type(fun is_ContextAttrAuditRequest/1, 'ContextAttrAuditRequest', R); +chk_ContextAttrAuditRequest( + #'ContextAttrAuditRequest'{topology = T1, + emergency = E1, + priority = P1, + iepscallind = I1, + contextPropAud = A1, + selectpriority = SP1, + selectemergency = SE1, + selectiepscallind = SI1, + selectLogic = SL1}, + #'ContextAttrAuditRequest'{topology = T2, + emergency = E2, + priority = P2, + iepscallind = I2, + contextPropAud = A2, + selectpriority = SP2, + selectemergency = SE2, + selectiepscallind = SI2, + selectLogic = SL2}) -> + validate(fun() -> chk_opt_NULL(T1, T2) end, + 'ContextAttrAuditRequest_topology'), + validate(fun() -> chk_opt_NULL(E1, E2) end, + 'ContextAttrAuditRequest_emergency'), + validate(fun() -> chk_opt_NULL(P1, P2) end, + 'ContextAttrAuditRequest_priority'), + validate(fun() -> chk_opt_NULL(I1, I2) end, + 'ContextAttrAuditRequest_iepscallind'), + chk_ContextAttrAuditRequest_contextPropAud(lists:sort(A1), + lists:sort(A2)), + chk_ContextAttrAuditRequest_selectpriority(SP1, SP2), + chk_ContextAttrAuditRequest_selectemergency(SE1, SE2), + chk_ContextAttrAuditRequest_selectiepscallind(SI1, SI2), + chk_ContextAttrAuditRequest_selectLogic(SL1, SL2), + ok. + +chk_ContextAttrAuditRequest_contextPropAud(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextAttrAuditRequest_contextPropAud(A, A) -> + chk_type(fun is_ContextAttrAuditRequest_contextPropAud/1, + 'ContextAttrAuditRequest_contextPropAud', A); +chk_ContextAttrAuditRequest_contextPropAud([], []) -> + ok; +chk_ContextAttrAuditRequest_contextPropAud([] = T1, T2) -> + not_equal('ContextAttrAuditRequest_contextPropAud', T1, T2); +chk_ContextAttrAuditRequest_contextPropAud(T1, [] = T2) -> + not_equal('ContextAttrAuditRequest_contextPropAud', T1, T2); +chk_ContextAttrAuditRequest_contextPropAud([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_ContextAttrAuditRequest_contextPropAud(T1, T2); + false -> + wrong_type('ContextAttrAuditRequest_contextPropAud_val', H) + end; +chk_ContextAttrAuditRequest_contextPropAud([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, + 'ContextAttrAuditRequest_contextPropAud_val'), + chk_ContextAttrAuditRequest_contextPropAud(T1, T2); +chk_ContextAttrAuditRequest_contextPropAud(T1, T2) -> + wrong_type('ContextAttrAuditRequest_contextPropAud', T1, T2). + +chk_ContextAttrAuditRequest_selectpriority(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextAttrAuditRequest_selectpriority(A, A) -> + chk_type(fun is_ContextAttrAuditRequest_selectpriority/1, + 'ContextAttrAuditRequest_selectpriority', A); +chk_ContextAttrAuditRequest_selectpriority(SP1, SP2) -> + case (is_ContextAttrAuditRequest_selectpriority(SP1) andalso + is_ContextAttrAuditRequest_selectpriority(SP2)) of + true -> + not_equal('ContextAttrAuditRequest_selectpriority', SP1, SP2); + false -> + wrong_type('ContextAttrAuditRequest_selectpriority', SP1, SP2) + end. + +chk_ContextAttrAuditRequest_selectemergency(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextAttrAuditRequest_selectemergency(A, A) -> + chk_type(fun is_ContextAttrAuditRequest_selectemergency/1, + 'ContextAttrAuditRequest_selectemergency', A); +chk_ContextAttrAuditRequest_selectemergency(SE1, SE2) -> + case (is_ContextAttrAuditRequest_selectemergency(SE1) andalso + is_ContextAttrAuditRequest_selectemergency(SE2)) of + true -> + not_equal('ContextAttrAuditRequest_selectemergency', SE1, SE2); + false -> + wrong_type('ContextAttrAuditRequest_selectemergency', SE1, SE2) + end. + +chk_ContextAttrAuditRequest_selectiepscallind(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_ContextAttrAuditRequest_selectiepscallind(A, A) -> + chk_type(fun is_ContextAttrAuditRequest_selectiepscallind/1, + 'ContextAttrAuditRequest_selectiepscallind', A); +chk_ContextAttrAuditRequest_selectiepscallind(SI1, SI2) -> + case (is_ContextAttrAuditRequest_selectiepscallind(SI1) andalso + is_ContextAttrAuditRequest_selectiepscallind(SI2)) of + true -> + not_equal('ContextAttrAuditRequest_selectiepscallind', SI1, SI2); + false -> + wrong_type('ContextAttrAuditRequest_selectiepscallind', SI1, SI2) + end. + +chk_ContextAttrAuditRequest_selectLogic(SL1, SL2) -> + validate(fun() -> chk_opt_SelectLogic(SL1, SL2) end, + 'ContextAttrAuditRequest_selectLogic'). + + +%% -- SelectLogic -- + +is_opt_SelectLogic(asn1_NOVALUE) -> + true; +is_opt_SelectLogic(SL) -> + is_SelectLogic(SL). + +is_SelectLogic({Tag, Val}) -> + d("is_SelectLogic -> entry"), + is_SelectLogic_tag(Tag) andalso is_SelectLogic_val(Tag, Val); +is_SelectLogic(_) -> + false. + +is_SelectLogic_tag(Tag) -> + Tags = [andAUDITSelect, orAUDITSelect], + lists:member(Tag, Tags). + +is_SelectLogic_val(andAUDITSelect, 'NULL') -> true; +is_SelectLogic_val(orAUDITSelect, 'NULL') -> true; +is_SelectLogic_val(_, _) -> false. + +chk_opt_SelectLogic(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SelectLogic(SL1, SL2) -> + chk_SelectLogic(SL1, SL2). + +chk_SelectLogic(SL, SL) -> + chk_type(fun is_SelectLogic/1, 'SelectLogic', SL); +chk_SelectLogic(asn1_NOVALUE, {andAUDITSelect, 'NULL'}) -> + ok; % AND is default +chk_SelectLogic({andAUDITSelect, 'NULL'}, asn1_NOVALUE) -> + ok; % AND is default +chk_SelectLogic({Tag, Val1} = SL1, {Tag, Val2} = SL2) -> + case (is_SelectLogic_tag(Tag) andalso + is_SelectLogic_val(Tag, Val1) andalso + is_SelectLogic_val(Tag, Val2)) of + true -> + chk_SelectLogic_val(Tag, Val1, Val2); + false -> + wrong_type('SelectLogic', SL1, SL2) + end; +chk_SelectLogic({Tag1, Val1} = SL1, {Tag2, Val2} = SL2) -> + case ((is_SelectLogic_tag(Tag1) andalso + is_SelectLogic_val(Tag1, Val1)) andalso + (is_SelectLogic_tag(Tag2) andalso + is_SelectLogic_val(Tag2, Val2))) of + true -> + not_equal('SelectLogic', SL1, SL2); + false -> + wrong_type('SelectLogic', SL1, SL2) + end; +chk_SelectLogic(SL1, SL2) -> + wrong_type('SelectLogic', SL1, SL2). + +chk_SelectLogic_val(andAUDITSelect, SL1, SL2) -> + validate(fun() -> chk_NULL(SL1, SL2) end, 'SelectLogic_andAUDITSelect'); +chk_SelectLogic_val(orAUDITSelect, SL1, SL2) -> + validate(fun() -> chk_NULL(SL1, SL2) end, 'SelectLogic_orAUDITSelect'). + + +%% -- CommandRequest -- + +is_CommandRequest(#'CommandRequest'{command = Cmd, + optional = Opt, + wildcardReturn = WR}) -> + d("is_CommandRequest -> entry with" + "~n Cmd: ~p" + "~n Opt: ~p" + "~n WR: ~p", [Cmd, Opt, WR]), + is_Command(Cmd) andalso is_opt_NULL(Opt) andalso is_opt_NULL(WR); +is_CommandRequest(_) -> + false. + +chk_CommandRequest(C, C) -> + chk_type(fun is_CommandRequest/1, 'CommandRequest', C); +chk_CommandRequest(#'CommandRequest'{command = Cmd1, + optional = Opt1, + wildcardReturn = WR1}, + #'CommandRequest'{command = Cmd2, + optional = Opt2, + wildcardReturn = WR2}) -> + validate(fun() -> chk_Command(Cmd1, Cmd2) end, 'CommandRequest'), + validate(fun() -> chk_opt_NULL(Opt1, Opt2) end, 'CommandRequest'), + validate(fun() -> chk_opt_NULL(WR1, WR2) end, 'CommandRequest'), + ok; +chk_CommandRequest(R1, R2) -> + wrong_type('CommandRequest', R1, R2). + + +%% -- Command -- + +is_Command({Tag, Val}) -> + d("is_Command -> entry with" + "~n Tag: ~p" + "~n Val: ~p", [Tag, Val]), + is_Command_tag(Tag) andalso is_Command_val(Tag, Val); +is_Command(_) -> + false. + +is_Command_tag(Tag) -> + Tags = [addReq, moveReq, modReq, subtractReq, auditCapRequest, + auditValueRequest, notifyReq, serviceChangeReq], + lists:member(Tag, Tags). + +is_Command_val(addReq, V) -> is_AmmRequest(V); +is_Command_val(moveReq, V) -> is_AmmRequest(V); +is_Command_val(modReq, V) -> is_AmmRequest(V); +is_Command_val(subtractReq, V) -> is_SubtractRequest(V); +is_Command_val(auditCapRequest, V) -> is_AuditRequest(V); +is_Command_val(auditValueRequest, V) -> is_AuditRequest(V); +is_Command_val(notifyReq, V) -> is_NotifyRequest(V); +is_Command_val(serviceChangeReq, V) -> is_ServiceChangeRequest(V). + +chk_Command(Cmd, Cmd) -> + chk_type(fun is_Command/1, 'Command', Cmd); +chk_Command({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> + case (is_Command_tag(Tag) andalso + is_Command_val(Tag, Val1) andalso + is_Command_val(Tag, Val2)) of + true -> + chk_Command_val(Tag, Val1, Val2); + false -> + wrong_type('Command', Cmd1, Cmd2) + end; +chk_Command({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> + case ((is_Command_tag(Tag1) andalso is_Command_val(Tag1, Val1)) andalso + (is_Command_tag(Tag2) andalso is_Command_val(Tag2, Val2))) of + true -> + not_equal('Command', Cmd1, Cmd2); + false -> + wrong_type('Command', Cmd1, Cmd2) + end; +chk_Command(Cmd1, Cmd2) -> + wrong_type('Command', Cmd1, Cmd2). + + +chk_Command_val(addReq, R1, R2) -> + validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_addReq'); +chk_Command_val(moveReq, R1, R2) -> + validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_moveReq'); +chk_Command_val(modReq, R1, R2) -> + validate(fun() -> chk_AmmRequest(R1, R2) end, 'Command_modReq'); +chk_Command_val(subtractReq, R1, R2) -> + validate(fun() -> chk_SubtractRequest(R1, R2) end, 'Command_subtractReq'); +chk_Command_val(auditCapRequest, R1, R2) -> + validate(fun() -> chk_AuditRequest(R1, R2) end, 'Command_auditCapRequest'); +chk_Command_val(auditValueRequest, R1, R2) -> + validate(fun() -> chk_AuditRequest(R1, R2) end, + 'Command_auditValueRequest'); +chk_Command_val(notifyReq, R1, R2) -> + validate(fun() -> chk_NotifyRequest(R1, R2) end, 'Command_notifyReq'); +chk_Command_val(serviceChangeReq, R1, R2) -> + validate(fun() -> chk_ServiceChangeRequest(R1, R2) end, + 'Command_serviceChangeReq'). + + +%% -- CommandReply -- + +is_CommandReply({Tag, Val}) -> + d("is_CommandReply -> entry"), + is_CommandReply_tag(Tag) andalso is_CommandReply_val(Tag, Val); +is_CommandReply(_) -> + false. + +is_CommandReply_tag(Tag) -> + Tags = [addReply, moveReply, modReply, subtractReply, + auditCapReply, auditValueReply, notifyReply, serviceChangeReply], + lists:member(Tag, Tags). + +is_CommandReply_val(addReply, V) -> is_AmmsReply(V); +is_CommandReply_val(moveReply, V) -> is_AmmsReply(V); +is_CommandReply_val(modReply, V) -> is_AmmsReply(V); +is_CommandReply_val(subtractReply, V) -> is_AmmsReply(V); +is_CommandReply_val(auditCapReply, V) -> is_AuditReply(V); +is_CommandReply_val(auditValueReply, V) -> is_AuditReply(V); +is_CommandReply_val(notifyReply, V) -> is_NotifyReply(V); +is_CommandReply_val(serviceChangeReply, V) -> is_ServiceChangeReply(V). + +chk_CommandReply({Tag, Val} = Cmd, Cmd) -> + case (is_CommandReply_tag(Tag) andalso is_CommandReply_val(Tag, Val)) of + true -> + ok; + false -> + wrong_type('CommandReply', Cmd) + end; +chk_CommandReply({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> + case (is_CommandReply_tag(Tag) andalso + is_CommandReply_val(Tag, Val1) andalso + is_CommandReply_val(Tag, Val2)) of + true -> + chk_CommandReply_val(Tag, Val1, Val2); + false -> + wrong_type('CommandReply', Cmd1, Cmd2) + end; +chk_CommandReply({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> + case ((is_CommandReply_tag(Tag1) andalso + is_CommandReply_val(Tag1, Val1)) andalso + (is_CommandReply_tag(Tag2) andalso + is_CommandReply_val(Tag2, Val2))) of + true -> + not_equal('CommandReply', Cmd1, Cmd2); + false -> + wrong_type('CommandReply', Cmd1, Cmd2) + end; +chk_CommandReply(Cmd1, Cmd2) -> + wrong_type('CommandReply', Cmd1, Cmd2). + +chk_CommandReply_val(addReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_addReply'); +chk_CommandReply_val(moveReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_moveReply'); +chk_CommandReply_val(modReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_modReply'); +chk_CommandReply_val(subtractReply, V1, V2) -> + validate(fun() -> chk_AmmsReply(V1, V2) end, 'CommandReply_subtractReply'); +chk_CommandReply_val(auditCapReply, V1, V2) -> + validate(fun() -> chk_AuditReply(V1, V2) end, + 'CommandReply_auditCapReply'); +chk_CommandReply_val(auditValueReply, V1, V2) -> + validate(fun() -> chk_AuditReply(V1, V2) end, + 'CommandReply_auditValueReply'); +chk_CommandReply_val(notifyReply, V1, V2) -> + validate(fun() -> chk_NotifyReply(V1, V2) end, 'CommandReply_notifyReply'); +chk_CommandReply_val(serviceChangeReply, V1, V2) -> + validate(fun() -> chk_ServiceChangeReply(V1, V2) end, + 'CommandReply_serviceChangeReply'). + + +%% -- TopologyRequest -- + +is_TopologyRequest(#'TopologyRequest'{terminationFrom = F, + terminationTo = T, + topologyDirection = TD, + streamID = S, + topologyDirectionExtension = TDE}) -> + d("is_TopologyRequest -> entry"), + is_TerminationID(F) andalso + is_TerminationID(T) andalso + is_TopologyRequest_topologyDirection(TD) andalso + is_opt_StreamID(S) andalso + is_TopologyRequest_topologyDirectionExtension(TDE); +is_TopologyRequest(_) -> + false. + +is_TopologyRequest_topologyDirection(D) -> + lists:member(D, [bothway, isolate, oneway]). + +is_TopologyRequest_topologyDirectionExtension(asn1_NOVALUE) -> + true; +is_TopologyRequest_topologyDirectionExtension(D) -> + lists:member(D, [onewayexternal, onewayboth]). + + +chk_TopologyRequest(T, T) when is_record(T,'TopologyRequest') -> + ok; +chk_TopologyRequest(#'TopologyRequest'{terminationFrom = F1, + terminationTo = T1, + topologyDirection = TD1, + streamID = S1, + topologyDirectionExtension = TDE1}, + #'TopologyRequest'{terminationFrom = F2, + terminationTo = T2, + topologyDirection = TD2, + streamID = S2, + topologyDirectionExtension = TDE2}) -> + validate(fun() -> chk_TerminationID(F1, F2) end, + 'TopologyRequest_terminationFrom'), + validate(fun() -> chk_TerminationID(T1, T2) end, + 'TopologyRequest_terminationTo'), + chk_TopologyRequest_topologyDirection(TD1, TD2), + validate(fun() -> chk_opt_StreamID(S1, S2) end, + 'TopologyRequest_streamID'), + chk_TopologyRequest_topologyDirectionExtension(TDE1, TDE2), + ok. + +chk_TopologyRequest_topologyDirection(D, D) -> + case is_TopologyRequest_topologyDirection(D) of + true -> + ok; + false -> + wrong_type('TopologyRequest_topologyDirection', D) + end; +chk_TopologyRequest_topologyDirection(D1, D2) -> + case (is_TopologyRequest_topologyDirection(D1) andalso + is_TopologyRequest_topologyDirection(D1)) of + true -> + not_equal('TopologyRequest_topologyDirection', D1, D2); + false -> + wrong_type('TopologyRequest_topologyDirection', D1, D2) + end. + +chk_TopologyRequest_topologyDirectionExtension(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_TopologyRequest_topologyDirectionExtension(D, D) -> + case is_TopologyRequest_topologyDirectionExtension(D) of + true -> + ok; + false -> + wrong_type('TopologyRequest_topologyDirectionExtension', D) + end; +chk_TopologyRequest_topologyDirectionExtension(D1, D2) -> + case (is_TopologyRequest_topologyDirectionExtension(D1) andalso + is_TopologyRequest_topologyDirectionExtension(D1)) of + true -> + not_equal('TopologyRequest_topologyDirectionExtension', D1, D2); + false -> + wrong_type('TopologyRequest_topologyDirectionExtension', D1, D2) + end. + + +%% -- AmmRequest -- + +is_AmmRequest(#'AmmRequest'{terminationID = Tids, + descriptors = Descs}) -> + d("is_AmmRequest -> entry with" + "~n Tids: ~p", [Tids]), + is_TerminationIDList(Tids) andalso is_AmmRequest_descriptors(Descs); +is_AmmRequest(_) -> + false. + +is_AmmRequest_descriptors(Descs) -> + d("is_AmmRequest_descriptors -> entry"), + is_AmmRequest_descriptors(Descs, []). + +is_AmmRequest_descriptors([], _) -> + true; +is_AmmRequest_descriptors([{Tag, _} = Desc|Descs], FoundDescs) -> + d("is_AmmRequest_descriptors -> entry with" + "~n Tag: ~p" + "~n FoundDescs: ~p", [Tag, FoundDescs]), + case lists:member(Tag, FoundDescs) of + true -> + atmost_once('AmmRequest_descriptors', Tag); + false -> + case is_AmmDescriptor(Desc) of + true -> + is_AmmRequest_descriptors(Descs, [Tag|FoundDescs]); + false -> + wrong_type('AmmRequest_descriptors', Desc) + end + end; +is_AmmRequest_descriptors(Descs, _) -> + d("is_AmmRequest_descriptors -> entry with WRONG TYPE" + "~n Descs: ~p", [Descs]), + wrong_type('AmmRequest_descriptors', Descs). + + +chk_AmmRequest(R, R) when is_record(R, 'AmmRequest') -> + d("chk_AmmRequest -> entry when equal"), + chk_type(fun is_AmmRequest/1, 'AmmRequest', R); +chk_AmmRequest(#'AmmRequest'{terminationID = Tids1, + descriptors = Descs1}, + #'AmmRequest'{terminationID = Tids2, + descriptors = Descs2}) -> + d("chk_AmmRequest -> entry with not equal" + "~n Tids1: ~p" + "~n Tids2: ~p", [Tids1, Tids2]), + validate( + fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'AmmRequest'), + validate( + fun() -> chk_AmmRequest_descriptors(Descs1, Descs2) end, + 'AmmRequest'), + ok. + + +chk_AmmRequest_descriptors([], []) -> + d("chk_AmmRequest_descriptors -> done when OK"), + ok; +chk_AmmRequest_descriptors([] = Descs1, Descs2) -> + d("chk_AmmRequest_descriptors -> done when NOT EQUAL:" + "~n Descs1: ~p" + "~n Descs1: ~p", [Descs1, Descs2]), + not_equal('AmmRequest_descriptors', Descs1, Descs2); +chk_AmmRequest_descriptors(Descs1, [] = Descs2) -> + d("chk_AmmRequest_descriptors -> done when NOT EQUAL:" + "~n Descs1: ~p" + "~n Descs1: ~p", [Descs1, Descs2]), + not_equal('AmmRequest_descriptors', Descs1, Descs2); +chk_AmmRequest_descriptors([H|T1], [H|T2]) -> + d("chk_AmmRequest_descriptors -> entry when equal"), + case is_AmmDescriptor(H) of + true -> + chk_AmmRequest_descriptors(T1, T2); + false -> + wrong_type('AmmRequest_descriptors_val', H) + end; +chk_AmmRequest_descriptors([H1|T1], [H2|T2]) -> + d("chk_AmmRequest_descriptors -> entry when not equal"), + validate(fun() -> chk_AmmDescriptor(H1, H2) end, + 'AmmRequest_descriptors_val'), + chk_AmmRequest_descriptors(T1, T2); +chk_AmmRequest_descriptors(Descs1, Descs2) -> + d("chk_AmmRequest_descriptors -> done when WRONG TYPE:" + "~n Descs1: ~p" + "~n Descs1: ~p", [Descs1, Descs2]), + wrong_type('AmmRequest_descriptors', Descs1, Descs2). + + +%% -- AmmDescriptor -- + +is_AmmDescriptor({Tag, Val}) -> + d("is_AmmDescriptor -> entry with" + "~n Tag: ~p" + "~n Val: ~p",[Tag, Val]), + is_AmmDescriptor_tag(Tag) andalso is_AmmDescriptor_val(Tag, Val); +is_AmmDescriptor(_) -> + false. + +is_AmmDescriptor_tag(Tag) -> + Tags = [mediaDescriptor, modemDescriptor, muxDescriptor, eventsDescriptor, + eventBufferDescriptor, signalsDescriptor, digitMapDescriptor, + auditDescriptor, statisticsDescriptor], + lists:member(Tag, Tags). + +is_AmmDescriptor_val(mediaDescriptor, D) -> + is_MediaDescriptor(D); +is_AmmDescriptor_val(modemDescriptor, D) -> + is_ModemDescriptor(D); +is_AmmDescriptor_val(muxDescriptor, D) -> + is_MuxDescriptor(D); +is_AmmDescriptor_val(eventsDescriptor, D) -> + is_EventsDescriptor(D); +is_AmmDescriptor_val(eventBufferDescriptor, D) -> + is_EventBufferDescriptor(D); +is_AmmDescriptor_val(signalsDescriptor, D) -> + is_SignalsDescriptor(D); +is_AmmDescriptor_val(digitMapDescriptor, D) -> + is_DigitMapDescriptor(D); +is_AmmDescriptor_val(auditDescriptor, D) -> + is_AuditDescriptor(D); +is_AmmDescriptor_val(statisticsDescriptor, D) -> + is_StatisticsDescriptor(D). + +chk_AmmDescriptor(D, D) -> + chk_type(fun is_AmmDescriptor_tag/1, 'AmmDescriptor', D); +chk_AmmDescriptor({Tag, Val1} = Cmd1, {Tag, Val2} = Cmd2) -> + case (is_AmmDescriptor_tag(Tag) andalso + is_AmmDescriptor_val(Tag, Val1) andalso + is_AmmDescriptor_val(Tag, Val2)) of + true -> + chk_AmmDescriptor_val(Tag, Val1, Val2); + false -> + wrong_type('AmmDescriptor', Cmd1, Cmd2) + end; +chk_AmmDescriptor({Tag1, Val1} = Cmd1, {Tag2, Val2} = Cmd2) -> + case ((is_AmmDescriptor_tag(Tag1) andalso + is_AmmDescriptor_val(Tag1, Val1)) andalso + (is_AmmDescriptor_tag(Tag2) andalso + is_AmmDescriptor_val(Tag2, Val2))) of + true -> + not_equal('AmmDescriptor', Cmd1, Cmd2); + false -> + wrong_type('AmmDescriptor', Cmd1, Cmd2) + end; +chk_AmmDescriptor(Cmd1, Cmd2) -> + wrong_type('AmmDescriptor', Cmd1, Cmd2). + +chk_AmmDescriptor_val(mediaDescriptor, D1, D2) -> + validate(fun() -> chk_MediaDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(modemDescriptor, D1, D2) -> + validate(fun() -> chk_ModemDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(muxDescriptor, D1, D2) -> + validate(fun() -> chk_MuxDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(eventsDescriptor, D1, D2) -> + validate(fun() -> chk_EventsDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(eventBufferDescriptor, D1, D2) -> + validate(fun() -> chk_EventBufferDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(signalsDescriptor, D1, D2) -> + validate(fun() -> chk_SignalsDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(digitMapDescriptor, D1, D2) -> + validate(fun() -> chk_DigitMapDescriptor(D1, D2) end, 'AmmDescriptor'); +chk_AmmDescriptor_val(auditDescriptor, D1, D2) -> + validate(fun() -> chk_AuditDescriptor(D1, D2) end, 'AmmDescriptor'). + + +%% -- AmmsReply -- + +is_AmmsReply(#'AmmsReply'{terminationID = Tids, + terminationAudit = TA}) -> + is_TerminationIDList(Tids) andalso is_opt_TerminationAudit(TA); +is_AmmsReply(_) -> + false. + +chk_AmmsReply(R, R) -> + is_AmmsReply(R); +chk_AmmsReply(#'AmmsReply'{terminationID = TID1, + terminationAudit = TA1}, + #'AmmsReply'{terminationID = TID2, + terminationAudit = TA2}) -> + validate(fun() -> chk_TerminationIDList(TID1, TID2) end, 'AmmsReply'), + validate(fun() -> chk_opt_TerminationAudit(TA1, TA2) end, 'AmmsReply'), + ok; +chk_AmmsReply(R1, R2) -> + wrong_type('AmmsReply', R1, R2). + + +%% -- SubtractRequest -- + +is_SubtractRequest(#'SubtractRequest'{terminationID = TID, + auditDescriptor = AD}) -> + d("is_SubtractDescriptor -> entry with" + "~n TID: ~p" + "~n AD: ~p",[TID, AD]), + is_TerminationIDList(TID) andalso is_opt_AuditDescriptor(AD); +is_SubtractRequest(_) -> + false. + +chk_SubtractRequest(R, R) -> + chk_type(fun is_SubtractRequest/1, 'SubtractRequest', R); +chk_SubtractRequest(#'SubtractRequest'{terminationID = Tids1, + auditDescriptor = AD1}, + #'SubtractRequest'{terminationID = Tids2, + auditDescriptor = AD2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'SubtractRequest'), + validate(fun() -> chk_opt_AuditDescriptor(AD1, AD2) end, + 'SubtractRequest'), + ok; +chk_SubtractRequest(SR1, SR2) -> + wrong_type('SubtractRequest', SR1, SR2). + + +%% -- AuditRequest -- + +is_AuditRequest(#'AuditRequest'{terminationID = TID, + auditDescriptor = AD, + terminationIDList = asn1_NOVALUE}) -> + d("is_AuditRequest -> entry with" + "~n TID: ~p" + "~n AD: ~p",[TID, AD]), + is_TerminationID(TID) andalso + is_AuditDescriptor(AD); +is_AuditRequest(#'AuditRequest'{terminationID = TID, + auditDescriptor = AD, + terminationIDList = [TID|_] = TIDs}) -> + d("is_AuditRequest -> entry with" + "~n TID: ~p" + "~n AD: ~p" + "~n TIDs: ~p",[TID, AD, TIDs]), + is_TerminationID(TID) andalso + is_AuditDescriptor(AD) andalso + is_TerminationIDList(TIDs); +is_AuditRequest(_) -> + false. + +chk_AuditRequest(R, R) -> + chk_type(fun is_AuditRequest/1, 'AuditRequest', R); +chk_AuditRequest(#'AuditRequest'{terminationID = TID1, + auditDescriptor = AD1, + terminationIDList = [TID1|_] = TIDs1}, + #'AuditRequest'{terminationID = TID2, + auditDescriptor = AD2, + terminationIDList = [TID2|_] = TIDs2}) -> + validate(fun() -> chk_TerminationID(TID1, TID2) end, + 'AuditRequest'), + validate(fun() -> chk_AuditDescriptor(AD1, AD2) end, + 'AuditRequest'), + validate(fun() -> chk_opt_TerminationIDList(TIDs1, TIDs2) end, + 'AuditRequest'), + ok; +chk_AuditRequest(AR1, AR2) -> + wrong_type('AuditRequest', AR1, AR2). + + +%% -- AuditReply -- + +is_AuditReply({Tag, Val}) -> + is_AuditReply_tag(Tag) andalso is_AuditReply_val(Tag, Val); +is_AuditReply(_) -> + false. + +is_AuditReply_tag(Tag) -> + Tags = [contextAuditResult, error, auditResult, auditResultTermList], + lists:member(Tag, Tags). + +is_AuditReply_val(contextAuditResult, Val) -> + is_TerminationIDList(Val); +is_AuditReply_val(error, Val) -> + is_ErrorDescriptor(Val); +is_AuditReply_val(auditResult, Val) -> + is_AuditResult(Val); +is_AuditReply_val(auditResultTermList, Val) -> + is_TermListAuditResult(Val). + +chk_AuditReply(R, R) -> + chk_type(fun is_AuditReply/1, 'AuditReply', R); +chk_AuditReply({Tag, Val1} = R1, {Tag, Val2} = R2) -> + case (is_AuditReply_tag(Tag) andalso + is_AuditReply_val(Tag, Val1)andalso + is_AuditReply_val(Tag, Val2)) of + true -> + chk_AuditReply_val(Tag, Val1, Val2); + false -> + wrong_type('AuditReply', R1, R2) + end; +chk_AuditReply({Tag1, Val1} = R1, {Tag2, Val2} = R2) -> + case ((is_AuditReply_tag(Tag1) andalso + is_AuditReply_val(Tag1, Val1)) andalso + (is_AuditReply_tag(Tag2) andalso + is_AuditReply_val(Tag2, Val2))) of + true -> + not_equal('AuditReply', R1, R2); + false -> + wrong_type('AuditReply', R1, R2) + end; +chk_AuditReply(AR1, AR2) -> + wrong_type('AuditReply', AR1, AR2). + +chk_AuditReply_val(contextAuditResult, Val1, Val2) -> + chk_TerminationIDList(Val1, Val2); +chk_AuditReply_val(error, Val1, Val2) -> + chk_ErrorDescriptor(Val1, Val2); +chk_AuditReply_val(auditResult, Val1, Val2) -> + chk_AuditResult(Val1, Val2); +chk_AuditReply_val(auditResultTermList, Val1, Val2) -> + chk_TermListAuditResult(Val1, Val2). + + +%% -- AuditResult -- + +is_AuditResult(#'AuditResult'{terminationID = TID, + terminationAuditResult = TAR}) -> + is_TerminationID(TID) andalso is_TerminationAudit(TAR); +is_AuditResult(_) -> + false. + +chk_AuditResult(R, R) -> + d("chk_AuditResult -> entry (1)"), + chk_type(fun is_AuditResult/1, 'AuditResult', R); +chk_AuditResult(#'AuditResult'{terminationID = TID1, + terminationAuditResult = TAR1}, + #'AuditResult'{terminationID = TID2, + terminationAuditResult = TAR2}) -> + d("chk_AuditResult -> entry (2)"), + validate(fun() -> chk_TerminationID(TID1, TID2) end, 'AuditResult'), + validate(fun() -> chk_TerminationAudit(TAR1, TAR2) end, 'AuditResult'), + ok; +chk_AuditResult(AR1, AR2) -> + d("chk_AuditResult -> entry (3)"), + wrong_type('AuditResult', AR1, AR2). + + +%% -- TermListAuditResult -- + +is_TermListAuditResult(#'TermListAuditResult'{terminationIDList = TIDs, + terminationAuditResult = TAR}) -> + is_TerminationIDList(TIDs) andalso is_TerminationAudit(TAR); +is_TermListAuditResult(_) -> + false. + +chk_TermListAuditResult(TLAR, TLAR) -> + d("chk_TermListAuditResult(1) -> entry with" + "~n TLAR: ~p", [TLAR]), + chk_type(fun is_TermListAuditResult/1, 'TermListAuditResult', TLAR); +chk_TermListAuditResult( + #'TermListAuditResult'{terminationIDList = TIDs1, + terminationAuditResult = TAR1}, + #'TermListAuditResult'{terminationIDList = TIDs2, + terminationAuditResult = TAR2}) -> + d("chk_TermListAuditResult(2) -> entry with" + "~n TIDs1: ~p" + "~n TAR1: ~p" + "~n TIDs2: ~p" + "~n TAR2: ~p", [TIDs1, TAR1, TIDs2, TAR2]), + validate(fun() -> chk_TerminationIDList(TIDs1, TIDs2) end, + 'TermListAuditResult_terminationIDList'), + validate(fun() -> chk_TerminationAudit(TAR1, TAR2) end, + 'TermListAuditResult_terminationAuditResult'), + ok; +chk_TermListAuditResult(TLAR1, TLAR2) -> + d("chk_TermListAuditResult(3) -> entry with" + "~n TLAR1: ~p" + "~n TLAR2: ~p", [TLAR1, TLAR2]), + wrong_type('TermListAuditResult', TLAR1, TLAR2). + + +%% -- TerminationAudit -- + +is_opt_TerminationAudit(TA) -> + is_OPTIONAL(fun is_TerminationAudit/1, TA). + +is_TerminationAudit([]) -> + true; +is_TerminationAudit([H|T]) -> + is_AuditReturnParameter(H) andalso is_TerminationAudit(T); +is_TerminationAudit(_) -> + false. + +chk_opt_TerminationAudit(TA1, TA2) -> + d("chk_opt_TerminationAudit -> entry with" + "~n TA1: ~p" + "~n TA2: ~p", [TA1, TA2]), + chk_OPTIONAL('TerminationAudit', + strip_TerminationAudit(TA1), + strip_TerminationAudit(TA2), + fun is_TerminationAudit/1, fun chk_TerminationAudit/2). + +strip_TerminationAudit(L) when is_list(L) -> + d("strip_TerminationAudit(1) -> entry with" + "~n L: ~p", [L]), + %% Drop all empty emptyDescriptor's + F = fun({emptyDescriptors, AD}) -> + case AD of + #'AuditDescriptor'{auditToken = asn1_NOVALUE, + auditPropertyToken = asn1_NOVALUE} -> + true; + _ -> + false + end; + (_) -> + false + end, + lists:dropwhile(F, L); +strip_TerminationAudit(asn1_NOVALUE) -> + d("strip_TerminationAudit(2) -> entry"), + []; +strip_TerminationAudit(X) -> + d("strip_TerminationAudit(3) -> entry with" + "~n X: ~p", [X]), + X. + +chk_TerminationAudit(TA1, TA2) -> + d("chk_TerminationAudit -> entry with" + "~n TA1: ~p" + "~n TA2: ~p", [TA1, TA2]), + do_chk_TerminationAudit(strip_TerminationAudit(TA1), + strip_TerminationAudit(TA2)). + +do_chk_TerminationAudit([], []) -> + d("do_chk_TerminationAudit(1) -> entry"), + ok; +do_chk_TerminationAudit([], asn1_NOVALUE) -> + d("do_chk_TerminationAudit(2) -> entry"), + ok; +do_chk_TerminationAudit(asn1_NOVALUE, []) -> + d("do_chk_TerminationAudit(3) -> entry"), + ok; +do_chk_TerminationAudit([] = TA1, TA2) -> + d("do_chk_TerminationAudit(4) -> entry with" + "~n TA2: ~p", [TA2]), + not_equal('TerminationAudit', TA1, TA2); +do_chk_TerminationAudit(TA1, [] = TA2) -> + d("do_chk_TerminationAudit(5) -> entry with" + "~n TA1: ~p", [TA1]), + not_equal('TerminationAudit', TA1, TA2); +do_chk_TerminationAudit([H|T1], [H|T2]) -> + d("do_chk_TerminationAudit(6) -> entry with" + "~n H: ~p", [H]), + case is_AuditReturnParameter(H) of + true -> + do_chk_TerminationAudit(T1, T2); + false -> + wrong_type('TerminationAudit', H) + end; +do_chk_TerminationAudit([H1|T1], [H2|T2]) -> + d("do_chk_TerminationAudit(7) -> entry with" + "~n H1: ~p" + "~n H2: ~p", [H1, H2]), + chk_AuditReturnParameter(H1, H2), + do_chk_TerminationAudit(T1, T2); +do_chk_TerminationAudit(TA1, TA2) -> + d("do_chk_TerminationAudit(8) -> entry with" + "~n TA1: ~p" + "~n TA2: ~p", [TA1, TA2]), + not_equal('TerminationAudit', TA1, TA2). + + +%% -- AuditReturnParameter -- + +is_AuditReturnParameter({Tag, Val}) -> + is_AuditReturnParameter_tag(Tag) andalso + is_AuditReturnParameter_val(Tag, Val); +is_AuditReturnParameter(_) -> + false. + +is_AuditReturnParameter_tag(Tag) -> + Tags = [errorDescriptor, + mediaDescriptor, + modemDescriptor, + muxDescriptor, + eventsDescriptor, + eventBufferDescriptor, + signalsDescriptor, + digitMapDescriptor, + observedEventsDescriptor, + statisticsDescriptor, + packagesDescriptor, + emptyDescriptors], + lists:member(Tag, Tags). + +is_AuditReturnParameter_val(errorDescriptor, V) -> + is_ErrorDescriptor(V); +is_AuditReturnParameter_val(mediaDescriptor, V) -> + is_MediaDescriptor(V); +is_AuditReturnParameter_val(modemDescriptor, V) -> + is_ModemDescriptor(V); +is_AuditReturnParameter_val(muxDescriptor, V) -> + is_MuxDescriptor(V); +is_AuditReturnParameter_val(eventsDescriptor, V) -> + is_EventsDescriptor(V); +is_AuditReturnParameter_val(eventBufferDescriptor, V) -> + is_EventBufferDescriptor(V); +is_AuditReturnParameter_val(signalsDescriptor, V) -> + is_SignalsDescriptor(V); +is_AuditReturnParameter_val(digitMapDescriptor, V) -> + is_DigitMapDescriptor(V); +is_AuditReturnParameter_val(observedEventsDescriptor, V) -> + is_ObservedEventsDescriptor(V); +is_AuditReturnParameter_val(statisticsDescriptor, V) -> + is_StatisticsDescriptor(V); +is_AuditReturnParameter_val(packagesDescriptor, V) -> + is_PackagesDescriptor(V); +is_AuditReturnParameter_val(emptyDescriptors, V) -> + is_AuditDescriptor(V). + +chk_AuditReturnParameter(ARP, ARP) -> + chk_type(fun is_AuditReturnParameter/1, 'AuditReturnParameter', ARP); +chk_AuditReturnParameter({Tag, Val1} = ARP1, {Tag, Val2} = ARP2) -> + case (is_AuditReturnParameter_tag(Tag) andalso + is_AuditReturnParameter_val(Tag, Val1) andalso + is_AuditReturnParameter_val(Tag, Val2)) of + true -> + chk_AuditReturnParameter_val(Tag, Val1, Val2); + false -> + wrong_type('AuditReturnParameter', ARP1, ARP2) + end; +chk_AuditReturnParameter({Tag1, Val1} = ARP1, {Tag2, Val2} = ARP2) -> + case ((is_AuditReturnParameter_tag(Tag1) andalso + is_AuditReturnParameter_val(Tag1, Val1)) andalso + (is_AuditReturnParameter_tag(Tag2) andalso + is_AuditReturnParameter_val(Tag2, Val2))) of + true -> + not_equal('AuditReturnParameter', ARP1, ARP2); + false -> + wrong_type('AuditReturnParameter', ARP1, ARP2) + end; +chk_AuditReturnParameter(ARP1, ARP2) -> + wrong_type('AuditReturnParameter', ARP1, ARP2). + +chk_AuditReturnParameter_val(errorDescriptor, V1, V2) -> + validate(fun() -> chk_ErrorDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(mediaDescriptor, V1, V2) -> + validate(fun() -> chk_MediaDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(modemDescriptor, V1, V2) -> + validate(fun() -> chk_ModemDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(muxDescriptor, V1, V2) -> + validate(fun() -> chk_MuxDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(eventsDescriptor, V1, V2) -> + validate(fun() -> chk_EventsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(eventBufferDescriptor, V1, V2) -> + validate(fun() -> chk_EventBufferDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(signalsDescriptor, V1, V2) -> + validate(fun() -> chk_SignalsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(digitMapDescriptor, V1, V2) -> + validate(fun() -> chk_DigitMapDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(observedEventsDescriptor, V1, V2) -> + validate(fun() -> chk_ObservedEventsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(statisticsDescriptor, V1, V2) -> + validate(fun() -> chk_StatisticsDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(packagesDescriptor, V1, V2) -> + validate(fun() -> chk_PackagesDescriptor(V1, V2) end, + 'AuditReturnParameter'); +chk_AuditReturnParameter_val(emptyDescriptors, V1, V2) -> + validate(fun() -> chk_AuditDescriptor(V1, V2) end, + 'AuditReturnParameter'). + + +%% -- AuditDescriptor -- + +is_opt_AuditDescriptor(asn1_NOVALUE) -> + true; +is_opt_AuditDescriptor(V) -> + is_AuditDescriptor(V). + +is_AuditDescriptor(#'AuditDescriptor'{auditToken = AT, + auditPropertyToken = APT}) -> + d("is_AuditDescriptor -> entry with" + "~n AT: ~p" + "~n APT: ~p", [AT, APT]), + is_AuditDescriptor_auditToken(AT) andalso + is_AuditDescriptor_auditPropertyToken(APT); +is_AuditDescriptor(_) -> + false. + +is_AuditDescriptor_auditToken(asn1_NOVALUE) -> + true; +is_AuditDescriptor_auditToken([]) -> + true; +is_AuditDescriptor_auditToken([H|T]) -> + is_AuditDescriptor_auditToken_val(H) andalso + is_AuditDescriptor_auditToken(T); +is_AuditDescriptor_auditToken(_) -> + false. + +is_AuditDescriptor_auditToken_val(V) -> + Toks = [muxToken, modemToken, mediaToken, eventsToken, signalsToken, + digitMapToken, statsToken, observedEventsToken, + packagesToken, eventBufferToken], + lists:member(V, Toks). + +is_AuditDescriptor_auditPropertyToken(asn1_NOVALUE) -> + true; +is_AuditDescriptor_auditPropertyToken([]) -> + true; +is_AuditDescriptor_auditPropertyToken([H|T]) -> + d("is_AuditDescriptor_auditPropertyToken -> entry with" + "~n H: ~p", [H]), + is_IndAuditParameter(H) andalso is_AuditDescriptor_auditPropertyToken(T); +is_AuditDescriptor_auditPropertyToken(_) -> + false. + +chk_opt_AuditDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_AuditDescriptor(AD1, AD2) -> + chk_AuditDescriptor(AD1, AD2). + +chk_AuditDescriptor(AD, AD) -> + chk_type(fun is_AuditDescriptor/1, 'AuditDescriptor', AD); +chk_AuditDescriptor(#'AuditDescriptor'{auditToken = AT1, + auditPropertyToken = APT1}, + #'AuditDescriptor'{auditToken = AT2, + auditPropertyToken = APT2}) -> + chk_AuditDescriptor_auditToken(maybe_sort(AT1), maybe_sort(AT2)), + chk_AuditDescriptor_auditPropertyToken(APT1, APT2), + ok; +chk_AuditDescriptor(AD1, AD2) -> + wrong_type('AuditDescriptor', AD1, AD2). + +chk_AuditDescriptor_auditToken(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_AuditDescriptor_auditToken([], []) -> + ok; +chk_AuditDescriptor_auditToken([] = AT1, AT2) -> + not_equal('AuditDescriptor_auditToken', AT1, AT2); +chk_AuditDescriptor_auditToken(AT1, [] = AT2) -> + not_equal('AuditDescriptor_auditToken', AT1, AT2); +chk_AuditDescriptor_auditToken([H|T1], [H|T2]) -> + case is_AuditDescriptor_auditToken_val(H) of + true -> + chk_AuditDescriptor_auditToken(T1, T2); + false -> + wrong_type('AuditDescriptor_auditToken_val', H) + end; +chk_AuditDescriptor_auditToken([H1|_T1], [H2|_T2]) -> + case (is_AuditDescriptor_auditToken_val(H1) andalso + is_AuditDescriptor_auditToken_val(H2)) of + true -> + not_equal('AuditDescriptor_auditToken_val', H1, H2); + false -> + wrong_type('AuditDescriptor_auditToken_val', H1, H2) + end; +chk_AuditDescriptor_auditToken(AT1, AT2) -> + wrong_type('AuditDescriptor_auditToken', AT1, AT2). + +chk_AuditDescriptor_auditPropertyToken(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_AuditDescriptor_auditPropertyToken([], []) -> + ok; +chk_AuditDescriptor_auditPropertyToken([] = AT1, AT2) -> + not_equal('AuditDescriptor_auditPropertyToken', AT1, AT2); +chk_AuditDescriptor_auditPropertyToken(AT1, [] = AT2) -> + not_equal('AuditDescriptor_auditPropertyToken', AT1, AT2); +chk_AuditDescriptor_auditPropertyToken([H|T1], [H|T2]) -> + case is_IndAuditParameter(H) of + true -> + chk_AuditDescriptor_auditPropertyToken(T1, T2); + false -> + wrong_type('AuditDescriptor_auditPropertyToken_val', H) + end; +chk_AuditDescriptor_auditPropertyToken([H1|_], [H2|_]) -> + chk_IndAuditParameter(H1, H2), + not_equal('AuditDescriptor_auditPropertyToken_val', H1, H2); +chk_AuditDescriptor_auditPropertyToken(AT1, AT2) -> + wrong_type('AuditDescriptor_auditPropertyToken', AT1, AT2). + + +%% -- IndAuditParameter -- + +is_IndAuditParameter({Tag, Val}) -> + is_IndAuditParameter_tag(Tag) andalso is_IndAuditParameter_val(Tag, Val); +is_IndAuditParameter(_) -> + false. + +is_IndAuditParameter_tag(Tag) -> + Tags = [indAudMediaDescriptor, + indAudEventsDescriptor, + indAudEventBufferDescriptor, + indAudSignalsDescriptor, + indAudDigitMapDescriptor, + indAudStatisticsDescriptor, + indAudPackagesDescriptor], + lists:member(Tag, Tags). + +is_IndAuditParameter_val(indAudMediaDescriptor, Val) -> + is_IndAudMediaDescriptor(Val); +is_IndAuditParameter_val(indAudEventsDescriptor, Val) -> + is_IndAudEventsDescriptor(Val); +is_IndAuditParameter_val(indAudEventBufferDescriptor, Val) -> + is_IndAudEventBufferDescriptor(Val); +is_IndAuditParameter_val(indAudSignalsDescriptor, Val) -> + is_IndAudSignalsDescriptor(Val); +is_IndAuditParameter_val(indAudDigitMapDescriptor, Val) -> + is_IndAudDigitMapDescriptor(Val); +is_IndAuditParameter_val(indAudStatisticsDescriptor, Val) -> + is_IndAudStatisticsDescriptor(Val); +is_IndAuditParameter_val(indAudPackagesDescriptor, Val) -> + is_IndAudPackagesDescriptor(Val). + +chk_IndAuditParameter(IAP, IAP) -> + chk_type(fun is_IndAuditParameter/1, 'IndAuditParameter', IAP); +chk_IndAuditParameter({Tag, Val1} = IAP1, {Tag, Val2} = IAP2) -> + case (is_IndAuditParameter_tag(Tag) andalso + is_IndAuditParameter_val(Tag, Val1) andalso + is_IndAuditParameter_val(Tag, Val2)) of + true -> + chk_IndAuditParameter_val(Tag, Val1, Val2); + false -> + wrong_type('IndAuditParameter', IAP1, IAP2) + end; +chk_IndAuditParameter({Tag1, Val1} = IAP1, {Tag2, Val2} = IAP2) -> + case ((is_IndAuditParameter_tag(Tag1) andalso + is_IndAuditParameter_val(Tag1, Val1)) andalso + (is_IndAuditParameter_tag(Tag2) andalso + is_IndAuditParameter_val(Tag2, Val2))) of + true -> + not_equal('IndAuditParameter', IAP1, IAP2); + false -> + wrong_type('IndAuditParameter', IAP1, IAP2) + end; +chk_IndAuditParameter(IAP1, IAP2) -> + wrong_type('IndAuditParameter', IAP1, IAP2). + +chk_IndAuditParameter_val(indAudMediaDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudMediaDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudEventsDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudEventsDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudEventBufferDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudEventBufferDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudSignalsDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudSignalsDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudDigitMapDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudDigitMapDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudStatisticsDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudStatisticsDescriptor(Val1, Val2) end, + 'IndAuditParameter'); +chk_IndAuditParameter_val(indAudPackagesDescriptor, Val1, Val2) -> + validate(fun() -> chk_IndAudPackagesDescriptor(Val1, Val2) end, + 'IndAuditParameter'). + + +%% -- IndAudMediaDescriptor -- + +is_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD, + streams = S}) -> + d("is_IndAudMediaDescriptor -> entry with" + "~n TSD: ~p" + "~n S: ~p", [TSD, S]), + is_opt_IndAudTerminationStateDescriptor(TSD) andalso + is_IndAudMediaDescriptor_streams(S); +is_IndAudMediaDescriptor(_) -> + false. + +is_IndAudMediaDescriptor_streams(asn1_NOVALUE) -> + true; +is_IndAudMediaDescriptor_streams({Tag, Val}) -> + d("is_IndAudMediaDescriptor_streams -> entry with" + "~n Tag: ~p" + "~n Val: ~p", [Tag, Val]), + is_IndAudMediaDescriptor_streams_tag(Tag) andalso + is_IndAudMediaDescriptor_streams_val(Tag, Val); +is_IndAudMediaDescriptor_streams(_) -> + false. + +is_IndAudMediaDescriptor_streams_tag(Tag) -> + Tags = [oneStream, multiStream], + lists:member(Tag, Tags). + +is_IndAudMediaDescriptor_streams_val(oneStream, Val) -> + d("is_IndAudMediaDescriptor_streams_val(oneStream) -> entry with" + "~n Val: ~p", [Val]), + is_IndAudStreamParms(Val); +is_IndAudMediaDescriptor_streams_val(multiStream, Val) -> + d("is_IndAudMediaDescriptor_streams_val(multiStream) -> entry with" + "~n Val: ~p", [Val]), + is_IndAudMediaDescriptor_multiStream(Val). + +is_IndAudMediaDescriptor_multiStream([]) -> + true; +is_IndAudMediaDescriptor_multiStream([H|T]) -> + d("is_IndAudMediaDescriptor_multiStream -> entry with" + "~n H: ~p", [H]), + is_IndAudStreamDescriptor(H) andalso + is_IndAudMediaDescriptor_multiStream(T); +is_IndAudMediaDescriptor_multiStream(_) -> + false. + +chk_IndAudMediaDescriptor(IAMD, IAMD) -> + chk_type(fun is_IndAudMediaDescriptor/1, 'IndAudMediaDescriptor', IAMD); +chk_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD1, + streams = S1}, + #'IndAudMediaDescriptor'{termStateDescr = TSD2, + streams = S2}) -> + validate(fun() -> chk_opt_IndAudTerminationStateDescriptor(TSD1, TSD2) end, + 'IndAudMediaDescriptor'), + validate(fun() -> chk_IndAudMediaDescriptor_streams(S1, S2) end, + 'IndAudMediaDescriptor'), + ok; +chk_IndAudMediaDescriptor(IAMD1, IAMD2) -> + wrong_type('IndAudMediaDescriptor', IAMD1, IAMD2). + +chk_IndAudMediaDescriptor_streams(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_IndAudMediaDescriptor_streams({Tag, Val1} = S1, + {Tag, Val2} = S2) -> + case (is_IndAudMediaDescriptor_streams_tag(Tag) andalso + is_IndAudMediaDescriptor_streams_val(Tag, Val1) andalso + is_IndAudMediaDescriptor_streams_val(Tag, Val2)) of + true -> + chk_IndAudMediaDescriptor_streams_val(Tag, Val1, Val2); + false -> + wrong_type('IndAudMediaDescriptor_streams', S1, S2) + end; +chk_IndAudMediaDescriptor_streams({Tag1, Val1} = S1, + {Tag2, Val2} = S2) -> + case ((is_IndAudMediaDescriptor_streams_tag(Tag1) andalso + is_IndAudMediaDescriptor_streams_val(Tag1, Val1)) andalso + (is_IndAudMediaDescriptor_streams_tag(Tag2) andalso + is_IndAudMediaDescriptor_streams_val(Tag2, Val2))) of + true -> + not_equal('IndAudMediaDescriptor_streams', S1, S2); + false -> + wrong_type('IndAudMediaDescriptor_streams', S1, S2) + end; +chk_IndAudMediaDescriptor_streams(S1, S2) -> + wrong_type('IndAudMediaDescriptor_streams', S1, S2). + +chk_IndAudMediaDescriptor_streams_val(oneStream, Val1, Val2) -> + validate(fun() -> chk_IndAudStreamParms(Val1, Val2) end, + 'IndAudMediaDescriptor_streams'); +chk_IndAudMediaDescriptor_streams_val(multiStream, Val1, Val2) -> + validate(fun() -> chk_IndAudMediaDescriptor_multiStream(Val1, Val2) end, + 'IndAudMediaDescriptor_streams'). + +chk_IndAudMediaDescriptor_multiStream([], []) -> + ok; +chk_IndAudMediaDescriptor_multiStream([] = MS1, MS2) -> + not_equal('IndAudMediaDescriptor_multiStream', MS1, MS2); +chk_IndAudMediaDescriptor_multiStream(MS1, [] = MS2) -> + not_equal('IndAudMediaDescriptor_multiStream', MS1, MS2); +chk_IndAudMediaDescriptor_multiStream([H|T1], [H|T2]) -> + case is_IndAudStreamDescriptor(H) of + true -> + chk_IndAudMediaDescriptor_multiStream(T1, T2); + false -> + wrong_type('IndAudMediaDescriptor_multiStream_val', H) + end; +chk_IndAudMediaDescriptor_multiStream([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudStreamDescriptor(H1, H2) end, + 'IndAudMediaDescriptor_multiStream_val'), + chk_IndAudMediaDescriptor_multiStream(T1, T2); +chk_IndAudMediaDescriptor_multiStream(MS1, MS2) -> + wrong_type('IndAudMediaDescriptor_multiStream', MS1, MS2). + + +%% -- IndAudStreamDescriptor -- + +is_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID, + streamParms = Parms}) -> + d("is_IndAudStreamDescriptor -> entry with" + "~n SID: ~p" + "~n Parms: ~p", [SID, Parms]), + is_StreamID(SID) andalso is_IndAudStreamParms(Parms); +is_IndAudStreamDescriptor(_) -> + false. + +chk_IndAudStreamDescriptor(D, D) -> + chk_type(fun is_IndAudStreamDescriptor/1, 'IndAudStreamDescriptor', D); +chk_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID1, + streamParms = Parms1}, + #'IndAudStreamDescriptor'{streamID = SID2, + streamParms = Parms2}) -> + validate(fun() -> chk_StreamID(SID1, SID2) end, 'IndAudStreamDescriptor'), + validate(fun() -> chk_IndAudStreamParms(Parms1, Parms2) end, + 'IndAudStreamDescriptor'), + ok; +chk_IndAudStreamDescriptor(D1, D2) -> + wrong_type('IndAudStreamDescriptor', D1, D2). + + +%% -- IndAudStreamParms -- + +is_IndAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD}) -> + d("is_IndAudStreamParms -> entry with" + "~n LCD: ~p" + "~n LD: ~p" + "~n RD: ~p", [LCD, LD, RD]), + is_opt_IndAudLocalControlDescriptor(LCD) andalso + is_opt_IndAudLocalRemoteDescriptor(LD) andalso + is_opt_IndAudLocalRemoteDescriptor(RD); +is_IndAudStreamParms(_) -> + false. + +chk_IndAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = LCD1, + localDescriptor = LD1, + remoteDescriptor = RD1}, + #'IndAudStreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2}) -> + validate(fun() -> chk_opt_IndAudLocalControlDescriptor(LCD1, LCD2) end, + 'IndAudStreamParms'), + validate(fun() -> chk_opt_IndAudLocalRemoteDescriptor(LD1, LD2) end, + 'IndAudStreamParms'), + validate(fun() -> chk_opt_IndAudLocalRemoteDescriptor(RD1, RD2) end, + 'IndAudStreamParms'), + ok; +chk_IndAudStreamParms(D1, D2) -> + wrong_type('IndAudStreamParms', D1, D2). + + +%% -- IndAudLocalControlDescriptor -- + +is_opt_IndAudLocalControlDescriptor(asn1_NOVALUE) -> + true; +is_opt_IndAudLocalControlDescriptor(D) -> + is_IndAudLocalControlDescriptor(D). + +is_IndAudLocalControlDescriptor( + #'IndAudLocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PPs, + streamModeSel = SMS}) -> + d("is_IndAudLocalControlDescriptor -> entry with" + "~n SM: ~p" + "~n RV: ~p" + "~n RG: ~p" + "~n PPs: ~p" + "~n SMS: ~p", [SM, RV, RG, PPs, SMS]), + is_opt_NULL(SM) andalso + is_opt_NULL(RV) andalso + is_opt_NULL(RG) andalso + is_IndAudLocalControlDescriptor_propertyParms(PPs) andalso + is_opt_StreamMode(SMS); +is_IndAudLocalControlDescriptor(_) -> + false. + +is_IndAudLocalControlDescriptor_propertyParms(asn1_NOVALUE) -> + true; +is_IndAudLocalControlDescriptor_propertyParms([]) -> + true; +is_IndAudLocalControlDescriptor_propertyParms([H|T]) -> + is_IndAudPropertyParm(H) andalso + is_IndAudLocalControlDescriptor_propertyParms(T); +is_IndAudLocalControlDescriptor_propertyParms(_) -> + false. + +chk_opt_IndAudLocalControlDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudLocalControlDescriptor( + #'IndAudLocalControlDescriptor'{streamMode = SM1, + reserveValue = RV1, + reserveGroup = RG1, + propertyParms = PPs1, + streamModeSel = SMS1}, + #'IndAudLocalControlDescriptor'{streamMode = SM2, + reserveValue = RV2, + reserveGroup = RG2, + propertyParms = PPs2, + streamModeSel = SMS2}) -> + chk_IndAudLocalControlDescriptor_streamMode(SM1, SM2), + chk_IndAudLocalControlDescriptor_reserveValue(RV1, RV2), + chk_IndAudLocalControlDescriptor_reserveGroup(RG1, RG2), + chk_IndAudLocalControlDescriptor_propertyParms(PPs1, PPs2), + chk_IndAudLocalControlDescriptor_streamModeSel(SMS1, SMS2), + ok; +chk_opt_IndAudLocalControlDescriptor(D1, D2) -> + wrong_type('IndAudLocalControlDescriptor', D1, D2). + +chk_IndAudLocalControlDescriptor_streamMode(SM1, SM2) -> + validate(fun() -> chk_opt_NULL(SM1, SM2) end, + 'IndAudLocalControlDescriptor_streamMode'). + +chk_IndAudLocalControlDescriptor_reserveValue(RV1, RV2) -> + validate(fun() -> chk_opt_NULL(RV1, RV2) end, + 'IndAudLocalControlDescriptor_reserveValue'). + +chk_IndAudLocalControlDescriptor_reserveGroup(RG1, RG2) -> + validate(fun() -> chk_opt_NULL(RG1, RG2) end, + 'IndAudLocalControlDescriptor_reserveGroup'). + +chk_IndAudLocalControlDescriptor_propertyParms(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_IndAudLocalControlDescriptor_propertyParms([], []) -> + ok; +chk_IndAudLocalControlDescriptor_propertyParms([] = PPs1, PPs2) -> + not_equal('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2); +chk_IndAudLocalControlDescriptor_propertyParms(PPs1, [] = PPs2) -> + not_equal('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2); +chk_IndAudLocalControlDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_IndAudLocalControlDescriptor_propertyParms(T1, T2); + false -> + wrong_type('IndAudLocalControlDescriptor_propertyParms_val', H) + end; +chk_IndAudLocalControlDescriptor_propertyParms([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, + 'IndAudLocalControlDescriptor_propertyParms_val'), + chk_IndAudLocalControlDescriptor_propertyParms(T1, T2); +chk_IndAudLocalControlDescriptor_propertyParms(PPs1, PPs2) -> + wrong_type('IndAudLocalControlDescriptor_propertyParms', PPs1, PPs2). + +chk_IndAudLocalControlDescriptor_streamModeSel(SMS1, SMS2) -> + validate(fun() -> chk_opt_StreamMode(SMS1, SMS2) end, + 'IndAudLocalControlDescriptor_streamModeSel'). + + +%% -- IndAudPropertyParm -- + +is_IndAudPropertyParm(#'IndAudPropertyParm'{name = Name, + propertyParms = PP}) -> + d("is_IndAudPropertyParm -> entry"), + is_PkgdName(Name) andalso is_opt_PropertyParm(PP); +is_IndAudPropertyParm(_) -> + false. + +chk_IndAudPropertyParm(#'IndAudPropertyParm'{name = Name1, + propertyParms = PP1}, + #'IndAudPropertyParm'{name = Name2, + propertyParms = PP2}) -> + validate(fun() -> chk_PkgdName(Name1, Name2) end, 'IndAudPropertyParm'), + validate(fun() -> chk_opt_PropertyParm(PP1, PP2) end, + 'IndAudPropertyParm'), + ok; +chk_IndAudPropertyParm(P1, P2) -> + wrong_type('IndAudPropertyParm', P1, P2). + + +%% -- IndAudLocalRemoteDescriptor -- + +is_opt_IndAudLocalRemoteDescriptor(asn1_NOVALUE) -> + true; +is_opt_IndAudLocalRemoteDescriptor(D) -> + is_IndAudLocalRemoteDescriptor(D). + +is_IndAudLocalRemoteDescriptor( + #'IndAudLocalRemoteDescriptor'{propGroupID = ID, + propGrps = Grps}) -> + is_IndAudLocalRemoteDescriptor_propGroupID(ID) andalso + is_IndAudPropertyGroup(Grps); +is_IndAudLocalRemoteDescriptor(_) -> + false. + +is_IndAudLocalRemoteDescriptor_propGroupID(asn1_NOVALUE) -> + true; +is_IndAudLocalRemoteDescriptor_propGroupID(V) -> + is_INTEGER(V, {range, 0, 65535}). + +chk_opt_IndAudLocalRemoteDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudLocalRemoteDescriptor(D1, D2) -> + chk_IndAudLocalRemoteDescriptor(D1, D2). + +chk_IndAudLocalRemoteDescriptor(D, D) -> + chk_type(fun is_IndAudLocalRemoteDescriptor/1, + 'IndAudLocalRemoteDescriptor', D); +chk_IndAudLocalRemoteDescriptor( + #'IndAudLocalRemoteDescriptor'{propGroupID = ID1, + propGrps = Grps1}, + #'IndAudLocalRemoteDescriptor'{propGroupID = ID2, + propGrps = Grps2}) -> + chk_IndAudLocalRemoteDescriptor_propGroupID(ID1, ID2), + chk_IndAudPropertyGroup(Grps1, Grps2), + ok; +chk_IndAudLocalRemoteDescriptor(D1, D2) -> + wrong_type('IndAudLocalRemoteDescriptor', D1, D2). + +chk_IndAudLocalRemoteDescriptor_propGroupID(ID, ID) -> + chk_type(fun is_IndAudLocalRemoteDescriptor_propGroupID/1, + 'IndAudLocalRemoteDescriptor_propGroupID', ID); +chk_IndAudLocalRemoteDescriptor_propGroupID(ID1, ID2) -> + case (is_IndAudLocalRemoteDescriptor_propGroupID(ID1) andalso + is_IndAudLocalRemoteDescriptor_propGroupID(ID2)) of + true -> + not_equal('IndAudLocalRemoteDescriptor_propGroupID', ID1, ID2); + false -> + wrong_type('IndAudLocalRemoteDescriptor_propGroupID', ID1, ID2) + end. + + +%% -- IndAudPropertyGroup -- + +is_IndAudPropertyGroup([]) -> + true; +is_IndAudPropertyGroup([H|T]) -> + is_IndAudPropertyParm(H) andalso is_IndAudPropertyGroup(T); +is_IndAudPropertyGroup(_) -> + false. + +chk_IndAudPropertyGroup([], []) -> + ok; +chk_IndAudPropertyGroup([] = PG1, PG2) -> + not_equal('IndAudPropertyGroup', PG1, PG2); +chk_IndAudPropertyGroup(PG1, [] = PG2) -> + not_equal('IndAudPropertyGroup', PG1, PG2); +chk_IndAudPropertyGroup([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_IndAudPropertyGroup(T1, T2); + false -> + wrong_type('IndAudPropertyGroup_val', H) + end; +chk_IndAudPropertyGroup([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, + 'IndAudPropertyGroup_val'), + chk_IndAudPropertyGroup(T1, T2); +chk_IndAudPropertyGroup(P1, P2) -> + wrong_type('IndAudPropertyGroup', P1, P2). + + +%% -- IndAudTerminationStateDescriptor -- + +is_opt_IndAudTerminationStateDescriptor(asn1_NOVALUE) -> + true; +is_opt_IndAudTerminationStateDescriptor(D) -> + is_IndAudTerminationStateDescriptor(D). + +is_IndAudTerminationStateDescriptor( + #'IndAudTerminationStateDescriptor'{propertyParms = Parms, + eventBufferControl = EBC, + serviceState = SS, + serviceStateSel = SSS}) -> + is_IndAudTerminationStateDescriptor_propertyParms(Parms) andalso + is_opt_NULL(EBC) andalso + is_opt_NULL(SS) andalso + is_opt_ServiceState(SSS); +is_IndAudTerminationStateDescriptor(_) -> + false. + +is_IndAudTerminationStateDescriptor_propertyParms([]) -> + true; +is_IndAudTerminationStateDescriptor_propertyParms([H|T]) -> + is_IndAudPropertyParm(H) andalso + is_IndAudTerminationStateDescriptor_propertyParms(T); +is_IndAudTerminationStateDescriptor_propertyParms(_) -> + false. + +chk_opt_IndAudTerminationStateDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudTerminationStateDescriptor(D1, D2) -> + chk_IndAudTerminationStateDescriptor(D1, D2). + +chk_IndAudTerminationStateDescriptor( + #'IndAudTerminationStateDescriptor'{propertyParms = Parms1, + eventBufferControl = EBC1, + serviceState = SS1, + serviceStateSel = SSS1}, + #'IndAudTerminationStateDescriptor'{propertyParms = Parms2, + eventBufferControl = EBC2, + serviceState = SS2, + serviceStateSel = SSS2}) -> + chk_IndAudTerminationStateDescriptor_propertyParms(Parms1, Parms2), + chk_IndAudTerminationStateDescriptor_eventBufferControl(EBC1, EBC2), + chk_IndAudTerminationStateDescriptor_serviceState(SS1, SS2), + chk_IndAudTerminationStateDescriptor_serviceStateSel(SSS1, SSS2), + ok; +chk_IndAudTerminationStateDescriptor(D1, D2) -> + wrong_type('IndAudTerminationStateDescriptor', D1, D2). + +chk_IndAudTerminationStateDescriptor_propertyParms([], []) -> + ok; +chk_IndAudTerminationStateDescriptor_propertyParms([] = PP1, PP2) -> + not_equal('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2); +chk_IndAudTerminationStateDescriptor_propertyParms(PP1, [] = PP2) -> + not_equal('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2); +chk_IndAudTerminationStateDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_IndAudPropertyParm(H) of + true -> + chk_IndAudTerminationStateDescriptor_propertyParms(T1, T2); + false -> + wrong_type('IndAudTerminationStateDescriptor_propertyParms', H) + end; +chk_IndAudTerminationStateDescriptor_propertyParms([H1|T1], [H2|T2]) -> + validate(fun() -> chk_IndAudPropertyParm(H1, H2) end, + 'IndAudTerminationStateDescriptor_propertyParms'), + chk_IndAudTerminationStateDescriptor_propertyParms(T1, T2); +chk_IndAudTerminationStateDescriptor_propertyParms(PP1, PP2) -> + wrong_type('IndAudTerminationStateDescriptor_propertyParms', PP1, PP2). + +chk_IndAudTerminationStateDescriptor_eventBufferControl(EBC1, EBC2) -> + validate(fun() -> chk_opt_NULL(EBC1, EBC2) end, + 'IndAudTerminationStateDescriptor_eventBufferControl'). + +chk_IndAudTerminationStateDescriptor_serviceState(SS1, SS2) -> + validate(fun() -> chk_opt_NULL(SS1, SS2) end, + 'IndAudTerminationStateDescriptor_serviceState'). + +chk_IndAudTerminationStateDescriptor_serviceStateSel(SSS1, SSS2) -> + validate(fun() -> chk_opt_ServiceState(SSS1, SSS2) end, + 'IndAudTerminationStateDescriptor_serviceStateSel'). + +%% -- IndAudEventsDescriptor -- + +is_IndAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID, + pkgdName = Name, + streamID = SID}) -> + is_opt_RequestID(RID) andalso + is_PkgdName(Name) andalso + is_opt_StreamID(SID); +is_IndAudEventsDescriptor(_) -> + false. + +chk_IndAudEventsDescriptor(#'IndAudEventsDescriptor'{requestID = RID1, + pkgdName = Name1, + streamID = SID1}, + #'IndAudEventsDescriptor'{requestID = RID2, + pkgdName = Name2, + streamID = SID2}) -> + chk_opt_RequestID(RID1, RID2), + chk_PkgdName(Name1, Name2), + chk_opt_StreamID(SID1, SID2), + ok; +chk_IndAudEventsDescriptor(D1, D2) -> + wrong_type('IndAudEventsDescriptor', D1, D2). + + +%% -- IndAudEventBufferDescriptor -- + +is_IndAudEventBufferDescriptor( + #'IndAudEventBufferDescriptor'{eventName = Name, + streamID = SID}) -> + is_PkgdName(Name) andalso is_opt_StreamID(SID); +is_IndAudEventBufferDescriptor(_) -> + false. + +chk_IndAudEventBufferDescriptor( + #'IndAudEventBufferDescriptor'{eventName = Name1, + streamID = SID1}, + #'IndAudEventBufferDescriptor'{eventName = Name2, + streamID = SID2}) -> + chk_PkgdName(Name1, Name2), + chk_opt_StreamID(SID1, SID2), + ok; +chk_IndAudEventBufferDescriptor(D1, D2) -> + wrong_type('IndAudEventBufferDescriptor', D1, D2). + + +%% -- IndAudSignalsDescriptor -- + +is_IndAudSignalsDescriptor({Tag, Val}) -> + is_IndAudSignalsDescriptor_tag(Tag) andalso + is_IndAudSignalsDescriptor_val(Tag, Val); +is_IndAudSignalsDescriptor(_) -> + false. + +is_IndAudSignalsDescriptor_tag(Tag) -> + Tags = [signal, seqSigList], + lists:member(Tag, Tags). + +is_IndAudSignalsDescriptor_val(signal, Val) -> + is_IndAudSignal(Val); +is_IndAudSignalsDescriptor_val(seqSigList, Val) -> + is_IndAudSeqSigList(Val). + +chk_IndAudSignalsDescriptor(D, D) -> + chk_type(fun is_IndAudSignalsDescriptor/1, 'IndAudSignalsDescriptor', D); +chk_IndAudSignalsDescriptor({Tag, Val1} = D1, {Tag, Val2} = D2) -> + case (is_IndAudSignalsDescriptor_tag(Tag) andalso + is_IndAudSignalsDescriptor_val(Tag, Val1) andalso + is_IndAudSignalsDescriptor_val(Tag, Val2)) of + true -> + chk_IndAudSignalsDescriptor_val(Tag, Val1, Val2); + false -> + wrong_type('IndAudSignalsDescriptor', D1, D2) + end; +chk_IndAudSignalsDescriptor({Tag1, Val1} = D1, {Tag2, Val2} = D2) -> + case ((is_IndAudSignalsDescriptor_tag(Tag1) andalso + is_IndAudSignalsDescriptor_val(Tag1, Val1)) andalso + (is_IndAudSignalsDescriptor_tag(Tag2) andalso + is_IndAudSignalsDescriptor_val(Tag2, Val2))) of + true -> + not_equal('IndAudSignalsDescriptor', D1, D2); + false -> + wrong_type('IndAudSignalsDescriptor', D1, D2) + end; +chk_IndAudSignalsDescriptor(D1, D2) -> + wrong_type('IndAudSignalsDescriptor', D1, D2). + +chk_IndAudSignalsDescriptor_val(signal, Val1, Val2) -> + chk_IndAudSignal(Val1, Val2); +chk_IndAudSignalsDescriptor_val(seqSigList, Val1, Val2) -> + chk_IndAudSeqSigList(Val1, Val2). + + +%% -- IndAudSeqSigList -- + +is_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID, + signalList = SL}) -> + is_IndAudSeqSigList_id(ID) andalso is_opt_IndAudSignal(SL); +is_IndAudSeqSigList(_) -> + false. + +is_IndAudSeqSigList_id(ID) -> is_INTEGER(ID, {range, 0, 65535}). + +chk_IndAudSeqSigList(L, L) -> + chk_type(fun is_IndAudSeqSigList/1, 'IndAudSeqSigList', L); +chk_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID1, + signalList = SL1}, + #'IndAudSeqSigList'{id = ID2, + signalList = SL2}) -> + chk_IndAudSeqSigList_id(ID1, ID2), + chk_opt_IndAudSignal(SL1, SL2), + ok; +chk_IndAudSeqSigList(L1, L2) -> + wrong_type('IndAudSeqSigList', L1, L2). + +chk_IndAudSeqSigList_id(ID, ID) -> + chk_type(fun is_IndAudSeqSigList_id/1, 'IndAudSeqSigList_id', ID); +chk_IndAudSeqSigList_id(ID1, ID2) -> + case (is_IndAudSeqSigList_id(ID1) andalso + is_IndAudSeqSigList_id(ID2)) of + true -> + not_equal('IndAudSeqSigList_id', ID1, ID2); + false -> + wrong_type('IndAudSeqSigList_id', ID1, ID2) + end. + + +%% -- IndAudSignal -- + +is_opt_IndAudSignal(asn1_NOVALUE) -> + true; +is_opt_IndAudSignal(V) -> + is_IndAudSignal(V). + +is_IndAudSignal(#'IndAudSignal'{signalName = Name, + streamID = SID, + signalRequestID = SRID}) -> + is_PkgdName(Name) andalso + is_opt_StreamID(SID) andalso + is_opt_RequestID(SRID); +is_IndAudSignal(_) -> + false. + +chk_opt_IndAudSignal(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_IndAudSignal(S1, S2) -> + chk_IndAudSignal(S1, S2). + +chk_IndAudSignal(S, S) -> + chk_type(fun is_IndAudSignal/1, 'IndAudSignal', S); +chk_IndAudSignal(#'IndAudSignal'{signalName = Name1, + streamID = SID1, + signalRequestID = SRID1}, + #'IndAudSignal'{signalName = Name2, + streamID = SID2, + signalRequestID = SRID2}) -> + validate(fun() -> chk_PkgdName(Name1, Name2) end, + 'IndAudSignal_signalName'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, + 'IndAudSignal_streamID'), + validate(fun() -> chk_opt_RequestID(SRID1, SRID2) end, + 'IndAudSignal_signalRequestID'), + ok; +chk_IndAudSignal(S1, S2) -> + wrong_type('IndAudSignal', S1, S2). + + +%% -- IndAudDigitMapDescriptor -- + +is_IndAudDigitMapDescriptor( + #'IndAudDigitMapDescriptor'{digitMapName = Name}) -> + is_opt_DigitMapName(Name); +is_IndAudDigitMapDescriptor(_) -> + false. + +chk_IndAudDigitMapDescriptor(D, D) -> + chk_type(fun is_IndAudDigitMapDescriptor/1, 'IndAudDigitMapDescriptor', D); +chk_IndAudDigitMapDescriptor( + #'IndAudDigitMapDescriptor'{digitMapName = Name1}, + #'IndAudDigitMapDescriptor'{digitMapName = Name2}) -> + validate(fun() -> chk_opt_DigitMapName(Name1, Name2) end, + 'IndAudDigitMapDescriptor'), + ok; +chk_IndAudDigitMapDescriptor(D1, D2) -> + wrong_type('IndAudDigitMapDescriptor', D1, D2). + + +%% -- IndAudStatisticsDescriptor -- + +is_IndAudStatisticsDescriptor( + #'IndAudStatisticsDescriptor'{statName = Name}) -> + is_PkgdName(Name); +is_IndAudStatisticsDescriptor(_) -> + false. + +chk_IndAudStatisticsDescriptor(D, D) -> + chk_type(fun is_IndAudStatisticsDescriptor/1, + 'IndAudStatisticsDescriptor', D); +chk_IndAudStatisticsDescriptor( + #'IndAudStatisticsDescriptor'{statName = Name1}, + #'IndAudStatisticsDescriptor'{statName = Name2}) -> + validate(fun() -> chk_PkgdName(Name1, Name2) end, + 'IndAudStatisticsDescriptor'), + ok; +chk_IndAudStatisticsDescriptor(D1, D2) -> + wrong_type('IndAudStatisticsDescriptor', D1, D2). + + +%% -- IndAudPackagesDescriptor -- + +is_IndAudPackagesDescriptor( + #'IndAudPackagesDescriptor'{packageName = Name, + packageVersion = Ver}) -> + is_Name(Name) andalso is_IndAudPackagesDescriptor_packageVersion(Ver); +is_IndAudPackagesDescriptor(_) -> + false. + +is_IndAudPackagesDescriptor_packageVersion(V) -> + is_INTEGER(V, {range, 0, 99}). + +chk_IndAudPackagesDescriptor( + #'IndAudPackagesDescriptor'{packageName = Name1, + packageVersion = Ver1}, + #'IndAudPackagesDescriptor'{packageName = Name2, + packageVersion = Ver2}) -> + validate(fun() -> chk_Name(Name1, Name2) end, 'IndAudPackagesDescriptor'), + chk_IndAudPackagesDescriptor_packageVersion(Ver1, Ver2), + ok; +chk_IndAudPackagesDescriptor(D1, D2) -> + wrong_type('IndAudPackagesDescriptor', D1, D2). + +chk_IndAudPackagesDescriptor_packageVersion(V, V) -> + chk_type(fun is_IndAudPackagesDescriptor_packageVersion/1, + 'IndAudPackagesDescriptor_packageVersion', V); +chk_IndAudPackagesDescriptor_packageVersion(V1, V2) -> + case (is_IndAudPackagesDescriptor_packageVersion(V1) andalso + is_IndAudPackagesDescriptor_packageVersion(V2)) of + true -> + not_equal('IndAudPackagesDescriptor_packageVersion', V1, V2); + false -> + wrong_type('IndAudPackagesDescriptor_packageVersion', V1, V2) + end. + + +%% -- NotifyRequest -- + +is_NotifyRequest(#'NotifyRequest'{terminationID = Tids, + observedEventsDescriptor = OED, + errorDescriptor = ED}) -> + is_TerminationIDList(Tids) andalso + is_ObservedEventsDescriptor(OED) andalso + is_opt_ErrorDescriptor(ED); +is_NotifyRequest(_) -> + false. + +chk_NotifyRequest(#'NotifyRequest'{terminationID = Tids1, + observedEventsDescriptor = OED1, + errorDescriptor = ED1}, + #'NotifyRequest'{terminationID = Tids2, + observedEventsDescriptor = OED2, + errorDescriptor = ED2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'NotifyRequest'), + validate(fun() -> chk_ObservedEventsDescriptor(OED1, OED2) end, + 'NotifyRequest'), + validate(fun() -> chk_opt_ErrorDescriptor(ED1, ED2) end, + 'NotifyRequest'), + ok; +chk_NotifyRequest(NR1, NR2) -> + wrong_type('NotifyRequest', NR1, NR2). + + +%% -- NotifyReply -- + +is_NotifyReply(#'NotifyReply'{terminationID = Tids, + errorDescriptor = ED}) -> + is_TerminationIDList(Tids) andalso is_opt_ErrorDescriptor(ED); +is_NotifyReply(_) -> + false. + +chk_NotifyReply(#'NotifyReply'{terminationID = Tids1, + errorDescriptor = ED1}, + #'NotifyReply'{terminationID = Tids2, + errorDescriptor = ED2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, 'NotifyReply'), + validate(fun() -> chk_opt_ErrorDescriptor(ED1, ED2) end, 'NotifyReply'), + ok; +chk_NotifyReply(NR1, NR2) -> + wrong_type('NotifyReply', NR1, NR2). + + +%% -- ObservedEventsDescriptor -- + +is_ObservedEventsDescriptor( + #'ObservedEventsDescriptor'{requestId = RID, + observedEventLst = OEL}) -> + is_RequestID(RID) andalso + is_ObservedEventsDescriptor_observedEventLst(OEL); +is_ObservedEventsDescriptor(_) -> + false. + +is_ObservedEventsDescriptor_observedEventLst([]) -> + true; +is_ObservedEventsDescriptor_observedEventLst([H|T]) -> + is_ObservedEvent(H) andalso + is_ObservedEventsDescriptor_observedEventLst(T); +is_ObservedEventsDescriptor_observedEventLst(_) -> + false. + +chk_ObservedEventsDescriptor( + #'ObservedEventsDescriptor'{requestId = RID1, + observedEventLst = OEL1}, + #'ObservedEventsDescriptor'{requestId = RID2, + observedEventLst = OEL2}) -> + validate(fun() -> chk_RequestID(RID1, RID2) end, + 'ObservedEventsDescriptor'), + validate( + fun() -> + chk_ObservedEventsDescriptor_observedEventLst(OEL1, OEL2) + end, + 'ObservedEventsDescriptor'), + ok; +chk_ObservedEventsDescriptor(D1, D2) -> + wrong_type('ObservedEventsDescriptor', D1, D2). + +chk_ObservedEventsDescriptor_observedEventLst([], []) -> + ok; +chk_ObservedEventsDescriptor_observedEventLst([] = L1, L2) -> + not_equal('ObservedEventsDescriptor_observedEventLst', L1, L2); +chk_ObservedEventsDescriptor_observedEventLst(L1, [] = L2) -> + not_equal('ObservedEventsDescriptor_observedEventLst', L1, L2); +chk_ObservedEventsDescriptor_observedEventLst([H|T1], [H|T2]) -> + case is_ObservedEvent(H) of + true -> + chk_ObservedEventsDescriptor_observedEventLst(T1, T2); + false -> + wrong_type('ObservedEventsDescriptor_observedEventLst_val', H) + end; +chk_ObservedEventsDescriptor_observedEventLst([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ObservedEvent(H1, H2) end, + 'ObservedEventsDescriptor_observedEventLst_val'), + chk_ObservedEventsDescriptor_observedEventLst(T1, T2); +chk_ObservedEventsDescriptor_observedEventLst(L1, L2) -> + wrong_type('ObservedEventsDescriptor_observedEventLst', L1, L2). + + +%% -- ObservedEvent -- + +is_ObservedEvent(#'ObservedEvent'{eventName = Name, + streamID = SID, + eventParList = EPL, + timeNotation = TN}) -> + is_EventName(Name) andalso + is_opt_StreamID(SID) andalso + is_ObservedEvent_eventParList(EPL) andalso + is_opt_TimeNotation(TN); +is_ObservedEvent(_) -> + false. + +is_ObservedEvent_eventParList([]) -> + true; +is_ObservedEvent_eventParList([H|T]) -> + is_EventParameter(H) andalso is_ObservedEvent_eventParList(T); +is_ObservedEvent_eventParList(_) -> + false. + +chk_ObservedEvent(E, E) -> + chk_type(fun is_ObservedEvent/1, 'ObservedEvent', E); +chk_ObservedEvent(#'ObservedEvent'{eventName = Name1, + streamID = SID1, + eventParList = EPL1, + timeNotation = TN1}, + #'ObservedEvent'{eventName = Name2, + streamID = SID2, + eventParList = EPL2, + timeNotation = TN2}) -> + validate(fun() -> chk_EventName(Name1, Name2) end, 'ObservedEvent'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'ObservedEvent'), + chk_ObservedEvent_eventParList(EPL1, EPL2), + validate(fun() -> chk_opt_TimeNotation(TN1, TN2) end, 'ObservedEvent'), + ok; +chk_ObservedEvent(E1, E2) -> + wrong_type('ObservedEvent', E1, E2). + +chk_ObservedEvent_eventParList([], []) -> + ok; +chk_ObservedEvent_eventParList([] = EPL1, EPL2) -> + not_equal('ObservedEvent_eventParList', EPL1, EPL2); +chk_ObservedEvent_eventParList(EPL1, [] = EPL2) -> + not_equal('ObservedEvent_eventParList', EPL1, EPL2); +chk_ObservedEvent_eventParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_ObservedEvent_eventParList(T1, T2); + false -> + wrong_type('ObservedEvent_eventParList_val', H) + end; +chk_ObservedEvent_eventParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'ObservedEvent_eventParList'), + chk_ObservedEvent_eventParList(T1, T2); +chk_ObservedEvent_eventParList(L1, L2) -> + wrong_type('ObservedEvent_eventParList', L1, L2). + + +%% -- EventName -- + +is_EventName(N) -> is_PkgdName(N). + +chk_EventName(N, N) -> + chk_type(fun is_EventName/1, 'EventName', N); +chk_EventName(N1, N2) -> + case (is_EventName(N1) andalso is_EventName(N2)) of + true -> + not_equal('EventName', N1, N2); + false -> + wrong_type('EventName', N1, N2) + end. + + +%% -- EventParameter -- + +is_EventParameter(#'EventParameter'{eventParameterName = Name, + value = Val, + extraInfo = EI}) -> + d("is_EventParameter -> entery with" + "~n Name: ~p" + "~n Val: ~p" + "~n EI: ~p", [Name, Val, EI]), + is_Name(Name) andalso + is_Value(Val) andalso + is_EventParameter_extraInfo(EI); +is_EventParameter(_) -> + false. + +is_EventParameter_extraInfo(asn1_NOVALUE) -> + true; +is_EventParameter_extraInfo({Tag, Val}) -> + is_EventParameter_extraInfo_tag(Tag) andalso + is_EventParameter_extraInfo_val(Tag, Val); +is_EventParameter_extraInfo(_) -> + false. + +is_EventParameter_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_EventParameter_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_EventParameter_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_EventParameter_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + +chk_EventParameter(#'EventParameter'{eventParameterName = Name1, + value = Val1, + extraInfo = EI1}, + #'EventParameter'{eventParameterName = Name2, + value = Val2, + extraInfo = EI2}) -> + validate(fun() -> chk_Name(Name1, Name2) end, 'EventParameter'), + validate(fun() -> chk_Value(Val1, Val2) end, 'EventParameter'), + chk_EventParameter_extraInfo(EI1, EI2), + ok; +chk_EventParameter(P1, P2) -> + wrong_type('EventParameter', P1, P2). + +chk_EventParameter_extraInfo(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_EventParameter_extraInfo(EI, EI) -> + chk_type(fun is_EventParameter_extraInfo/1, + 'EventParameter_extraInfo', EI); +chk_EventParameter_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> + case (is_EventParameter_extraInfo_tag(Tag) andalso + is_EventParameter_extraInfo_val(Tag, Val1) andalso + is_EventParameter_extraInfo_val(Tag, Val2)) of + true -> + chk_EventParameter_extraInfo_val(Tag, Val1, Val2); + false -> + wrong_type('EventParameter_extraInfo', EI1, EI2) + end; +chk_EventParameter_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> + case ((is_EventParameter_extraInfo_tag(Tag1) andalso + is_EventParameter_extraInfo_val(Tag1, Val1)) andalso + (is_EventParameter_extraInfo_tag(Tag2) andalso + is_EventParameter_extraInfo_val(Tag2, Val2))) of + true -> + not_equal('EventParameter_extraInfo', EI1, EI2); + false -> + wrong_type('EventParameter_extraInfo', EI1, EI2) + end; +chk_EventParameter_extraInfo(EI1, EI2) -> + wrong_type('EventParameter_extraInfo', EI1, EI2). + +chk_EventParameter_extraInfo_val(relation, Val1, Val2) -> + validate(fun() -> chk_Relation(Val1, Val2) end, + 'EventParameter_extraInfo_val'); +chk_EventParameter_extraInfo_val(range, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, + 'EventParameter_extraInfo_val'); +chk_EventParameter_extraInfo_val(sublist, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, + 'EventParameter_extraInfo_val'). + + +%% -- ServiceChangeRequest -- + +is_ServiceChangeRequest(#'ServiceChangeRequest'{terminationID = Tids, + serviceChangeParms = Parms}) -> + is_TerminationIDList(Tids) andalso is_ServiceChangeParm(Parms); +is_ServiceChangeRequest(_) -> + false. + +chk_ServiceChangeRequest(R, R) -> + chk_type(fun is_ServiceChangeRequest/1, 'ServiceChangeRequest', R); +chk_ServiceChangeRequest( + #'ServiceChangeRequest'{terminationID = Tids1, + serviceChangeParms = Parms1}, + #'ServiceChangeRequest'{terminationID = Tids2, + serviceChangeParms = Parms2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'ServiceChangeRequest'), + validate(fun() -> chk_ServiceChangeParm(Parms1, Parms2) end, + 'ServiceChangeRequest'), + ok; +chk_ServiceChangeRequest(R1, R2) -> + wrong_type('ServiceChangeRequest', R1, R2). + + +%% -- ServiceChangeReply -- + +is_ServiceChangeReply(#'ServiceChangeReply'{terminationID = Tids, + serviceChangeResult = Res}) -> + is_TerminationIDList(Tids) andalso is_ServiceChangeResult(Res); +is_ServiceChangeReply(_) -> + false. + +chk_ServiceChangeReply(R, R) -> + chk_type(fun is_ServiceChangeReply/1, 'ServiceChangeReply', R); +chk_ServiceChangeReply( + #'ServiceChangeReply'{terminationID = Tids1, + serviceChangeResult = Res1}, + #'ServiceChangeReply'{terminationID = Tids2, + serviceChangeResult = Res2}) -> + validate(fun() -> chk_TerminationIDList(Tids1, Tids2) end, + 'ServiceChangeReply'), + validate(fun() -> chk_ServiceChangeResult(Res1, Res2) end, + 'ServiceChangeReply'), + ok; +chk_ServiceChangeReply(R1, R2) -> + wrong_type('ServiceChangeReply', R1, R2). + + +%% -- ServiceChangeResult -- + +is_ServiceChangeResult({Tag, Val}) -> + is_ServiceChangeResult_tag(Tag) andalso + is_ServiceChangeResult_val(Tag, Val); +is_ServiceChangeResult(_) -> + false. + +is_ServiceChangeResult_tag(Tag) -> + Tags = [errorDescriptor, serviceChangeResParms], + lists:member(Tag, Tags). + +is_ServiceChangeResult_val(errorDescriptor, Val) -> + is_ErrorDescriptor(Val); +is_ServiceChangeResult_val(serviceChangeResParms, Val) -> + is_ServiceChangeResParm(Val). + +chk_ServiceChangeResult(Res, Res) -> + chk_type(fun is_ServiceChangeResult/1, 'ServiceChangeResult', Res); +chk_ServiceChangeResult({Tag, Val1} = Res1, {Tag, Val2} = Res2) -> + case (is_ServiceChangeResult_tag(Tag) andalso + is_ServiceChangeResult_val(Tag, Val1) andalso + is_ServiceChangeResult_val(Tag, Val2)) of + true -> + chk_ServiceChangeResult_val(Tag, Val1, Val2); + false -> + wrong_type('ServiceChangeResult', Res1, Res2) + end; +chk_ServiceChangeResult({Tag1, Val1} = Res1, {Tag2, Val2} = Res2) -> + case ((is_ServiceChangeResult_tag(Tag1) andalso + is_ServiceChangeResult_val(Tag1, Val1)) andalso + (is_ServiceChangeResult_tag(Tag2) andalso + is_ServiceChangeResult_val(Tag2, Val2))) of + true -> + not_equal('ServiceChangeResult', Res1, Res2); + false -> + wrong_type('ServiceChangeResult', Res1, Res2) + end; +chk_ServiceChangeResult(Res1, Res2) -> + wrong_type('ServiceChangeResult', Res1, Res2). + +chk_ServiceChangeResult_val(errorDescriptor, Val1, Val2) -> + validate(fun() -> chk_ErrorDescriptor(Val1, Val2) end, + 'ServiceChangeResult'); +chk_ServiceChangeResult_val(serviceChangeResParms, Val1, Val2) -> + validate(fun() -> chk_ServiceChangeResParm(Val1, Val2) end, + 'ServiceChangeResult'). + + +%% -- WildcardField -- + +is_WildcardField(WF) -> is_OCTET_STRING(WF, {exact, 1}). + +chk_WildcardField(WF, WF) -> + case is_WildcardField(WF) of + true -> + ok; + false -> + wrong_type('WildcardField', WF) + end; +chk_WildcardField(WF1, WF2) -> + case (is_WildcardField(WF1) andalso is_WildcardField(WF2)) of + true -> + not_equal('WildcardField', WF1, WF2); + false -> + wrong_type('WildcardField', WF1, WF2) + end. + + +%% -- TerminationID -- + +is_TerminationID(#'TerminationID'{wildcard = W, + id = ID}) -> + is_TerminationID_wildcard(W) andalso is_TerminationID_id(ID); +is_TerminationID(#megaco_term_id{contains_wildcards = _W, + id = _ID}) -> + true; % What are the types? +is_TerminationID(_) -> + false. + +is_TerminationID_wildcard([]) -> + true; +is_TerminationID_wildcard([H|T]) -> + is_WildcardField(H) andalso is_TerminationID_wildcard(T); +is_TerminationID_wildcard(_) -> + false. + +is_TerminationID_id(ID) -> is_OCTET_STRING(ID, {range, 1, 8}). + +chk_TerminationID(Id,Id) -> + d("chk_TerminationID(1) -> entry with" + "~n Id: ~p", [Id]), + chk_type(fun is_TerminationID/1, 'TerminationID', Id); +chk_TerminationID(#'TerminationID'{wildcard = W1, + id = I1}, + #'TerminationID'{wildcard = W2, + id = I2}) -> + d("chk_TerminationID(2) -> entry with" + "~n W1: ~p" + "~n W2: ~p" + "~n I1: ~p" + "~n I2: ~p", [W1, W2, I1, I2]), + chk_TerminationID_wildcard(W1, W2), + chk_TerminationID_id(I1, I2), + ok; +chk_TerminationID(#megaco_term_id{contains_wildcards = W1, + id = I1}, + #megaco_term_id{contains_wildcards = W2, + id = I2}) -> + d("chk_TerminationID(3) -> entry with" + "~n W1: ~p" + "~n W2: ~p" + "~n I1: ~p" + "~n I2: ~p", [W1, W2, I1, I2]), + validate(fun() -> chk_BOOLEAN(W1, W2) end, 'TerminationID_wildcard'), + chk_TerminationID_id(I1, I2), + ok; +chk_TerminationID(Tid1, Tid2) -> + d("chk_TerminationID(4) -> entry with" + "~n Tid1: ~p" + "~n Tid2: ~p", [Tid1, Tid2]), + wrong_type('TerminationID', Tid1, Tid2). + +chk_TerminationID_wildcard([], []) -> + ok; +chk_TerminationID_wildcard([] = WF1, WF2) -> + not_equal('TerminationID_wildcard', WF1, WF2); +chk_TerminationID_wildcard(WF1, [] = WF2) -> + not_equal('TerminationID_wildcard', WF1, WF2); +chk_TerminationID_wildcard([H|T1], [H|T2]) -> + case is_WildcardField(H) of + true -> + chk_TerminationID_wildcard(T1, T2); + false -> + wrong_type('TerminationID_wildcard_val', H) + end; +chk_TerminationID_wildcard([H1|T1], [H2|T2]) -> + validate(fun() -> chk_WildcardField(H1, H2) end, + 'TerminationID_wildcard_val'), + chk_TerminationID_wildcard(T1, T2); +chk_TerminationID_wildcard(WF1,WF2) -> + not_equal('TerminationId_wildcard', WF1, WF2). + +chk_TerminationID_id(Id, Id) -> + case is_OCTET_STRING(Id, {range, 1, 8}) of + true -> + ok; + false -> + wrong_type('TerminationID_id', Id, Id) + end; +chk_TerminationID_id(Id1, Id2) -> + Id12 = flatten_TerminationID_id(Id1, []), + Id22 = flatten_TerminationID_id(Id2, []), + case Id12 == Id22 of + true -> + ok; + false -> + not_equal(terminationId_id, Id1, Id2) + end. + +flatten_TerminationID_id([], Acc) -> + lists:flatten(lists:reverse(Acc)); +flatten_TerminationID_id([H|T], Acc) -> + flatten_TerminationID_id(T, [string:tokens(H, [$/])|Acc]). + +%% -- TerminationIDList -- + +%% is_opt_TerminationIDList(asn1_NOVALUE) -> +%% true; +%% is_opt_TerminationIDList(TIDs) -> +%% is_TerminationIDList(TIDs). + +is_TerminationIDList([]) -> + true; +is_TerminationIDList([H|T]) -> + is_TerminationID(H) andalso is_TerminationIDList(T); +is_TerminationIDList(_) -> + false. + +chk_opt_TerminationIDList(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_TerminationIDList(TIDs1, TIDs2) -> + chk_TerminationIDList(TIDs1, TIDs2). + +chk_TerminationIDList([], []) -> + ok; +chk_TerminationIDList([] = L1, L2) -> + not_equal('TerminationIDList', L1, L2); +chk_TerminationIDList(L1, [] = L2) -> + not_equal('TerminationIDList', L1, L2); +chk_TerminationIDList([H|T1], [H|T2]) -> + case is_TerminationID(H) of + true -> + chk_TerminationIDList(T1, T2); + false -> + wrong_type('TerminationIDList', H) + end; +chk_TerminationIDList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TerminationID(H1, H2) end, 'TerminationIDList'), + chk_TerminationIDList(T1, T2); +chk_TerminationIDList(L1, L2) -> + wrong_type('TerminationIDList', L1, L2). + + +%% -- MediaDescriptor -- + +is_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TSD, + streams = S}) -> + d("is_MediaDescriptor -> entry with" + "~n TSD: ~p" + "~n S: ~p", [TSD, S]), + is_opt_TerminationStateDescriptor(TSD) andalso + is_MediaDescriptor_streams(S); +is_MediaDescriptor(_) -> + false. + +is_MediaDescriptor_streams(asn1_NOVALUE) -> + true; +is_MediaDescriptor_streams({Tag, Val}) -> + is_MediaDescriptor_streams_tag(Tag) andalso + is_MediaDescriptor_streams_val(Tag, Val); +is_MediaDescriptor_streams(_) -> + false. + +is_MediaDescriptor_streams_tag(Tag) -> + Tags = [oneStream, multiStream], + lists:member(Tag, Tags). + +is_MediaDescriptor_streams_val(oneStream, SP) -> + is_StreamParms(SP); +is_MediaDescriptor_streams_val(multiStream, SDL) -> + is_MediaDescriptor_multiStream(SDL). + +is_MediaDescriptor_multiStream([]) -> + true; +is_MediaDescriptor_multiStream([H|T]) -> + is_StreamDescriptor(H) andalso is_MediaDescriptor_multiStream(T); +is_MediaDescriptor_multiStream(_) -> + false. + +chk_MediaDescriptor(D, D) -> + chk_type(fun is_MediaDescriptor/1, 'MediaDescriptor', D); +chk_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TSD1, + streams = S1}, + #'MediaDescriptor'{termStateDescr = TSD2, + streams = S2}) -> + validate( + fun() -> + chk_opt_TerminationStateDescriptor(TSD1, TSD2) + end, + 'MediaDescriptor'), + validate( + fun() -> + chk_MediaDescriptor_streams(S1, S2) + end, + 'MediaDescriptor'), + ok; +chk_MediaDescriptor(D1, D2) -> + wrong_type('MediaDescriptor', D1, D2). + + +chk_MediaDescriptor_streams(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_MediaDescriptor_streams({oneStream, SP1}, {oneStream, SP2}) -> + validate(fun() -> + chk_StreamParms(SP1, SP2) + end, + 'MediaDescriptor_streams'); +chk_MediaDescriptor_streams({multiStream, SDs1}, {multiStream, SDs2}) -> + validate(fun() -> + chk_MediaDescriptor_multiStream(SDs1, SDs2) + end, + 'MediaDescriptor_streams'); +chk_MediaDescriptor_streams(S1, S2) -> + wrong_type('MediaDescriptor_streams', S1, S2). + +chk_MediaDescriptor_multiStream([], []) -> + ok; +chk_MediaDescriptor_multiStream([] = MS1, MS2) -> + not_equal('MediaDescriptor_multiStream', MS1, MS2); +chk_MediaDescriptor_multiStream(MS1, [] = MS2) -> + not_equal('MediaDescriptor_multiStream', MS1, MS2); +chk_MediaDescriptor_multiStream([H|T1], [H|T2]) -> + case is_StreamDescriptor(H) of + true -> + chk_MediaDescriptor_multiStream(T1, T2); + false -> + wrong_type('MediaDescriptor_multiStream_val', H) + end; +chk_MediaDescriptor_multiStream([H1|T1], [H2|T2]) -> + validate(fun() -> chk_StreamDescriptor(H1, H2) end, + 'MediaDescriptor_multiStream_val'), + chk_MediaDescriptor_multiStream(T1, T2); +chk_MediaDescriptor_multiStream(MS1, MS2) -> + wrong_type('MediaDescriptor_multiStream_val', MS1, MS2). + + +%% -- StreamDescriptor -- + +is_StreamDescriptor(#'StreamDescriptor'{streamID = SID, + streamParms = Parms}) -> + d("is_StreamDescriptor -> entry with" + "~n SID: ~p" + "~n Parms: ~p", [SID, Parms]), + is_StreamID(SID) andalso is_StreamParms(Parms); +is_StreamDescriptor(X) -> + d("is_StreamDescriptor -> entry when ERROR with" + "~n X: ~p", [X]), + false. + +chk_StreamDescriptor(D, D) -> + chk_type(fun is_StreamDescriptor/1, 'StreamDescriptor', D); +chk_StreamDescriptor(#'StreamDescriptor'{streamID = SID1, + streamParms = Parms1}, + #'StreamDescriptor'{streamID = SID2, + streamParms = Parms2}) -> + validate(fun() -> chk_StreamID(SID1, SID2) end, 'StreamDescriptor'), + validate(fun() -> chk_StreamParms(Parms1, Parms2) end, 'StreamDescriptor'), + ok; +chk_StreamDescriptor(D1, D2) -> + wrong_type('StreamDescriptor', D1, D2). + + +%% -- StreamParms -- + +is_StreamParms(#'StreamParms'{localControlDescriptor = LCD, + localDescriptor = LD, + remoteDescriptor = RD, + statisticsDescriptor = SD}) -> + d("is_StreamParms -> entry with" + "~n LCD: ~p" + "~n LD: ~p" + "~n RD: ~p" + "~n SD: ~p", [LCD, LD, RD, SD]), + is_opt_LocalControlDescriptor(LCD) andalso + is_opt_LocalRemoteDescriptor(LD) andalso + is_opt_LocalRemoteDescriptor(RD) andalso + is_opt_StatisticsDescriptor(SD); +is_StreamParms(X) -> + d("is_StreamParms -> entry when ERROR with" + "~n X: ~p", [X]), + false. + +chk_StreamParms(SP, SP) -> + chk_type(fun is_StreamParms/1, 'StreamParms', SP); +chk_StreamParms(#'StreamParms'{localControlDescriptor = LCD1, + localDescriptor = LD1, + remoteDescriptor = RD1, + statisticsDescriptor = SD1}, + #'StreamParms'{localControlDescriptor = LCD2, + localDescriptor = LD2, + remoteDescriptor = RD2, + statisticsDescriptor = SD2}) -> + validate(fun() -> chk_opt_LocalControlDescriptor(LCD1, LCD2) end, + 'StreamParms_localControlDescriptor'), + validate(fun() -> chk_opt_LocalRemoteDescriptor(LD1, LD2) end, + 'StreamParms_localDescriptor'), + validate(fun() -> chk_opt_LocalRemoteDescriptor(RD1, RD2) end, + 'StreamParms_remoteDescriptor'), + validate(fun() -> chk_opt_StatisticsDescriptor(SD1, SD2) end, + 'StreamParms_statisticsDescriptor'), + ok; +chk_StreamParms(P1, P2) -> + wrong_type('StreamParms', P1, P2). + + +%% -- LocalControlDescriptor -- + +is_opt_LocalControlDescriptor(D) -> + d("is_opt_LocalControlDescriptor -> entry"), + is_OPTIONAL(fun is_LocalControlDescriptor/1, D). + +is_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = SM, + reserveValue = RV, + reserveGroup = RG, + propertyParms = PP}) -> + d("is_LocalControlDescriptor -> entry with" + "~n SM: ~p" + "~n RV: ~p" + "~n RG: ~p" + "~n PP: ~p", [SM, RV, RG, PP]), + is_opt_StreamMode(SM) andalso + is_opt_BOOLEAN(RV) andalso + is_opt_BOOLEAN(RG) andalso + is_LocalControlDescriptor_propertyParms(PP); +is_LocalControlDescriptor(_) -> + false. + +is_LocalControlDescriptor_propertyParms([]) -> + d("is_LocalControlDescriptor_propertyParms -> entry when done"), + true; +is_LocalControlDescriptor_propertyParms([H|T]) -> + d("is_LocalControlDescriptor_propertyParms -> entry with" + "~n H: ~p" + "~n T: ~p", [H, T]), + is_PropertyParm(H) andalso is_LocalControlDescriptor_propertyParms(T); +is_LocalControlDescriptor_propertyParms(_) -> + false. + +chk_opt_LocalControlDescriptor(LCD1, LCD2) -> + chk_OPTIONAL('LocalControlDescriptor', LCD1, LCD2, + fun is_LocalControlDescriptor/1, + fun chk_LocalControlDescriptor/2). + +chk_LocalControlDescriptor(LCD, LCD) -> + chk_type(fun is_LocalControlDescriptor/1, 'LocalControlDescriptor', LCD); +chk_LocalControlDescriptor(#'LocalControlDescriptor'{streamMode = SM1, + reserveValue = RV1, + reserveGroup = RG1, + propertyParms = PP1}, + #'LocalControlDescriptor'{streamMode = SM2, + reserveValue = RV2, + reserveGroup = RG2, + propertyParms = PP2}) -> + validate( + fun() -> chk_opt_StreamMode(SM1, SM2) end, + 'LocalControlDescriptor'), + validate( + fun() -> chk_opt_BOOLEAN(RV1, RV2) end, + 'LocalControlDescriptor_reserveValue'), + validate( + fun() -> chk_opt_BOOLEAN(RG1, RG2) end, + 'LocalControlDescriptor_reserveGroup'), + chk_LocalControlDescriptor_propertyParms(PP1, PP2), + ok; +chk_LocalControlDescriptor(LCD1, LCD2) -> + wrong_type('LocalControlDescriptor', LCD1, LCD2). + + +chk_LocalControlDescriptor_propertyParms([], []) -> + ok; +chk_LocalControlDescriptor_propertyParms([] = PP1, PP2) -> + not_equal('LocalControlDescriptor_propertyParms', PP1, PP2); +chk_LocalControlDescriptor_propertyParms(PP1, [] = PP2) -> + not_equal('LocalControlDescriptor_propertyParms', PP1, PP2); +chk_LocalControlDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_LocalControlDescriptor_propertyParms(T1, T2); + false -> + wrong_type('LocalControlDescriptor_propertyParms_val', H) + end; +chk_LocalControlDescriptor_propertyParms([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, + 'LocalControlDescriptor_propertyParms_val'), + chk_LocalControlDescriptor_propertyParms(T1, T2); +chk_LocalControlDescriptor_propertyParms(PP1, PP2) -> + wrong_type('LocalControlDescriptor_propertyParms', PP1, PP2). + + +%% -- StreamMode -- + +is_opt_StreamMode(asn1_NOVALUE) -> + true; +is_opt_StreamMode(SM) -> + is_StreamMode(SM). + +is_StreamMode(SM) -> + lists:member(SM, [sendOnly, recvOnly, sendRecv, inactive, loopBack]). + +chk_opt_StreamMode(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_StreamMode(SM1, SM2) -> + chk_StreamMode(SM1, SM2). + +chk_StreamMode(SM, SM) -> + chk_type(fun is_StreamMode/1, 'StreamMode', SM); +chk_StreamMode(SM1, SM2) -> + case (is_StreamMode(SM1) andalso is_StreamMode(SM2)) of + true -> + not_equal('StreamMode', SM1, SM2); + false -> + wrong_type('StreamMode', SM1, SM2) + end. + + +%% -- PropertyParm -- + +is_opt_PropertyParm(asn1_NOVALUE) -> + true; +is_opt_PropertyParm(PP) -> + is_PropertyParm(PP). + +is_PropertyParm(#'PropertyParm'{name = N, + value = V, + extraInfo = I}) -> + d("is_PropertyParm -> entry with" + "~n N: ~p" + "~n V: ~p" + "~n I: ~p", [N, V, I]), + is_PkgdName(N) andalso + is_PropertyParm_value(V) andalso + is_PropertyParm_extraInfo(I); +is_PropertyParm(_) -> + false. + +is_PropertyParm_value([]) -> + d("is_PropertyParm_value -> entry when done"), + true; +is_PropertyParm_value([H|T]) -> + d("is_PropertyParm_value -> entry with" + "~n H: ~p", [H]), + is_OCTET_STRING(H) andalso is_PropertyParm_value(T); +is_PropertyParm_value(_) -> + false. + +is_PropertyParm_extraInfo(asn1_NOVALUE) -> + true; +is_PropertyParm_extraInfo({Tag, Val}) -> + d("is_PropertyParm_extraInfo -> entry with" + "~n Tag: ~p" + "~n Val: ~p", [Tag, Val]), + is_PropertyParm_extraInfo_tag(Tag) andalso + is_PropertyParm_extraInfo_val(Tag, Val); +is_PropertyParm_extraInfo(_) -> + false. + +is_PropertyParm_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_PropertyParm_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_PropertyParm_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_PropertyParm_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + + +chk_opt_PropertyParm(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_PropertyParm(P1, P2) -> + chk_PropertyParm(P1, P2). + +chk_PropertyParm(P, P) -> + chk_type(fun is_PropertyParm/1, 'PropertyParm', P); +chk_PropertyParm(#'PropertyParm'{name = N1, + value = V1, + extraInfo = I1}, + #'PropertyParm'{name = N2, + value = V2, + extraInfo = I2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'PropertyParm'), + chk_PropertyParm_value(V1, V2), + chk_PropertyParm_extraInfo(I1, I2), + ok; +chk_PropertyParm(P1, P2) -> + wrong_type('PropertyParm', P1, P2). + +chk_PropertyParm_value([], []) -> + ok; +chk_PropertyParm_value([] = V1, V2) -> + not_equal('PropertyParm_value', V1, V2); +chk_PropertyParm_value(V1, [] = V2) -> + not_equal('PropertyParm_value', V1, V2); +chk_PropertyParm_value([H|T1], [H|T2]) -> + case is_OCTET_STRING(H) of + true -> + chk_PropertyParm_value(T1, T2); + false -> + wrong_type('PropertyParm_value_val', H) + end; +chk_PropertyParm_value([H1|_], [H2|_]) -> + case (is_OCTET_STRING(H1) andalso is_OCTET_STRING(H2)) of + true -> + not_equal('PropertyParm_value_val', H1, H2); + false -> + wrong_type('PropertyParm_value_val', H1, H2) + end; +chk_PropertyParm_value(V1, V2) -> + wrong_type('PropertyParm_value', V1, V2). + +chk_PropertyParm_extraInfo(EI, EI) -> + chk_type(fun is_PropertyParm_extraInfo/1, 'PropertyParm_extraInfo', EI); +chk_PropertyParm_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> + case (is_PropertyParm_extraInfo_tag(Tag) and + is_PropertyParm_extraInfo_val(Tag, Val1) and + is_PropertyParm_extraInfo_val(Tag, Val2)) of + true -> + chk_PropertyParm_extraInfo_val(Tag, Val1, Val2); + false -> + wrong_type('PropertyParm_extraInfo', EI1, EI2) + end; +chk_PropertyParm_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> + case ((is_PropertyParm_extraInfo_tag(Tag1) and + is_PropertyParm_extraInfo_val(Tag1, Val1)) and + (is_PropertyParm_extraInfo_tag(Tag2) and + is_PropertyParm_extraInfo_val(Tag2, Val2))) of + true -> + not_equal('PropertyParm_extraInfo', EI1, EI2); + false -> + wrong_type('PropertyParm_extraInfo', EI1, EI2) + end; +chk_PropertyParm_extraInfo(EI1, EI2) -> + wrong_type('PropertyParm_extraInfo', EI1, EI2). + +chk_PropertyParm_extraInfo_val(relation, Val1, Val2) -> + validate(fun() -> chk_Relation(Val1, Val2) end, 'PropertyParm_extraInfo'); +chk_PropertyParm_extraInfo_val(range, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'PropertyParm_extraInfo'); +chk_PropertyParm_extraInfo_val(sublist, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'PropertyParm_extraInfo'). + + +%% -- Name -- + +is_Name(N) -> + %% Binary: is_OCTET_STRING(N, {exact, 2}). + case is_OCTET_STRING(N, {range, 1, 64}) of + true -> + is_NAME(N); + false -> + false + end. + +is_NAME([H|T]) when (H =< $z) and ($a =< H) -> + is_NAME2(T); +is_NAME([H|T]) when (H =< $Z) and ($A =< H) -> + is_NAME2(T); +is_NAME(_) -> + false. + +is_NAME2([]) -> + true; +is_NAME2([$_|T]) -> + is_NAME2(T); +is_NAME2([H|T]) when (H =< $z) and ($a =< H) -> + is_NAME2(T); +is_NAME2([H|T]) when (H =< $Z) and ($A =< H) -> + is_NAME2(T); +is_NAME2([H|T]) when (H =< $9) and ($0 =< H) -> + is_NAME2(T); +is_NAME2(_) -> + false. + + + +chk_Name(N, N) -> + chk_type(fun is_Name/1, 'Name', N); +chk_Name(N1, N2) -> + case (is_Name(N1) andalso is_Name(N2)) of + true -> + not_equal('Name', N1, N2); + false -> + wrong_type('Name', N1, N2) + end. + + +%% -- PkgdName -- + +%% PkgdName is either "AB/CD" or just plain "ABCD" +%% Note that in ASN.1 the parts is exactly 2 char +%% each, unless you don't use the native config +%% option. In text and in binary without the native +%% option, it is 63 + 1 chars for each. +is_PkgdName(N) -> + d("is_PkgdName -> entry with" + "~n N: ~p", [N]), + case string:tokens(N, "/") of + ["*" = PackageName, "*" = ItemID] -> + d("is_PkgdName -> tokenized (0): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + true; + [PackageName, "*" = ItemID] -> + d("is_PkgdName -> tokenized (1): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + is_Name(PackageName); + [PackageName, ItemID] -> + d("is_PkgdName -> tokenized (2): " + "~n PackageName: ~p" + "~n ItemID: ~p", [PackageName, ItemID]), + is_Name(PackageName) andalso is_Name(ItemID); + _ -> + is_Name(N) + end. + +chk_PkgdName(N, N) -> + case is_PkgdName(N) of + true -> + ok; + false -> + wrong_type('PkgdName', N, N) + end; +chk_PkgdName(N1, N2) -> + case (is_PkgdName(N1) andalso is_PkgdName(N2)) of + true -> + not_equal('PkgdName', N1, N2); + false -> + wrong_type('PkgdName', N1, N2) + end. + + +%% -- Relation -- + +is_Relation(R) -> + lists:member(R, [greaterThan, smallerThan, unequalTo]). + +chk_Relation(R, R) -> + chk_type(fun is_Relation/1, 'Relation', R); +chk_Relation(R1, R2) -> + case (is_Relation(R1) andalso is_Relation(R2)) of + true -> + not_equal('Relation', R1, R2); + false -> + wrong_type('Relation', R1, R2) + end. + + +%% -- LocalRemoteDescriptor -- + +is_opt_LocalRemoteDescriptor(D) -> + d("is_LocalRemoteDescriptor -> entry"), + is_OPTIONAL(fun is_LocalRemoteDescriptor/1, D). + +is_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = PGs}) -> + d("is_LocalRemoteDescriptor -> entry with" + "~n PGs: ~p", [PGs]), + is_LocalRemoteDescriptor_propGrps(PGs); +is_LocalRemoteDescriptor(_) -> + false. + +is_LocalRemoteDescriptor_propGrps([]) -> + true; +is_LocalRemoteDescriptor_propGrps([H|T]) -> + is_PropertyGroup(H) andalso is_LocalRemoteDescriptor_propGrps(T); +is_LocalRemoteDescriptor_propGrps(_) -> + false. + +chk_opt_LocalRemoteDescriptor(D1, D2) -> + chk_OPTIONAL('LocalRemoteDescriptor', D1, D2, + fun is_LocalRemoteDescriptor/1, + fun chk_LocalRemoteDescriptor/2). + +chk_LocalRemoteDescriptor(LRD, LRD) -> + chk_type(fun is_LocalRemoteDescriptor/1, 'LocalRemoteDescriptor', LRD); +chk_LocalRemoteDescriptor(#'LocalRemoteDescriptor'{propGrps = PG1}, + #'LocalRemoteDescriptor'{propGrps = PG2}) -> + chk_LocalRemoteDescriptor_propGrps(PG1, PG2), + ok; +chk_LocalRemoteDescriptor(LRD1, LRD2) -> + wrong_type('LocalRemoteDescriptor', LRD1, LRD2). + +chk_LocalRemoteDescriptor_propGrps([], []) -> + ok; +chk_LocalRemoteDescriptor_propGrps([] = PG1, PG2) -> + not_equal('LocalRemoteDescriptor_propGrps', PG1, PG2); +chk_LocalRemoteDescriptor_propGrps(PG1, [] = PG2) -> + not_equal('LocalRemoteDescriptor_propGrps', PG1, PG2); +chk_LocalRemoteDescriptor_propGrps([H|T1], [H|T2]) -> + case is_PropertyGroup(H) of + true -> + chk_LocalRemoteDescriptor_propGrps(T1, T2); + false -> + wrong_type('LocalRemoteDescriptor_propGrps_val', H) + end; +chk_LocalRemoteDescriptor_propGrps([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyGroup(H1, H2) end, + 'LocalRemoteDescriptor_propGrps_val'), + chk_LocalRemoteDescriptor_propGrps(T1, T2); +chk_LocalRemoteDescriptor_propGrps(PG1, PG2) -> + wrong_type('LocalRemoteDescriptor_propGrps', PG1, PG2). + + +%% -- PropertyGroup -- + +is_PropertyGroup([]) -> + true; +is_PropertyGroup([H|T]) -> + is_PropertyParm(H) andalso is_PropertyGroup(T); +is_PropertyGroup(_) -> + false. + +chk_PropertyGroup([], []) -> + ok; +chk_PropertyGroup([] = PG1, PG2) -> + not_equal('PropertyGroup', PG1, PG2); +chk_PropertyGroup(PG1, [] = PG2) -> + not_equal('PropertyGroup', PG1, PG2); +chk_PropertyGroup([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_PropertyGroup(T1, T2); + false -> + wrong_type('PropertyGroup_val', H) + end; +chk_PropertyGroup([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, 'PropertyGroup_val'), + chk_PropertyGroup(T1, T2); +chk_PropertyGroup(PG1, PG2) -> + wrong_type('PropertyGroup', PG1, PG2). + + +%% -- TerminationStateDescriptor -- + +is_opt_TerminationStateDescriptor(D) -> + is_OPTIONAL(fun is_TerminationStateDescriptor/1, D). + +is_TerminationStateDescriptor( + #'TerminationStateDescriptor'{propertyParms = PP, + eventBufferControl = EBC, + serviceState = SS}) -> + is_TerminationStateDescriptor_propertyParms(PP) andalso + is_opt_EventBufferControl(EBC) andalso + is_opt_ServiceState(SS); +is_TerminationStateDescriptor(_) -> + false. + +is_TerminationStateDescriptor_propertyParms([]) -> + true; +is_TerminationStateDescriptor_propertyParms([H|T]) -> + is_PropertyParm(H) andalso is_TerminationStateDescriptor_propertyParms(T); +is_TerminationStateDescriptor_propertyParms(_) -> + false. + +chk_opt_TerminationStateDescriptor(D1, D2) -> + chk_OPTIONAL('TerminationStateDescriptor', D1, D2, + fun is_TerminationStateDescriptor/1, + fun chk_TerminationStateDescriptor/2). + +chk_TerminationStateDescriptor(D, D) -> + chk_type(fun is_TerminationStateDescriptor/1, + 'TerminationStateDescriptor', D); +chk_TerminationStateDescriptor( + #'TerminationStateDescriptor'{propertyParms = PP1, + eventBufferControl = EBC1, + serviceState = SS1}, + #'TerminationStateDescriptor'{propertyParms = PP2, + eventBufferControl = EBC2, + serviceState = SS2}) -> + chk_TerminationStateDescriptor_propertyParms(PP1, PP2), + validate( + fun() -> + chk_opt_EventBufferControl(EBC1, EBC2) + end, + 'TerminationStateDescriptor'), + validate( + fun() -> + chk_opt_ServiceState(SS1, SS2) + end, + 'TerminationStateDescriptor'), + ok; +chk_TerminationStateDescriptor(D1, D2) -> + wrong_type('TerminationStateDescriptor', D1, D2). + + +chk_TerminationStateDescriptor_propertyParms([], []) -> + ok; +chk_TerminationStateDescriptor_propertyParms([] = P1, P2) -> + not_equal('TerminationStateDescriptor_propertyParms', P1, P2); +chk_TerminationStateDescriptor_propertyParms(P1, [] = P2) -> + not_equal('TerminationStateDescriptor_propertyParms', P1, P2); +chk_TerminationStateDescriptor_propertyParms([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_TerminationStateDescriptor_propertyParms(T1, T2); + false -> + wrong_type('TerminationStateDescriptor_propertyParms_val', H) + end; +chk_TerminationStateDescriptor_propertyParms([H1|_], [H2|_]) -> + case (is_PropertyParm(H1) andalso is_PropertyParm(H2)) of + true -> + not_equal('TerminationStateDescriptor_propertyParms_val', H1, H2); + false -> + wrong_type('TerminationStateDescriptor_propertyParms_val', H1, H2) + end; +chk_TerminationStateDescriptor_propertyParms(P1, P2) -> + wrong_type('TerminationStateDescriptor_propertyParms', P1, P2). + + +%% -- EventBufferControl -- + +is_opt_EventBufferControl(asn1_NOVALUE) -> + true; +is_opt_EventBufferControl(EBC) -> + is_EventBufferControl(EBC). + +is_EventBufferControl(EBC) -> + lists:member(EBC, [off, lockStep]). + +chk_opt_EventBufferControl(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_EventBufferControl(EBC1, EBC2) -> + chk_EventBufferControl(EBC1, EBC2). + +chk_EventBufferControl(EBC, EBC) -> + chk_type(fun is_EventBufferControl/1, 'EventBufferControl', EBC); +chk_EventBufferControl(EBC1, EBC2) -> + case (is_EventBufferControl(EBC1) andalso is_EventBufferControl(EBC2)) of + true -> + not_equal('EventBufferControl', EBC1, EBC2); + false -> + wrong_type('EventBufferControl', EBC1, EBC2) + end. + + +%% -- ServiceState -- + +is_opt_ServiceState(asn1_NOVALUE) -> + true; +is_opt_ServiceState(SS) -> + is_ServiceState(SS). + +is_ServiceState(SS) -> + lists:member(SS, [test, outOfSvc, inSvc]). + +chk_opt_ServiceState(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_ServiceState(SS1, SS2) -> + chk_ServiceState(SS1, SS2). + +chk_ServiceState(SS, SS) -> + chk_type(fun is_ServiceState/1, 'ServiceState', SS); +chk_ServiceState(SS1, SS2) -> + case (is_ServiceState(SS1) andalso is_ServiceState(SS2)) of + true -> + not_equal('ServiceState', SS1, SS2); + false -> + wrong_type('ServiceState', SS1, SS2) + end. + + +%% -- MuxDescriptor -- + +is_MuxDescriptor(#'MuxDescriptor'{muxType = MT, + termList = TL, + nonStandardData = NSD}) -> + is_MuxType(MT) andalso + is_MuxDescriptor_termList(TL) andalso + is_NonStandardData(NSD); +is_MuxDescriptor(_) -> + false. + +is_MuxDescriptor_termList([]) -> + true; +is_MuxDescriptor_termList([H|T]) -> + is_TerminationID(H) andalso is_MuxDescriptor_termList(T); +is_MuxDescriptor_termList(_) -> + false. + +chk_MuxDescriptor(D, D) -> + chk_type(fun is_MuxDescriptor/1, 'MuxDescriptor', D); +chk_MuxDescriptor(#'MuxDescriptor'{muxType = MT1, + termList = TL1, + nonStandardData = NSD1}, + #'MuxDescriptor'{muxType = MT2, + termList = TL2, + nonStandardData = NSD2}) -> + validate(fun() -> chk_MuxType(MT1, MT2) end, 'MuxDescriptor'), + chk_MuxDescriptor_termList(TL1, TL2), + validate(fun() -> chk_NonStandardData(NSD1, NSD2) end, 'MuxDescriptor'), + ok; +chk_MuxDescriptor(D1, D2) -> + wrong_type('MuxDescriptor', D1, D2). + +chk_MuxDescriptor_termList([], []) -> + ok; +chk_MuxDescriptor_termList([] = TL1, TL2) -> + not_equal('MuxDescriptor_termList', TL1, TL2); +chk_MuxDescriptor_termList(TL1, [] = TL2) -> + not_equal('MuxDescriptor_termList', TL1, TL2); +chk_MuxDescriptor_termList([H|T1], [H|T2]) -> + case is_TerminationID(H) of + true -> + chk_MuxDescriptor_termList(T1, T2); + false -> + wrong_type('MuxDescriptor_termList_val', H) + end; +chk_MuxDescriptor_termList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_TerminationID(H1, H2) end, + 'MuxDescriptor_termList_val'), + chk_MuxDescriptor_termList(T1, T2); +chk_MuxDescriptor_termList(TL1, TL2) -> + wrong_type('MuxDescriptor_termList', TL1, TL2). + + +%% -- MuxType -- + +is_MuxType(MT) -> + lists:member(MT, [h221, h223, h226, v76, nx64k]). + +chk_MuxType(MT, MT) -> + chk_type(fun is_MuxType/1, 'MuxType', MT); +chk_MuxType(MT1, MT2) -> + case (is_MuxType(MT1) andalso is_MuxType(MT2)) of + true -> + not_equal('MuxType', MT1, MT2); + false -> + wrong_type('MuxType', MT1, MT2) + end. + + +%% -- StreamID -- + +is_opt_StreamID(V) -> + is_OPTIONAL(fun is_StreamID/1, V). + +is_StreamID(V) -> + d("is_StreamID -> entry with" + "~n V: ~p", [V]), + is_INTEGER(V, {range, 0, 65535}). + +chk_opt_StreamID(V1, V2) -> + chk_OPTIONAL('StreamID', V1, V2, fun is_StreamID/1, fun chk_StreamID/2). + +chk_StreamID(ID, ID) -> + chk_type(fun is_StreamID/1, 'StreamID', ID); +chk_StreamID(ID1, ID2) -> + case (is_StreamID(ID1) andalso is_StreamID(ID2)) of + true -> + not_equal('StreamID', ID1, ID2); + false -> + wrong_type('StreamID', ID1, ID2) + end. + + +%% -- EventsDescriptor -- + +is_EventsDescriptor(#'EventsDescriptor'{requestID = RID, + eventList = EVL}) -> + d("is_EventsDescriptor -> entry with" + "~n RID: ~p" + "~n EVL: ~p", [RID, EVL]), + is_opt_RequestID(RID) andalso is_EventsDescriptor_eventList(EVL); +is_EventsDescriptor(_) -> + false. + +is_EventsDescriptor_eventList([]) -> + true; +is_EventsDescriptor_eventList([H|T]) -> + is_RequestedEvent(H) andalso is_EventsDescriptor_eventList(T); +is_EventsDescriptor_eventList(_) -> + false. + +chk_EventsDescriptor(D, D) -> + chk_type(fun is_EventsDescriptor/1, 'EventsDescriptor', D); +chk_EventsDescriptor(#'EventsDescriptor'{requestID = RID1, + eventList = EVL1}, + #'EventsDescriptor'{requestID = RID2, + eventList = EVL2}) -> + validate(fun() -> chk_opt_RequestID(RID1, RID2) end, 'EventsDescriptor'), + chk_EventsDescriptor_eventList(EVL1, EVL2), + ok; +chk_EventsDescriptor(D1, D2) -> + wrong_type('EventsDescriptor', D1, D2). + +chk_EventsDescriptor_eventList([], []) -> + ok; +chk_EventsDescriptor_eventList([] = EVL1, EVL2) -> + not_equal('EventsDescriptor_eventList', EVL1, EVL2); +chk_EventsDescriptor_eventList(EVL1, [] = EVL2) -> + not_equal('EventsDescriptor_eventList', EVL1, EVL2); +chk_EventsDescriptor_eventList([H|T1], [H|T2]) -> + case is_RequestedEvent(H) of + true -> + chk_EventsDescriptor_eventList(T1, T2); + false -> + wrong_type('EventsDescriptor_eventList_val', H) + end; +chk_EventsDescriptor_eventList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_RequestedEvent(H1, H2) end, + 'EventsDescriptor_eventList_val'), + chk_EventsDescriptor_eventList(T1, T2); +chk_EventsDescriptor_eventList(EVL1, EVL2) -> + wrong_type('EventsDescriptor_eventList', EVL1, EVL2). + + +%% -- RequestedEvent -- + +is_RequestedEvent(#'RequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}) -> + d("is_RequestedEvent -> entry with" + "~n N: ~p" + "~n SID: ~p" + "~n EA: ~p" + "~n EPL: ~p", [N, SID, EA, EPL]), + is_PkgdName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_RequestedActions(EA) andalso + is_RequestedEvent_evParList(EPL); +is_RequestedEvent(_) -> + false. + +is_RequestedEvent_evParList([]) -> + true; +is_RequestedEvent_evParList([H|T]) -> + is_EventParameter(H) andalso is_RequestedEvent_evParList(T); +is_RequestedEvent_evParList(_) -> + false. + +chk_RequestedEvent(RE, RE) -> + chk_type(fun is_RequestedEvent/1, 'RequestedEvent', RE); +chk_RequestedEvent(#'RequestedEvent'{pkgdName = N1, + streamID = SID1, + eventAction = EA1, + evParList = EPL1}, + #'RequestedEvent'{pkgdName = N2, + streamID = SID2, + eventAction = EA2, + evParList = EPL2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'RequestedEvent'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'RequestedEvent'), + validate(fun() -> chk_opt_RequestedActions(EA1, EA2) end, + 'RequestedEvent'), + chk_RequestedEvent_evParList(EPL1, EPL2), + ok; +chk_RequestedEvent(RE1, RE2) -> + wrong_type('RequestedEvent', RE1, RE2). + +chk_RequestedEvent_evParList([], []) -> + ok; +chk_RequestedEvent_evParList([] = EPL1, EPL2) -> + not_equal('RequestedEvent_evParList', EPL1, EPL2); +chk_RequestedEvent_evParList(EPL1, [] = EPL2) -> + not_equal('RequestedEvent_evParList', EPL1, EPL2); +chk_RequestedEvent_evParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_RequestedEvent_evParList(T1, T2); + false -> + wrong_type('RequestedEvent_evParList_val', H) + end; +chk_RequestedEvent_evParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'RequestedEvent_evParList_val'), + chk_RequestedEvent_evParList(T1, T2); +chk_RequestedEvent_evParList(EPL1, EPL2) -> + wrong_type('RequestedEvent_evParList', EPL1, EPL2). + + +%% -- RegulatedEmbeddedDescriptor -- + +is_RegulatedEmbeddedDescriptor( + #'RegulatedEmbeddedDescriptor'{secondEvent = SE, + signalsDescriptor = SD}) -> + is_opt_SecondEventsDescriptor(SE) andalso + is_opt_SignalsDescriptor(SD); +is_RegulatedEmbeddedDescriptor(_) -> + false. + + +chk_RegulatedEmbeddedDescriptor( + #'RegulatedEmbeddedDescriptor'{secondEvent = SE1, + signalsDescriptor = SD1}, + #'RegulatedEmbeddedDescriptor'{secondEvent = SE2, + signalsDescriptor = SD2}) -> + chk_RegulatedEmbeddedDescriptor_secondEvent(SE1, SE2), + chk_RegulatedEmbeddedDescriptor_signalsDescriptor(SD1, SD2), + ok; +chk_RegulatedEmbeddedDescriptor(RED1, RED2) -> + wrong_type('RegulatedEmbeddedDescriptor', RED1, RED2). + +chk_RegulatedEmbeddedDescriptor_secondEvent(SE1, SE2) -> + validate(fun() -> chk_opt_SecondEventsDescriptor(SE1, SE2) end, + 'RegulatedEmbeddedDescriptor_secondEvent'). + +chk_RegulatedEmbeddedDescriptor_signalsDescriptor(SD1, SD2) -> + validate(fun() -> chk_opt_SignalsDescriptor(SD1, SD2) end, + 'RegulatedEmbeddedDescriptor_signalsDescriptor'). + + +%% -- NotifyBehaviour -- + +tags_NotifyBehaviour() -> + [ + {notifyImmediate, + fun is_NULL/1, + fun chk_NULL/2}, + + {notifyRegulated, + fun is_RegulatedEmbeddedDescriptor/1, + fun chk_RegulatedEmbeddedDescriptor/2}, + + {neverNotify, + fun is_NULL/1, + fun chk_NULL/2} + ]. + +is_opt_NotifyBehaviour(asn1_NOVALUE) -> + true; +is_opt_NotifyBehaviour(NB) -> + is_NotifyBehaviour(NB). + +is_NotifyBehaviour(NB) -> + is_CHOICE(NB, tags_NotifyBehaviour()). + +chk_opt_NotifyBehaviour(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_NotifyBehaviour(NB1, NB2) -> + chk_NotifyBehaviour(NB1, NB2). + +chk_NotifyBehaviour(NB1, NB2) -> + chk_CHOICE(NB1, NB2, 'NotifyBehaviour', tags_NotifyBehaviour()). + + +%% -- RequestedActions -- + +is_opt_RequestedActions(asn1_NOVALUE) -> + true; +is_opt_RequestedActions(RA) -> + is_RequestedActions(RA). + +is_RequestedActions(#'RequestedActions'{keepActive = KA, + eventDM = EDM, + secondEvent = SE, + signalsDescriptor = SD, + notifyBehaviour = NB, + resetEventsDescriptor = RED}) -> + d("is_RequestedActions -> entry with" + "~n KA: ~p" + "~n EDM: ~p" + "~n SE: ~p" + "~n SD: ~p" + "~n NB: ~p" + "~n RED: ~p", [KA, EDM, SE, SD, NB, RED]), + is_opt_BOOLEAN(KA) andalso + is_opt_EventDM(EDM) andalso + is_opt_SecondEventsDescriptor(SE) andalso + is_opt_SignalsDescriptor(SD) andalso + is_opt_NotifyBehaviour(SD) andalso + is_opt_NULL(SD); +is_RequestedActions(_) -> + false. + +chk_opt_RequestedActions(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_RequestedActions(RA1, RA2) -> + chk_RequestedActions(RA1, RA2). + +chk_RequestedActions(RA, RA) -> + chk_type(fun is_RequestedActions/1, 'RequestedActions', RA); +chk_RequestedActions(#'RequestedActions'{keepActive = KA1, + eventDM = EDM1, + secondEvent = SE1, + signalsDescriptor = SD1, + notifyBehaviour = NB1, + resetEventsDescriptor = RED1}, + #'RequestedActions'{keepActive = KA2, + eventDM = EDM2, + secondEvent = SE2, + signalsDescriptor = SD2, + notifyBehaviour = NB2, + resetEventsDescriptor = RED2}) -> + chk_RequestedActions_keepActive(KA1, KA2), + chk_RequestedActions_eventDM(EDM1, EDM2), + chk_RequestedActions_secondEvent(SE1, SE2), + chk_RequestedActions_signalsDescriptor(SD1, SD2), + chk_RequestedActions_notifyBehaviour(NB1, NB2), + chk_RequestedActions_resetEventsDescriptor(RED1, RED2), + ok; +chk_RequestedActions(RA1, RA2) -> + wrong_type('RequestedActions', RA1, RA2). + +chk_RequestedActions_keepActive(V1, V2) -> + validate(fun() -> chk_opt_BOOLEAN(V1, V2) end, + 'RequestedActions_keepActive'). + +chk_RequestedActions_eventDM(V1, V2) -> + validate(fun() -> chk_opt_EventDM(V1, V2) end, + 'RequestedActions_eventDM'). + +chk_RequestedActions_secondEvent(V1, V2) -> + validate(fun() -> chk_opt_SecondEventsDescriptor(V1, V2) end, + 'RequestedActions_secondEvent'). + +chk_RequestedActions_signalsDescriptor(V1, V2) -> + validate(fun() -> chk_opt_SignalsDescriptor(V1, V2) end, + 'RequestedActions_signalsDescriptor'). + +chk_RequestedActions_notifyBehaviour(V1, V2) -> + validate(fun() -> chk_opt_NotifyBehaviour(V1, V2) end, + 'RequestedActions_notifyBehaviour'). + +chk_RequestedActions_resetEventsDescriptor(V1, V2) -> + validate(fun() -> chk_opt_NULL(V1, V2) end, + 'RequestedActions_resetEventsDescriptor'). + + +%% -- EventDM -- + +is_opt_EventDM(EDM) -> + is_OPTIONAL(fun is_EventDM/1, EDM). + +is_EventDM({Tag, Val}) -> + is_EventDM_tag(Tag) andalso is_EventDM_val(Tag, Val); +is_EventDM(_) -> + false. + +is_EventDM_tag(Tag) -> + Tags = [digitMapName, digitMapValue], + lists:member(Tag, Tags). + +is_EventDM_val(digitMapName, Val) -> + is_DigitMapName(Val); +is_EventDM_val(digitMapValue, Val) -> + is_DigitMapValue(Val). + +chk_opt_EventDM(EDM1, EDM2) -> + chk_OPTIONAL('EventDM', EDM1, EDM2, fun is_EventDM/1, fun chk_EventDM/2). + +chk_EventDM(EDM, EDM) -> + chk_type(fun is_EventDM/1, 'EventDM', EDM); +chk_EventDM({Tag, Val1} = EDM1, {Tag, Val2} = EDM2) -> + case (is_EventDM_tag(Tag) andalso + is_EventDM_val(Tag, Val1) andalso + is_EventDM_val(Tag, Val2)) of + true -> + chk_EventDM_val(Tag, Val1, Val2); + false -> + wrong_type('EventDM', EDM1, EDM2) + end; +chk_EventDM({Tag1, Val1} = EDM1, {Tag2, Val2} = EDM2) -> + case ((is_EventDM_tag(Tag1) andalso + is_EventDM_val(Tag1, Val1)) andalso + (is_EventDM_tag(Tag2) andalso + is_EventDM_val(Tag2, Val2))) of + true -> + not_equal('EventDM', EDM1, EDM2); + false -> + wrong_type('EventDM', EDM1, EDM2) + end; +chk_EventDM(EDM1, EDM2) -> + wrong_type('EventDM', EDM1, EDM2). + +chk_EventDM_val(digitMapName, Val1, Val2) -> + validate(fun() -> chk_DigitMapName(Val1, Val2) end, 'EventDM'); +chk_EventDM_val(digitMapValue, Val1, Val2) -> + validate(fun() -> chk_DigitMapValue(Val1, Val2) end, 'EventDM'). + + +%% -- SecondEventsDescriptor -- + +is_opt_SecondEventsDescriptor(asn1_NOVALUE) -> + true; +is_opt_SecondEventsDescriptor(D) -> + is_SecondEventsDescriptor(D). + +is_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = RID, + eventList = EL}) -> + is_opt_RequestID(RID) andalso is_SecondEventsDescriptor_eventList(EL); +is_SecondEventsDescriptor(_) -> + false. + +is_SecondEventsDescriptor_eventList([]) -> + true; +is_SecondEventsDescriptor_eventList([H|T]) -> + is_SecondRequestedEvent(H) andalso is_SecondEventsDescriptor_eventList(T); +is_SecondEventsDescriptor_eventList(_) -> + false. + +chk_opt_SecondEventsDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SecondEventsDescriptor(D1, D2) -> + chk_SecondEventsDescriptor(D1, D2). + +chk_SecondEventsDescriptor(D, D) -> + chk_type(fun is_SecondEventsDescriptor/1, 'SecondEventsDescriptor', D); +chk_SecondEventsDescriptor(#'SecondEventsDescriptor'{requestID = RID1, + eventList = EL1}, + #'SecondEventsDescriptor'{requestID = RID2, + eventList = EL2}) -> + validate(fun() -> chk_opt_RequestID(RID1, RID2) end, + 'SecondEventsDescriptor'), + chk_SecondEventsDescriptor_eventList(EL1, EL2), + ok; +chk_SecondEventsDescriptor(D1, D2) -> + wrong_type('SecondEventsDescriptor', D1, D2). + +chk_SecondEventsDescriptor_eventList([], []) -> + ok; +chk_SecondEventsDescriptor_eventList([] = EL1, EL2) -> + not_equal('SecondEventsDescriptor_eventList', EL1, EL2); +chk_SecondEventsDescriptor_eventList(EL1, [] = EL2) -> + not_equal('SecondEventsDescriptor_eventList', EL1, EL2); +chk_SecondEventsDescriptor_eventList([H|T1], [H|T2]) -> + case is_SecondRequestedEvent(H) of + true -> + chk_SecondEventsDescriptor_eventList(T1, T2); + false -> + wrong_type('SecondEventsDescriptor_eventList_val', H) + end; +chk_SecondEventsDescriptor_eventList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_SecondRequestedEvent(H1, H2) end, + 'SecondEventsDescriptor_eventList_val'), + chk_SecondEventsDescriptor_eventList(T1, T2); +chk_SecondEventsDescriptor_eventList(L1, L2) -> + wrong_type('SecondEventsDescriptor_eventList_val', L1, L2). + + +%% -- SecondRequestedEvent -- + +is_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N, + streamID = SID, + eventAction = EA, + evParList = EPL}) -> + is_PkgdName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_SecondRequestedActions(EA) andalso + is_SecondRequestedEvent_evParList(EPL); +is_SecondRequestedEvent(_) -> + false. + +is_SecondRequestedEvent_evParList([]) -> + true; +is_SecondRequestedEvent_evParList([H|T]) -> + is_EventParameter(H) andalso is_SecondRequestedEvent_evParList(T); +is_SecondRequestedEvent_evParList(_) -> + false. + +chk_SecondRequestedEvent(RE, RE) -> + chk_type(fun is_SecondRequestedEvent/1, 'SecondRequestedEvent', RE); +chk_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N1, + streamID = SID1, + eventAction = EA1, + evParList = EPL1}, + #'SecondRequestedEvent'{pkgdName = N2, + streamID = SID2, + eventAction = EA2, + evParList = EPL2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'SecondRequestedEvent'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, + 'SecondRequestedEvent'), + validate(fun() -> chk_opt_SecondRequestedActions(EA1, EA2) end, + 'SecondRequestedEvent'), + chk_SecondRequestedEvent_evParList(EPL1, EPL2), + ok; +chk_SecondRequestedEvent(RE1, RE2) -> + wrong_type('SecondRequestedEvent', RE1, RE2). + +chk_SecondRequestedEvent_evParList([], []) -> + ok; +chk_SecondRequestedEvent_evParList([] = EPL1, EPL2) -> + not_equal('SecondRequestedEvent_evParList', EPL1, EPL2); +chk_SecondRequestedEvent_evParList(EPL1, [] = EPL2) -> + not_equal('SecondRequestedEvent_evParList', EPL1, EPL2); +chk_SecondRequestedEvent_evParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_SecondRequestedEvent_evParList(T1, T2); + false -> + wrong_type('SecondRequestedEvent_evParList_val', H) + end; +chk_SecondRequestedEvent_evParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'SecondRequestedEvent_evParList_val'), + chk_SecondRequestedEvent_evParList(T1, T2); +chk_SecondRequestedEvent_evParList(EPL1, EPL2) -> + wrong_type('SecondRequestedEvent_evParList', EPL1, EPL2). + + +%% -- SecondRequestedActions -- + +is_opt_SecondRequestedActions(asn1_NOVALUE) -> + true; +is_opt_SecondRequestedActions(SRA) -> + is_SecondRequestedActions(SRA). + +is_SecondRequestedActions( + #'SecondRequestedActions'{keepActive = KA, + eventDM = EDM, + signalsDescriptor = SD, + notifyBehaviour = NB, + resetEventsDescriptor = RED}) -> + is_opt_BOOLEAN(KA) andalso + is_opt_EventDM(EDM) andalso + is_opt_SignalsDescriptor(SD) andalso + is_opt_NotifyBehaviour(NB) andalso + is_opt_NULL(RED); +is_SecondRequestedActions(_) -> + false. + +chk_opt_SecondRequestedActions(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SecondRequestedActions(SRA1, SRA2) -> + chk_SecondRequestedActions(SRA1, SRA2). + +chk_SecondRequestedActions(SRA, SRA) -> + chk_type(fun is_SecondRequestedActions/1, 'SecondRequestedActions', SRA); +chk_SecondRequestedActions( + #'SecondRequestedActions'{keepActive = KA1, + eventDM = EDM1, + signalsDescriptor = SD1, + notifyBehaviour = NB1, + resetEventsDescriptor = RED1}, + #'SecondRequestedActions'{keepActive = KA2, + eventDM = EDM2, + signalsDescriptor = SD2, + notifyBehaviour = NB2, + resetEventsDescriptor = RED2}) -> + chk_SecondRequestedActions_keepActive(KA1, KA2), + chk_SecondRequestedActions_eventDM(EDM1, EDM2), + chk_SecondRequestedActions_signalsDescriptor(SD1, SD2), + chk_SecondRequestedActions_notifyBehaviour(NB1, NB2), + chk_SecondRequestedActions_resetEventsDescriptor(RED1, RED2), + ok; +chk_SecondRequestedActions(SRA1, SRA2) -> + wrong_type('SecondRequestedActions', SRA1, SRA2). + +chk_SecondRequestedActions_keepActive(V1, V2) -> + validate(fun() -> chk_opt_BOOLEAN(V1, V2) end, + 'SecondRequestedActions_keepActive'). + +chk_SecondRequestedActions_eventDM(V1, V2) -> + validate(fun() -> chk_opt_EventDM(V1, V2) end, + 'SecondRequestedActions_eventDM'). + +chk_SecondRequestedActions_signalsDescriptor(V1, V2) -> + validate(fun() -> chk_opt_SignalsDescriptor(V1, V2) end, + 'SecondRequestedActions_signalsDescriptor'). + +chk_SecondRequestedActions_notifyBehaviour(V1, V2) -> + validate(fun() -> chk_opt_NotifyBehaviour(V1, V2) end, + 'SecondRequestedActions_notifyBehaviour'). + +chk_SecondRequestedActions_resetEventsDescriptor(V1, V2) -> + validate(fun() -> chk_opt_NULL(V1, V2) end, + 'SecondRequestedActions_resetEventsDescriptor'). + + +%% -- EventBufferDescriptor -- + +is_EventBufferDescriptor(D) -> + is_SEQUENCE_OF(D, fun is_EventSpec/1). + +chk_EventBufferDescriptor(D1, D2) -> + chk_SEQUENCE_OF(D1, D2, 'EventBufferDescriptor', + fun is_EventSpec/1, fun chk_EventSpec/2). + + +%% -- EventSpec -- + +is_EventSpec(#'EventSpec'{eventName = N, + streamID = SID, + eventParList = EPL}) -> + is_EventName(N) andalso + is_opt_StreamID(SID) andalso + is_EventSpec_eventParList(EPL); +is_EventSpec(_) -> + false. + +is_EventSpec_eventParList([]) -> + true; +is_EventSpec_eventParList([H|T]) -> + is_EventParameter(H) andalso is_EventSpec_eventParList(T); +is_EventSpec_eventParList(_) -> + false. + +chk_EventSpec(ES, ES) -> + chk_type(fun is_EventSpec/1, 'EventSpec', ES); +chk_EventSpec(#'EventSpec'{eventName = N1, + streamID = SID1, + eventParList = EPL1}, + #'EventSpec'{eventName = N2, + streamID = SID2, + eventParList = EPL2}) -> + validate(fun() -> chk_EventName(N1, N2) end, 'EventSpec'), + validate(fun() -> chk_opt_StreamID(SID1, SID2) end, 'EventSpec'), + chk_EventSpec_eventParList(EPL1, EPL2), + ok; +chk_EventSpec(ES1, ES2) -> + wrong_type('EventSpec', ES1, ES2). + +chk_EventSpec_eventParList([], []) -> + ok; +chk_EventSpec_eventParList([] = EPL1, EPL2) -> + not_equal('EventSpec_eventParList', EPL1, EPL2); +chk_EventSpec_eventParList(EPL1, [] = EPL2) -> + not_equal('EventSpec_eventParList', EPL1, EPL2); +chk_EventSpec_eventParList([H|T1], [H|T2]) -> + case is_EventParameter(H) of + true -> + chk_EventSpec_eventParList(T1, T2); + false -> + wrong_type('EventSpec_eventParList_val', H) + end; +chk_EventSpec_eventParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_EventParameter(H1, H2) end, + 'EventSpec_eventParList_val'), + chk_EventSpec_eventParList(T1, T2); +chk_EventSpec_eventParList(EPL1, EPL2) -> + wrong_type('EventSpec_eventParList', EPL1, EPL2). + + +%% -- SignalsDescriptor -- + +is_opt_SignalsDescriptor(asn1_NOVALUE) -> + true; +is_opt_SignalsDescriptor(D) -> + is_SignalsDescriptor(D). + +is_SignalsDescriptor(D) -> + is_SEQUENCE_OF(D, fun is_SignalRequest/1). + +chk_opt_SignalsDescriptor(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_SignalsDescriptor(D1, D2) -> + chk_SignalsDescriptor(D1, D2). + +chk_SignalsDescriptor(D1, D2) -> + chk_SEQUENCE_OF(D1, D2, 'SignalsDescriptor', + fun is_SignalRequest/1, fun chk_SignalRequest/2). + + +%% -- SignalRequest -- + +tags_SignalRequest() -> + [ + {signal, fun is_Signal/1, fun chk_Signal/2}, + {seqSigList, fun is_SeqSigList/1, fun chk_SeqSigList/2} + ]. + +is_SignalRequest(SR) -> + is_CHOICE(SR, tags_SignalRequest()). + +chk_SignalRequest(R1, R2) -> + chk_CHOICE(R1, R2, 'SignalRequest', tags_SignalRequest()). + + +%% -- SeqSigList -- + +%% fields_SeqSigList() -> +%% [ +%% {id, +%% 'INTEGER(0,65535)', +%% fun(ID) -> is_INTEGER(ID, {range, 0, 65535}) end, +%% fun(ID1, ID2) -> chk_INTEGER(ID1, ID2, {range, 0, 65535}) end}, + +%% {signalList, +%% 'SEQUENCE OF Signal', +%% fun(S) -> +%% is_SEQUENCE_OF(S, fun is_Signal/1) +%% end, +%% fun(S1, S2) -> +%% chk_SEQUENCE_OF(S1, S2, fun is_Signal/1, fun chk_Signal/2) +%% end} +%% ]. + +%% is_SeqSigList(V) -> +%% is_SEQUENCE(V, 'SeqSigList', fields_SeqSigList()). + + +is_SeqSigList(#'SeqSigList'{id = ID, + signalList = SL}) -> + is_INTEGER(ID, {range, 0, 65535}) andalso + is_SeqSigList_signalList(SL); +is_SeqSigList(_) -> + false. + +is_SeqSigList_signalList([]) -> + true; +is_SeqSigList_signalList([H|T]) -> + is_Signal(H) andalso is_SeqSigList_signalList(T); +is_SeqSigList_signalList(_) -> + false. + +chk_SeqSigList(L, L) -> + chk_type(fun is_SeqSigList/1, 'SeqSigList', L); +chk_SeqSigList(#'SeqSigList'{id = ID1, + signalList = SL1}, + #'SeqSigList'{id = ID2, + signalList = SL2}) -> + validate(fun() -> chk_INTEGER(ID1, ID2, {range, 0, 65535}) end, + 'SeqSigList'), + chk_SeqSigList_signalList(SL1, SL2), + ok; +chk_SeqSigList(L1, L2) -> + wrong_type('SeqSigList', L1, L2). + +chk_SeqSigList_signalList([], []) -> + ok; +chk_SeqSigList_signalList([] = L1, L2) -> + not_equal('SeqSigList_signalList', L1, L2); +chk_SeqSigList_signalList(L1, [] = L2) -> + not_equal('SeqSigList_signalList', L1, L2); +chk_SeqSigList_signalList([H|T1], [H|T2]) -> + case is_Signal(H) of + true -> + chk_SeqSigList_signalList(T1, T2); + false -> + wrong_type('SeqSigList_signalList_val', H) + end; +chk_SeqSigList_signalList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_Signal(H1, H2) end, + 'SeqSigList_signalList_val'), + chk_SeqSigList_signalList(T1, T2); +chk_SeqSigList_signalList(L1, L2) -> + wrong_type('SeqSigList_signalList', L1, L2). + + +%% -- Signal -- + +is_Signal(#'Signal'{signalName = N, + streamID = SID, + sigType = ST, + duration = Dur, + notifyCompletion = NC, + keepActive = KA, + sigParList = SPL, + direction = Dir, + requestID = RID, + intersigDelay = ISD}) -> + d("is_Signal -> entry with" + "~n N: ~p" + "~n SID: ~p" + "~n ST: ~p" + "~n Dur: ~p" + "~n NC: ~p" + "~n KA: ~p" + "~n SPL: ~p" + "~n Dir: ~p" + "~n RID: ~p" + "~n ISD: ~p", [N, SID, ST, Dur, NC, KA, SPL, Dir, RID, ISD]), + is_SignalName(N) andalso + is_opt_StreamID(SID) andalso + is_opt_SignalType(ST) andalso + is_opt_INTEGER(Dur, {range, 0, 65535}) andalso + is_opt_NotifyCompletion(NC) andalso + is_opt_BOOLEAN(KA) andalso + is_Signal_sigParList(SPL) andalso + is_opt_SignalDirection(Dir) andalso + is_opt_RequestID(RID) andalso + is_opt_INTEGER(ISD, {range, 0, 65535}). + +is_Signal_sigParList([]) -> + true; +is_Signal_sigParList([H|T]) -> + is_SigParameter(H) andalso is_Signal_sigParList(T); +is_Signal_sigParList(_) -> + false. + +chk_Signal(S, S) -> + chk_type(fun is_Signal/1, 'Signal', S); +chk_Signal(#'Signal'{signalName = N1, + streamID = SID1, + sigType = ST1, + duration = Dur1, + notifyCompletion = NC1, + keepActive = KA1, + sigParList = SPL1, + direction = Dir1, + requestID = RID1, + intersigDelay = ISD1}, + #'Signal'{signalName = N2, + streamID = SID2, + sigType = ST2, + duration = Dur2, + notifyCompletion = NC2, + keepActive = KA2, + sigParList = SPL2, + direction = Dir2, + requestID = RID2, + intersigDelay = ISD2}) -> + chk_Signal_signalName(N1, N2), + chk_Signal_streamID(SID1, SID2), + chk_Signal_sigType(ST1, ST2), + chk_Signal_duration(Dur1, Dur2), + chk_Signal_notifyCompletion(NC1, NC2), + chk_Signal_keepActive(KA1, KA2), + chk_Signal_sigParList(SPL1, SPL2), + chk_Signal_direction(Dir1, Dir2), + chk_Signal_requestID(RID1, RID2), + chk_Signal_intersigDelay(ISD1, ISD2), + ok; +chk_Signal(S1, S2) -> + wrong_type('Signal', S1, S2). + +chk_Signal_signalName(N1, N2) -> + validate(fun() -> chk_SignalName(N1, N2) end, 'Signal_signalName'). + +chk_Signal_streamID(V1, V2) -> + validate(fun() -> chk_opt_StreamID(V1, V2) end, 'Signal_streamID'). + +chk_Signal_sigType(V1, V2) -> + validate(fun() -> chk_opt_SignalType(V1, V2) end, 'Signal_sigType'). + +chk_Signal_duration(V1, V2) -> + validate(fun() -> + chk_opt_INTEGER(V1, V2, {range, 0, 65535}) + end, + 'Signal_duration'). + +chk_Signal_notifyCompletion(V1, V2) -> + validate(fun() -> chk_opt_NotifyCompletion(V1, V2) end, + 'Signal_notifyCompletion'). + +chk_Signal_keepActive(false, asn1_NOVALUE) -> + ok; +chk_Signal_keepActive(asn1_NOVALUE, false) -> + ok; +chk_Signal_keepActive(V1, V2) -> + validate(fun() -> chk_opt_BOOLEAN(V1, V2) end, 'Signal_keepActive'). + +chk_Signal_sigParList([], []) -> + ok; +chk_Signal_sigParList([] = L1, L2) -> + not_equal('Signal_sigParList', L1, L2); +chk_Signal_sigParList(L1, [] = L2) -> + not_equal('Signal_sigParList', L1, L2); +chk_Signal_sigParList([H|T1], [H|T2]) -> + case is_SigParameter(H) of + true -> + chk_Signal_sigParList(T1, T2); + false -> + wrong_type('Signal_sigParList_val', H) + end; +chk_Signal_sigParList([H1|T1], [H2|T2]) -> + validate(fun() -> chk_SigParameter(H1, H2) end, + 'Signal_sigParList_val'), + chk_Signal_sigParList(T1, T2); +chk_Signal_sigParList(L1, L2) -> + wrong_type('Signal_sigParList', L1, L2). + +chk_Signal_direction(V1, V2) -> + validate(fun() -> chk_opt_SignalDirection(V1, V2) end, 'Signal_direction'). + +chk_Signal_requestID(V1, V2) -> + validate(fun() -> chk_opt_RequestID(V1, V2) end, 'Signal_requestID'). + +chk_Signal_intersigDelay(V1, V2) -> + validate(fun() -> chk_opt_INTEGER(V1, V2, {range, 0, 65535}) end, + 'Signal_intersigDelay'). + + +%% -- SignalType -- + +is_opt_SignalType(T) -> + is_OPTIONAL(fun is_SignalType/1, T). + +is_SignalType(T) -> + d("is_SignalType -> entry with" + "~n T: ~p", [T]), + Types = [brief, onOff, timeOut], + lists:member(T, Types). + +chk_opt_SignalType(T1, T2) -> + chk_OPTIONAL('SignalType', T1, T2, + fun is_SignalType/1, fun chk_SignalType/2). + +chk_SignalType(T, T) -> + chk_type(fun is_SignalType/1, 'SignalType', T); +chk_SignalType(T1, T2) -> + case (is_SignalType(T1) andalso is_SignalType(T2)) of + true -> + not_equal('SignalType', T1, T2); + false -> + wrong_type('SignalType', T1, T2) + end. + + +%% -- SignalDirection -- + +is_opt_SignalDirection(T) -> + is_OPTIONAL(fun is_SignalDirection/1, T). + +is_SignalDirection(Dir) -> + d("is_SignalDirection -> entry with" + "~n Dir: ~p", [Dir]), + Dirs = [internal, external, both], + lists:member(Dir, Dirs). + +chk_opt_SignalDirection(T1, T2) -> + chk_OPTIONAL('SignalDirection', T1, T2, + fun is_SignalDirection/1, fun chk_SignalDirection/2). + +chk_SignalDirection(Dir, Dir) -> + chk_type(fun is_SignalDirection/1, 'SignalDirection', Dir); +chk_SignalDirection(Dir1, Dir2) -> + case (is_SignalDirection(Dir1) andalso is_SignalDirection(Dir2)) of + true -> + not_equal('SignalDirection', Dir1, Dir2); + false -> + wrong_type('SignalDirection', Dir1, Dir2) + end. + + +%% -- SignalName -- + +is_SignalName(N) -> + d("is_SignalName -> entry with" + "~n N: ~p", [N]), + is_PkgdName(N). + +chk_SignalName(N1, N2) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'SignalName'). + + +%% -- NotifyCompletion -- + +is_opt_NotifyCompletion(NC) -> + is_OPTIONAL(fun is_NotifyCompletion/1, NC). + +is_NotifyCompletion(NC) -> + d("is_NotifyCompletion -> entry with" + "~n NC: ~p", [NC]), + Valids = [onTimeOut, + onInterruptByEvent, + onInterruptByNewSignalDescr, + otherReason], + lists:all(fun(X) -> lists:member(X, Valids) end, NC). + +chk_opt_NotifyCompletion(NC1, NC2) -> + chk_OPTIONAL('NotifyCompletion', NC1, NC2, + fun is_NotifyCompletion/1, + fun chk_NotifyCompletion/2). + +chk_NotifyCompletion(NC, NC) -> + chk_type(fun is_NotifyCompletion/1, 'NotifyCompletion', NC); +chk_NotifyCompletion(NC1, NC2) -> + case (is_NotifyCompletion(NC1) andalso is_NotifyCompletion(NC2)) of + true -> + not_equal('NotifyCompletion', NC1, NC2); + false -> + wrong_type('NotifyCompletion', NC1, NC2) + end. + + +%% -- SigParameter -- + +is_SigParameter(#'SigParameter'{sigParameterName = N, + value = V, + extraInfo = I}) -> + d("is_SigParameter -> entry with" + "~n N: ~p" + "~n V: ~p" + "~n I: ~p", [N, V, I]), + is_Name(N) andalso + is_Value(V) andalso + is_SigParameter_extraInfo(I); +is_SigParameter(_) -> + false. + +is_SigParameter_extraInfo(asn1_NOVALUE) -> + true; +is_SigParameter_extraInfo({Tag, Val}) -> + is_SigParameter_extraInfo_tag(Tag) andalso + is_SigParameter_extraInfo_val(Tag, Val); +is_SigParameter_extraInfo(_) -> + false. + +is_SigParameter_extraInfo_tag(Tag) -> + Tags = [relation, range, sublist], + lists:member(Tag, Tags). + +is_SigParameter_extraInfo_val(relation, Val) -> + is_Relation(Val); +is_SigParameter_extraInfo_val(range, Val) -> + is_BOOLEAN(Val); +is_SigParameter_extraInfo_val(sublist, Val) -> + is_BOOLEAN(Val). + +chk_SigParameter(P, P) -> + chk_type(fun is_SigParameter/1, 'SigParameter', P); +chk_SigParameter(#'SigParameter'{sigParameterName = N1, + value = V1, + extraInfo = I1}, + #'SigParameter'{sigParameterName = N2, + value = V2, + extraInfo = I2}) -> + validate(fun() -> chk_Name(N1, N2) end, 'SigParameter'), + validate(fun() -> chk_Value(V1, V2) end, 'SigParameter'), + chk_SigParameter_extraInfo(I1, I2), + ok; +chk_SigParameter(P1, P2) -> + wrong_type('SigParameter', P1, P2). + +chk_SigParameter_extraInfo(EI, EI) -> + chk_type(fun is_SigParameter_extraInfo/1, 'SigParameter_extraInfo', EI); +chk_SigParameter_extraInfo({Tag, Val1} = EI1, {Tag, Val2} = EI2) -> + case (is_SigParameter_extraInfo_tag(Tag) and + is_SigParameter_extraInfo_val(Tag, Val1) and + is_SigParameter_extraInfo_val(Tag, Val2)) of + true -> + chk_SigParameter_extraInfo_val(Tag, Val1, Val2); + false -> + wrong_type('SigParameter_extraInfo', EI1, EI2) + end; +chk_SigParameter_extraInfo({Tag1, Val1} = EI1, {Tag2, Val2} = EI2) -> + case ((is_SigParameter_extraInfo_tag(Tag1) and + is_SigParameter_extraInfo_val(Tag1, Val1)) and + (is_SigParameter_extraInfo_tag(Tag2) and + is_SigParameter_extraInfo_val(Tag2, Val2))) of + true -> + not_equal('SigParameter_extraInfo', EI1, EI2); + false -> + wrong_type('SigParameter_extraInfo', EI1, EI2) + end; +chk_SigParameter_extraInfo(EI1, EI2) -> + wrong_type('SigParameter_extraInfo', EI1, EI2). + +chk_SigParameter_extraInfo_val(relation, Val1, Val2) -> + validate(fun() -> chk_Relation(Val1, Val2) end, 'SigParameter_extraInfo'); +chk_SigParameter_extraInfo_val(range, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'SigParameter_extraInfo'); +chk_SigParameter_extraInfo_val(sublist, Val1, Val2) -> + validate(fun() -> chk_BOOLEAN(Val1, Val2) end, 'SigParameter_extraInfo'). + + +%% -- RequestID -- + +is_opt_RequestID(asn1_NOVALUE) -> + true; +is_opt_RequestID(V) -> + is_RequestID(V). + +is_RequestID(V) -> is_INTEGER(V, {range, 0, 4294967295}). + +chk_opt_RequestID(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_RequestID(V1, V2) -> + chk_RequestID(V1, V2). + +chk_RequestID(ID, ID) -> + chk_type(fun is_RequestID/1, 'RequestID', ID); +chk_RequestID(ID1, ID2) -> + case (is_RequestID(ID1) andalso is_RequestID(ID2)) of + true -> + not_equal('RequestID', ID1, ID2); + false -> + wrong_type('RequestID', ID1, ID2) + end. + + +%% -- ModemDescriptor -- + +is_ModemDescriptor(D) when is_record(D, 'ModemDescriptor') -> + true; +is_ModemDescriptor(_) -> + false. + +chk_ModemDescriptor(D, D) when is_record(D, 'ModemDescriptor') -> + ok; +chk_ModemDescriptor(#'ModemDescriptor'{mtl = MTL1, + mpl = MPL1, + nonStandardData = NSD1}, + #'ModemDescriptor'{mtl = MTL2, + mpl = MPL2, + nonStandardData = NSD2}) -> + chk_ModemDescriptor_mtl(MTL1, MTL2), + chk_ModemDescriptor_mpl(MPL1, MPL2), + chk_opt_NonStandardData(NSD1, NSD2), + ok; +chk_ModemDescriptor(D1, D2) -> + wrong_type('ModemDescriptor', D1, D2). + +chk_ModemDescriptor_mtl([], []) -> + ok; +chk_ModemDescriptor_mtl([] = MTL1, MTL2) -> + not_equal('ModemDescriptor_mtl', MTL1, MTL2); +chk_ModemDescriptor_mtl(MTL1, [] = MTL2) -> + not_equal('ModemDescriptor_mtl', MTL1, MTL2); +chk_ModemDescriptor_mtl([H|T1], [H|T2]) -> + case is_ModemType(H) of + true -> + chk_ModemDescriptor_mtl(T1, T2); + false -> + wrong_type('ModemDescriptor_mtl_val', H) + end; +chk_ModemDescriptor_mtl([H1|T1], [H2|T2]) -> + validate(fun() -> chk_ModemType(H1, H2) end, 'ModemDescriptor_mtl_val'), + chk_ModemDescriptor_mtl(T1, T2); +chk_ModemDescriptor_mtl(MTL1, MTL2) -> + wrong_type('ModemDescriptor_mtl', MTL1, MTL2). + + +chk_ModemDescriptor_mpl([], []) -> + ok; +chk_ModemDescriptor_mpl([] = MPL1, MPL2) -> + not_equal('ModemDescriptor_mpl', MPL1, MPL2); +chk_ModemDescriptor_mpl(MPL1, [] = MPL2) -> + not_equal('ModemDescriptor_mpl', MPL1, MPL2); +chk_ModemDescriptor_mpl([H|T1], [H|T2]) -> + case is_PropertyParm(H) of + true -> + chk_ModemDescriptor_mpl(T1, T2); + false -> + wrong_type('ModemDescriptor_mpl_val', H) + end; +chk_ModemDescriptor_mpl([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PropertyParm(H1, H2) end, 'ModemDescriptor_mpl_val'), + chk_ModemDescriptor_mpl(T1, T2); +chk_ModemDescriptor_mpl(MPL1, MPL2) -> + wrong_type('ModemDescriptor_mpl', MPL1, MPL2). + + +%% -- ModemType -- + +chk_ModemType(MT, MT) -> + case is_ModemType(MT) of + true -> + ok; + false -> + wrong_type('ModemType', MT, MT) + end; +chk_ModemType(MT1, MT2) -> + case (is_ModemType(MT1) andalso is_ModemType(MT2)) of + true -> + not_equal('ModemType', MT1, MT2); + false -> + wrong_type('ModemType', MT1, MT2) + end. + +is_ModemType(MT) -> + lists:member(MT, + [v18, v22, v22bis, v32, v32bis, v34, v90, v91, synchISDN]). + + +%% -- DigitMapDescriptor -- + +is_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name, + digitMapValue = Val}) -> + is_opt_DigitMapName(Name) andalso is_opt_DigitMapValue(Val); +is_DigitMapDescriptor(_) -> + false. + +chk_DigitMapDescriptor(D, D) -> + chk_type(fun is_DigitMapDescriptor/1, 'DigitMapDescriptor', D); +chk_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name1, + digitMapValue = Val1}, + #'DigitMapDescriptor'{digitMapName = Name2, + digitMapValue = Val2}) -> + d("chk_DigitMapDescriptor -> entry with" + "~n Name1: ~p" + "~n Name2: ~p" + "~n Val1: ~p" + "~n Val2: ~p", [Name1, Name2, Val1, Val2]), + validate(fun() -> chk_opt_DigitMapName(Name1, Name2) end, + 'DigitMapDescriptor'), + validate(fun() -> chk_opt_DigitMapValue(Val1, Val2) end, + 'DigitMapDescriptor'), + ok; +chk_DigitMapDescriptor(D1, D2) -> + wrong_type('DigitMapDescriptor', D1, D2). + + +%% -- DigitMapName -- + +is_opt_DigitMapName(asn1_NOVALUE) -> + true; +is_opt_DigitMapName(N) -> + is_DigitMapName(N). + +is_DigitMapName(N) -> is_Name(N). + +chk_opt_DigitMapName(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_DigitMapName(N1, N2) -> + chk_DigitMapName(N1, N2). + +chk_DigitMapName(N, N) -> + chk_type(fun is_DigitMapName/1, 'DigitMapName', N); +chk_DigitMapName(N1, N2) -> + case (is_DigitMapName(N1) andalso is_DigitMapName(N2)) of + true -> + not_equal('DigitMapName', N1, N2); + false -> + wrong_type('DigitMapName', N1, N2) + end. + + +%% -- DigitMapValue -- + +is_opt_DigitMapValue(V) -> + is_OPTIONAL(fun is_DigitMapValue/1, V). + +is_DigitMapValue(#'DigitMapValue'{startTimer = Start, + shortTimer = Short, + longTimer = Long, + digitMapBody = Body, + durationTimer = Dur}) -> + is_DigitMapValue_startTimer(Start) andalso + is_DigitMapValue_shortTimer(Short) andalso + is_DigitMapValue_longTimer(Long) andalso + is_IA5String(Body) andalso + is_DigitMapValue_durationTimer(Dur); +is_DigitMapValue(_) -> + false. + +is_DigitMapValue_startTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_startTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +is_DigitMapValue_shortTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_shortTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +is_DigitMapValue_longTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_longTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +is_DigitMapValue_durationTimer(asn1_NOVALUE) -> true; +is_DigitMapValue_durationTimer(T) -> is_INTEGER(T, {range, 0, 99}). + +chk_opt_DigitMapValue(V1, V2) -> + chk_OPTIONAL('DigitMapValue', V1, V2, + fun is_DigitMapValue/1, fun chk_DigitMapValue/2). + +chk_DigitMapValue(#'DigitMapValue'{startTimer = Start1, + shortTimer = Short1, + longTimer = Long1, + digitMapBody = Body1, + durationTimer = Dur1}, + #'DigitMapValue'{startTimer = Start2, + shortTimer = Short2, + longTimer = Long2, + digitMapBody = Body2, + durationTimer = Dur2}) -> + d("chk_DigitMapValue -> entry with" + "~n Start1: ~p" + "~n Start2: ~p" + "~n Short1: ~p" + "~n Short2: ~p" + "~n Long1: ~p" + "~n Long2: ~p" + "~n Body1: ~p" + "~n Body2: ~p" + "~n Dur1: ~p" + "~n Dur2: ~p", [Start1, Start2, + Short1, Short2, + Long1, Long2, + Body1, Body2, + Dur1, Dur2]), + chk_DigitMapValue_startTimer(Start1, Start2), + chk_DigitMapValue_shortTimer(Short1, Short2), + chk_DigitMapValue_longTimer(Long1, Long2), + chk_DigitMapValue_digitMapBody(Body1, Body2), + chk_DigitMapValue_durationTimer(Dur1, Dur2), + ok; +chk_DigitMapValue(V1, V2) -> + wrong_type('DigitMapValue', V1, V2). + +chk_DigitMapValue_startTimer(T, T) -> + chk_type(fun is_DigitMapValue_startTimer/1, 'DigitMapValue_startTimer', T); +chk_DigitMapValue_startTimer(T1, T2) -> + case (is_DigitMapValue_startTimer(T1) andalso + is_DigitMapValue_startTimer(T2)) of + true -> + not_equal('DigitMapValue_startTimer', T1, T2); + false -> + wrong_type('DigitMapValue_startTimer', T1, T2) + end. + +chk_DigitMapValue_shortTimer(T, T) -> + chk_type(fun is_DigitMapValue_shortTimer/1, 'DigitMapValue_shortTimer', T); +chk_DigitMapValue_shortTimer(T1, T2) -> + case (is_DigitMapValue_shortTimer(T1) andalso + is_DigitMapValue_shortTimer(T2)) of + true -> + not_equal('DigitMapValue_shortTimer', T1, T2); + false -> + wrong_type('DigitMapValue_shortTimer', T1, T2) + end. + +chk_DigitMapValue_longTimer(T, T) -> + chk_type(fun is_DigitMapValue_longTimer/1, 'DigitMapValue_longTimer', T); +chk_DigitMapValue_longTimer(T1, T2) -> + case (is_DigitMapValue_longTimer(T1) andalso + is_DigitMapValue_longTimer(T2)) of + true -> + not_equal('DigitMapValue_longTimer', T1, T2); + false -> + wrong_type('DigitMapValue_longTimer', T1, T2) + end. + +chk_DigitMapValue_durationTimer(T, T) -> + chk_type(fun is_DigitMapValue_durationTimer/1, + 'DigitMapValue_durationTimer', T); +chk_DigitMapValue_durationTimer(T1, T2) -> + case (is_DigitMapValue_durationTimer(T1) andalso + is_DigitMapValue_durationTimer(T2)) of + true -> + not_equal('DigitMapValue_durationTimer', T1, T2); + false -> + wrong_type('DigitMapValue_durationTimer', T1, T2) + end. + +chk_DigitMapValue_digitMapBody(B, B) -> + d("chk_DigitMapValue_digitMapBody -> entry with" + "~n B: ~p", [B]), + chk_type(fun is_IA5String/1, 'DigitMapValue_digitMapBody', B); +chk_DigitMapValue_digitMapBody(B1, B2) -> + d("chk_DigitMapValue_digitMapBody -> entry with" + "~n B1: ~p" + "~n B2: ~p", [B1, B2]), + case (is_IA5String(B1) andalso is_IA5String(B2)) of + true -> + %% If they are different it could be because + %% of trailing tab's and newline's. + case compare_strings(B1, B2) of + {[], []} -> + ok; + {Str1, []} -> + case strip_tab_and_newline(Str1) of + [] -> + ok; + _ -> + not_equal('DigitMapValue_digitMapBody', B1, B2) + end; + {[], Str2} -> + case strip_tab_and_newline(Str2) of + [] -> + ok; + _ -> + not_equal('DigitMapValue_digitMapBody', B1, B2) + end; + _ -> + not_equal('DigitMapValue_digitMapBody', B1, B2) + end; + false -> + wrong_type('DigitMapValue_digitMapBody', B1, B2) + end. + +%% -- ServiceChangeParm -- + +is_ServiceChangeParm(#'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeAddress = A, + serviceChangeVersion = V, + serviceChangeProfile = P, + serviceChangeReason = R, + serviceChangeDelay = D, + serviceChangeMgcId = Id, + timeStamp = TS, + nonStandardData = NSD, + serviceChangeInfo = I}) -> + is_ServiceChangeMethod(M) andalso + is_opt_ServiceChangeAddress(A) andalso + is_opt_INTEGER(V, {range, 0, 99}) andalso + is_opt_ServiceChangeProfile(P) andalso + is_Value(R) andalso + is_opt_INTEGER(D, {range, 0, 4294967295}) andalso + is_opt_MId(Id) andalso + is_opt_TimeNotation(TS) andalso + is_opt_NonStandardData(NSD) andalso + is_opt_AuditDescriptor(I); +is_ServiceChangeParm(_) -> + false. + +chk_ServiceChangeParm(P, P) -> + chk_type(fun is_ServiceChangeParm/1, 'ServiceChangeParm', P); +chk_ServiceChangeParm(#'ServiceChangeParm'{serviceChangeMethod = M1, + serviceChangeAddress = A1, + serviceChangeVersion = V1, + serviceChangeProfile = P1, + serviceChangeReason = R1, + serviceChangeDelay = D1, + serviceChangeMgcId = Id1, + timeStamp = TS1, + nonStandardData = NSD1, + serviceChangeInfo = I1}, + #'ServiceChangeParm'{serviceChangeMethod = M2, + serviceChangeAddress = A2, + serviceChangeVersion = V2, + serviceChangeProfile = P2, + serviceChangeReason = R2, + serviceChangeDelay = D2, + serviceChangeMgcId = Id2, + timeStamp = TS2, + nonStandardData = NSD2, + serviceChangeInfo = I2}) -> + validate(fun() -> chk_ServiceChangeMethod(M1, M2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_ServiceChangeAddress(A1, A2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_INTEGER(V1, V2, {range, 0, 99}) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_ServiceChangeProfile(P1, P2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_Value(R1, R2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_INTEGER(D1, D2, {range, 0, 4294967295}) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_MId(Id1, Id2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_TimeNotation(TS1, TS2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_NonStandardData(NSD1, NSD2) end, + 'ServiceChangeParm'), + validate(fun() -> chk_opt_AuditDescriptor(I1, I2) end, + 'ServiceChangeParm'), + ok; +chk_ServiceChangeParm(P1, P2) -> + wrong_type('ServiceChangeParm', P1, P2). + + +%% -- ServiceChangeAddress -- + +is_opt_ServiceChangeAddress(A) -> + is_OPTIONAL(fun is_ServiceChangeAddress/1, A). + +is_ServiceChangeAddress({Tag, Val}) -> + is_ServiceChangeAddress_tag(Tag) andalso + is_ServiceChangeAddress_val(Tag, Val); +is_ServiceChangeAddress(_) -> + false. + +is_ServiceChangeAddress_tag(Tag) -> + Tags = [portNumber, ip4Address, ip6Address, domainName, deviceName, + mtpAddress], + lists:member(Tag, Tags). + +is_ServiceChangeAddress_val(portNumber, Val) -> + is_INTEGER(Val, {range, 0, 65535}); +is_ServiceChangeAddress_val(ip4Address, Val) -> + is_IP4Address(Val); +is_ServiceChangeAddress_val(ip6Address, Val) -> + is_IP6Address(Val); +is_ServiceChangeAddress_val(domainName, Val) -> + is_DomainName(Val); +is_ServiceChangeAddress_val(deviceName, Val) -> + is_PathName(Val); +is_ServiceChangeAddress_val(mtpAddress, Val) -> + is_OCTET_STRING(Val, {range, 2, 4}). + + +chk_opt_ServiceChangeAddress(A1, A2) -> + chk_OPTIONAL('ServiceChangeAddress', A1, A2, + fun is_ServiceChangeAddress/1, + fun chk_ServiceChangeAddress/2). + +chk_ServiceChangeAddress(A, A) -> + chk_type(fun is_ServiceChangeAddress/1, 'ServiceChangeAddress', A); +chk_ServiceChangeAddress({Tag, Val1} = A1, {Tag, Val2} = A2) -> + case (is_ServiceChangeAddress_tag(Tag) andalso + is_ServiceChangeAddress_val(Tag, Val1) andalso + is_ServiceChangeAddress_val(Tag, Val2)) of + true -> + chk_ServiceChangeAddress_val(Tag, Val1, Val2); + false -> + wrong_type('ServiceChangeAddress', A1, A2) + end; +chk_ServiceChangeAddress({Tag1, Val1} = A1, {Tag2, Val2} = A2) -> + case ((is_ServiceChangeAddress_tag(Tag1) andalso + is_ServiceChangeAddress_val(Tag1, Val1)) andalso + (is_ServiceChangeAddress_tag(Tag2) andalso + is_ServiceChangeAddress_val(Tag2, Val2))) of + true -> + not_equal('ServiceChangeAddress', A1, A2); + false -> + wrong_type('ServiceChangeAddress', A1, A2) + end; +chk_ServiceChangeAddress(A1, A2) -> + wrong_type('ServiceChangeAddress', A1, A2). + +chk_ServiceChangeAddress_val(portNumber, Val1, Val2) -> + validate(fun() -> chk_INTEGER(Val1, Val2, {range, 0, 99}) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(ip4Address, Val1, Val2) -> + validate(fun() -> chk_IP4Address(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(ip6Address, Val1, Val2) -> + validate(fun() -> chk_IP6Address(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(domainName, Val1, Val2) -> + validate(fun() -> chk_DomainName(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(deviceName, Val1, Val2) -> + validate(fun() -> chk_PathName(Val1, Val2) end, + 'ServiceChangeAddress'); +chk_ServiceChangeAddress_val(mtpAddress, Val1, Val2) -> + validate(fun() -> chk_OCTET_STRING(Val1, Val2, {range, 2, 4}) end, + 'ServiceChangeAddress'). + + +%% -- ServiceChangeResParm -- + +is_ServiceChangeResParm(#'ServiceChangeResParm'{serviceChangeMgcId = Id, + serviceChangeAddress = A, + serviceChangeVersion = V, + serviceChangeProfile = P, + timeStamp = TS}) -> + is_opt_MId(Id) andalso + is_opt_ServiceChangeAddress(A) andalso + is_opt_INTEGER(V, {range, 0, 99}) andalso + is_opt_ServiceChangeProfile(P) andalso + is_opt_TimeNotation(TS); +is_ServiceChangeResParm(_) -> + false. + +chk_ServiceChangeResParm(P, P) -> + chk_type(fun is_ServiceChangeResParm/1, 'ServiceChangeResParm', P); +chk_ServiceChangeResParm( + #'ServiceChangeResParm'{serviceChangeMgcId = Id1, + serviceChangeAddress = A1, + serviceChangeVersion = V1, + serviceChangeProfile = P1, + timeStamp = TS1}, + #'ServiceChangeResParm'{serviceChangeMgcId = Id2, + serviceChangeAddress = A2, + serviceChangeVersion = V2, + serviceChangeProfile = P2, + timeStamp = TS2}) -> + validate(fun() -> chk_opt_MId(Id1, Id2) end, 'ServiceChangeResParm'), + validate(fun() -> chk_opt_ServiceChangeAddress(A1, A2) end, + 'ServiceChangeResParm'), + validate(fun() -> chk_opt_INTEGER(V1, V2, {range, 0, 99}) end, + 'ServiceChangeResParm'), + validate(fun() -> chk_opt_ServiceChangeProfile(P1, P2) end, + 'ServiceChangeResParm'), + validate(fun() -> chk_opt_TimeNotation(TS1, TS2) end, + 'ServiceChangeResParm'), + ok; +chk_ServiceChangeResParm(P1, P2) -> + wrong_type('ServiceChangeResParm', P1, P2). + + +%% -- ServiceChangeMethod -- + +is_ServiceChangeMethod(M) -> + Methods = [failover, forced, graceful, restart, disconnected, handOff], + lists:member(M, Methods). + +chk_ServiceChangeMethod(M, M) -> + chk_type(fun is_ServiceChangeMethod/1, 'ServiceChangeMethod', M); +chk_ServiceChangeMethod(M1, M2) -> + case (is_ServiceChangeMethod(M1) andalso is_ServiceChangeMethod(M2)) of + true -> + not_equal('ServiceChangeMethod', M1, M2); + false -> + wrong_type('ServiceChangeMethod', M1, M2) + end. + + +%% -- ServiceChangeProfile -- + +is_opt_ServiceChangeProfile(P) -> + is_OPTIONAL(fun is_ServiceChangeProfile/1, P). + +is_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = N}) -> + is_IA5String(N, {range, 1, 67}); +is_ServiceChangeProfile(_) -> + false. + +chk_opt_ServiceChangeProfile(P1, P2) -> + chk_OPTIONAL('ServiceChangeProfile', P1, P2, + fun is_ServiceChangeProfile/1, + fun chk_ServiceChangeProfile/2). + +chk_ServiceChangeProfile(P, P) -> + chk_type(fun is_ServiceChangeProfile/1, 'ServiceChangeProfile', P); +chk_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = N1}, + #'ServiceChangeProfile'{profileName = N2}) -> + validate(fun() -> chk_IA5String(N1, N2, {range, 1, 67}) end, + 'ServiceChangeProfile'), + ok; +chk_ServiceChangeProfile(P1, P2) -> + wrong_type('ServiceChangeProfile', P1, P2). + + +%% -- PackagesDescriptor -- + +is_PackagesDescriptor([]) -> + true; +is_PackagesDescriptor([H|T]) -> + is_PackagesItem(H) andalso is_PackagesDescriptor(T); +is_PackagesDescriptor(_) -> + false. + +chk_PackagesDescriptor([], []) -> + ok; +chk_PackagesDescriptor([] = D1, D2) -> + not_equal('PackagesDescriptor', D1, D2); +chk_PackagesDescriptor(D1, [] = D2) -> + not_equal('PackagesDescriptor', D1, D2); +chk_PackagesDescriptor([H|T1], [H|T2]) -> + case is_PackagesItem(H) of + true -> + chk_PackagesDescriptor(T1, T2); + false -> + wrong_type('PackagesDescriptor_val', H) + end; +chk_PackagesDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_PackagesItem(H1, H2) end, + 'PackagesDescriptor_val'), + chk_PackagesDescriptor(T1, T2); +chk_PackagesDescriptor(D1, D2) -> + wrong_type('PackagesDescriptor_val', D1, D2). + + +%% -- PackagesItem -- + +is_PackagesItem(#'PackagesItem'{packageName = N, + packageVersion = V}) -> + is_Name(N) andalso is_INTEGER(V, {range, 0, 99}); +is_PackagesItem(_) -> + false. + +chk_PackagesItem(I, I) -> + chk_type(fun is_PackagesItem/1, 'PackagesItem', I); +chk_PackagesItem(#'PackagesItem'{packageName = N1, + packageVersion = V1}, + #'PackagesItem'{packageName = N2, + packageVersion = V2}) -> + validate(fun() -> chk_Name(N1, N2) end, 'PackagesItem'), + validate(fun() -> chk_INTEGER(V1, V2, {range, 0, 99}) end, 'PackagesItem'), + ok; +chk_PackagesItem(I1, I2) -> + wrong_type('PackagesItem', I1, I2). + + +%% -- StatisticsDescriptor -- + +is_opt_StatisticsDescriptor(D) -> + is_OPTIONAL(fun is_StatisticsDescriptor/1, D). + +is_StatisticsDescriptor([]) -> + true; +is_StatisticsDescriptor([H|T]) -> + is_StatisticsParameter(H) andalso is_StatisticsDescriptor(T); +is_StatisticsDescriptor(_) -> + false. + +chk_opt_StatisticsDescriptor(D1, D2) -> + chk_OPTIONAL('StatisticsDescriptor', D1, D2, + fun is_StatisticsDescriptor/1, + fun chk_StatisticsDescriptor/2). + +chk_StatisticsDescriptor([], []) -> + ok; +chk_StatisticsDescriptor([] = D1, D2) -> + not_equal('StatisticsDescriptor', D1, D2); +chk_StatisticsDescriptor(D1, [] = D2) -> + not_equal('StatisticsDescriptor', D1, D2); +chk_StatisticsDescriptor([H|T1], [H|T2]) -> + case is_StatisticsParameter(H) of + true -> + chk_StatisticsDescriptor(T1, T2); + false -> + wrong_type('StatisticsDescriptor_val', H) + end; +chk_StatisticsDescriptor([H1|T1], [H2|T2]) -> + validate(fun() -> chk_StatisticsParameter(H1, H2) end, + 'StatisticsDescriptor_val'), + chk_StatisticsDescriptor(T1, T2); +chk_StatisticsDescriptor(D1, D2) -> + wrong_type('StatisticsDescriptor_val', D1, D2). + + +%% -- StatisticsParameter -- + +is_StatisticsParameter(#'StatisticsParameter'{statName = N, + statValue = V}) -> + is_PkgdName(N) andalso is_opt_Value(V); +is_StatisticsParameter(_) -> + false. + +chk_StatisticsParameter(P, P) -> + chk_type(fun is_StatisticsParameter/1, 'StatisticsParameter', P); +chk_StatisticsParameter(#'StatisticsParameter'{statName = N1, + statValue = V1}, + #'StatisticsParameter'{statName = N2, + statValue = V2}) -> + validate(fun() -> chk_PkgdName(N1, N2) end, 'StatisticsParameter'), + validate(fun() -> chk_opt_Value(V1, V2) end, 'StatisticsParameter'), + ok; +chk_StatisticsParameter(P1, P2) -> + wrong_type('StatisticsParameter', P1, P2). + + +%% -- NonStandardData -- + +is_opt_NonStandardData(asn1_NOVALUE) -> + true; +is_opt_NonStandardData(NSD) -> + is_NonStandardData(NSD). + +%% is_NonStandardData(#'NonStandardData'{nonStandardIdentifier = Id, +%% data = D}) -> +%% is_NonStandardIdentifier(Id) andalso is_OCTET_STRING(D); +%% is_NonStandardData(_) -> +%% false. + +is_NonStandardData(_) -> + true. + +chk_opt_NonStandardData(asn1_NOVALUE, asn1_NOVALUE) -> + true; +chk_opt_NonStandardData(NSD1, NSD2) -> + chk_NonStandardData(NSD1, NSD2). + +chk_NonStandardData(NSD, NSD) -> + chk_type(fun is_NonStandardData/1, 'NonStandardData', NSD); +%% chk_NonStandardData(#'NonStandardData'{nonStandardIdentifier = Id1, +%% data = D1}, +%% #'NonStandardData'{nonStandardIdentifier = Id2, +%% data = D2}) -> +%% validate(fun() -> chk_NonStandardIdentifier(Id1, Id2) end, +%% 'NonStandardData'), +%% validate(fun() -> chk_OCTET_STRING(D1, D2) end, 'NonStandardData'), +%% ok; +%% chk_NonStandardData(NSD1, NSD2) -> +%% wrong_type('NonStandardData', NSD1, NSD2). +chk_NonStandardData(NSD1, NSD2) -> + not_equal('NonStandardData', NSD1, NSD2). + + +%% -- NonStandardIdentifier -- + +%% is_NonStandardIdentifier({Tag, Val}) -> +%% is_NonStandardIdentifier_tag(Tag) andalso +%% is_NonStandardIdentifier_val(Tag, Val); +%% is_NonStandardIdentifier(_) -> +%% false. + +%% is_NonStandardIdentifier_tag(Tag) -> +%% Tags = [object, h221NonStandard, experimental], +%% lists:member(Tag, Tags). + +%% is_NonStandardIdentifier_val(object, Val) -> +%% is_OBJECT_IDENTIFIER(Val); +%% is_NonStandardIdentifier_val(h221NonStandard, Val) -> +%% is_H221NonStandard(Val); +%% is_NonStandardIdentifier_val(experimental, Val) -> +%% is_IA5String(Val, {exact, 8}). + +%% chk_NonStandardIdentifier(Id, Id) -> +%% chk_type(fun is_NonStandardIdentifier/1, 'NonStandardIdentifier', Id); +%% chk_NonStandardIdentifier({Tag, Val1} = Id1, {Tag, Val2} = Id2) -> +%% case (is_NonStandardIdentifier_tag(Tag) andalso +%% is_NonStandardIdentifier_val(Tag, Val1) andalso +%% is_NonStandardIdentifier_val(Tag, Val1)) of +%% true -> +%% chk_NonStandardIdentifier_val(Tag, Val1, Val2); +%% false -> +%% wrong_type('NonStandardIdentifier', Id1, Id2) +%% end; +%% chk_NonStandardIdentifier({Tag1, Val1} = Id1, {Tag2, Val2} = Id2) -> +%% case ((is_NonStandardIdentifier_tag(Tag1) andalso +%% is_NonStandardIdentifier_val(Tag1, Val1)) andalso +%% (is_NonStandardIdentifier_tag(Tag2) andalso +%% is_NonStandardIdentifier_val(Tag2, Val1))) of +%% true -> +%% not_equal('NonStandardIdentifier', Id1, Id2); +%% false -> +%% wrong_type('NonStandardIdentifier', Id1, Id2) +%% end; +%% chk_NonStandardIdentifier(Id1, Id2) -> +%% wrong_type('NonStandardIdentifier', Id1, Id2). + +%% chk_NonStandardIdentifier_val(object, Val1, Val2) -> +%% chk_OBJECT_IDENTIFIER(Val1, Val2); +%% chk_NonStandardIdentifier_val(h221NonStandard, Val1, Val2) -> +%% chk_H221NonStandard(Val1, Val2); +%% chk_NonStandardIdentifier_val(experimental, Val1, Val2) -> +%% chk_IA5String(Val1, Val2, {exact, 8}). + + +%% -- H221NonStandard -- + +%% is_H221NonStandard(#'H221NonStandard'{t35CountryCode1 = CC1, +%% t35CountryCode2 = CC2, +%% t35Extension = Ext, +%% manufacturerCode = MC}) -> +%% is_INTEGER(CC1, {range, 0, 255}) andalso +%% is_INTEGER(CC2, {range, 0, 255}) andalso +%% is_INTEGER(Ext, {range, 0, 255}) andalso +%% is_INTEGER(Ext, {range, 0, 65535}); +%% is_H221NonStandard(_) -> +%% false. + +%% chk_H221NonStandard(NS, NS) -> +%% chk_type(fun is_H221NonStandard/1, 'H221NonStandard', NS); +%% chk_H221NonStandard(#'H221NonStandard'{t35CountryCode1 = CC11, +%% t35CountryCode2 = CC21, +%% t35Extension = Ext1, +%% manufacturerCode = MC1}, +%% #'H221NonStandard'{t35CountryCode1 = CC12, +%% t35CountryCode2 = CC22, +%% t35Extension = Ext2, +%% manufacturerCode = MC2}) -> +%% validate(fun() -> chk_INTEGER(CC11, CC12, {range, 0, 255}) end, +%% 'H221NonStandard'), +%% validate(fun() -> chk_INTEGER(CC21, CC22, {range, 0, 255}) end, +%% 'H221NonStandard'), +%% validate(fun() -> chk_INTEGER(Ext1, Ext2, {range, 0, 255}) end, +%% 'H221NonStandard'), +%% validate(fun() -> chk_INTEGER(MC1, MC2, {range, 0, 65535}) end, +%% 'H221NonStandard'), +%% ok; +%% chk_H221NonStandard(NS1, NS2) -> +%% wrong_type('H221NonStandard', NS1, NS2). + + +%% -- TimeNotation -- + +is_opt_TimeNotation(asn1_NOVALUE) -> + true; +is_opt_TimeNotation(TN) -> + is_TimeNotation(TN). + +is_TimeNotation(#'TimeNotation'{date = D, time = T}) -> + is_IA5String(D, {exact, 8}) andalso is_IA5String(T, {exact, 8}); +is_TimeNotation(_) -> + false. + +chk_opt_TimeNotation(asn1_NOVALUE, asn1_NOVALUE) -> + ok; +chk_opt_TimeNotation(TN1, TN2) -> + chk_TimeNotation(TN1, TN2). + +chk_TimeNotation(TN, TN) -> + chk_type(fun is_TimeNotation/1, 'TimeNotation', TN); +chk_TimeNotation(#'TimeNotation'{date = D1, time = T1}, + #'TimeNotation'{date = D2, time = T2}) -> + validate(fun() -> chk_IA5String(D1, D2, {exact, 8}) end, 'TimeNotation'), + validate(fun() -> chk_IA5String(T1, T2, {exact, 8}) end, 'TimeNotation'), + ok; +chk_TimeNotation(TN1, TN2) -> + wrong_type('TimeNotation', TN1, TN2). + + +%% -- Value -- + +is_opt_Value(V) -> + is_OPTIONAL(fun is_Value/1, V). + +is_Value([]) -> + true; +is_Value([H|T]) -> + is_OCTET_STRING(H) andalso is_Value(T); +is_Value(_) -> + false. + +chk_opt_Value(V1, V2) -> + chk_OPTIONAL('Value', V1, V2, fun is_Value/1, fun chk_Value/2). + +chk_Value(V, V) -> + case is_Value(V) of + true -> + ok; + false -> + wrong_type('Value', V, V) + end; +chk_Value(V1, V2) -> + case (is_Value(V1) andalso is_Value(V2)) of + true -> + not_equal('Value', V1, V2); + false -> + wrong_type('Value', V1, V2) + end. + + +%% ---------------------------------------------------------------------- +%% Basic type check functions +%% ---------------------------------------------------------------------- + + +is_opt_BOOLEAN(B) -> + is_OPTIONAL(fun is_BOOLEAN/1, B). + +is_BOOLEAN(B) -> + d("is_BOOLEAN -> entry with" + "~n B: ~p", [B]), + lists:member(B, [true, false]). + +chk_opt_BOOLEAN(B1, B2) -> + chk_OPTIONAL('BOOLEAN', B1, B2, fun is_BOOLEAN/1, fun chk_BOOLEAN/2). + +chk_BOOLEAN(B, B) -> + chk_type(fun is_BOOLEAN/1, 'BOOLEAN', B); +chk_BOOLEAN(B1, B2) -> + case (is_BOOLEAN(B1) andalso is_BOOLEAN(B2)) of + true -> + not_equal('BOOLEAN', B1, B2); + false -> + wrong_type('BOOLEAN', B1, B2) + end. + + +is_IA5String(S) when is_list(S) -> + true; +is_IA5String(_) -> + false. + +% chk_IA5String(S, S) -> +% chk_type(fun is_IA5String/1, 'IA5String', S); +% chk_IA5String(S1, S2) -> +% case (is_IA5String(S1) andalso is_IA5String(S2)) of +% true -> +% not_equal('IA5String', S1, S2); +% false -> +% wrong_type('IA5String', S1, S2) +% end. + +is_IA5String(S, _) when is_list(S) -> + true; +is_IA5String(_, _) -> + false. + +chk_IA5String(S, S, R) -> + chk_type(fun is_IA5String/2, 'IA5String', S, R); +chk_IA5String(S1, S2, R) -> + case (is_IA5String(S1, R) andalso is_IA5String(S2, R)) of + true -> + not_equal('IA5String', S1, S2); + false -> + wrong_type('IA5String', S1, S2) + end. + + +is_OCTET_STRING(L) -> is_OCTET_STRING(L, any). + +is_OCTET_STRING(L, any) when is_list(L) -> + true; +is_OCTET_STRING(L, {exact, Len}) when is_list(L) and (length(L) == Len) -> + true; +is_OCTET_STRING(L, {atleast, Len}) when is_list(L) and (Len =< length(L)) -> + true; +is_OCTET_STRING(L, {atmost, Len}) when is_list(L) and (length(L) =< Len) -> + true; +is_OCTET_STRING(L, {range, Min, Max}) + when is_list(L) and (Min =< length(L)) and (length(L) =< Max) -> + true; +is_OCTET_STRING(_, _) -> + false. + +%% chk_OCTET_STRING(L1, L2) -> +%% chk_OCTET_STRING(L1, L2, any). + +chk_OCTET_STRING(L, L, R) -> + chk_type(fun is_OCTET_STRING/2, 'OCTET STRING', L, R); +chk_OCTET_STRING(L1, L2, R) -> + case (is_OCTET_STRING(L1, R) andalso is_OCTET_STRING(L2, R)) of + true -> + not_equal('OCTET STRING', L1, L2); + false -> + wrong_type('OCTET STRING', L1, L2) + end. + + +%% is_OBJECT_IDENTIFIER(_) -> +%% true. + +%% chk_OBJECT_IDENTIFIER(X, X) -> +%% ok; +%% chk_OBJECT_IDENTIFIER(X1, X2) -> +%% not_equal('OBJECT IDENTIFIER', X1, X2). + + +is_opt_NULL(N) -> + is_OPTIONAL(fun is_NULL/1, N). + +is_NULL('NULL') -> + true; +is_NULL(_) -> + false. + +chk_opt_NULL(N1, N2) -> + chk_OPTIONAL('NULL', N1, N2, fun is_NULL/1, fun chk_NULL/2). + +chk_NULL(N, N) -> + chk_type(fun is_NULL/1, 'NULL', N); +chk_NULL(N1, N2) -> + case (is_NULL(N1) andalso is_NULL(N2)) of + true -> + not_equal('NULL', N1, N2); + false -> + wrong_type('NULL', N1, N2) + end. + + +is_opt_INTEGER(I, R) -> + d("is_opt_INTEGER -> entry with" + "~n I: ~p" + "~n R: ~p", [I, R]), + is_OPTIONAL(fun(X) -> is_INTEGER(X, R) end, I). + +is_INTEGER(I, any) when is_integer(I) -> + true; +is_INTEGER(I, {exact, I}) when is_integer(I) -> + true; +is_INTEGER(I, {atleast, Min}) when + is_integer(I) and is_integer(Min) and (Min =< I) -> + true; +is_INTEGER(I, {atmost, Max}) + when is_integer(I) and is_integer(Max) and (I =< Max) -> + true; +is_INTEGER(I, {range, Min, Max}) + when is_integer(I) and + is_integer(Min) and (Min =< I) and + is_integer(Max) and (I =< Max) -> + true; +is_INTEGER(_, _) -> + false. + +chk_opt_INTEGER(I1, I2, R) -> + chk_OPTIONAL('INTEGER', I1, I2, + fun(X) -> is_INTEGER(X, R) end, + fun(Y1, Y2) -> chk_INTEGER(Y1, Y2, R) end). + +chk_INTEGER(I, I, R) -> + chk_type(fun is_INTEGER/2, 'INTEGER', I, R); +chk_INTEGER(I1, I2, R) -> + case (is_INTEGER(I1, R) andalso is_INTEGER(I2, R)) of + true -> + not_equal('INTEGER', I1, I2); + false -> + wrong_type('INTEGER', I1, I2) + end. + + +%% ---------------------------------------------------------------------- +%% Various utility functions +%% ---------------------------------------------------------------------- + + +to_lower([C|Cs]) when (C >= $A) and (C =< $Z) -> + [C+($a-$A)|to_lower(Cs)]; +to_lower([C|Cs]) -> + [C|to_lower(Cs)]; +to_lower([]) -> + []. + + +validate(F, Type) when is_function(F) -> + case (catch F()) of + {error, Reason} -> + error({Type, Reason}); + ok -> + ok + end. + + +chk_type(F, T, V) when is_function(F) and is_atom(T) -> + case F(V) of + true -> + ok; + false -> + wrong_type(T, V) + end. + +chk_type(F, T, V1, V2) when is_function(F) and is_atom(T) -> + case F(V1, V2) of + true -> + ok; + false -> + wrong_type(T, V1) + end. + + +is_OPTIONAL(_, asn1_NOVALUE) -> + true; +is_OPTIONAL(F, Val) when is_function(F) -> + F(Val). + +chk_OPTIONAL(_, asn1_NOVALUE, asn1_NOVALUE, _, _) -> + ok; +chk_OPTIONAL(Type, asn1_NOVALUE = V1, V2, IS, _CHK) when is_function(IS) -> + case IS(V2) of + true -> + not_equal(Type, V1, V2); + false -> + wrong_type(Type, V1, V2) + end; +chk_OPTIONAL(Type, V1, asn1_NOVALUE = V2, IS, _CHK) when is_function(IS) -> + case IS(V1) of + true -> + not_equal(Type, V1, V2); + false -> + wrong_type(Type, V1, V2) + end; +chk_OPTIONAL(_Type, V1, V2, _IS, CHK) when is_function(CHK) -> + CHK(V1, V2). + + +%% -- CHOICE -- + +is_CHOICE({Tag, Val}, Tags) when is_list(Tags) -> + d("is_CHOICE -> entry with" + "~n Tag: ~p" + "~n Val: ~p", [Tag, Val]), + is_CHOICE_tag(Tag, Tags) andalso + is_CHOICE_val(Tag, Val, Tags); +is_CHOICE(_, _) -> + false. + +is_CHOICE_tag(Tag, Tags) -> + lists:keymember(Tag, 1, Tags). + +is_CHOICE_val(Tag, Val, Tags) -> + {value, {_, IsVal, _}} = lists:keysearch(Tag, 1, Tags), + IsVal(Val). + + +chk_CHOICE(V1, V2, Type, Tags) when is_atom(Type) and is_list(Tags) -> + IsTag = fun(Tag) -> is_CHOICE_tag(Tag, Tags) end, + IsVal = fun(Tag, Val) -> is_CHOICE_val(Tag, Val, Tags) end, + ChkVal = fun(Tag, Val1, Val2) -> + chk_CHOICE_val(Tag, Val1, Val2, Tags) + end, + chk_CHOICE(V1, V2, Type, IsTag, IsVal, ChkVal). + +chk_CHOICE_val(Tag, Val1, Val2, Tags) -> + {value, {_, _, ChkVal}} = lists:keysearch(Tag, 1, Tags), + ChkVal(Val1, Val2). + +chk_CHOICE({Tag, Val1} = V1, {Tag, Val2} = V2, Type, IsTag, IsVal, ChkVal) -> + case (IsTag(Tag) andalso + IsVal(Tag, Val1) andalso IsVal(Tag, Val2)) of + true -> + ChkVal(Tag, Val1, Val2); + false -> + wrong_type(Type, V1, V2) + end; +chk_CHOICE({Tag1, Val1} = V1, {Tag2, Val2} = V2, Type, + IsTag, IsVal, _ChkVal) -> + case ((IsTag(Tag1) andalso IsVal(Tag1, Val1)) andalso + (IsTag(Tag2) andalso IsVal(Tag2, Val2))) of + true -> + not_equal(Type, V1, V2); + false -> + wrong_type(Type, V1, V2) + end; +chk_CHOICE(V1, V2, Type, _, _, _) -> + wrong_type(Type, V1, V2). + + +%% -- SEQUENCE OF -- + +is_SEQUENCE_OF([], _) -> + true; +is_SEQUENCE_OF([H|T], IS) when is_function(IS) -> + IS(H) andalso is_SEQUENCE_OF(T, IS); +is_SEQUENCE_OF(_, _) -> + false. + +chk_SEQUENCE_OF([], [], _, _, _) -> + ok; +chk_SEQUENCE_OF([] = V1, V2, Type, _, _) -> + not_equal(Type, V1, V2); +chk_SEQUENCE_OF(V1, [] = V2, Type, _, _) -> + not_equal(Type, V1, V2); +chk_SEQUENCE_OF([H|T1], [H|T2], Type, IS, CHK) -> + case IS(H) of + true -> + chk_SEQUENCE_OF(T1, T2, Type, IS, CHK); + false -> + Type2 = list_to_atom(atom_to_list(Type) ++ "_val"), + wrong_type(Type2, H) + end; +chk_SEQUENCE_OF([H1|T1], [H2|T2], Type, IS, CHK) -> + Type2 = list_to_atom(atom_to_list(Type) ++ "_val"), + validate(fun() -> CHK(H1, H2) end, Type2), + chk_SEQUENCE_OF(T1, T2, Type, IS, CHK); +chk_SEQUENCE_OF(V1, V2, Type, _, _) -> + wrong_type(Type, V1, V2). + + +%% ---------------------------------------------------------------------- + +compare_strings([] = L1, L2) -> + {L1, L2}; +compare_strings(L1, [] = L2) -> + {L1, L2}; +compare_strings([H|T1], [H|T2]) -> + compare_strings(T1, T2); +compare_strings(L1, L2) -> + {L1, L2}. + +strip_tab_and_newline([]) -> + []; +strip_tab_and_newline([$\n|T]) -> + strip_tab_and_newline(T); +strip_tab_and_newline([$\t|T]) -> + strip_tab_and_newline(T); +strip_tab_and_newline([H|T]) -> + [H|strip_tab_and_newline(T)]. + + +%% ---------------------------------------------------------------------- + +maybe_sort(L) when is_list(L) -> + lists:sort(L); +maybe_sort(X) -> + X. + + +%% ---------------------------------------------------------------------- + +atmost_once(Type, Val) -> + error({atmost_once, {Type, Val}}). + +wrong_type(Type, Val) -> + error({wrong_type, {Type, Val}}). + +wrong_type(Type, Val1, Val2) -> + error({wrong_type, {Type, Val1, Val2}}). + +not_equal(What, Val1, Val2) -> + error({not_equal, {What, Val1, Val2}}). + +error(Reason) -> + throw({error, Reason}). + + +%% ---------------------------------------------------------------------- + +d(F) -> + d(F, []). + +d(F, A) -> + d(get(dbg), F, A). + +d(true, F, A) -> + io:format("DBG:" ++ F ++ "~n", A); +d(_, _, _) -> + ok. + diff --git a/lib/megaco/test/megaco_test_tcp_generator.erl b/lib/megaco/test/megaco_test_tcp_generator.erl new file mode 100644 index 0000000000..e4f27f32f5 --- /dev/null +++ b/lib/megaco/test/megaco_test_tcp_generator.erl @@ -0,0 +1,504 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: megaco_tcp sequence generator for the megaco test suite +%%---------------------------------------------------------------------- + +-module(megaco_test_tcp_generator). + +-behaviour(megaco_test_generator). + +%% API +-export([ + start_link/1, start_link/2, + stop/1, + exec/2, exec/3 + ]). + +%% genarator behaviour callback exports +-export([ + init/1, + handle_parse/2, + handle_exec/2, + terminate/2 + ]). + + +-record(state, + { + listen, % Listen socket + connection, % Connection socket + encode, % Encode fun + decode, % Decode fun + result = [] % Accumulated results from exec + }). + + +%%---------------------------------------------------------------------- +%% API +%%---------------------------------------------------------------------- + +start_link(Name) -> + megaco_test_generator:start_link(?MODULE, [], Name). + +start_link(Name, Node) -> + megaco_test_generator:start_link(?MODULE, [], Name, Node). + +stop(Server) -> + megaco_test_generator:stop(Server). + +exec(Server, Instructions) when is_list(Instructions) -> + megaco_test_generator:exec(Server, Instructions). + +exec(Server, Instructions, Timeout) when is_list(Instructions) -> + megaco_test_generator:exec(Server, Instructions, Timeout). + + +%%---------------------------------------------------------------------- +%% generator callback functions +%%---------------------------------------------------------------------- + +init([]) -> + {ok, #state{}}. + + +%% ----- instruction parser ----- + +handle_parse({debug, Debug} = Instruction, State) + when (Debug == true) orelse (Debug == false) -> + {ok, Instruction, State}; + +handle_parse({decode, Decode} = Instruction, State) + when is_function(Decode) -> + {ok, Instruction, State}; + +handle_parse({encode, Encode} = Instruction, State) + when is_function(Encode) -> + {ok, Instruction, State}; + +handle_parse(disconnect = Instruction, State) -> + {ok, Instruction, State}; + +handle_parse({listen, Port} = Instruction, State) + when is_integer(Port) andalso (Port >= 0) -> + {ok, Instruction, State}; + +handle_parse({expect_accept, any} = _Instruction, State) -> + {ok, {expect_accept, {any, infinity}}, State}; + +handle_parse({expect_accept, {any, To}} = Instruction, State) + when (is_integer(To) andalso (To >= 0)) orelse (To == infinity) -> + {ok, Instruction, State}; + +handle_parse({expect_accept, {Host, To}} = _Instruction, State) + when (is_integer(To) andalso (To >= 0)) orelse (To == infinity) -> + case inet:getaddr(Host, inet) of + {ok, Addr} -> + Instruction = {expect_accept, {Addr, To}}, + {ok, Instruction, State}; + {error, Reason} -> + {error, {bad_host, Host, Reason}} + end; + +handle_parse({expect_accept, Host} = _Instruction, State) -> + case inet:getaddr(Host, inet) of + {ok, Addr} -> + Instruction = {expect_accept, {Addr, infinity}}, + {ok, Instruction, State}; + {error, Reason} -> + {error, {bad_host, Host, Reason}} + end; + +handle_parse({active, NewState} = Instruction, State) + when (NewState == true) orelse + (NewState == false) orelse + (NewState == once) -> + {ok, Instruction, State}; + +handle_parse({connect, Port} = _Instruction, State) + when is_integer(Port) andalso (Port >= 0) -> + Host = + case inet:gethostname() of + {ok, Hostname} -> + Hostname; + {error, Reason1} -> + error({failed_geting_own_hostname, Reason1}) + end, + case inet:getaddr(Host, inet) of + {ok, Address} -> + Instruction = {connect, {Address, Port, infinity}}, + {ok, Instruction, State}; + {error, Reason2} -> + {error, {bad_host, Host, Reason2}} + end; + +handle_parse({connect, {Port, To}} = _Instruction, State) + when (is_integer(Port) andalso + (Port >= 0)) andalso ((is_integer(To) andalso (To >= 0)) orelse + (To == infinity)) -> + Host = + case inet:gethostname() of + {ok, Hostname} -> + Hostname; + {error, Reason1} -> + error({failed_geting_own_hostname, Reason1}) + end, + case inet:getaddr(Host, inet) of + {ok, Address} -> + Instruction = {connect, {Address, Port, To}}, + {ok, Instruction, State}; + {error, Reason2} -> + {error, {bad_host, Host, Reason2}} + end; + +handle_parse({connect, {Host, Port}} = _Instruction, State) + when (is_integer(Port) andalso (Port >= 0)) -> + case inet:getaddr(Host, inet) of + {ok, Address} -> + Instruction = {connect, {Address, Port, infinity}}, + {ok, Instruction, State}; + {error, Reason} -> + {error, {bad_host, Host, Reason}} + end; + +handle_parse({connect, {Host, Port, To}} = _Instruction, State) + when (is_integer(Port) andalso + (Port >= 0)) andalso ((is_integer(To) andalso (To >= 0)) orelse + (To == infinity)) -> + case inet:getaddr(Host, inet) of + {ok, Address} -> + Instruction = {connect, {Address, Port, To}}, + {ok, Instruction, State}; + {error, Reason} -> + {error, {bad_host, Host, Reason}} + end; + +handle_parse({sleep, To} = Instruction, State) + when is_integer(To) andalso (To > 0) -> + {ok, Instruction, State}; + +handle_parse({expect_nothing, To} = Instruction, State) + when is_integer(To) andalso (To > 0) -> + {ok, Instruction, State}; + +handle_parse({expect_closed, To} = Instruction, State) + when is_integer(To) andalso (To > 0) -> + {ok, Instruction, State}; + +handle_parse({expect_receive, Desc, Verify} = _Instruction, State) + when is_list(Desc) andalso is_function(Verify) -> + Instruction = {expect_receive, Desc, {Verify, infinity}}, + {ok, Instruction, State}; + +handle_parse({expect_receive, Desc, {Verify, To}} = Instruction, State) + when is_list(Desc) andalso + is_function(Verify) andalso + ((is_integer(To) andalso (To >= 0)) orelse (To == infinity)) -> + {ok, Instruction, State}; + +handle_parse({send, Desc, Msg} = Instruction, State) + when is_list(Desc) andalso (is_tuple(Msg) orelse is_binary(Msg)) -> + {ok, Instruction, State}; + +handle_parse({trigger, Desc, Trigger} = Instruction, State) + when is_list(Desc) andalso is_function(Trigger) -> + {ok, Instruction, State}; + +handle_parse(Instruction, _State) -> + {error, {unknown_instruction, Instruction}}. + + +%% ----- instruction exececutor ----- + +handle_exec({debug, Debug}, + State) -> + p("debug: ~p", [Debug]), + put(debug, Debug), + {ok, State}; + +handle_exec({encode, Encode}, + State) -> + p("encode: ~p", [Encode]), + {ok, State#state{encode = Encode}}; + +handle_exec({decode, Decode}, + State) -> + p("Decode: ~p", [Decode]), + {ok, State#state{decode = Decode}}; + +handle_exec(disconnect, + #state{listen = Listen, + connection = Sock, + result = Res} = State) -> + p("disconnect"), + (catch gen_tcp:close(Sock)), + (catch gen_tcp:close(Listen)), + {ok, State#state{listen = undefined, + connection = undefined, + result = [disconnected|Res]}}; + +handle_exec({listen, Port}, #state{result = Res} = State) -> + p("listen to ~p", [Port]), + Opts = [binary, + {packet, tpkt}, + {active, false}, + {reuseaddr, true}, + {nodelay, true}], + case (catch gen_tcp:listen(Port, Opts)) of + {ok, Listen} -> + d("listen -> listen socket created"), + {ok, State#state{listen = Listen, result = [listening | Res]}}; + {error, Reason} -> + e("failed creating listen socket: ~p", [Reason]), + {error, {failed_creating_listen_socket, Reason, Res}} + end; + +handle_exec({expect_accept, {Addr, To}}, + #state{listen = Listen, + result = Res} = State) -> + p("expect_accept from ~p (~p)", [Addr, To]), + case (catch gen_tcp:accept(Listen, To)) of + {ok, Sock} -> + d("expect_accept -> connection accepted"), + case (catch inet:peername(Sock)) of + {ok, {Addr, _Port}} -> + d("expect_accept -> valid address"), + NewState = + State#state{connection = Sock, + result = [{connected, Addr}|Res]}, + {ok, NewState}; + {ok, {OtherAddr, _Port}} when Addr == any -> + d("expect_accept -> valid (~p)", [OtherAddr]), + NewState = + State#state{connection = Sock, + result = [{connected, OtherAddr}|Res]}, + {ok, NewState}; + {ok, AddrAndPort} -> + {error, {invalid_connect, AddrAndPort, Res}}; + {error, Reason} -> + e("failed getting peername for socket: ~p", [Reason]), + (catch gen_tcp:close(Sock)), + {error, {failed_getting_peername, Sock, Reason}} + end; + {error, Reason} -> + e("failed accepting connection: ~p", [Reason]), + (catch gen_tcp:close(Listen)), + {error, {failed_accepting_conection, Reason, Listen}} + end; + +handle_exec({active, NewState}, + #state{connection = Sock, + result = Res} = State) -> + p("active to ~p", [NewState]), + case inet:setopts(Sock, [{active, NewState}]) of + ok -> + d("active -> state changed"), + {ok, State#state{result = [{active, NewState}|Res]}}; + {error, Reason} -> + e("failed changing active state to ~w: ~p", [NewState, Reason]), + {error, {failed_setting_active, Reason}} + end; + +handle_exec({connect, {Addr, Port, To}}, + #state{result = Res} = State) -> + p("connect to ~p, ~p", [Addr, Port]), + Opts = [binary, {packet, tpkt}, {active, once}, {nodelay, true}], + case (catch gen_tcp:connect(Addr, Port, Opts, To)) of + {ok, Sock} -> + d("connect -> connected"), + {ok, State#state{connection = Sock, + result = [{connected, Addr, Port}|Res]}}; + {error, Reason} -> + e("failed connecting: ~p", [Reason]), + {error, {failed_connect, Addr, Port, Reason}} + end; + +%% Already encoded +handle_exec({send, Desc, Bin}, + #state{connection = Sock, + result = Res} = State) + when is_binary(Bin) -> + p("send ~s message", [Desc]), + NewBin = add_tpkt_header(Bin), + d("send -> tpkt header added [~w], now send", [sz(NewBin)]), + case (catch gen_tcp:send(Sock, NewBin)) of + ok -> + d("send -> message sent"), + {ok, State#state{result = [{sent, Desc}|Res]}}; + {error, Reason} -> + e("send -> send failed: ~n~p",[Reason]), + {error, {failed_send, Reason}} + end; + +handle_exec({send, Desc, Msg}, + #state{connection = Sock, + encode = Encode, + result = Res} = State) -> + p("send ~s message", [Desc]), + case (catch Encode(Msg)) of + {ok, Bin} -> + d("send -> message encoded [~w], now add tpkt header: ~n~s", + [sz(Bin), binary_to_list(Bin)]), + NewBin = add_tpkt_header(Bin), + d("send -> tpkt header added [~w], now send", [sz(NewBin)]), + case (catch gen_tcp:send(Sock, NewBin)) of + ok -> + d("send -> message sent"), + {ok, State#state{result = [{sent, Desc}|Res]}}; + {error, Reason} -> + e("send -> send failed: ~n~p", [Reason]), + {error, {failed_send, Reason}} + end; + Error -> + e("send -> encode failed: ~n~p", [Error]), + {error, {encode_failed, Error}} + end; + +handle_exec({expect_receive, Desc, {Verify, To}}, + #state{connection = Sock, + decode = Decode, + result = Acc} = State) -> + p("expect_receive ~s message", [Desc]), + inet:setopts(Sock, [{active, once}]), + receive + {tcp, Sock, <<3:8, _X:8, Length:16, Msg/binary>>} -> + d("expect_receive -> received message: Length = ~p", [Length]), + case (catch Decode(Msg)) of + {ok, MegaMsg} when is_tuple(MegaMsg) -> + d("expect_receive -> decode successfull, now verify"), + case (catch Verify(MegaMsg)) of + {ok, Res} -> + d("expect_receive -> verify successfull"), + {ok, State#state{result = [Res|Acc]}}; + Else -> + e("failed to verify message: ~n~p~n~p", + [Else, MegaMsg]), + {error, {expect_receive, {verify_failed, Else}}} + end; + Error -> + e("failed decoding message: ~p", [Error]), + {error, {expect_receive, Error}} + end; + Else -> + e("received unknown message: ~p", [Else]), + {error, {expect_receive, {unexpected_message, Else}}} + after To -> + {error, {expect_receive, timeout}} + end; + +handle_exec({expect_closed, To}, + #state{connection = Sock, + result = Acc} = State) -> + p("expect_closed ~w", [To]), + inet:setopts(Sock, [{active, once}]), + p("expect_closed - await closed", []), + receive + {tcp_closed, Sock} -> + p("expect_closed - received closed"), + {ok, State#state{connection = undefined, + result = [closed|Acc]}} + after To -> + e("expect_closed timeout after ~w", [To]), + {error, {expect_closed, timeout}} + end; + +handle_exec({expect_nothing, To}, + #state{connection = Sock, + result = Acc} = State) -> + p("expect_nothing ~w", [To]), + inet:setopts(Sock, [{active, once}]), + p("expect_nothing - await anything", []), + receive + Any -> + e("expect_nothing - received: ~p", [Any]), + {error, {expect_nothing, Any}} + after To -> + p("expect_nothing timeout after ~w", [To]), + {ok, State#state{result = [{nothing, To}|Acc]}} + end; + +handle_exec({trigger, Desc, Trigger}, + #state{result = Acc} = State) when is_function(Trigger) -> + p("trigger: ~s", [Desc]), + Trigger(), + {ok, State#state{result = [triggered|Acc]}}; + +handle_exec({sleep, To}, + #state{result = Acc} = State) -> + p("sleep ~p", [To]), + sleep(To), + {ok, State#state{result = [{slept, To}|Acc]}}; + +handle_exec(Instruction, _State) -> + {error, {unknown_instruction, Instruction}}. + + +%% ----- terminate ----- + +terminate(normal, #state{listen = Listen, + connection = Sock, + result = Result}) -> + (catch gen_tcp:close(Sock)), + (catch gen_tcp:close(Listen)), + {ok, Result}; +terminate(Reason, #state{listen = Listen, + connection = Sock, + result = Result}) -> + (catch gen_tcp:close(Sock)), + (catch gen_tcp:close(Listen)), + {error, {Reason, Result}}. + + +%%---------------------------------------------------------------------- +%% internal utility functions +%%---------------------------------------------------------------------- + +error(Reason) -> + throw({error, Reason}). + + +%%% ---------------------------------------------------------------- + +add_tpkt_header(Bin) when is_binary(Bin) -> + L = size(Bin) + 4, + SZ1 = ((L) bsr 8) band 16#ff, + SZ2 = (L) band 16#ff, + <<3, 0, SZ1, SZ2, Bin/binary>>; +add_tpkt_header(IOList) when is_list(IOList) -> + add_tpkt_header(list_to_binary(IOList)). + +sleep(X) -> megaco_test_generator:sleep(X). + +sz(X) -> megaco_test_generator:sz(X). + + +%%% ---------------------------------------------------------------- + +d(F) -> megaco_test_generator:debug(F). +d(F, A) -> megaco_test_generator:debug(F, A). + +e(F, A) -> megaco_test_generator:error(F, A). + +p(F ) -> p("", F, []). +p(F, A) -> p("", F, A). +p(P, F, A) -> megaco_test_generator:print(P, F, A). + + diff --git a/lib/megaco/test/megaco_timer_test.erl b/lib/megaco/test/megaco_timer_test.erl new file mode 100644 index 0000000000..8bcfc5a907 --- /dev/null +++ b/lib/megaco/test/megaco_timer_test.erl @@ -0,0 +1,472 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Verify the application specifics of the Megaco application +%%---------------------------------------------------------------------- +-module(megaco_timer_test). + +-export([ + t/0, t/1, + init_per_testcase/2, fin_per_testcase/2, + + all/1, + + simple/1, + simple_init/1, + simple_usage/1, + + integer_timer/1, + integer_timer_start_and_expire/1, + integer_timer_start_and_stop/1%% , + +%% incr_timer/1 + + ]). + +-export([ + timeout/3 + ]). + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). + + +-define(TEST_VERBOSITY, info). % silence | info | debug + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + +%% Test server callbacks +%% init_per_testcase(multi_user_extreme_load = Case, Config) -> +%% C = lists:keydelete(tc_timeout, 1, Config), +%% do_init_per_testcase(Case, [{tc_timeout, min(20)}|C]); +init_per_testcase(Case, Config) -> + do_init_per_testcase(Case, Config). + +do_init_per_testcase(Case, Config) -> + process_flag(trap_exit, true), + {ok, _Pid} = megaco_monitor:start_link(), + megaco_test_lib:init_per_testcase(Case, [{monitor_running, true}|Config]). + +fin_per_testcase(Case, Config) -> + io:format("fin_per_testcase -> entry with" + "~n Case: ~p" + "~n Config: ~p" + "~n", [Case, Config]), + process_flag(trap_exit, false), + case lists:keydelete(monitor_running, 1, Config) of + Config -> + megaco_test_lib:fin_per_testcase(Case, Config); + Config2 -> + megaco_monitor:stop(), + megaco_test_lib:fin_per_testcase(Case, Config2) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all(suite) -> + Cases = + [ + simple, + integer_timer%% , +%% incr_timer + ], + Cases. + + +simple(suite) -> + Cases = + [ + simple_init, + simple_usage + ], + Cases. + + +integer_timer(suite) -> + Cases = + [ + integer_timer_start_and_expire, + integer_timer_start_and_stop + ], + Cases. + + +%% incr_timer(suite) -> +%% Cases = +%% [ +%% ], +%% Cases. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +simple_init(suite) -> + []; +simple_init(doc) -> + []; +simple_init(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(tc, si), + put(sname, "TEST"), + put(verbosity, info), + i("starting"), + + Init = + fun(Tmr) -> + case (catch megaco_timer:init(Tmr)) of + {WaitFor, {NewTmr, _}} when + (((WaitFor == infinity) or is_integer(WaitFor)) andalso + is_record(NewTmr, megaco_incr_timer) andalso + (is_record(Tmr, megaco_incr_timer) andalso + (Tmr#megaco_incr_timer.max_retries == infinity_restartable))) -> + ok; + {WaitFor, NewTmr} when + (((WaitFor == infinity) or is_integer(WaitFor)) andalso + ((NewTmr == timeout) or is_record(NewTmr, megaco_incr_timer))) -> + ok; + X -> + d("initiation of timer failed: " + "~n X: ~p", [X]), + {error, X} + end + end, + Verify = + fun(A, A) -> + ok; + (error, {error, Reason}) -> + d("Error reason: ~p", [Reason]), + ok; + (A, B) -> + d("unexpected result: " + "~n Expected: ~p" + "~n Actual: ~p", [A, B]), + error({unexpected_result, A, B}) + end, + VerifyTMR = + fun(false, Tmr) -> + not megaco_timer:verify(Tmr); + (true, Tmr) -> + megaco_timer:verify(Tmr) + end, + + d(" 1) verify infinity timer"), + TMR01 = infinity, + Verify(true, VerifyTMR(true, TMR01)), + Verify(ok, Init(TMR01)), + + d(" 2) verify integer (2007) timer"), + TMR02 = 2007, + Verify(true, VerifyTMR(true, TMR02)), + Verify(ok, Init(TMR02)), + + d(" 3) verify default megaco incr timer timer"), + TMR03 = #megaco_incr_timer{}, + Verify(true, VerifyTMR(true, TMR03)), + Verify(ok, Init(TMR03)), + + d(" 4) verify megaco incr timer timer"), + TMR04 = #megaco_incr_timer{max_retries = infinity_restartable}, + Verify(true, VerifyTMR(true, TMR04)), + Verify(ok, Init(TMR04)), + + d(" 5) verify megaco incr timer timer"), + TMR05 = #megaco_incr_timer{incr = -1}, %% This is new + Verify(true, VerifyTMR(true, TMR05)), + Verify(ok, Init(TMR05)), + + d(" 6) verify invalid timer"), + TMR06 = infinit, + Verify(true, VerifyTMR(false, TMR06)), + Verify(error, Init(TMR06)), + + d(" 7) verify invalid timer"), + TMR07 = -2007, + Verify(true, VerifyTMR(false, TMR07)), + Verify(error, Init(TMR07)), + + d(" 8) verify invalid timer"), + TMR08 = 20.33, + Verify(true, VerifyTMR(false, TMR08)), + Verify(error, Init(TMR08)), + + d(" 9) verify invalid timer"), + TMR09 = -20.33, + Verify(true, VerifyTMR(false, TMR09)), + Verify(error, Init(TMR09)), + + d("10) verify invalid timer"), + TMR10 = "kalle anka", + Verify(true, VerifyTMR(false, TMR10)), + Verify(error, Init(TMR10)), + + d("11) verify invalid timer"), + TMR11 = #megaco_incr_timer{wait_for = 10, + factor = 1, + incr = 0, + max_retries = infinit}, + Verify(true, VerifyTMR(false, TMR11)), + Verify(error, Init(TMR11)), + + i("done", []), + ok. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +simple_usage(suite) -> + []; +simple_usage(doc) -> + []; +simple_usage(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(tc, su), + put(sname, "TEST"), + i("starting"), + + Verify = fun(Tmr) -> megaco_timer:verify(Tmr) end, + Init = fun(Tmr) -> megaco_timer:init(Tmr) end, + Restart = fun(Tmr) -> megaco_timer:restart(Tmr) end, + + VerifyRes = + fun(A, A) -> + ok; + (A, B) -> + error({unexpected_result, A, B}) + end, + + + %% Timer 1 + d(" 1) verify (infinity) timer"), + TMR01 = infinity, + VerifyRes(true, Verify(TMR01)), + d(" 1) init (infinity) timer"), + VerifyRes({TMR01, timeout}, Init(TMR01)), + + %% Timer 2 + d(" 2) verify (integer) timer"), + TMR02 = 1000, + VerifyRes(true, Verify(TMR02)), + d(" 2) init (integer) timer"), + VerifyRes({TMR02, timeout}, Init(TMR02)), + + %% Timer 3 + d(" 3) verify (megaco_incr_timer) timer"), + TMR03 = #megaco_incr_timer{wait_for = TMR02, + factor = 1, + incr = 0, + max_retries = infinity}, + VerifyRes(true, Verify(TMR03)), + d(" 3) init (megaco_incr_timer) timer"), + {TMR02, NewTMR03_1} = Init(TMR03), + d(" 3) restart (megaco_incr_timer) timer"), + {TMR02, _} = Restart(NewTMR03_1), + + %% Timer 4 + d(" 4) verify (megaco_incr_timer) timer"), + TMR04 = #megaco_incr_timer{wait_for = 1000, + factor = 1, + incr = 0, + max_retries = 2}, + VerifyRes(true, Verify(TMR04)), + d(" 4) init (megaco_incr_timer) timer"), + {TMR02, NewTMR04_1} = Init(TMR04), + d(" 4) restart (megaco_incr_timer) timer"), + {TMR02, NewTMR04_2} = Restart(NewTMR04_1), + d(" 4) last restart (megaco_incr_timer) timer"), + {TMR02, timeout} = Restart(NewTMR04_2), + + %% Timer 5 + d(" 5) verify (megaco_incr_timer) timer"), + TMR05 = #megaco_incr_timer{wait_for = 1000, + factor = 1, + incr = -300, + max_retries = infinity}, + VerifyRes(true, Verify(TMR05)), + d(" 5) init (megaco_incr_timer) timer"), + {TMR02, NewTMR05_1} = Init(TMR05), + d(" 5) restart (1) (megaco_incr_timer) timer"), + TMR05_1 = TMR02-300, + {TMR05_1, NewTMR05_2} = Restart(NewTMR05_1), + d(" 5) restart (2) (megaco_incr_timer) timer"), + TMR05_2 = TMR05_1-300, + {TMR05_2, NewTMR05_3} = Restart(NewTMR05_2), + d(" 5) restart (3) (megaco_incr_timer) timer"), + TMR05_3 = TMR05_2-300, + {TMR05_3, NewTMR05_4} = Restart(NewTMR05_3), + d(" 5) restart (4) (megaco_incr_timer) timer"), + {0, NewTMR05_5} = Restart(NewTMR05_4), + d(" 5) restart (5) (megaco_incr_timer) timer"), + {0, _} = Restart(NewTMR05_5), + + i("done", []), + ok. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +integer_timer_start_and_expire(suite) -> + []; +integer_timer_start_and_expire(doc) -> + []; +integer_timer_start_and_expire(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(tc, itsae), + put(sname, "TEST"), + i("starting"), + + Timeout = 5000, + Ref = tmr_start(Timeout), + receive + {timeout, Timeout} -> + ok + after Timeout + 100 -> + tmr_stop(Ref), + error(no_timeout) + end, + + i("done", []), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +integer_timer_start_and_stop(suite) -> + []; +integer_timer_start_and_stop(doc) -> + []; +integer_timer_start_and_stop(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(tc, itsas), + put(sname, "TEST"), + i("starting"), + + Timeout = 5000, + Ref = tmr_start(Timeout), + receive + {timeout, Timeout} -> + error(bad_timeout) + after Timeout - 100 -> + tmr_stop(Ref) + end, + + %% Make sure it does not reach us after we attempted to stop it. + receive + {timeout, Timeout} -> + error(unexpected_timeout) + after Timeout -> + ok + end, + + i("done", []), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +tmr_start(Timeout) -> + Pid = self(), + megaco_monitor:apply_after(?MODULE, timeout, [Pid, Timeout, get(tc)], Timeout). + +tmr_stop(Ref) -> + megaco_monitor:cancel_apply_after(Ref). + +timeout(Pid, Timeout, Tc) -> + put(sname, timer), + put(tc, Tc), + print("DBG", + "timeout -> entry with" + "~n Pid: ~p" + "~n Timeout: ~p", [Pid, Timeout]), + Pid ! {timeout, Timeout}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% tim() -> +%% {A,B,C} = erlang:now(), +%% A*1000000000+B*1000+(C div 1000). + +%% min(M) -> timer:minutes(M). + +%% sleep(X) -> receive after X -> ok end. + +error(Reason) -> throw({error, Reason}). + +%% error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +i(F) -> + i(F, []). + +i(F, A) -> + print(info, "INF", F, A). + +d(F) -> + d(F, []). + +d(F, A) -> + print(debug, "DBG", F, A). + +printable(_, debug) -> true; +printable(info, info) -> true; +printable(_,_) -> false. + + +print(Severity, Prefix, F, A) -> + print1(printable(Severity, get(verbosity)), Prefix, F, A). + +print1(true, Prefix, F, A) -> + print(Prefix, F, A); +print1(_, _, _, _) -> + ok. + +print(Prefix, F, A) -> + io:format("*** [~s] ~s ~p ~s:~w ***" + "~n " ++ F ++ "~n", + [formated_timestamp(), Prefix, self(), get(sname), get(tc) | A]). + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +formated_timestamp() -> + format_timestamp(now()). + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). diff --git a/lib/megaco/test/megaco_trans_test.erl b/lib/megaco/test/megaco_trans_test.erl new file mode 100644 index 0000000000..44d4b3fff7 --- /dev/null +++ b/lib/megaco/test/megaco_trans_test.erl @@ -0,0 +1,9401 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Verify that the transaction sender works with acks. +%% +%% Test: ts:run(megaco, megaco_trans_test, [batch]). +%% +%%---------------------------------------------------------------------- +-module(megaco_trans_test). + +-compile(export_all). + +-include("megaco_test_lib.hrl"). +-include_lib("megaco/include/megaco.hrl"). +-include_lib("megaco/include/megaco_message_v1.hrl"). + +-define(VERSION, 1). +-define(TEST_VERBOSITY, debug). +-define(MGC_VERBOSITY, debug). +-define(MG_VERBOSITY, debug). + +-define(LOAD_COUNTER_START, 10). +-define(A4444, ["11111111", "00000000", "00000000"]). +-define(A4445, ["11111111", "00000000", "11111111"]). +-define(A5555, ["11111111", "11111111", "00000000"]). +-define(A5556, ["11111111", "11111111", "11111111"]). + +-define(MGC_START(Pid, Mid, ET, Verb), + megaco_test_mgc:start(Pid, Mid, ET, Verb)). +-define(MGC_STOP(Pid), megaco_test_mgc:stop(Pid)). +-define(MGC_GET_STATS(Pid, No), megaco_test_mgc:get_stats(Pid, No)). +-define(MGC_RESET_STATS(Pid), megaco_test_mgc:reset_stats(Pid)). +-define(MGC_REQ_DISC(Pid,To), megaco_test_mgc:request_discard(Pid,To)). +-define(MGC_REQ_PEND(Pid,To), megaco_test_mgc:request_pending(Pid,To)). +-define(MGC_REQ_HAND(Pid), megaco_test_mgc:request_handle(Pid)). +-define(MGC_REQ_HANDS(Pid), megaco_test_mgc:request_handle_sloppy(Pid)). +-define(MGC_UPDATE_UI(Pid,Tag,Val), + megaco_test_mgc:update_user_info(Pid,Tag,Val)). +-define(MGC_UPDATE_CI(Pid,Tag,Val), + megaco_test_mgc:update_conn_info(Pid,Tag,Val)). +-define(MGC_USER_INFO(Pid,Tag), megaco_test_mgc:user_info(Pid,Tag)). +-define(MGC_CONN_INFO(Pid,Tag), megaco_test_mgc:conn_info(Pid,Tag)). +-define(MGC_ACK_INFO(Pid,To), megaco_test_mgc:ack_info(Pid,To)). +-define(MGC_REQ_INFO(Pid,To), megaco_test_mgc:req_info(Pid,To)). + +-define(MG_START(Pid, Mid, Enc, Transp, Conf, Verb), + megaco_test_mg:start(Pid, Mid, Enc, Transp, Conf, Verb)). +-define(MG_STOP(Pid), megaco_test_mg:stop(Pid)). +-define(MG_GET_STATS(Pid), megaco_test_mg:get_stats(Pid)). +-define(MG_RESET_STATS(Pid), megaco_test_mg:reset_stats(Pid)). +-define(MG_SERV_CHANGE(Pid), megaco_test_mg:service_change(Pid)). +-define(MG_NOTIF_RAR(Pid), megaco_test_mg:notify_request_and_reply(Pid)). +-define(MG_NOTIF_REQ(Pid), megaco_test_mg:notify_request(Pid)). +-define(MG_NOTIF_AR(Pid), megaco_test_mg:await_notify_reply(Pid)). +-define(MG_CANCEL(Pid,R), megaco_test_mg:cancel_request(Pid,R)). +-define(MG_APPLY_LOAD(Pid,CntStart), megaco_test_mg:apply_load(Pid,CntStart)). +-define(MG_UPDATE_UI(Pid,Tag,Val), + megaco_test_mg:update_user_info(Pid,Tag,Val)). +-define(MG_UPDATE_CI(Pid,Tag,Val), + megaco_test_mg:update_conn_info(Pid,Tag,Val)). +-define(MG_USER_INFO(Pid,Tag), megaco_test_mg:user_info(Pid,Tag)). +-define(MG_CONN_INFO(Pid,Tag), megaco_test_mg:conn_info(Pid,Tag)). +-define(MG_GRP_REQ(Pid,N), megaco_test_mg:group_requests(Pid,N)). +-define(MG_ACK_INFO(Pid,To), megaco_test_mg:ack_info(Pid,To)). +-define(MG_REP_INFO(Pid,To), megaco_test_mg:rep_info(Pid,To)). + +t() -> megaco_test_lib:t(?MODULE). +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + + +%% Test server callbacks +init_per_testcase(multi_ack_maxcount = Case, Config) -> + process_flag(trap_exit, true), + C = lists:keydelete(tc_timeout, 1, Config), + megaco_test_lib:init_per_testcase(Case, [{tc_timeout,timer:minutes(10)}|C]); +init_per_testcase(Case, Config) -> + process_flag(trap_exit, true), + megaco_test_lib:init_per_testcase(Case, Config). + +fin_per_testcase(Case, Config) -> + process_flag(trap_exit, false), + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all(suite) -> + [ + ack, + trans_req, + trans_req_and_ack, + pending, + reply, + + tickets + ]. + +ack(suite) -> + [ + single_ack, + multi_ack_timeout, + multi_ack_maxcount + ]. + +trans_req(suite) -> + [ + single_trans_req, + multi_trans_req_timeout, + multi_trans_req_maxcount1, + multi_trans_req_maxcount2, + multi_trans_req_maxsize1, + multi_trans_req_maxsize2 + ]. + +trans_req_and_ack(suite) -> + [ + single_trans_req_and_ack, + multi_trans_req_and_ack_timeout, + multi_trans_req_and_ack_ackmaxcount, + multi_trans_req_and_ack_reqmaxcount, + multi_trans_req_and_ack_maxsize1, + multi_trans_req_and_ack_maxsize2 + ]. + +pending(suite) -> + [ + single_trans_req_and_pending, + multi_trans_req_and_pending, + multi_trans_req_and_ack_and_pending, + multi_ack_and_pending + ]. + +reply(suite) -> + [ + multi_trans_req_and_reply, + multi_trans_req_and_ack_and_reply, + multi_ack_and_reply + ]. + +tickets(suite) -> + [ + otp_7192 + ]. + +otp_7192(suite) -> + [ + otp_7192_1, + otp_7192_2, + otp_7192_3 + ]. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +single_ack(suite) -> + []; +single_ack(doc) -> + []; +single_ack(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, single_ack), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + %% Start the MGC and MGs + i("[MGC] start"), + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + {ok, Mgc} = + ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY), + + i("[MG] start"), + %% MgConf0 = [{MgNode, "mg", text, tcp, ?MG_VERBOSITY}], + MgMid = {deviceName, "mg"}, + MgConfig = [{auto_ack, true}, {trans_timer, 5000}, {trans_ack, true}], + {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY), + + d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]), + + i("[MG] connect to the MGC (service change)"), + ServChRes = ?MG_SERV_CHANGE(Mg), + d("service change result: ~p", [ServChRes]), + + d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]), + + d("ensure the megaco stack calls the handle_trans_ack callback"), + ?MGC_REQ_HANDS(Mgc), + + d("tell the MGC to send the ack's to us"), + ?MGC_ACK_INFO(Mgc, self()), + + d("send the notify"), + ?MG_GRP_REQ(Mg, 1), + + d("send the notify"), + ?MG_NOTIF_REQ(Mg), + + d("await the ack"), + await_ack(Mgc, 1, infinity, ok), + + %% Tell MG to stop + i("[MG] stop"), + ?MG_STOP(Mg), + + %% Tell Mgc to stop + i("[MGC] stop"), + ?MGC_STOP(Mgc), + + i("done", []), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_ack_timeout(suite) -> + []; +multi_ack_timeout(doc) -> + []; +multi_ack_timeout(Config) when is_list(Config) -> + %% <CONDITIONAL-SKIP> + Skippable = [win32, {unix, [darwin, linux]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, multi_ack_timeout), + i("starting"), + + + MaxCount = 20, + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + %% Start the MGC and MGs + i("[MGC] start"), + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + {ok, Mgc} = + ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY), + + i("[MG] start"), + %% MgConf0 = [{MgNode, "mg", text, tcp, ?MG_VERBOSITY}], + MgMid = {deviceName, "mg"}, + MgConfig = [{auto_ack, true}, + {trans_ack, true}, + {trans_timer, 10000}, + {trans_ack_maxcount, MaxCount + 10}], + {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY), + + d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]), + + i("[MG] connect the MGC (service change)"), + ServChRes = ?MG_SERV_CHANGE(Mg), + d("service change result: ~p", [ServChRes]), + + i("wait some time"), + sleep(1000), + + d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]), + + {ok, _OldAction} = ?MGC_REQ_HANDS(Mgc), + + d("tell the MGC to send the ack's to us"), + ?MGC_ACK_INFO(Mgc, self()), + + d("set group size to ~p", [MaxCount]), + ?MG_GRP_REQ(Mg, MaxCount), + + d("[MG] send a group of requests (and await the replies)"), + ?MG_NOTIF_RAR(Mg), + + d("await the ack(s)"), + await_ack(Mgc, MaxCount, 60000, ok), + + i("wait some time before closing down"), + sleep(5000), + + %% Tell MG to stop + i("[MG] stop"), + ?MG_STOP(Mg), + + %% Tell Mgc to stop + i("[MGC] stop"), + ?MGC_STOP(Mgc), + + i("done"), + ok. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_ack_maxcount(suite) -> + []; +multi_ack_maxcount(doc) -> + []; +multi_ack_maxcount(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, multi_ack_maxcount), + i("starting"), + + MaxCount = 10, + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + %% Start the MGC and MGs + i("[MGC] start"), + ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}], + {ok, Mgc} = + ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY), + + i("[MG] start"), + %% MgConf0 = [{MgNode, "mg", text, tcp, ?MG_VERBOSITY}], + MgMid = {deviceName, "mg"}, + MgConfig = [%% {auto_ack, true}, + %% {trans_timer, 120000}, + %% {trans_ack_maxcount, MaxCount} + ], + {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY), + + d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]), + + i("[MG] connect the MGC (service change)"), + ServChRes = ?MG_SERV_CHANGE(Mg), + d("service change result: ~p", [ServChRes]), + + i("wait some time"), + sleep(1000), + + d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]), + + ?MG_UPDATE_CI(Mg,auto_ack,true), + ?MG_UPDATE_CI(Mg,trans_timer,120000), + ?MG_UPDATE_CI(Mg,trans_ack_maxcount,MaxCount), + ?MG_UPDATE_CI(Mg,trans_ack,true), + + d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]), + + {ok, _OldAction} = ?MGC_REQ_HANDS(Mgc), + + d("tell the MGC to send the ack's to us"), + ?MGC_ACK_INFO(Mgc, self()), + + d("set group size to ~p", [MaxCount]), + ?MG_GRP_REQ(Mg, MaxCount), + + d("[MG] send a group of requests (and await the replies)"), + ?MG_NOTIF_RAR(Mg), + + d("await the ack"), + await_ack(Mgc, MaxCount, 60000, ok), + + i("wait some time before closing down"), + sleep(5000), + + + %% Tell MG to stop + i("[MG] stop"), + ?MG_STOP(Mg), + + %% Tell Mgc to stop + i("[MGC] stop"), + ?MGC_STOP(Mgc), + + i("done"), + ok. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +single_trans_req(suite) -> + []; +single_trans_req(doc) -> + []; +single_trans_req(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, single_trans_req), + process_flag(trap_exit, true), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = str_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = str_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(str_mgc_connect_verify_fun(), + {?MODULE, str_mgc_verify_handle_connect, []}). +-define(str_mgc_service_change_req_verify_fun(Mid), + {?MODULE, str_mgc_verify_service_change_req, [Mid]}). +-define(str_mgc_notify_req_verify_fun(), + {?MODULE, str_mgc_verify_notify_request, []}). +-define(str_mgc_disco_verify_fun(), + {?MODULE, str_mgc_verify_handle_disconnect, []}). +-else. +-define(str_mgc_connect_verify_fun(), + fun str_mgc_verify_handle_connect/1). +-define(str_mgc_service_change_req_verify_fun(Mid), + str_mgc_verify_service_change_req_fun(Mid)). +-define(str_mgc_notify_req_verify_fun(), + str_mgc_verify_notify_request_fun()). +-define(str_mgc_disco_verify_fun(), + fun str_mgc_verify_handle_disconnect/1). +-endif. + +str_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?str_mgc_connect_verify_fun(), + ServiceChangeReqVerify = ?str_mgc_service_change_req_verify_fun(Mid), + NotifyReqVerify = ?str_mgc_notify_req_verify_fun(), + DiscoVerify = ?str_mgc_disco_verify_fun(), +%% ConnectVerify = fun str_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = str_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = str_mgc_verify_notify_request_fun(), +%% DiscoVerify = fun str_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, false}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +str_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("str_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +str_mgc_verify_handle_connect(Else) -> + io:format("str_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +str_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + str_mgc_verify_service_change_req(Ev, Mid) + end. + +str_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("str_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [str_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = str_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = str_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = str_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = str_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = str_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +str_mgc_verify_service_change_req(Else, _Mid) -> + io:format("str_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = str_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + + +str_mgc_verify_notify_request_fun() -> + fun(Ev) -> + str_mgc_verify_notify_request(Ev) + end. + +str_mgc_verify_notify_request({handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("str_mgc_verify_notify_request:fun -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [str_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = str_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +str_mgc_verify_notify_request(Else) -> + io:format("str_mgc_verify_notify_request:fun -> unknown" + "~n Else: ~p~n", [Else]), + ED = str_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + + +str_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("str_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +str_mgc_verify_handle_disconnect(Else) -> + io:format("str_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +str_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +str_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = str_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +str_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +str_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = str_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(str_mg_connect_verify_fun(), + {?MODULE, str_mg_verify_handle_connect, []}). +-define(str_mg_service_change_reply_verify_fun(), + {?MODULE, str_mg_verify_service_change_reply, []}). +-define(str_mg_notify_reply_verify_fun(), + {?MODULE, str_mg_verify_notify_reply, []}). +-else. +-define(str_mg_connect_verify_fun(), + fun str_mg_verify_handle_connect/1). +-define(str_mg_service_change_reply_verify_fun(), + fun str_mg_verify_service_change_reply/1). +-define(str_mg_notify_reply_verify_fun(), + fun str_mg_verify_notify_reply/1). +-endif. + +str_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [str_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq = [str_mg_notify_request_ar(1, Tid, 1)], + ConnectVerify = ?str_mg_connect_verify_fun(), + ServiceChangeReplyVerify = ?str_mg_service_change_reply_verify_fun(), + NotifyReplyVerify = ?str_mg_notify_reply_verify_fun(), + %% ConnectVerify = fun str_mg_verify_handle_connect/1, + %% ServiceChangeReplyVerify = fun str_mg_verify_service_change_reply/1, + %% NotifyReplyVerify = fun str_mg_verify_notify_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, max}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_cast, NotifyReq, []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +str_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("str_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +str_mg_verify_handle_connect(Else) -> + io:format("str_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +str_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("str_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +str_mg_verify_service_change_reply(Else) -> + io:format("str_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +str_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("str_mg_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +str_mg_verify_notify_reply(Else) -> + io:format("str_mg_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +str_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +str_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = str_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +str_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +str_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = str_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% Common functions for the single_trans_req test case +%% + +str_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_trans_req_timeout(suite) -> + []; +multi_trans_req_timeout(doc) -> + []; +multi_trans_req_timeout(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, multi_trans_req_timeout), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = mtrt_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = mtrt_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrt_mgc_verify_handle_connect_fun(), + {?MODULE, mtrt_mgc_verify_handle_connect, []}). +-define(mtrt_mgc_verify_service_change_req_fun(Mid), + {?MODULE, mtrt_mgc_verify_service_change_req, [Mid]}). +-define(mtrt_mgc_verify_notify_req_fun(), + {?MODULE, mtrt_mgc_verify_notify_request, []}). +-define(mtrt_mgc_verify_handle_disconnect_fun(), + {?MODULE, mtrt_mgc_verify_handle_disconnect, []}). +-else. +-define(mtrt_mgc_verify_handle_connect_fun(), + fun mtrt_mgc_verify_handle_connect/1). +-define(mtrt_mgc_verify_service_change_req_fun(Mid), + mtrt_mgc_verify_service_change_req_fun(Mid)). +-define(mtrt_mgc_verify_notify_req_fun(), + mtrt_mgc_verify_notify_request_fun()). +-define(mtrt_mgc_verify_handle_disconnect_fun(), + fun mtrt_mgc_verify_handle_disconnect/1). +-endif. + +mtrt_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?mtrt_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?mtrt_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?mtrt_mgc_verify_notify_req_fun(), + DiscoVerify = ?mtrt_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun mtrt_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = mtrt_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = mtrt_mgc_verify_notify_request_fun(), +%% DiscoVerify = fun mtrt_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +mtrt_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrt_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrt_mgc_verify_handle_connect(Else) -> + io:format("mtrt_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrt_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + mtrt_mgc_verify_service_change_req(Ev, Mid) + end. + +mtrt_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("mtrt_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [mtrt_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = mtrt_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = mtrt_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = mtrt_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = mtrt_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = mtrt_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +mtrt_mgc_verify_service_change_req(Else, _Mid) -> + io:format("mtrt_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrt_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrt_mgc_verify_notify_request_fun() -> + fun(Ev) -> + mtrt_mgc_verify_notify_request(Ev) + end. + +mtrt_mgc_verify_notify_request({handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("mtrt_mgc_verify_notify_request:fun -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [mtrt_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = mtrt_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +mtrt_mgc_verify_notify_request(Else) -> + io:format("mtrt_mgc_verify_notify_request:fun -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrt_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrt_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("mtrt_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +mtrt_mgc_verify_handle_disconnect(Else) -> + io:format("mtrt_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +mtrt_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +mtrt_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = mtrt_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrt_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +mtrt_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = mtrt_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrt_mg_verify_handle_connect_fun(), + {?MODULE, mtrt_mg_verify_handle_connect, []}). +-define(mtrt_mg_verify_service_change_reply_fun(), + {?MODULE, mtrt_mg_verify_service_change_reply, []}). +-define(mtrt_mg_verify_notify_reply_fun(), + {?MODULE, mtrt_mg_verify_notify_reply, []}). +-else. +-define(mtrt_mg_verify_handle_connect_fun(), + fun mtrt_mg_verify_handle_connect/1). +-define(mtrt_mg_verify_service_change_reply_fun(), + fun mtrt_mg_verify_service_change_reply/1). +-define(mtrt_mg_verify_notify_reply_fun(), + fun mtrt_mg_verify_notify_reply/1). +-endif. + +mtrt_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [mtrt_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq = [mtrt_mg_notify_request_ar(1, Tid, 1)], + ConnectVerify = ?mtrt_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?mtrt_mg_verify_service_change_reply_fun(), + NotifyReplyVerify = ?mtrt_mg_verify_notify_reply_fun(), + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_update_conn_info, trans_timer, 5000}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {megaco_cast, NotifyReq, []}, + {megaco_cast, NotifyReq, []}, + {megaco_cast, NotifyReq, []}, + {megaco_cast, NotifyReq, []}, + {megaco_cast, NotifyReq, []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +mtrt_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrt_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrt_mg_verify_handle_connect(Else) -> + io:format("mtrt_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrt_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrt_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +mtrt_mg_verify_service_change_reply(Else) -> + io:format("mtrt_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrt_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrt_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +mtrt_mg_verify_notify_reply(Else) -> + io:format("mtrt_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrt_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrt_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = mtrt_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrt_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrt_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = mtrt_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% Common functions for the multi_trans_req_timeout test case +%% + +mtrt_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_trans_req_maxcount1(suite) -> + []; +multi_trans_req_maxcount1(doc) -> + "Test that a message is sent when req_maxcount is reached"; +multi_trans_req_maxcount1(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, multi_trans_req_maxcount1), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = mtrmc1_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = mtrmc1_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrmc1_mgc_verify_handle_connect_fun(), + {?MODULE, mtrmc1_mgc_verify_handle_connect, []}). +-define(mtrmc1_mgc_verify_service_change_req_fun(Mid), + {?MODULE, mtrmc1_mgc_verify_service_change_req, [Mid]}). +-define(mtrmc1_mgc_verify_notify_req_fun(), + {?MODULE, mtrmc1_mgc_verify_notify_request, []}). +-define(mtrmc1_mgc_verify_handle_disconnect_fun(), + {?MODULE, mtrmc1_mgc_verify_handle_disconnect, []}). +-else. +-define(mtrmc1_mgc_verify_handle_connect_fun(), + fun mtrmc1_mgc_verify_handle_connect/1). +-define(mtrmc1_mgc_verify_service_change_req_fun(Mid), + mtrmc1_mgc_verify_service_change_req_fun(Mid)). +-define(mtrmc1_mgc_verify_notify_req_fun(), + mtrmc1_mgc_verify_notify_request_fun()). +-define(mtrmc1_mgc_verify_handle_disconnect_fun(), + fun mtrmc1_mgc_verify_handle_disconnect/1). +-endif. + +mtrmc1_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?mtrmc1_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?mtrmc1_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?mtrmc1_mgc_verify_notify_req_fun(), + DiscoVerify = ?mtrmc1_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun mtrmc1_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = mtrmc1_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = mtrmc1_mgc_verify_notify_request_fun(), +%% DiscoVerify = fun mtrmc1_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +mtrmc1_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrmc1_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrmc1_mgc_verify_handle_connect(Else) -> + io:format("mtrmc1_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrmc1_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + mtrmc1_mgc_verify_service_change_req(Ev, Mid) + end. + +mtrmc1_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("mtrmc1_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [mtrmc1_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = mtrmc1_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = mtrmc1_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = mtrmc1_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = mtrmc1_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = mtrmc1_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +mtrmc1_mgc_verify_service_change_req(Else, _Mid) -> + io:format("mtrmc1_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrmc1_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrmc1_mgc_verify_notify_request_fun() -> + fun(Ev) -> + mtrmc1_mgc_verify_notify_request(Ev) + end. + +mtrmc1_mgc_verify_notify_request({handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("mtrmc1_mgc_verify_notify_request:fun -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [mtrmc1_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = mtrmc1_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +mtrmc1_mgc_verify_notify_request(Else) -> + io:format("mtrmc1_mgc_verify_notify_request:fun -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrmc1_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrmc1_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("mtrmc1_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +mtrmc1_mgc_verify_handle_disconnect(Else) -> + io:format("mtrmc1_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +mtrmc1_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +mtrmc1_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = mtrmc1_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrmc1_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +mtrmc1_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = mtrmc1_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrmc1_mg_verify_handle_connect_fun(), + {?MODULE, mtrmc1_mg_verify_handle_connect, []}). +-define(mtrmc1_mg_verify_service_change_reply_fun(), + {?MODULE, mtrmc1_mg_verify_service_change_reply, []}). +-define(mtrmc1_mg_verify_notify_reply_fun(), + {?MODULE, mtrmc1_mg_verify_notify_reply, []}). +-else. +-define(mtrmc1_mg_verify_handle_connect_fun(), + fun mtrmc1_mg_verify_handle_connect/1). +-define(mtrmc1_mg_verify_service_change_reply_fun(), + fun mtrmc1_mg_verify_service_change_reply/1). +-define(mtrmc1_mg_verify_notify_reply_fun(), + fun mtrmc1_mg_verify_notify_reply/1). +-endif. + +mtrmc1_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [mtrmc1_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq = [mtrmc1_mg_notify_request_ar(1, Tid, 1)], + ConnectVerify = ?mtrmc1_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?mtrmc1_mg_verify_service_change_reply_fun(), + NotifyReplyVerify = ?mtrmc1_mg_verify_notify_reply_fun(), +%% ConnectVerify = fun mtrmc1_mg_verify_handle_connect/1, +%% ServiceChangeReplyVerify = fun mtrmc1_mg_verify_service_change_reply/1, +%% NotifyReplyVerify = fun mtrmc1_mg_verify_notify_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_update_conn_info, trans_req_maxcount, 5}, + {megaco_update_conn_info, trans_req_maxsize, 4096}, + {megaco_update_conn_info, trans_timer, 120000}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {megaco_cast, NotifyReq, []}, + {megaco_cast, NotifyReq, []}, + {megaco_cast, NotifyReq, []}, + {megaco_cast, NotifyReq, []}, + {megaco_cast, NotifyReq, []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +mtrmc1_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrmc1_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrmc1_mg_verify_handle_connect(Else) -> + io:format("mtrmc1_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrmc1_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrmc1_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +mtrmc1_mg_verify_service_change_reply(Else) -> + io:format("mtrmc1_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrmc1_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrmc1_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +mtrmc1_mg_verify_notify_reply(Else) -> + io:format("mtrmc1_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrmc1_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrmc1_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = mtrmc1_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrmc1_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrmc1_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = mtrmc1_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% Common functions for the multi_trans_req_timeout test case +%% + +mtrmc1_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_trans_req_maxcount2(suite) -> + []; +multi_trans_req_maxcount2(doc) -> + "Test that the message is sent when req_maxcount is reached " + "with a request bigger then maxsize limit"; +multi_trans_req_maxcount2(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, multi_trans_req_maxcount2), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = mtrmc2_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = mtrmc2_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrmc2_mgc_verify_handle_connect_fun(), + {?MODULE, mtrmc2_mgc_verify_handle_connect, []}). +-define(mtrmc2_mgc_verify_service_change_req_fun(Mid), + {?MODULE, mtrmc2_mgc_verify_service_change_req, [Mid]}). +-define(mtrmc2_mgc_verify_notify_req_fun(), + {?MODULE, mtrmc2_mgc_verify_notify_request, []}). +-define(mtrmc2_mgc_verify_handle_disconnect_fun(), + {?MODULE, mtrmc2_mgc_verify_handle_disconnect, []}). +-else. +-define(mtrmc2_mgc_verify_handle_connect_fun(), + fun mtrmc2_mgc_verify_handle_connect/1). +-define(mtrmc2_mgc_verify_service_change_req_fun(Mid), + mtrmc2_mgc_verify_service_change_req_fun(Mid)). +-define(mtrmc2_mgc_verify_notify_req_fun(), + mtrmc2_mgc_verify_notify_request_fun()). +-define(mtrmc2_mgc_verify_handle_disconnect_fun(), + fun mtrmc2_mgc_verify_handle_disconnect/1). +-endif. + +mtrmc2_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?mtrmc2_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?mtrmc2_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?mtrmc2_mgc_verify_notify_req_fun(), + DiscoVerify = ?mtrmc2_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun mtrmc2_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = mtrmc2_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = mtrmc2_mgc_verify_notify_request_fun(), +%% DiscoVerify = fun mtrmc2_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +mtrmc2_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrmc2_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrmc2_mgc_verify_handle_connect(Else) -> + io:format("mtrmc2_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrmc2_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + mtrmc2_mgc_verify_service_change_req(Ev, Mid) + end. + +mtrmc2_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("mtrmc2_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [mtrmc2_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = mtrmc2_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = mtrmc2_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = mtrmc2_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = mtrmc2_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = mtrmc2_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +mtrmc2_mgc_verify_service_change_req(Else, _Mid) -> + io:format("mtrmc2_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrmc2_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrmc2_mgc_verify_notify_request_fun() -> + fun(Ev) -> + mtrmc2_mgc_verify_notify_request(Ev) + end. + +mtrmc2_mgc_verify_notify_request({handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("mtrmc2_mgc_verify_notify_request:fun -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = Cid, + commandRequests = [CR]} -> + io:format("mtrmc2_mgc_verify_notify_request:fun -> " + "single command",[]), + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, + [mtrmc2_mgc_notify_reply_ar1(Cid, Tid)]}, + {ok, AR, Reply}; + #'ActionRequest'{contextId = Cid, + commandRequests = CRs} -> + io:format("mtrmc2_mgc_verify_notify_request:fun -> " + "multi command (~w)",[length(CRs)]), + Tids = [Tid || + #'CommandRequest'{command = + {notifyReq, + #'NotifyRequest'{ + terminationID = [Tid]}}} + <- CRs], + Reply = + {discard_ack, + [mtrmc2_mgc_notify_reply_ar2(Cid, Tids)]}, + {ok, AR, Reply}; + _ -> + ED = mtrmc2_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +mtrmc2_mgc_verify_notify_request(Else) -> + io:format("mtrmc2_mgc_verify_notify_request:fun -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrmc2_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrmc2_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("mtrmc2_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +mtrmc2_mgc_verify_handle_disconnect(Else) -> + io:format("mtrmc2_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +mtrmc2_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +mtrmc2_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = mtrmc2_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrmc2_mgc_notify_reply_ar1(Cid, Tid) -> + NR = cre_notifyReply([Tid]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +mtrmc2_mgc_notify_reply_ar2(Cid, Tids) -> + CRs = [cre_cmdReply(cre_notifyReply([Tid])) || Tid <- Tids], + cre_actionReply(Cid, CRs). + +mtrmc2_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = mtrmc2_mgc_notify_reply_ar1(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrmc2_mg_verify_handle_connect_fun(), + {?MODULE, mtrmc2_mg_verify_handle_connect, []}). +-define(mtrmc2_mg_verify_service_change_reply_fun(), + {?MODULE, mtrmc2_mg_verify_service_change_reply, []}). +-define(mtrmc2_mg_verify_notify_reply_fun(), + {?MODULE, mtrmc2_mg_verify_notify_reply, []}). +-else. +-define(mtrmc2_mg_verify_handle_connect_fun(), + fun mtrmc2_mg_verify_handle_connect/1). +-define(mtrmc2_mg_verify_service_change_reply_fun(), + fun mtrmc2_mg_verify_service_change_reply/1). +-define(mtrmc2_mg_verify_notify_reply_fun(), + fun mtrmc2_mg_verify_notify_reply/1). +-endif. + +mtrmc2_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [mtrmc2_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR1 = fun(N) -> + [mtrmc2_mg_notify_request_ar1(N, Tid, N)] + end, + NR2 = fun(N) -> + [mtrmc2_mg_notify_request_ar2(N, Tid, N)] + end, + ConnectVerify = ?mtrmc2_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?mtrmc2_mg_verify_service_change_reply_fun(), + NotifyReplyVerify = ?mtrmc2_mg_verify_notify_reply_fun(), +%% ConnectVerify = fun mtrmc2_mg_verify_handle_connect/1, +%% ServiceChangeReplyVerify = fun mtrmc2_mg_verify_service_change_reply/1, +%% NotifyReplyVerify = fun mtrmc2_mg_verify_notify_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_update_conn_info, trans_req_maxcount, 5}, + {megaco_update_conn_info, trans_req_maxsize, 1024}, + {megaco_update_conn_info, trans_timer, 120000}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {megaco_cast, NR1(1), []}, + {megaco_cast, [NR1(2), NR1(3)], []}, + {megaco_cast, NR1(4), []}, + {megaco_cast, NR2(5), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +mtrmc2_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrmc2_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrmc2_mg_verify_handle_connect(Else) -> + io:format("mtrmc2_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrmc2_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrmc2_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +mtrmc2_mg_verify_service_change_reply(Else) -> + io:format("mtrmc2_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrmc2_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrmc2_mg_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [{notifyReply, _NR}]} -> + io:format("mtrmc2_mg_verify_notify_reply -> " + "single notify reply", []), + {ok, AR, ok}; + #'ActionReply'{commandReply = [{notifyReply, _NR}|_] = CR} -> + io:format("mtrmc2_mg_verify_notify_reply -> " + "multi notify reply: (~w)", [length(CR)]), + {ok, AR, ok}; + _ -> + {error, {invalid_action_reply, AR}, ok} + end; +mtrmc2_mg_verify_notify_reply(Else) -> + io:format("mtrmc2_mg_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrmc2_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrmc2_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = mtrmc2_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrmc2_mg_notify_request_ar1(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrmc2_mg_notify_request_ar2(Rid, Tid, Cid) -> + F = fun(N) -> + T = 22000000 + N, + TS = integer_to_list(T), + TT = cre_timeNotation("19990729", TS), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid+N, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + cre_cmdReq(CMD) + end, + Ns = [0,1,2,3,4,5,6,7,8,9], + CRs = [F(N) || N <- Ns], + cre_actionReq(Cid, CRs). + +mtrmc2_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = mtrmc2_mg_notify_request_ar1(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% Common functions for the multi_trans_req_timeout test case +%% + +mtrmc2_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_trans_req_maxsize1(suite) -> + []; +multi_trans_req_maxsize1(doc) -> + "Test that the message is sent when req_maxsize is reached"; +multi_trans_req_maxsize1(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, multi_trans_req_maxsize1), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = mtrms1_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = mtrms1_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrms1_mgc_verify_handle_connect_fun(), + {?MODULE, mtrms1_mgc_verify_handle_connect, []}). +-define(mtrms1_mgc_verify_service_change_req_fun(Mid), + {?MODULE, mtrms1_mgc_verify_service_change_req, [Mid]}). +-define(mtrms1_mgc_verify_notify_req_fun(), + {?MODULE, mtrms1_mgc_verify_notify_request, []}). +-define(mtrms1_mgc_verify_handle_disconnect_fun(), + {?MODULE, mtrms1_mgc_verify_handle_disconnect, []}). +-else. +-define(mtrms1_mgc_verify_handle_connect_fun(), + fun mtrms1_mgc_verify_handle_connect/1). +-define(mtrms1_mgc_verify_service_change_req_fun(Mid), + mtrms1_mgc_verify_service_change_req_fun(Mid)). +-define(mtrms1_mgc_verify_notify_req_fun(), + mtrms1_mgc_verify_notify_request_fun()). +-define(mtrms1_mgc_verify_handle_disconnect_fun(), + fun mtrms1_mgc_verify_handle_disconnect/1). +-endif. + +mtrms1_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?mtrms1_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?mtrms1_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?mtrms1_mgc_verify_notify_req_fun(), + DiscoVerify = ?mtrms1_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun mtrms1_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = mtrms1_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify1 = mtrms1_mgc_verify_notify_request_fun1(), +%% DiscoVerify = fun mtrms1_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +mtrms1_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrms1_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrms1_mgc_verify_handle_connect(Else) -> + io:format("mtrms1_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrms1_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + mtrms1_mgc_verify_service_change_req(Ev, Mid) + end. + +mtrms1_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("mtrms1_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [mtrms1_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = mtrms1_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = mtrms1_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = mtrms1_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = mtrms1_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = mtrms1_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +mtrms1_mgc_verify_service_change_req(Else, _Mid) -> + io:format("mtrms1_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrms1_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrms1_mgc_verify_notify_request_fun() -> + fun(Ev) -> + mtrms1_mgc_verify_notify_request(Ev) + end. + +mtrms1_mgc_verify_notify_request({handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("mtrms1_mgc_verify_notify_request:fun1 -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, + [mtrms1_mgc_notify_reply_ar1(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = mtrms1_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +mtrms1_mgc_verify_notify_request(Else) -> + io:format("mtrms1_mgc_verify_notify_request:fun1 -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrms1_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrms1_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("mtrms1_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +mtrms1_mgc_verify_handle_disconnect(Else) -> + io:format("mtrms1_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +mtrms1_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +mtrms1_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = mtrms1_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrms1_mgc_notify_reply_ar1(Cid, Tid) -> + NR = cre_notifyReply([Tid]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +mtrms1_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = mtrms1_mgc_notify_reply_ar1(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrms1_mg_verify_handle_connect_fun(), + {?MODULE, mtrms1_mg_verify_handle_connect, []}). +-define(mtrms1_mg_verify_service_change_reply_fun(Mid), + {?MODULE, mtrms1_mg_verify_service_change_reply, [Mid]}). +-define(mtrms1_mg_verify_notify_reply_fun(), + {?MODULE, mtrms1_mg_verify_notify_reply, []}). +-else. +-define(mtrms1_mg_verify_handle_connect_fun(), + fun mtrms1_mg_verify_handle_connect/1). +-define(mtrms1_mg_verify_service_change_reply_fun(), + fun mtrms1_mg_verify_service_change_reply/1). +-define(mtrms1_mg_verify_notify_reply_fun(), + fun mtrms1_mg_verify_notify_reply/1). +-endif. + +mtrms1_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [mtrms1_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(N) -> + [mtrms1_mg_notify_request_ar1(N, Tid, N)] + end, + ConnectVerify = ?mtrms1_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?mtrms1_mg_verify_service_change_reply_fun(), + NotifyReplyVerify = ?mtrms1_mg_verify_notify_reply_fun(), +%% ConnectVerify = fun mtrms1_mg_verify_handle_connect/1, +%% ServiceChangeReplyVerify = fun mtrms1_mg_verify_service_change_reply/1, +%% NotifyReplyVerify = fun mtrms1_mg_verify_notify_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_update_conn_info, trans_req_maxcount, 10}, + {megaco_update_conn_info, trans_req_maxsize, 650}, + {megaco_update_conn_info, trans_timer, 120000}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {megaco_cast, NR(1), []}, + {megaco_cast, [NR(2), NR(3)], []}, + {megaco_cast, NR(4), []}, + {megaco_cast, NR(5), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +mtrms1_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrms1_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrms1_mg_verify_handle_connect(Else) -> + io:format("mtrms1_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrms1_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrms1_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +mtrms1_mg_verify_service_change_reply(Else) -> + io:format("mtrms1_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrms1_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrms1_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +mtrms1_mg_verify_notify_reply(Else) -> + io:format("mtrms1_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrms1_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrms1_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = mtrms1_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrms1_mg_notify_request_ar1(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrms1_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = mtrms1_mg_notify_request_ar1(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +mtrms1_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_trans_req_maxsize2(suite) -> + []; +multi_trans_req_maxsize2(doc) -> + "Test that the message is sent when req_maxsize is reached, " + "when the 'last' message is bigger then req_maxsize itself"; +multi_trans_req_maxsize2(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, multi_trans_req_maxsize2), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = mtrms2_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = mtrms2_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrms2_mgc_verify_handle_connect_fun(), + {?MODULE, mtrms2_mgc_verify_handle_connect, []}). +-define(mtrms2_mgc_verify_service_change_req_fun(Mid), + {?MODULE, mtrms2_mgc_verify_service_change_req, [Mid]}). +-define(mtrms2_mgc_verify_notify_req_fun(), + {?MODULE, mtrms2_mgc_verify_notify_request, []}). +-define(mtrms2_mgc_verify_handle_disconnect_fun(), + {?MODULE, mtrms2_mgc_verify_handle_disconnect, []}). +-else. +-define(mtrms2_mgc_verify_handle_connect_fun(), + fun mtrms2_mgc_verify_handle_connect/1). +-define(mtrms2_mgc_verify_service_change_req_fun(Mid), + mtrms2_mgc_verify_service_change_req_fun(Mid)). +-define(mtrms2_mgc_verify_notify_req_fun(), + mtrms2_mgc_verify_notify_request_fun()). +-define(mtrms2_mgc_verify_handle_disconnect_fun(), + fun mtrms2_mgc_verify_handle_disconnect/1). +-endif. + +mtrms2_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?mtrms2_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?mtrms2_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?mtrms2_mgc_verify_notify_req_fun(), + DiscoVerify = ?mtrms2_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun mtrms2_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = mtrms2_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = mtrms2_mgc_verify_notify_request_fun(), +%% DiscoVerify = fun mtrms2_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +mtrms2_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrms2_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrms2_mgc_verify_handle_connect(Else) -> + io:format("mtrms2_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrms2_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + mtrms2_mgc_verify_service_change_req(Ev, Mid) + end. + +mtrms2_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("mtrms2_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [mtrms2_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = mtrms2_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = mtrms2_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = mtrms2_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = mtrms2_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = mtrms2_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +mtrms2_mgc_verify_service_change_req(Else, _Mid) -> + io:format("mtrms2_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrms2_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrms2_mgc_verify_notify_request_fun() -> + fun(Ev) -> + mtrms2_mgc_verify_notify_request(Ev) + end. + +mtrms2_mgc_verify_notify_request({handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("mtrms2_mgc_verify_notify_request -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = Cid, + commandRequests = [CR]} -> + io:format("mtrms2_mgc_verify_notify_request:fun -> " + "single command", []), + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, + [mtrms2_mgc_notify_reply_ar1(Cid, Tid)]}, + {ok, AR, Reply}; + #'ActionRequest'{contextId = Cid, + commandRequests = CRs} -> + io:format("mtrms2_mgc_verify_notify_request:fun -> " + "multi command (~w)", [length(CRs)]), + Tids = [Tid || + #'CommandRequest'{command = + {notifyReq, + #'NotifyRequest'{ + terminationID = [Tid]}}} + <- CRs], + Reply = + {discard_ack, + [mtrms2_mgc_notify_reply_ar2(Cid, Tids)]}, + {ok, AR, Reply}; + _ -> + ED = mtrms2_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +mtrms2_mgc_verify_notify_request(Else) -> + io:format("mtrms2_mgc_verify_notify_request -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrms2_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrms2_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("mtrms2_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +mtrms2_mgc_verify_handle_disconnect(Else) -> + io:format("mtrms2_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +mtrms2_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +mtrms2_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = mtrms2_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrms2_mgc_notify_reply_ar1(Cid, Tid) -> + NR = cre_notifyReply([Tid]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +mtrms2_mgc_notify_reply_ar2(Cid, Tids) -> + CRs = [cre_cmdReply(cre_notifyReply([Tid])) || Tid <- Tids], + cre_actionReply(Cid, CRs). + +mtrms2_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = mtrms2_mgc_notify_reply_ar1(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrms2_mg_verify_handle_connect_fun(), + {?MODULE, mtrms2_mg_verify_handle_connect, []}). +-define(mtrms2_mg_verify_service_change_reply_fun(Mid), + {?MODULE, mtrms2_mg_verify_service_change_reply, [Mid]}). +-define(mtrms2_mg_verify_notify_reply_fun(), + {?MODULE, mtrms2_mg_verify_notify_reply, []}). +-else. +-define(mtrms2_mg_verify_handle_connect_fun(), + fun mtrms2_mg_verify_handle_connect/1). +-define(mtrms2_mg_verify_service_change_reply_fun(), + fun mtrms2_mg_verify_service_change_reply/1). +-define(mtrms2_mg_verify_notify_reply_fun(), + fun mtrms2_mg_verify_notify_reply/1). +-endif. + +mtrms2_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [mtrms2_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NotifyReq1 = [mtrms2_mg_notify_request_ar1(1, Tid, 1)], + NotifyReq2 = [mtrms2_mg_notify_request_ar2(2, Tid, 2)], + ConnectVerify = ?mtrms2_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?mtrms2_mg_verify_service_change_reply_fun(), + NotifyReplyVerify = ?mtrms2_mg_verify_notify_reply_fun(), +%% ConnectVerify = fun mtrms2_mg_verify_handle_connect/1, +%% ServiceChangeReplyVerify = fun mtrms2_mg_verify_service_change_reply/1, +%% NotifyReplyVerify = fun mtrms2_mg_verify_notify_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_update_conn_info, trans_req_maxcount, 10}, + {megaco_update_conn_info, trans_req_maxsize, 1024}, + {megaco_update_conn_info, trans_timer, 120000}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {megaco_cast, NotifyReq1, []}, + {megaco_cast, [NotifyReq1, NotifyReq1], []}, + {megaco_cast, NotifyReq1, []}, + {megaco_cast, NotifyReq2, []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +mtrms2_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrms2_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrms2_mg_verify_handle_connect(Else) -> + io:format("mtrms2_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrms2_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrms2_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +mtrms2_mg_verify_service_change_reply(Else) -> + io:format("mtrms2_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrms2_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrms2_mg_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [{notifyReply, _NR}]} -> + io:format("mtrms2_mg_verify_notify_reply -> " + "single notify reply", []), + {ok, AR, ok}; + #'ActionReply'{commandReply = [{notifyReply, _NR}|_] = CR} -> + io:format("mtrms2_mg_verify_notify_reply -> " + "multi notify reply: (~w)", [length(CR)]), + {ok, AR, ok}; + _ -> + {error, {invalid_action_reply, AR}, ok} + end; +mtrms2_mg_verify_notify_reply(Else) -> + io:format("mtrms2_mg_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrms2_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrms2_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = mtrms2_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrms2_mg_notify_request_ar1(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrms2_mg_notify_request_ar2(Rid, Tid, Cid) -> + F = fun(N) -> + T = 22000000 + N, + TS = integer_to_list(T), + TT = cre_timeNotation("19990729", TS), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid+N, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + cre_cmdReq(CMD) + end, + Ns = [0,1,2,3,4,5,6,7,8,9], + CRs = [F(N) || N <- Ns], + cre_actionReq(Cid, CRs). + +mtrms2_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = mtrms2_mg_notify_request_ar1(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +mtrms2_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +single_trans_req_and_ack(suite) -> + []; +single_trans_req_and_ack(doc) -> + []; +single_trans_req_and_ack(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, single_trans_req_and_ack), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = straa_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = straa_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(straa_mgc_verify_handle_connect_fun(), + {?MODULE, straa_mgc_verify_handle_connect, []}). +-define(straa_mgc_verify_service_change_req_fun(Mid), + {?MODULE, straa_mgc_verify_service_change_req, [Mid]}). +-define(straa_mgc_verify_notify_req_fun(), + {?MODULE, straa_mgc_verify_notify_request, []}). +-define(straa_mgc_verify_ack_fun(), + {?MODULE, straa_mgc_verify_ack, []}). +-define(straa_mgc_verify_handle_disconnect_fun(), + {?MODULE, straa_mgc_verify_handle_disconnect, []}). +-else. +-define(straa_mgc_verify_handle_connect_fun(), + fun straa_mgc_verify_handle_connect/1). +-define(straa_mgc_verify_service_change_req_fun(Mid), + straa_mgc_verify_service_change_req_fun(Mid)). +-define(straa_mgc_verify_notify_req_fun(), + straa_mgc_verify_notify_request_fun()). +-define(straa_mgc_verify_ack_fun(), + fun straa_mgc_verify_ack/1). +-define(straa_mgc_verify_handle_disconnect_fun(), + fun straa_mgc_verify_handle_disconnect/1). +-endif. + +straa_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?straa_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?straa_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?straa_mgc_verify_notify_req_fun(), + AckVerify = ?straa_mgc_verify_ack_fun(), + DiscoVerify = ?straa_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun straa_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = straa_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = straa_mgc_verify_notify_request_fun(), +%% AckVerify = fun straa_mgc_verify_ack/1, +%% DiscoVerify = fun straa_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +straa_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("straa_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +straa_mgc_verify_handle_connect(Else) -> + io:format("straa_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +straa_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + straa_mgc_verify_service_change_req(Ev, Mid) + end. + +straa_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("straa_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [straa_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = straa_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = straa_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = straa_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = straa_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = straa_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +straa_mgc_verify_service_change_req(Else, _Mid) -> + io:format("straa_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = straa_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +straa_mgc_verify_notify_request_fun() -> + fun(Ev) -> + straa_mgc_verify_notify_request(Ev) + end. + +straa_mgc_verify_notify_request({handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("straa_mgc_verify_notify_request:fun -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + HandleAck = {handle_sloppy_ack, kalle}, + Reply = {HandleAck, + [straa_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + #'ActionRequest'{contextId = 2 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, + [straa_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = straa_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +straa_mgc_verify_notify_request(Else) -> + io:format("straa_mgc_verify_notify_request:fun -> unknown" + "~n Else: ~p~n", [Else]), + ED = straa_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +straa_mgc_verify_ack({handle_trans_ack, CH, ?VERSION, ok, kalle}) -> + io:format("straa_mgc_verify_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +straa_mgc_verify_ack(Else) -> + io:format("straa_mgc_verify_ack -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +straa_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("straa_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +straa_mgc_verify_handle_disconnect(Else) -> + io:format("straa_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +straa_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +straa_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = straa_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +straa_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +straa_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = straa_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(straa_mg_verify_handle_connect_fun(), + {?MODULE, straa_mg_verify_handle_connect, []}). +-define(straa_mg_verify_service_change_reply_fun(), + {?MODULE, straa_mg_verify_service_change_reply, []}). +-define(straa_mg_verify_notify_reply_fun(), + {?MODULE, straa_mg_verify_notify_reply, []}). +-else. +-define(straa_mg_verify_handle_connect_fun(), + fun straa_mg_verify_handle_connect/1). +-define(straa_mg_verify_service_change_reply_fun(), + fun straa_mg_verify_service_change_reply/1). +-define(straa_mg_verify_notify_reply_fun(), + fun straa_mg_verify_notify_reply/1). +-endif. + +straa_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [straa_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(N) -> + [straa_mg_notify_request_ar(N, Tid, N)] + end, + ConnectVerify = ?straa_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?straa_mg_verify_service_change_reply_fun(), + NotifyReplyVerify = ?straa_mg_verify_notify_reply_fun(), +%% ConnectVerify = fun straa_mg_verify_handle_connect/1, +%% ServiceChangeReplyVerify = fun straa_mg_verify_service_change_reply/1, +%% NotifyReplyVerify = fun straa_mg_verify_notify_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_update_conn_info, auto_ack, true}, + {megaco_update_conn_info, trans_ack_maxcount, 10}, + {megaco_update_conn_info, trans_timer, 1000}, + {megaco_update_conn_info, trans_ack, true}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {sleep, 1000}, + {megaco_cast, NR(1), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_cast, NR(2), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 3000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +straa_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("straa_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +straa_mg_verify_handle_connect(Else) -> + io:format("straa_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +straa_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("straa_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +straa_mg_verify_service_change_reply(Else) -> + io:format("straa_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +straa_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("straa_mg_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +straa_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {error, Err}, _}) -> + io:format("straa_mg_verify_notify_reply -> error" + "~n Err: ~p~n", [Err]), + {error, Err, ok}; +straa_mg_verify_notify_reply(Else) -> + io:format("straa_mg_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +straa_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +straa_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = straa_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +straa_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +straa_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = straa_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% Common functions for the single_trans_req test case +%% + +straa_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_trans_req_and_ack_timeout(suite) -> + []; +multi_trans_req_and_ack_timeout(doc) -> + []; +multi_trans_req_and_ack_timeout(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, multi_trans_req_and_ack_timeout), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = mtrtaat_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = mtrtaat_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrtaat_mgc_verify_handle_connect_fun(), + {?MODULE, mtrtaat_mgc_verify_handle_connect, []}). +-define(mtrtaat_mgc_verify_service_change_req_fun(Mid), + {?MODULE, mtrtaat_mgc_verify_service_change_req, [Mid]}). +-define(mtrtaat_mgc_verify_notify_req_fun(), + {?MODULE, mtrtaat_mgc_verify_notify_request, []}). +-define(mtrtaat_mgc_verify_ack_fun(), + {?MODULE, mtrtaat_mgc_verify_ack, []}). +-define(mtrtaat_mgc_verify_handle_disconnect_fun(), + {?MODULE, mtrtaat_mgc_verify_handle_disconnect, []}). +-else. +-define(mtrtaat_mgc_verify_handle_connect_fun(), + fun mtrtaat_mgc_verify_handle_connect/1). +-define(mtrtaat_mgc_verify_service_change_req_fun(Mid), + mtrtaat_mgc_verify_service_change_req_fun(Mid)). +-define(mtrtaat_mgc_verify_notify_req_fun(), + mtrtaat_mgc_verify_notify_request_fun()). +-define(mtrtaat_mgc_verify_ack_fun(), + fun mtrtaat_mgc_verify_ack/1). +-define(mtrtaat_mgc_verify_handle_disconnect_fun(), + fun mtrtaat_mgc_verify_handle_disconnect/1). +-endif. + +mtrtaat_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?mtrtaat_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?mtrtaat_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?mtrtaat_mgc_verify_notify_req_fun(), + AckVerify = ?mtrtaat_mgc_verify_ack_fun(), + DiscoVerify = ?mtrtaat_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun mtrtaat_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = mtrtaat_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = mtrtaat_mgc_verify_notify_request_fun(), +%% AckVerify = fun mtrtaat_mgc_verify_ack/1, +%% DiscoVerify = fun mtrtaat_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +mtrtaat_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrtaat_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrtaat_mgc_verify_handle_connect(Else) -> + io:format("mtrtaat_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaat_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + mtrtaat_mgc_verify_service_change_req(Ev, Mid) + end. + +mtrtaat_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("mtrtaat_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [mtrtaat_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = mtrtaat_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = mtrtaat_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = mtrtaat_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = mtrtaat_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = mtrtaat_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +mtrtaat_mgc_verify_service_change_req(Else, _Mid) -> + io:format("mtrtaat_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrtaat_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrtaat_mgc_verify_notify_request_fun() -> + fun(Ev) -> + mtrtaat_mgc_verify_notify_request(Ev) + end. + +mtrtaat_mgc_verify_notify_request({handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("mtrtaat_mgc_verify_notify_request -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + HandleAck = {handle_sloppy_ack, kalle}, + Reply = {HandleAck, + [mtrtaat_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + #'ActionRequest'{contextId = 2 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [mtrtaat_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = mtrtaat_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +mtrtaat_mgc_verify_notify_request(Else) -> + io:format("mtrtaat_mgc_verify_notify_request -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrtaat_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + + +mtrtaat_mgc_verify_ack({handle_trans_ack, CH, ?VERSION, ok, kalle}) -> + io:format("mtrtaat_mgc_verify_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +mtrtaat_mgc_verify_ack(Else) -> + io:format("mtrtaat_mgc_verify_ack -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaat_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("mtrtaat_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +mtrtaat_mgc_verify_handle_disconnect(Else) -> + io:format("mtrtaat_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +mtrtaat_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +mtrtaat_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = mtrtaat_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrtaat_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +mtrtaat_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = mtrtaat_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrtaat_mg_verify_handle_connect_fun(), + {?MODULE, mtrtaat_mg_verify_handle_connect, []}). +-define(mtrtaat_mg_verify_service_change_reply_fun(), + {?MODULE, mtrtaat_mg_verify_service_change_reply, []}). +-define(mtrtaat_mg_verify_notify_reply_fun(), + {?MODULE, mtrtaat_mg_verify_notify_reply, []}). +-else. +-define(mtrtaat_mg_verify_handle_connect_fun(), + fun mtrtaat_mg_verify_handle_connect/1). +-define(mtrtaat_mg_verify_service_change_reply_fun(), + fun mtrtaat_mg_verify_service_change_reply/1). +-define(mtrtaat_mg_verify_notify_reply_fun(), + fun mtrtaat_mg_verify_notify_reply/1). +-endif. + +mtrtaat_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [mtrtaat_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [mtrtaat_mg_notify_request_ar(Rid, Tid, Cid)] + end, + ConnectVerify = ?mtrtaat_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?mtrtaat_mg_verify_service_change_reply_fun(), + NotifyReplyVerify = ?mtrtaat_mg_verify_notify_reply_fun(), +%% ConnectVerify = fun mtrtaat_mg_verify_handle_connect/1, +%% ServiceChangeReplyVerify = fun mtrtaat_mg_verify_service_change_reply/1, +%% NotifyReplyVerify = fun mtrtaat_mg_verify_notify_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_update_conn_info, auto_ack, true}, + {megaco_update_conn_info, trans_ack_maxcount, 10}, + {megaco_update_conn_info, trans_req_maxcount, 10}, + {megaco_update_conn_info, trans_timer, 1000}, + {megaco_update_conn_info, trans_ack, true}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {megaco_cast, NR(1,1), []}, + {megaco_cast, NR(1,2), []}, + {megaco_cast, NR(1,3), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_cast, NR(2,1), []}, + {megaco_cast, NR(2,2), []}, + {megaco_cast, NR(2,3), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 3000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +mtrtaat_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrtaat_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrtaat_mg_verify_handle_connect(Else) -> + io:format("mtrtaat_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaat_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrtaat_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +mtrtaat_mg_verify_service_change_reply(Else) -> + io:format("mtrtaat_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaat_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrtaat_mg_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +mtrtaat_mg_verify_notify_reply(Else) -> + io:format("mtrtaat_mg_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaat_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrtaat_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = mtrtaat_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrtaat_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrtaat_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = mtrtaat_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% Common functions for the multi_trans_req_timeout test case +%% + +mtrtaat_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_trans_req_and_ack_ackmaxcount(suite) -> + []; +multi_trans_req_and_ack_ackmaxcount(doc) -> + []; +multi_trans_req_and_ack_ackmaxcount(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, multi_trans_req_and_ack_ackmaxcount), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = mtrtaaamc_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = mtrtaaamc_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrtaaamc_mgc_verify_handle_connect_fun(), + {?MODULE, mtrtaaamc_mgc_verify_handle_connect, []}). +-define(mtrtaaamc_mgc_verify_service_change_req_fun(Mid), + {?MODULE, mtrtaaamc_mgc_verify_service_change_req, [Mid]}). +-define(mtrtaaamc_mgc_verify_notify_req_fun(), + {?MODULE, mtrtaaamc_mgc_verify_notify_request, []}). +-define(mtrtaaamc_mgc_verify_ack_fun(), + {?MODULE, mtrtaaamc_mgc_verify_ack, []}). +-define(mtrtaaamc_mgc_verify_handle_disconnect_fun(), + {?MODULE, mtrtaaamc_mgc_verify_handle_disconnect, []}). +-else. +-define(mtrtaaamc_mgc_verify_handle_connect_fun(), + fun mtrtaaamc_mgc_verify_handle_connect/1). +-define(mtrtaaamc_mgc_verify_service_change_req_fun(Mid), + mtrtaaamc_mgc_verify_service_change_req_fun(Mid)). +-define(mtrtaaamc_mgc_verify_notify_req_fun(), + mtrtaaamc_mgc_verify_notify_request_fun()). +-define(mtrtaaamc_mgc_verify_ack_fun(), + fun mtrtaaamc_mgc_verify_ack/1). +-define(mtrtaaamc_mgc_verify_handle_disconnect_fun(), + fun mtrtaaamc_mgc_verify_handle_disconnect/1). +-endif. + +mtrtaaamc_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?mtrtaaamc_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?mtrtaaamc_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?mtrtaaamc_mgc_verify_notify_req_fun(), + AckVerify = ?mtrtaaamc_mgc_verify_ack_fun(), + DiscoVerify = ?mtrtaaamc_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun mtrtaaamc_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = mtrtaaamc_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = mtrtaaamc_mgc_verify_notify_request_fun(), +%% AckVerify = fun mtrtaaamc_mgc_verify_ack/1, +%% DiscoVerify = fun mtrtaaamc_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +mtrtaaamc_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrtaaamc_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrtaaamc_mgc_verify_handle_connect(Else) -> + io:format("mtrtaaamc_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaaamc_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + mtrtaaamc_mgc_verify_service_change_req(Ev, Mid) + end. + +mtrtaaamc_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("mtrtaaamc_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [mtrtaaamc_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = mtrtaaamc_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = mtrtaaamc_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = mtrtaaamc_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = mtrtaaamc_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = mtrtaaamc_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +mtrtaaamc_mgc_verify_service_change_req(Else, _Mid) -> + io:format("mtrtaaamc_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrtaaamc_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrtaaamc_mgc_verify_notify_request_fun() -> + fun(Ev) -> + mtrtaaamc_mgc_verify_notify_request(Ev) + end. + +mtrtaaamc_mgc_verify_notify_request( + {handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("mtrtaaamc_mgc_verify_notify_request:fun -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{requestId = Rid, + observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + HandleAck = {handle_sloppy_ack, {kalle, Rid}}, + Reply = {HandleAck, + [mtrtaaamc_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + #'ActionRequest'{contextId = 2 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [mtrtaaamc_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = mtrtaaamc_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +mtrtaaamc_mgc_verify_notify_request(Else) -> + io:format("mtrtaaamc_mgc_verify_notify_request:fun -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrtaaamc_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrtaaamc_mgc_verify_ack({handle_trans_ack, CH, ?VERSION, ok, + {kalle, Rid}}) -> + io:format("mtrtaaamc_mgc_verify_ack -> ok" + "~n CH: ~p" + "~n Rid: ~p" + "~n", [CH, Rid]), + {ok, CH, ok}; +mtrtaaamc_mgc_verify_ack(Else) -> + io:format("mtrtaaamc_mgc_verify_ack -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaaamc_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("mtrtaaamc_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +mtrtaaamc_mgc_verify_handle_disconnect(Else) -> + io:format("mtrtaaamc_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +mtrtaaamc_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +mtrtaaamc_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = mtrtaaamc_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrtaaamc_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +mtrtaaamc_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = mtrtaaamc_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrtaaamc_mg_verify_handle_connect_fun(), + {?MODULE, mtrtaaamc_mg_verify_handle_connect, []}). +-define(mtrtaaamc_mg_verify_service_change_reply_fun(), + {?MODULE, mtrtaaamc_mg_verify_service_change_reply, []}). +-define(mtrtaaamc_mg_verify_notify_reply_fun(), + {?MODULE, mtrtaaamc_mg_verify_notify_reply, []}). +-else. +-define(mtrtaaamc_mg_verify_handle_connect_fun(), + fun mtrtaaamc_mg_verify_handle_connect/1). +-define(mtrtaaamc_mg_verify_service_change_reply_fun(), + fun mtrtaaamc_mg_verify_service_change_reply/1). +-define(mtrtaaamc_mg_verify_notify_reply_fun(), + fun mtrtaaamc_mg_verify_notify_reply/1). +-endif. + +mtrtaaamc_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [mtrtaaamc_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [mtrtaaamc_mg_notify_request_ar(Rid, Tid, Cid)] + end, + ConnectVerify = ?mtrtaaamc_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?mtrtaaamc_mg_verify_service_change_reply_fun(), + NotifyReplyVerify = ?mtrtaaamc_mg_verify_notify_reply_fun(), +%% ConnectVerify = fun mtrtaaamc_mg_verify_handle_connect/1, +%% ServiceChangeReplyVerify = fun mtrtaaamc_mg_verify_service_change_reply/1, +%% NotifyReplyVerify = fun mtrtaaamc_mg_verify_notify_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_update_conn_info, auto_ack, true}, + {megaco_update_conn_info, trans_ack_maxcount, 4}, + {megaco_update_conn_info, trans_req_maxcount, 10}, + {megaco_update_conn_info, trans_timer, 5000}, + {megaco_update_conn_info, trans_ack, true}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {megaco_cast, NR(1,1), []}, + {megaco_cast, NR(1,2), []}, + {megaco_cast, NR(1,3), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_cast, NR(2,1), []}, + {megaco_cast, NR(2,2), []}, + {megaco_cast, NR(2,3), []}, + {megaco_cast, NR(1,4), [{trans_req,false}]}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 3000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +mtrtaaamc_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrtaaamc_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrtaaamc_mg_verify_handle_connect(Else) -> + io:format("mtrtaaamc_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaaamc_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrtaaamc_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +mtrtaaamc_mg_verify_service_change_reply(Else) -> + io:format("mtrtaaamc_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaaamc_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrtaaamc_mg_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +mtrtaaamc_mg_verify_notify_reply(Else) -> + io:format("mtrtaaamc_mg_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaaamc_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrtaaamc_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = mtrtaaamc_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrtaaamc_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrtaaamc_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = mtrtaaamc_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% Common functions for the multi_trans_req_timeout test case +%% + +mtrtaaamc_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_trans_req_and_ack_reqmaxcount(suite) -> + []; +multi_trans_req_and_ack_reqmaxcount(doc) -> + []; +multi_trans_req_and_ack_reqmaxcount(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, multi_trans_req_and_ack_reqmaxcount), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = mtrtaarac_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = mtrtaarac_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrtaarac_mgc_verify_handle_connect_fun(), + {?MODULE, mtrtaarac_mgc_verify_handle_connect, []}). +-define(mtrtaarac_mgc_verify_service_change_req_fun(Mid), + {?MODULE, mtrtaarac_mgc_verify_service_change_req, [Mid]}). +-define(mtrtaarac_mgc_verify_notify_req_fun(), + {?MODULE, mtrtaarac_mgc_verify_notify_request, []}). +-define(mtrtaarac_mgc_verify_ack_fun(), + {?MODULE, mtrtaarac_mgc_verify_ack, []}). +-define(mtrtaarac_mgc_verify_handle_disconnect_fun(), + {?MODULE, mtrtaarac_mgc_verify_handle_disconnect, []}). +-else. +-define(mtrtaarac_mgc_verify_handle_connect_fun(), + fun mtrtaarac_mgc_verify_handle_connect/1). +-define(mtrtaarac_mgc_verify_service_change_req_fun(Mid), + mtrtaarac_mgc_verify_service_change_req_fun(Mid)). +-define(mtrtaarac_mgc_verify_notify_req_fun(), + mtrtaarac_mgc_verify_notify_request_fun()). +-define(mtrtaarac_mgc_verify_ack_fun(), + fun mtrtaarac_mgc_verify_ack/1). +-define(mtrtaarac_mgc_verify_handle_disconnect_fun(), + fun mtrtaarac_mgc_verify_handle_disconnect/1). +-endif. + +mtrtaarac_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?mtrtaarac_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?mtrtaarac_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?mtrtaarac_mgc_verify_notify_req_fun(), + AckVerify = ?mtrtaarac_mgc_verify_ack_fun(), + DiscoVerify = ?mtrtaarac_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun mtrtaarac_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = mtrtaarac_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = mtrtaarac_mgc_verify_notify_request_fun(), +%% AckVerify = fun mtrtaarac_mgc_verify_ack/1, +%% DiscoVerify = fun mtrtaarac_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +mtrtaarac_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrtaarac_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrtaarac_mgc_verify_handle_connect(Else) -> + io:format("mtrtaarac_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaarac_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + mtrtaarac_mgc_verify_service_change_req(Ev, Mid) + end. + +mtrtaarac_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("mtrtaarac_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [mtrtaarac_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = mtrtaarac_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = mtrtaarac_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = mtrtaarac_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = mtrtaarac_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = mtrtaarac_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +mtrtaarac_mgc_verify_service_change_req(Else, _Mid) -> + io:format("mtrtaarac_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrtaarac_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrtaarac_mgc_verify_notify_request_fun() -> + fun(Ev) -> + mtrtaarac_mgc_verify_notify_request(Ev) + end. + +mtrtaarac_mgc_verify_notify_request( + {handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("mtrtaarac_mgc_verify_notify_request:fun -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{requestId = Rid, + observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + HandleAck = {handle_sloppy_ack, {kalle, Rid}}, + Reply = {HandleAck, + [mtrtaarac_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + #'ActionRequest'{contextId = 2 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [mtrtaarac_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = mtrtaarac_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +mtrtaarac_mgc_verify_notify_request(Else) -> + io:format("mtrtaarac_mgc_verify_notify_request:fun -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrtaarac_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrtaarac_mgc_verify_ack({handle_trans_ack, CH, ?VERSION, ok, + {kalle, Rid}}) -> + io:format("mtrtaarac_mgc_verify_ack -> ok" + "~n CH: ~p" + "~n Rid: ~p" + "~n", [CH, Rid]), + {ok, CH, ok}; +mtrtaarac_mgc_verify_ack(Else) -> + io:format("mtrtaarac_mgc_verify_ack -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaarac_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("mtrtaarac_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +mtrtaarac_mgc_verify_handle_disconnect(Else) -> + io:format("mtrtaarac_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +mtrtaarac_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +mtrtaarac_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = mtrtaarac_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrtaarac_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +mtrtaarac_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = mtrtaarac_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrtaarac_mg_verify_handle_connect_fun(), + {?MODULE, mtrtaarac_mg_verify_handle_connect, []}). +-define(mtrtaarac_mg_verify_service_change_reply_fun(), + {?MODULE, mtrtaarac_mg_verify_service_change_reply, []}). +-define(mtrtaarac_mg_verify_notify_reply_fun(), + {?MODULE, mtrtaarac_mg_verify_notify_reply, []}). +-else. +-define(mtrtaarac_mg_verify_handle_connect_fun(), + fun mtrtaarac_mg_verify_handle_connect/1). +-define(mtrtaarac_mg_verify_service_change_reply_fun(), + fun mtrtaarac_mg_verify_service_change_reply/1). +-define(mtrtaarac_mg_verify_notify_reply_fun(), + fun mtrtaarac_mg_verify_notify_reply/1). +-endif. + +mtrtaarac_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [mtrtaarac_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [mtrtaarac_mg_notify_request_ar(Rid, Tid, Cid)] + end, + ConnectVerify = ?mtrtaarac_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?mtrtaarac_mg_verify_service_change_reply_fun(), + NotifyReplyVerify = ?mtrtaarac_mg_verify_notify_reply_fun(), +%% ConnectVerify = fun mtrtaarac_mg_verify_handle_connect/1, +%% ServiceChangeReplyVerify = fun mtrtaarac_mg_verify_service_change_reply/1, +%% NotifyReplyVerify = fun mtrtaarac_mg_verify_notify_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_update_conn_info, auto_ack, true}, + {megaco_update_conn_info, trans_ack_maxcount, 10}, + {megaco_update_conn_info, trans_req_maxcount, 4}, + {megaco_update_conn_info, trans_timer, 5000}, + {megaco_update_conn_info, trans_ack, true}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {megaco_cast, NR(1,1), []}, + {megaco_cast, NR(1,2), []}, + {megaco_cast, NR(1,3), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_cast, NR(2,1), []}, + {megaco_cast, NR(2,2), []}, + {megaco_cast, NR(2,3), []}, + {megaco_cast, NR(2,4), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 3000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +mtrtaarac_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrtaarac_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrtaarac_mg_verify_handle_connect(Else) -> + io:format("mtrtaarac_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaarac_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrtaarac_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +mtrtaarac_mg_verify_service_change_reply(Else) -> + io:format("mtrtaarac_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaarac_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrtaarac_mg_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +mtrtaarac_mg_verify_notify_reply(Else) -> + io:format("mtrtaarac_mg_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaarac_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrtaarac_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = mtrtaarac_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrtaarac_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrtaarac_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = mtrtaarac_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% Common functions for the multi_trans_req_timeout test case +%% + +mtrtaarac_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_trans_req_and_ack_maxsize1(suite) -> + []; +multi_trans_req_and_ack_maxsize1(doc) -> + []; +multi_trans_req_and_ack_maxsize1(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, multi_trans_req_and_ack_maxsize1), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = mtrtaams1_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = mtrtaams1_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrtaams1_mgc_verify_handle_connect_fun(), + {?MODULE, mtrtaams1_mgc_verify_handle_connect, []}). +-define(mtrtaams1_mgc_verify_service_change_req_fun(Mid), + {?MODULE, mtrtaams1_mgc_verify_service_change_req, [Mid]}). +-define(mtrtaams1_mgc_verify_notify_req_fun(), + {?MODULE, mtrtaams1_mgc_verify_notify_request, []}). +-define(mtrtaams1_mgc_verify_ack_fun(), + {?MODULE, mtrtaams1_mgc_verify_ack, []}). +-define(mtrtaams1_mgc_verify_handle_disconnect_fun(), + {?MODULE, mtrtaams1_mgc_verify_handle_disconnect, []}). +-else. +-define(mtrtaams1_mgc_verify_handle_connect_fun(), + fun mtrtaams1_mgc_verify_handle_connect/1). +-define(mtrtaams1_mgc_verify_service_change_req_fun(Mid), + mtrtaams1_mgc_verify_service_change_req_fun(Mid)). +-define(mtrtaams1_mgc_verify_notify_req_fun(), + mtrtaams1_mgc_verify_notify_request_fun()). +-define(mtrtaams1_mgc_verify_ack_fun(), + fun mtrtaams1_mgc_verify_ack/1). +-define(mtrtaams1_mgc_verify_handle_disconnect_fun(), + fun mtrtaams1_mgc_verify_handle_disconnect/1). +-endif. + +mtrtaams1_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?mtrtaams1_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?mtrtaams1_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?mtrtaams1_mgc_verify_notify_req_fun(), + AckVerify = ?mtrtaams1_mgc_verify_ack_fun(), + DiscoVerify = ?mtrtaams1_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun mtrtaams1_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = mtrtaams1_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = mtrtaams1_mgc_verify_notify_request_fun(), +%% AckVerify = fun mtrtaams1_mgc_verify_ack/1, +%% DiscoVerify = fun mtrtaams1_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +mtrtaams1_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrtaams1_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrtaams1_mgc_verify_handle_connect(Else) -> + io:format("mtrtaams1_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaams1_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + mtrtaams1_mgc_verify_service_change_req(Ev, Mid) + end. + +mtrtaams1_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("mtrtaams1_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [mtrtaams1_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = mtrtaams1_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = mtrtaams1_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = mtrtaams1_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = mtrtaams1_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = mtrtaams1_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +mtrtaams1_mgc_verify_service_change_req(Else, _Mid) -> + io:format("mtrtaams1_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrtaams1_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrtaams1_mgc_verify_notify_request_fun() -> + fun(Ev) -> + mtrtaams1_mgc_verify_notify_request(Ev) + end. + +mtrtaams1_mgc_verify_notify_request( + {handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("mtrtaams1_mgc_verify_notify_request -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{requestId = Rid, + observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + HandleAck = {handle_sloppy_ack, {kalle, Rid}}, + Reply = {HandleAck, + [mtrtaams1_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + #'ActionRequest'{contextId = 2 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [mtrtaams1_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = mtrtaams1_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +mtrtaams1_mgc_verify_notify_request(Else) -> + io:format("mtrtaams1_mgc_verify_notify_request -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtrtaams1_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrtaams1_mgc_verify_ack({handle_trans_ack, CH, ?VERSION, ok, + {kalle, Rid}}) -> + io:format("mtrtaams1_mgc_verify_ack -> ok" + "~n CH: ~p" + "~n Rid: ~p" + "~n", [CH, Rid]), + {ok, CH, ok}; +mtrtaams1_mgc_verify_ack(Else) -> + io:format("mtrtaams1_mgc_verify_ack -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaams1_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("mtrtaams1_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +mtrtaams1_mgc_verify_handle_disconnect(Else) -> + io:format("mtrtaams1_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +mtrtaams1_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +mtrtaams1_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = mtrtaams1_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrtaams1_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +mtrtaams1_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = mtrtaams1_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrtaams1_mg_verify_handle_connect_fun(), + {?MODULE, mtrtaams1_mg_verify_handle_connect, []}). +-define(mtrtaams1_mg_verify_service_change_reply_fun(), + {?MODULE, mtrtaams1_mg_verify_service_change_reply, []}). +-define(mtrtaams1_mg_verify_notify_reply_fun(), + {?MODULE, mtrtaams1_mg_verify_notify_reply, []}). +-else. +-define(mtrtaams1_mg_verify_handle_connect_fun(), + fun mtrtaams1_mg_verify_handle_connect/1). +-define(mtrtaams1_mg_verify_service_change_reply_fun(), + fun mtrtaams1_mg_verify_service_change_reply/1). +-define(mtrtaams1_mg_verify_notify_reply_fun(), + fun mtrtaams1_mg_verify_notify_reply/1). +-endif. + +mtrtaams1_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [mtrtaams1_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [mtrtaams1_mg_notify_request_ar(Rid, Tid, Cid)] + end, + ConnectVerify = ?mtrtaams1_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?mtrtaams1_mg_verify_service_change_reply_fun(), + NotifyReplyVerify = ?mtrtaams1_mg_verify_notify_reply_fun(), +%% ConnectVerify = fun mtrtaams1_mg_verify_handle_connect/1, +%% ServiceChangeReplyVerify = fun mtrtaams1_mg_verify_service_change_reply/1, +%% NotifyReplyVerify = fun mtrtaams1_mg_verify_notify_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_update_conn_info, auto_ack, true}, + {megaco_update_conn_info, trans_ack_maxcount, 10}, + {megaco_update_conn_info, trans_req_maxcount, 10}, + {megaco_update_conn_info, trans_req_maxsize, 650}, + {megaco_update_conn_info, trans_timer, 5000}, + {megaco_update_conn_info, trans_ack, true}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {megaco_cast, [NR(1,2), NR(1,3), NR(1,4)], []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_cast, NR(2,1), []}, + {megaco_cast, NR(2,2), []}, + {megaco_cast, NR(2,3), []}, + {megaco_cast, NR(2,4), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 3000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +mtrtaams1_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtrtaams1_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtrtaams1_mg_verify_handle_connect(Else) -> + io:format("mtrtaams1_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaams1_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrtaams1_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +mtrtaams1_mg_verify_service_change_reply(Else) -> + io:format("mtrtaams1_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaams1_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtrtaams1_mg_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +mtrtaams1_mg_verify_notify_reply(Else) -> + io:format("mtrtaams1_mg_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtrtaams1_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrtaams1_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = mtrtaams1_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrtaams1_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrtaams1_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = mtrtaams1_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% Common functions for the multi_trans_req_timeout test case +%% + +mtrtaams1_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_trans_req_and_ack_maxsize2(suite) -> + []; +multi_trans_req_and_ack_maxsize2(doc) -> + []; +multi_trans_req_and_ack_maxsize2(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, multi_trans_req_and_ack_maxsize2), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = mtrtaams2_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = mtrtaams2_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrtaams2_mgc_verify_handle_connect_fun(), + {?MODULE, mtrtaams2_mgc_verify_handle_connect, []}). +-define(mtrtaams2_mgc_verify_service_change_req_fun(Mid), + {?MODULE, mtrtaams2_mgc_verify_service_change_req, [Mid]}). +-define(mtrtaams2_mgc_verify_notify_req_fun(), + {?MODULE, mtrtaams2_mgc_verify_notify_request, []}). +-define(mtrtaams2_mgc_verify_ack_fun(), + {?MODULE, mtrtaams2_mgc_verify_ack, []}). +-define(mtrtaams2_mgc_verify_handle_disconnect_fun(), + {?MODULE, mtrtaams2_mgc_verify_handle_disconnect, []}). +-else. +-define(mtrtaams2_mgc_verify_handle_connect_fun(), + fun mtrtaams2_mgc_verify_handle_connect/1). +-define(mtrtaams2_mgc_verify_service_change_req_fun(Mid), + mtrtaams2_mgc_verify_service_change_req_fun(Mid)). +-define(mtrtaams2_mgc_verify_notify_req_fun(), + mtrtaams2_mgc_verify_notify_request_fun()). +-define(mtrtaams2_mgc_verify_ack_fun(), + fun mtrtaams2_mgc_verify_ack/1). +-define(mtrtaams2_mgc_verify_handle_disconnect_fun(), + fun mtrtaams2_mgc_verify_handle_disconnect/1). +-endif. + +mtrtaams2_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ConnectVerify = ?mtrtaams2_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?mtrtaams2_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?mtrtaams2_mgc_verify_notify_req_fun(), + AckVerify = ?mtrtaams2_mgc_verify_ack_fun(), + DiscoVerify = ?mtrtaams2_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun mtrtaams2_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = mtrtaams2_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = mtrtaams2_mgc_verify_notify_request_fun(), +%% AckVerify = fun mtrtaams2_mgc_verify_ack/1, +%% DiscoVerify = fun mtrtaams2_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {listen, [{serialize, true}]}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_ack, AckVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +mtrtaams2_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + p("mtrtaams2_mgc_verify_handle_connect -> ok" + "~n CH: ~p", [CH]), + {ok, CH, ok}; +mtrtaams2_mgc_verify_handle_connect(Else) -> + p("mtrtaams2_mgc_verify_handle_connect -> unknown" + "~n Else: ~p", [Else]), + {error, Else, ok}. + +mtrtaams2_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + mtrtaams2_mgc_verify_service_change_req(Ev, Mid) + end. + +mtrtaams2_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + p("mtrtaams2_mgc_verify_service_change_req -> ok" + "~n AR: ~p", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [mtrtaams2_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = mtrtaams2_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = mtrtaams2_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = mtrtaams2_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = mtrtaams2_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = mtrtaams2_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +mtrtaams2_mgc_verify_service_change_req(Else, _Min) -> + p("mtrtaams2_mgc_verify_service_change_req -> unknown" + "~n Else: ~p", [Else]), + ED = mtrtaams2_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrtaams2_mgc_verify_notify_request_fun() -> + fun(Ev) -> + mtrtaams2_mgc_verify_notify_request(Ev) + end. + +mtrtaams2_mgc_verify_notify_request( + {handle_trans_request, _, ?VERSION, [AR]}) -> + p("mtrtaams2_mgc_verify_notify_request:fun -> ok" + "~n AR: ~p", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + p("mtrtaams2_mgc_verify_notify_request:fun -> " + "single command", []), + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{requestId = Rid, + observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + HandleAck = {handle_sloppy_ack, {kalle, Rid}}, + Reply = {HandleAck, + [mtrtaams2_mgc_notify_reply_ar1(Cid, Tid)]}, + {ok, AR, Reply}; + #'ActionRequest'{contextId = 2 = Cid, + commandRequests = CRs} -> + p("mtrtaams2_mgc_verify_notify_request:fun -> " + "multi command (~w)", [length(CRs)]), + Tids = [Tid || + #'CommandRequest'{command = + {notifyReq, + #'NotifyRequest'{ + terminationID = [Tid]}}} + <- CRs], + Reply = + {discard_ack, + [mtrtaams2_mgc_notify_reply_ar2(Cid, Tids)]}, + {ok, AR, Reply}; + _ -> + ED = mtrtaams2_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +mtrtaams2_mgc_verify_notify_request(Else) -> + p("mtrtaams2_mgc_verify_notify_request:fun -> unknown" + "~n Else: ~p", [Else]), + ED = mtrtaams2_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtrtaams2_mgc_verify_ack({handle_trans_ack, CH, ?VERSION, ok, + {kalle, Rid}}) -> + p("mtrtaams2_mgc_verify_ack -> ok" + "~n CH: ~p" + "~n Rid: ~p", [CH, Rid]), + {ok, CH, ok}; +mtrtaams2_mgc_verify_ack(Else) -> + p("mtrtaams2_mgc_verify_ack -> Else: " + "~n~p", [Else]), + {error, Else, ok}. + +mtrtaams2_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + p("mtrtaams2_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p", [CH, R]), + {ok, CH, ok}; +mtrtaams2_mgc_verify_handle_disconnect(Else) -> + p("mtrtaams2_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p", [Else]), + {error, Else, ok}. + + +mtrtaams2_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +mtrtaams2_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = mtrtaams2_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrtaams2_mgc_notify_reply_ar1(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +mtrtaams2_mgc_notify_reply_ar2(Cid, Tids) -> + CRs = [cre_cmdReply(cre_notifyReply([Tid])) || Tid <- Tids], + cre_actionReply(Cid, CRs). + +mtrtaams2_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = mtrtaams2_mgc_notify_reply_ar1(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtrtaams2_mg_verify_handle_connect_fun(), + {?MODULE, mtrtaams2_mg_verify_handle_connect, []}). +-define(mtrtaams2_mg_verify_service_change_reply_fun(), + {?MODULE, mtrtaams2_mg_verify_service_change_reply, []}). +-define(mtrtaams2_mg_verify_notify_reply_fun(), + {?MODULE, mtrtaams2_mg_verify_notify_reply, []}). +-else. +-define(mtrtaams2_mg_verify_handle_connect_fun(), + fun mtrtaams2_mg_verify_handle_connect/1). +-define(mtrtaams2_mg_verify_service_change_reply_fun(), + fun mtrtaams2_mg_verify_service_change_reply/1). +-define(mtrtaams2_mg_verify_notify_reply_fun(), + fun mtrtaams2_mg_verify_notify_reply/1). +-endif. + +mtrtaams2_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [mtrtaams2_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR1 = fun(Cid, Rid) -> + [mtrtaams2_mg_notify_request_ar1(10 + Rid, Tid, Cid)] + end, + NR2 = fun(Cid, Rid) -> + [mtrtaams2_mg_notify_request_ar2(20 + Rid, Tid, Cid)] + end, + ConnectVerify = ?mtrtaams2_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?mtrtaams2_mg_verify_service_change_reply_fun(), + NotifyReplyVerify = ?mtrtaams2_mg_verify_notify_reply_fun(), +%% ConnectVerify = fun mtrtaams2_mg_verify_handle_connect/1, +%% ServiceChangeReplyVerify = fun mtrtaams2_mg_verify_service_change_reply/1, +%% NotifyReplyVerify = fun mtrtaams2_mg_verify_notify_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {connect, [{serialize, true}]}, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_update_conn_info, auto_ack, true}, + {megaco_update_conn_info, trans_ack_maxcount, 10}, + {megaco_update_conn_info, trans_req_maxcount, 10}, + {megaco_update_conn_info, trans_req_maxsize, 1024}, + {megaco_update_conn_info, trans_timer, 5000}, + {megaco_update_conn_info, trans_ack, true}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {megaco_cast, [NR1(1,2), NR1(1,3), NR1(1,4)], []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_cast, [NR1(2,5), NR1(2,6), NR1(2,7)], []}, + {megaco_cast, NR2(2,1), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 3000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +mtrtaams2_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + p("mtrtaams2_mg_verify_handle_connect -> ok" + "~n CH: ~p", [CH]), + {ok, CH, ok}; +mtrtaams2_mg_verify_handle_connect(Else) -> + p("mtrtaams2_mg_verify_handle_connect -> unknown" + "~n Else: ~p", [Else]), + {error, Else, ok}. + +mtrtaams2_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + p("mtrtaams2_mg_verify_service_change_reply -> ok" + "~n AR: ~p", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +mtrtaams2_mg_verify_service_change_reply(Else) -> + p("mtrtaams2_mg_verify_service_change_reply -> unknown" + "~n Else: ~p", [Else]), + {error, Else, ok}. + +mtrtaams2_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + p("mtrtaams2_mg_verify_notify_reply -> ok" + "~n AR: ~p", [AR]), + {ok, AR, ok}; +mtrtaams2_mg_verify_notify_reply(Else) -> + p("mtrtaams2_mg_verify_notify_reply -> unknown" + "~n Else: ~p", [Else]), + {error, Else, ok}. + +mtrtaams2_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrtaams2_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = mtrtaams2_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtrtaams2_mg_notify_request_ar1(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtrtaams2_mg_notify_request_ar2(Rid, Tid, Cid) -> + F = fun(N) -> + T = 22000000 + N, + TS = integer_to_list(T), + TT = cre_timeNotation("19990729", TS), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid+N, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + cre_cmdReq(CMD) + end, + Ns = [0,1,2,3,4,5,6,7,8,9], + CRs = [F(N) || N <- Ns], + cre_actionReq(Cid, CRs). + +mtrtaams2_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = mtrtaams2_mg_notify_request_ar1(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% Common functions for the multi_trans_req_timeout test case +%% + +mtrtaams2_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +single_trans_req_and_pending(suite) -> + []; +single_trans_req_and_pending(doc) -> + []; +single_trans_req_and_pending(Config) when is_list(Config) -> + ?SKIP(not_yet_implemented). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_trans_req_and_pending(suite) -> + []; +multi_trans_req_and_pending(doc) -> + []; +multi_trans_req_and_pending(Config) when is_list(Config) -> + ?SKIP(not_yet_implemented). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_trans_req_and_ack_and_pending(suite) -> + []; +multi_trans_req_and_ack_and_pending(doc) -> + []; +multi_trans_req_and_ack_and_pending(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, mtraaap), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = mtraaap_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = mtraaap_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtraaap_mgc_verify_handle_connect_fun(), + {?MODULE, mtraaap_mgc_verify_handle_connect, []}). +-define(mtraaap_mgc_verify_service_change_req_fun(Mid), + {?MODULE, mtraaap_mgc_verify_service_change_req, [Mid]}). +-define(mtraaap_mgc_verify_notify_req_fun(), + {?MODULE, mtraaap_mgc_verify_notify_request, []}). +-define(mtraaap_mgc_verify_notify_reply_fun(), + {?MODULE, mtraaap_mgc_verify_notify_reply, []}). +-define(mtraaap_mgc_verify_ack_fun(), + {?MODULE, mtraaap_mgc_verify_ack, []}). +-define(mtraaap_mgc_verify_handle_disconnect_fun(), + {?MODULE, mtraaap_mgc_verify_handle_disconnect, []}). +-else. +-define(mtraaap_mgc_verify_handle_connect_fun(), + fun mtraaap_mgc_verify_handle_connect/1). +-define(mtraaap_mgc_verify_service_change_req_fun(Mid), + mtraaap_mgc_verify_service_change_req_fun(Mid)). +-define(mtraaap_mgc_verify_notify_req_fun(), + mtraaap_mgc_verify_notify_request_fun()). +-define(mtraaap_mgc_verify_notify_reply_fun(), + fun mtraaap_mgc_verify_notify_reply/1). +-define(mtraaap_mgc_verify_ack_fun(), + fun mtraaap_mgc_verify_ack/1). +-define(mtraaap_mgc_verify_handle_disconnect_fun(), + fun mtraaap_mgc_verify_handle_disconnect/1). +-endif. + +mtraaap_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [mtraaap_mgc_notify_request_ar(Rid, Tid, Cid)] + end, + ReqTmr = #megaco_incr_timer{wait_for = 500, + factor = 1, + max_retries = 1}, + ConnectVerify = ?mtraaap_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?mtraaap_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?mtraaap_mgc_verify_notify_req_fun(), + NotifyReplyVerify = ?mtraaap_mgc_verify_notify_reply_fun(), + AckVerify = ?mtraaap_mgc_verify_ack_fun(), + DiscoVerify = ?mtraaap_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun mtraaap_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = mtraaap_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = mtraaap_mgc_verify_notify_request_fun(), +%% NotifyReplyVerify = fun mtraaap_mgc_verify_notify_reply/1, +%% AckVerify = fun mtraaap_mgc_verify_ack/1, +%% DiscoVerify = fun mtraaap_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_update_conn_info, request_timer, ReqTmr}, + {megaco_cast, NR(1,1), []}, + {megaco_callback, [{handle_trans_ack, 3, AckVerify}, + {handle_trans_request, 3, NotifyReqVerify}, + {handle_trans_reply, 1, NotifyReplyVerify}]}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +mtraaap_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtraaap_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtraaap_mgc_verify_handle_connect(Else) -> + io:format("mtraaap_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtraaap_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + mtraaap_mgc_verify_service_change_req(Ev, Mid) + end. + +mtraaap_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("mtraaap_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [mtraaap_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = mtraaap_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = mtraaap_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = mtraaap_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = mtraaap_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = mtraaap_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +mtraaap_mgc_verify_service_change_req(Else, _Mid) -> + io:format("mtraaap_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtraaap_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtraaap_mgc_verify_notify_request_fun() -> + fun(Ev) -> + mtraaap_mgc_verify_notify_request(Ev) + end. + +mtraaap_mgc_verify_notify_request( + {handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("mtraaap_mgc_verify_notify_request -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + HandleAck = {handle_sloppy_ack, kalle}, + Reply = {HandleAck, + [mtraaap_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + #'ActionRequest'{contextId = 2 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [mtraaap_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = mtraaap_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +mtraaap_mgc_verify_notify_request(Else) -> + io:format("mtraaap_mgc_verify_notify_request -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtraaap_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtraaap_mgc_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtraaap_mgc_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +mtraaap_mgc_verify_notify_reply(Else) -> + io:format("mtraaap_mgc_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtraaap_mgc_verify_ack({handle_trans_ack, CH, ?VERSION, ok, kalle}) -> + io:format("mtraaap_mgc_verify_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +mtraaap_mgc_verify_ack(Else) -> + io:format("mtraaap_mgc_verify_ack -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtraaap_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("mtraaap_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +mtraaap_mgc_verify_handle_disconnect(Else) -> + io:format("mtraaap_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +mtraaap_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +mtraaap_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = mtraaap_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtraaap_mgc_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "44000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtraaap_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +mtraaap_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = mtraaap_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtraaap_mg_verify_handle_connect_fun(), + {?MODULE, mtraaap_mg_verify_handle_connect, []}). +-define(mtraaap_mg_verify_service_change_reply_fun(), + {?MODULE, mtraaap_mg_verify_service_change_reply, []}). +-define(mtraaap_mg_verify_notify_req_fun(), + {?MODULE, mtraaap_mgc_verify_notify_request, []}). +-define(mtraaap_mg_verify_notify_reply_fun(), + {?MODULE, mtraaap_mg_verify_notify_reply, []}). +-else. +-define(mtraaap_mg_verify_handle_connect_fun(), + fun mtraaap_mg_verify_handle_connect/1). +-define(mtraaap_mg_verify_service_change_reply_fun(), + fun mtraaap_mg_verify_service_change_reply/1). +-define(mtraaap_mg_verify_notify_req_fun(), + mtraaap_mgc_verify_notify_request_fun()). +-define(mtraaap_mg_verify_notify_reply_fun(), + fun mtraaap_mg_verify_notify_reply/1). +-endif. + +mtraaap_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [mtraaap_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [mtraaap_mg_notify_request_ar(Rid, Tid, Cid)] + end, + ConnectVerify = ?mtraaap_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?mtraaap_mg_verify_service_change_reply_fun(), + NotifyReqVerify = ?mtraaap_mg_verify_notify_req_fun(), + NotifyReplyVerify = ?mtraaap_mg_verify_notify_reply_fun(), +%% ConnectVerify = fun mtraaap_mg_verify_handle_connect/1, +%% ServiceChangeReplyVerify = fun mtraaap_mg_verify_service_change_reply/1, +%% NotifyReqVerify = mtraaap_mg_verify_notify_request_fun(), +%% NotifyReplyVerify = fun mtraaap_mg_verify_notify_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_update_conn_info, auto_ack, true}, + {megaco_update_conn_info, trans_ack_maxcount, 10}, + {megaco_update_conn_info, trans_req_maxcount, 10}, + {megaco_update_conn_info, trans_timer, 1000}, + {megaco_update_conn_info, trans_ack, true}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {megaco_cast, NR(1,1), []}, + {megaco_cast, NR(1,2), []}, + {megaco_cast, NR(1,3), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_update_conn_info, trans_timer, 120000}, + {megaco_cast, NR(2,1), []}, + {megaco_cast, NR(2,2), []}, + {megaco_cast, NR(2,3), []}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 3000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +mtraaap_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtraaap_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtraaap_mg_verify_handle_connect(Else) -> + io:format("mtraaap_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtraaap_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtraaap_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +mtraaap_mg_verify_service_change_reply(Else) -> + io:format("mtraaap_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtraaap_mg_verify_notify_request_fun() -> + fun(Ev) -> + mtraaap_mg_verify_notify_request(Ev) + end. + +mtraaap_mg_verify_notify_request( + {handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("mtraaap_mg_verify_notify_request -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [mtraaap_mg_notify_reply_ar(Cid, Tid)]}, + {ok, 3000, AR, Reply}; + _ -> + ED = mtraaap_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +mtraaap_mg_verify_notify_request(Else) -> + io:format("mtraaap_mg_verify_notify_request:fun -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtraaap_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtraaap_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtraaap_mg_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +mtraaap_mg_verify_notify_reply(Else) -> + io:format("mtraaap_mg_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtraaap_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtraaap_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = mtraaap_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtraaap_mg_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +mtraaap_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtraaap_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = mtraaap_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% Common functions for this test case +%% + +mtraaap_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_ack_and_pending(suite) -> + []; +multi_ack_and_pending(doc) -> + []; +multi_ack_and_pending(Config) when is_list(Config) -> + ?SKIP(not_yet_implemented). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_trans_req_and_reply(suite) -> + []; +multi_trans_req_and_reply(doc) -> + []; +multi_trans_req_and_reply(Config) when is_list(Config) -> + ?SKIP(not_yet_implemented). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_trans_req_and_ack_and_reply(suite) -> + []; +multi_trans_req_and_ack_and_reply(doc) -> + []; +multi_trans_req_and_ack_and_reply(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, multi_trans_req_and_ack_and_reply), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = mtraaar_mgc_event_sequence(text, tcp), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = mtraaar_mg_event_sequence(text, tcp), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator reply(s)"), + await_completion([MgcId, MgId]), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtraaar_mgc_verify_handle_connect_fun(), + {?MODULE, mtraaar_mgc_verify_handle_connect, []}). +-define(mtraaar_mgc_verify_service_change_req_fun(Mid), + {?MODULE, mtraaar_mgc_verify_service_change_req, [Mid]}). +-define(mtraaar_mgc_verify_notify_req_fun(), + {?MODULE, mtraaar_mgc_verify_notify_request, []}). +-define(mtraaar_mgc_verify_notify_reply_fun(), + {?MODULE, mtraaar_mgc_verify_notify_reply, []}). +-define(mtraaar_mgc_verify_ack_fun(), + {?MODULE, mtraaar_mgc_verify_ack, []}). +-define(mtraaar_mgc_verify_handle_disconnect_fun(), + {?MODULE, mtraaar_mgc_verify_handle_disconnect, []}). +-else. +-define(mtraaar_mgc_verify_handle_connect_fun(), + fun mtraaar_mgc_verify_handle_connect/1). +-define(mtraaar_mgc_verify_service_change_req_fun(Mid), + mtraaar_mgc_verify_service_change_req_fun(Mid)). +-define(mtraaar_mgc_verify_notify_req_fun(), + mtraaar_mgc_verify_notify_request_fun()). +-define(mtraaar_mgc_verify_notify_reply_fun(), + fun mtraaar_mgc_verify_notify_reply/1). +-define(mtraaar_mgc_verify_ack_fun(), + fun mtraaar_mgc_verify_ack/1). +-define(mtraaar_mgc_verify_handle_disconnect_fun(), + fun mtraaar_mgc_verify_handle_disconnect/1). +-endif. + +mtraaar_mgc_event_sequence(text, tcp) -> + Mid = {deviceName,"ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [mtraaar_mgc_notify_request_ar(Rid, Tid, Cid)] + end, + ConnectVerify = ?mtraaar_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?mtraaar_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?mtraaar_mgc_verify_notify_req_fun(), + NotifyReplyVerify = ?mtraaar_mgc_verify_notify_reply_fun(), + AckVerify = ?mtraaar_mgc_verify_ack_fun(), + DiscoVerify = ?mtraaar_mgc_verify_handle_disconnect_fun(), +%% ConnectVerify = fun mtraaar_mgc_verify_handle_connect/1, +%% ServiceChangeReqVerify = mtraaar_mgc_verify_service_change_req_fun(Mid), +%% NotifyReqVerify = mtraaar_mgc_verify_notify_request_fun(), +%% NotifyReplyVerify = fun mtraaar_mgc_verify_notify_reply/1, +%% AckVerify = fun mtraaar_mgc_verify_ack/1, +%% DiscoVerify = fun mtraaar_mgc_verify_handle_disconnect/1, + EvSeq = [ + {debug, true}, + %% {megaco_trace, max}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_update_conn_info, request_timer, 1000}, + {megaco_cast, NR(1,1), []}, + + {megaco_callback, [{handle_trans_ack, 3, AckVerify}, + {handle_trans_request, 3, NotifyReqVerify}, + {handle_trans_reply, 1, NotifyReplyVerify}]}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +mtraaar_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtraaar_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtraaar_mgc_verify_handle_connect(Else) -> + io:format("mtraaar_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtraaar_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + mtraaar_mgc_verify_service_change_req(Ev, Mid) + end. + +mtraaar_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("mtraaar_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [mtraaar_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = mtraaar_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = mtraaar_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = mtraaar_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = mtraaar_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = mtraaar_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +mtraaar_mgc_verify_service_change_req(Else, _Mid) -> + io:format("mtraaar_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtraaar_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtraaar_mgc_verify_notify_request_fun() -> + fun(Ev) -> + mtraaar_mgc_verify_notify_request(Ev) + end. + +mtraaar_mgc_verify_notify_request( + {handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("mtraaar_mgc_verify_notify_request -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + HandleAck = {handle_sloppy_ack, kalle}, + Reply = {HandleAck, + [mtraaar_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + #'ActionRequest'{contextId = 2 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [mtraaar_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = mtraaar_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +mtraaar_mgc_verify_notify_request(Else) -> + io:format("mtraaar_mgc_verify_notify_request -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtraaar_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtraaar_mgc_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtraaar_mgc_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +mtraaar_mgc_verify_notify_reply({handle_trans_reply, CH, ?VERSION, + UnknownResult, _}) -> + io:format("mtraaar_mgc_verify_notify_reply -> unknown result" + "~n UnknownResult: ~p~n", [UnknownResult]), + {error, {unknown_reply_result, UnknownResult, CH}, ok}; +mtraaar_mgc_verify_notify_reply(Else) -> + io:format("mtraaar_mgc_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, {unknown_reply, Else}, ok}. + +mtraaar_mgc_verify_ack({handle_trans_ack, CH, ?VERSION, ok, kalle}) -> + io:format("mtraaar_mgc_verify_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +mtraaar_mgc_verify_ack(Else) -> + io:format("mtraaar_mgc_verify_ack -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtraaar_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("mtraaar_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +mtraaar_mgc_verify_handle_disconnect(Else) -> + io:format("mtraaar_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +mtraaar_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +mtraaar_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = mtraaar_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtraaar_mgc_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "44000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtraaar_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +mtraaar_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = mtraaar_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(mtraaar_mg_verify_handle_connect_fun(), + {?MODULE, mtraaar_mg_verify_handle_connect, []}). +-define(mtraaar_mg_verify_service_change_reply_fun(), + {?MODULE, mtraaar_mg_verify_service_change_reply, []}). +-define(mtraaar_mg_verify_notify_req_fun(), + {?MODULE, mtraaar_mgc_verify_notify_request, []}). +-define(mtraaar_mg_verify_notify_reply_fun(), + {?MODULE, mtraaar_mg_verify_notify_reply, []}). +-else. +-define(mtraaar_mg_verify_handle_connect_fun(), + fun mtraaar_mg_verify_handle_connect/1). +-define(mtraaar_mg_verify_service_change_reply_fun(), + fun mtraaar_mg_verify_service_change_reply/1). +-define(mtraaar_mg_verify_notify_req_fun(), + mtraaar_mgc_verify_notify_request_fun()). +-define(mtraaar_mg_verify_notify_reply_fun(), + fun mtraaar_mg_verify_notify_reply/1). +-endif. + +mtraaar_mg_event_sequence(text, tcp) -> + Mid = {deviceName,"mg"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [mtraaar_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [mtraaar_mg_notify_request_ar(Rid, Tid, Cid)] + end, + ConnectVerify = ?mtraaar_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?mtraaar_mg_verify_service_change_reply_fun(), + NotifyReqVerify = ?mtraaar_mg_verify_notify_req_fun(), + NotifyReplyVerify = ?mtraaar_mg_verify_notify_reply_fun(), +%% ConnectVerify = fun mtraaar_mg_verify_handle_connect/1, +%% ServiceChangeReplyVerify = fun mtraaar_mg_verify_service_change_reply/1, +%% NotifyReqVerify = mtraaar_mg_verify_notify_request_fun(), +%% NotifyReplyVerify = fun mtraaar_mg_verify_notify_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + %% {megaco_trace, max}, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_update_conn_info, auto_ack, true}, + {megaco_update_conn_info, trans_ack_maxcount, 10}, + {megaco_update_conn_info, trans_req_maxcount, 10}, + {megaco_update_conn_info, trans_timer, 1000}, + {megaco_update_conn_info, trans_ack, true}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {megaco_cast, NR(1,1), []}, + {megaco_cast, NR(1,2), []}, + {megaco_cast, NR(1,3), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_update_conn_info, trans_timer, 120000}, + {megaco_cast, NR(2,1), []}, + {megaco_cast, NR(2,2), []}, + {megaco_cast, NR(2,3), []}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 3000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +mtraaar_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("mtraaar_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +mtraaar_mg_verify_handle_connect(Else) -> + io:format("mtraaar_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtraaar_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtraaar_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +mtraaar_mg_verify_service_change_reply(Else) -> + io:format("mtraaar_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtraaar_mg_verify_notify_request_fun() -> + fun(Ev) -> + mtraaar_mg_verify_notify_request(Ev) + end. + +mtraaar_mg_verify_notify_request( + {handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("mtraaar_mg_verify_notify_request -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [mtraaar_mg_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = mtraaar_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +mtraaar_mg_verify_notify_request(Else) -> + io:format("mtraaar_mg_verify_notify_request -> unknown" + "~n Else: ~p~n", [Else]), + ED = mtraaar_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +mtraaar_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("mtraaar_mg_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +mtraaar_mg_verify_notify_reply(Else) -> + io:format("mtraaar_mg_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +mtraaar_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtraaar_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = mtraaar_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +mtraaar_mg_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +mtraaar_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +mtraaar_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = mtraaar_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% Common functions for the multi_trans_req_timeout test case +%% + +mtraaar_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +multi_ack_and_reply(suite) -> + []; +multi_ack_and_reply(doc) -> + []; +multi_ack_and_reply(Config) when is_list(Config) -> + ?SKIP(not_yet_implemented). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_7192_1(suite) -> + []; +otp_7192_1(doc) -> + [""]; +otp_7192_1(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, otp_7192_1), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + + MgMid = {deviceName,"mg"}, + + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = otp71921_mgc_event_sequence(text, tcp, MgMid), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = otp71921_mg_event_sequence(text, tcp, MgMid), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator(s) completion"), + await_completion([MgcId, MgId], 30000), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp71921_mgc_verify_handle_connect_fun(), + {?MODULE, otp71921_mgc_verify_handle_connect, []}). +-define(otp71921_mgc_verify_service_change_req_fun(Mid), + {?MODULE, otp71921_mgc_verify_service_change_req, [Mid]}). +-define(otp71921_mgc_verify_notify_req_fun(), + {?MODULE, otp71921_mgc_verify_notify_request, []}). +-define(otp71921_mgc_verify_notify_reply_fun(), + {?MODULE, otp71921_mgc_verify_notify_reply, []}). +-define(otp71921_mgc_verify_ack_fun(), + {?MODULE, otp71921_mgc_verify_ack, []}). +-define(otp71921_mgc_verify_handle_disconnect_fun(), + {?MODULE, otp71921_mgc_verify_handle_disconnect, []}). +-else. +-define(otp71921_mgc_verify_handle_connect_fun(), + fun otp71921_mgc_verify_handle_connect/1). +-define(otp71921_mgc_verify_service_change_req_fun(Mid), + otp71921_mgc_verify_service_change_req_fun(Mid)). +-define(otp71921_mgc_verify_notify_req_fun(), + otp71921_mgc_verify_notify_request_fun()). +-define(otp71921_mgc_verify_notify_reply_fun(), + fun otp71921_mgc_verify_notify_reply/1). +-define(otp71921_mgc_verify_ack_fun(), + fun otp71921_mgc_verify_ack/1). +-define(otp71921_mgc_verify_handle_disconnect_fun(), + fun otp71921_mgc_verify_handle_disconnect/1). +-endif. + +otp71921_mgc_event_sequence(text, tcp, MgMid) -> + Mid = {deviceName, "ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [otp71921_mgc_notify_request_ar(Rid, Tid, Cid)] + end, + LocalConnectVerify = ?otp71921_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?otp71921_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?otp71921_mgc_verify_notify_req_fun(), + NotifyReplyVerify = ?otp71921_mgc_verify_notify_reply_fun(), + AckVerify = ?otp71921_mgc_verify_ack_fun(), + DiscoVerify = ?otp71921_mgc_verify_handle_disconnect_fun(), + EvSeq = [ + {debug, true}, + %% {megaco_trace, max}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_connect, MgMid}, + {megaco_callback, handle_connect, LocalConnectVerify}, + %% {megaco_callback, handle_connect, RemoteConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_update_conn_info, request_timer, 1000}, + {megaco_cast, NR(1,1), []}, + + {megaco_callback, [{handle_trans_ack, 3, AckVerify}, + {handle_trans_request, 3, NotifyReqVerify}, + {handle_trans_reply, 1, NotifyReplyVerify}]}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +otp71921_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("otp71921_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +otp71921_mgc_verify_handle_connect(Else) -> + io:format("otp71921_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp71921_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + otp71921_mgc_verify_service_change_req(Ev, Mid) + end. + +otp71921_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("otp71921_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [otp71921_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = otp71921_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = otp71921_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = otp71921_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = otp71921_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = otp71921_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +otp71921_mgc_verify_service_change_req(Else, _Mid) -> + io:format("otp71921_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = otp71921_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +otp71921_mgc_verify_notify_request_fun() -> + fun(Ev) -> + otp71921_mgc_verify_notify_request(Ev) + end. + +otp71921_mgc_verify_notify_request( + {handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("otp71921_mgc_verify_notify_request -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + HandleAck = {handle_sloppy_ack, kalle}, + Reply = {HandleAck, + [otp71921_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + #'ActionRequest'{contextId = 2 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [otp71921_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = otp71921_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +otp71921_mgc_verify_notify_request(Else) -> + io:format("otp71921_mgc_verify_notify_request -> unknown" + "~n Else: ~p~n", [Else]), + ED = otp71921_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +otp71921_mgc_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("otp71921_mgc_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +otp71921_mgc_verify_notify_reply({handle_trans_reply, CH, ?VERSION, + UnknownResult, _}) -> + io:format("otp71921_mgc_verify_notify_reply -> unknown result" + "~n UnknownResult: ~p~n", [UnknownResult]), + {error, {unknown_reply_result, UnknownResult, CH}, ok}; +otp71921_mgc_verify_notify_reply(Else) -> + io:format("otp71921_mgc_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, {unknown_reply, Else}, ok}. + +otp71921_mgc_verify_ack({handle_trans_ack, CH, ?VERSION, ok, kalle}) -> + io:format("otp71921_mgc_verify_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +otp71921_mgc_verify_ack(Else) -> + io:format("otp71921_mgc_verify_ack -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp71921_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("otp71921_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +otp71921_mgc_verify_handle_disconnect(Else) -> + io:format("otp71921_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +otp71921_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +otp71921_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = otp71921_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +otp71921_mgc_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "44000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp71921_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +otp71921_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = otp71921_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp71921_mg_verify_handle_connect_fun(), + {?MODULE, otp71921_mg_verify_handle_connect, []}). +-define(otp71921_mg_verify_service_change_reply_fun(), + {?MODULE, otp71921_mg_verify_service_change_reply, []}). +-define(otp71921_mg_verify_notify_req_fun(), + {?MODULE, otp71921_mgc_verify_notify_request, []}). +-define(otp71921_mg_verify_notify_reply_fun(), + {?MODULE, otp71921_mg_verify_notify_reply, []}). +-else. +-define(otp71921_mg_verify_handle_connect_fun(), + fun otp71921_mg_verify_handle_connect/1). +-define(otp71921_mg_verify_service_change_reply_fun(), + fun otp71921_mg_verify_service_change_reply/1). +-define(otp71921_mg_verify_notify_req_fun(), + otp71921_mgc_verify_notify_request_fun()). +-define(otp71921_mg_verify_notify_reply_fun(), + fun otp71921_mg_verify_notify_reply/1). +-endif. + +otp71921_mg_event_sequence(text, tcp, Mid) -> + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [otp71921_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [otp71921_mg_notify_request_ar(Rid, Tid, Cid)] + end, + ConnectVerify = ?otp71921_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?otp71921_mg_verify_service_change_reply_fun(), + NotifyReqVerify = ?otp71921_mg_verify_notify_req_fun(), + NotifyReplyVerify = ?otp71921_mg_verify_notify_reply_fun(), +%% ConnectVerify = fun otp71921_mg_verify_handle_connect/1, +%% ServiceChangeReplyVerify = fun otp71921_mg_verify_service_change_reply/1, +%% NotifyReqVerify = otp71921_mg_verify_notify_request_fun(), +%% NotifyReplyVerify = fun otp71921_mg_verify_notify_reply/1, + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + %% {megaco_trace, max}, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_update_conn_info, auto_ack, true}, + {megaco_update_conn_info, trans_ack_maxcount, 10}, + {megaco_update_conn_info, trans_req_maxcount, 10}, + {megaco_update_conn_info, trans_timer, 1000}, + {megaco_update_conn_info, trans_ack, true}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {megaco_cast, NR(1,1), []}, + {megaco_cast, NR(1,2), []}, + {megaco_cast, NR(1,3), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_update_conn_info, trans_timer, 120000}, + {megaco_cast, NR(2,1), []}, + {megaco_cast, NR(2,2), []}, + {megaco_cast, NR(2,3), []}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 3000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +otp71921_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("otp71921_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +otp71921_mg_verify_handle_connect(Else) -> + io:format("otp71921_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp71921_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("otp71921_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +otp71921_mg_verify_service_change_reply(Else) -> + io:format("otp71921_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp71921_mg_verify_notify_request_fun() -> + fun(Ev) -> + otp71921_mg_verify_notify_request(Ev) + end. + +otp71921_mg_verify_notify_request( + {handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("otp71921_mg_verify_notify_request -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [otp71921_mg_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = otp71921_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +otp71921_mg_verify_notify_request(Else) -> + io:format("otp71921_mg_verify_notify_request -> unknown" + "~n Else: ~p~n", [Else]), + ED = otp71921_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +otp71921_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("otp71921_mg_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +otp71921_mg_verify_notify_reply(Else) -> + io:format("otp71921_mg_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp71921_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp71921_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = otp71921_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +otp71921_mg_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +otp71921_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp71921_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = otp71921_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% Common functions for the multi_trans_req_timeout test case +%% + +otp71921_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_7192_2(suite) -> + []; +otp_7192_2(doc) -> + []; +otp_7192_2(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, otp_7192_2), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + + MgMid = {deviceName,"mg"}, + + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = otp71922_mgc_event_sequence(text, tcp, MgMid), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = otp71922_mg_event_sequence(text, tcp, MgMid), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator(s) completion"), + await_completion([MgcId, MgId], 30000), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp71922_mgc_verify_handle_connect_fun(), + {?MODULE, otp71922_mgc_verify_handle_connect, []}). +-define(otp71922_mgc_verify_service_change_req_fun(Mid), + {?MODULE, otp71922_mgc_verify_service_change_req, [Mid]}). +-define(otp71922_mgc_verify_notify_req_fun(), + {?MODULE, otp71922_mgc_verify_notify_request, []}). +-define(otp71922_mgc_verify_notify_reply_fun(), + {?MODULE, otp71922_mgc_verify_notify_reply, []}). +-define(otp71922_mgc_verify_ack_fun(), + {?MODULE, otp71922_mgc_verify_ack, []}). +-define(otp71922_mgc_verify_handle_disconnect_fun(), + {?MODULE, otp71922_mgc_verify_handle_disconnect, []}). +-else. +-define(otp71922_mgc_verify_handle_connect_fun(), + fun otp71922_mgc_verify_handle_connect/1). +-define(otp71922_mgc_verify_service_change_req_fun(Mid), + otp71922_mgc_verify_service_change_req_fun(Mid)). +-define(otp71922_mgc_verify_notify_req_fun(), + otp71922_mgc_verify_notify_request_fun()). +-define(otp71922_mgc_verify_notify_reply_fun(), + fun otp71922_mgc_verify_notify_reply/1). +-define(otp71922_mgc_verify_ack_fun(), + fun otp71922_mgc_verify_ack/1). +-define(otp71922_mgc_verify_handle_disconnect_fun(), + fun otp71922_mgc_verify_handle_disconnect/1). +-endif. + +otp71922_mgc_event_sequence(text, tcp, MgMid) -> + Mid = {deviceName, "ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [otp71922_mgc_notify_request_ar(Rid, Tid, Cid)] + end, + LocalConnectVerify = ?otp71922_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?otp71922_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?otp71922_mgc_verify_notify_req_fun(), + NotifyReplyVerify = ?otp71922_mgc_verify_notify_reply_fun(), + AckVerify = ?otp71922_mgc_verify_ack_fun(), + DiscoVerify = ?otp71922_mgc_verify_handle_disconnect_fun(), + EvSeq = [ + {debug, true}, + %% {megaco_trace, max}, + {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_connect, MgMid}, + {megaco_callback, handle_connect, LocalConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_update_conn_info, request_timer, 1000}, + {megaco_cast, NR(1,1), []}, + + {megaco_callback, [{handle_trans_ack, 3, AckVerify}, + {handle_trans_request, 3, NotifyReqVerify}, + {handle_trans_reply, 1, NotifyReplyVerify}]}, + {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +otp71922_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("otp71922_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, timer:seconds(2), CH, ok}; +otp71922_mgc_verify_handle_connect(Else) -> + io:format("otp71922_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp71922_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + otp71922_mgc_verify_service_change_req(Ev, Mid) + end. + +otp71922_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("otp71922_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [otp71922_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = otp71922_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = otp71922_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = otp71922_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = otp71922_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = otp71922_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +otp71922_mgc_verify_service_change_req(Else, _Mid) -> + io:format("otp71922_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = otp71922_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +otp71922_mgc_verify_notify_request_fun() -> + fun(Ev) -> + otp71922_mgc_verify_notify_request(Ev) + end. + +otp71922_mgc_verify_notify_request( + {handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("otp71922_mgc_verify_notify_request -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + HandleAck = {handle_sloppy_ack, kalle}, + Reply = {HandleAck, + [otp71922_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + #'ActionRequest'{contextId = 2 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [otp71922_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = otp71922_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +otp71922_mgc_verify_notify_request(Else) -> + io:format("otp71922_mgc_verify_notify_request -> unknown" + "~n Else: ~p~n", [Else]), + ED = otp71922_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +otp71922_mgc_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("otp71922_mgc_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +otp71922_mgc_verify_notify_reply({handle_trans_reply, CH, ?VERSION, + UnknownResult, _}) -> + io:format("otp71922_mgc_verify_notify_reply -> unknown result" + "~n UnknownResult: ~p~n", [UnknownResult]), + {error, {unknown_reply_result, UnknownResult, CH}, ok}; +otp71922_mgc_verify_notify_reply(Else) -> + io:format("otp71922_mgc_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, {unknown_reply, Else}, ok}. + +otp71922_mgc_verify_ack({handle_trans_ack, CH, ?VERSION, ok, kalle}) -> + io:format("otp71922_mgc_verify_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +otp71922_mgc_verify_ack(Else) -> + io:format("otp71922_mgc_verify_ack -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp71922_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> + io:format("otp71922_mgc_verify_handle_disconnect -> ok" + "~n CH: ~p" + "~n R: ~p" + "~n", [CH, R]), + {ok, CH, ok}; +otp71922_mgc_verify_handle_disconnect(Else) -> + io:format("otp71922_mgc_verify_handle_disconnect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + + +otp71922_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +otp71922_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = otp71922_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +otp71922_mgc_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "44000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp71922_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +otp71922_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = otp71922_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp71922_mg_verify_handle_connect_fun(), + {?MODULE, otp71922_mg_verify_handle_connect, []}). +-define(otp71922_mg_verify_service_change_reply_fun(), + {?MODULE, otp71922_mg_verify_service_change_reply, []}). +-define(otp71922_mg_verify_notify_req_fun(), + {?MODULE, otp71922_mgc_verify_notify_request, []}). +-define(otp71922_mg_verify_notify_reply_fun(), + {?MODULE, otp71922_mg_verify_notify_reply, []}). +-else. +-define(otp71922_mg_verify_handle_connect_fun(), + fun otp71922_mg_verify_handle_connect/1). +-define(otp71922_mg_verify_service_change_reply_fun(), + fun otp71922_mg_verify_service_change_reply/1). +-define(otp71922_mg_verify_notify_req_fun(), + otp71922_mgc_verify_notify_request_fun()). +-define(otp71922_mg_verify_notify_reply_fun(), + fun otp71922_mg_verify_notify_reply/1). +-endif. + +otp71922_mg_event_sequence(text, tcp, Mid) -> + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_tcp} + ], + ServiceChangeReq = [otp71922_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [otp71922_mg_notify_request_ar(Rid, Tid, Cid)] + end, + ConnectVerify = ?otp71922_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?otp71922_mg_verify_service_change_reply_fun(), + NotifyReqVerify = ?otp71922_mg_verify_notify_req_fun(), + NotifyReplyVerify = ?otp71922_mg_verify_notify_reply_fun(), + EvSeq = [ + {debug, true}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + %% {megaco_trace, max}, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_update_conn_info, auto_ack, true}, + {megaco_update_conn_info, trans_ack_maxcount, 10}, + {megaco_update_conn_info, trans_req_maxcount, 10}, + {megaco_update_conn_info, trans_timer, 1000}, + {megaco_update_conn_info, trans_ack, true}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {megaco_cast, NR(1,1), []}, + {megaco_cast, NR(1,2), []}, + {megaco_cast, NR(1,3), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_update_conn_info, trans_timer, 120000}, + {megaco_cast, NR(2,1), []}, + {megaco_cast, NR(2,2), []}, + {megaco_cast, NR(2,3), []}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 3000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +otp71922_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("otp71922_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +otp71922_mg_verify_handle_connect(Else) -> + io:format("otp71922_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp71922_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("otp71922_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +otp71922_mg_verify_service_change_reply(Else) -> + io:format("otp71922_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp71922_mg_verify_notify_request_fun() -> + fun(Ev) -> + otp71922_mg_verify_notify_request(Ev) + end. + +otp71922_mg_verify_notify_request( + {handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("otp71922_mg_verify_notify_request -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [otp71922_mg_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = otp71922_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +otp71922_mg_verify_notify_request(Else) -> + io:format("otp71922_mg_verify_notify_request -> unknown" + "~n Else: ~p~n", [Else]), + ED = otp71922_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +otp71922_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("otp71922_mg_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +otp71922_mg_verify_notify_reply(Else) -> + io:format("otp71922_mg_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp71922_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp71922_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = otp71922_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +otp71922_mg_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +otp71922_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp71922_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = otp71922_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% Common functions for the multi_trans_req_timeout test case +%% + +otp71922_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +otp_7192_3(suite) -> + []; +otp_7192_3(doc) -> + ["Same as otp_7192_2 but transport is UDP instead of TCP"]; +otp_7192_3(Config) when is_list(Config) -> + put(verbosity, ?TEST_VERBOSITY), + put(sname, "TEST"), + put(tc, otp_7192_3), + i("starting"), + + MgcNode = make_node_name(mgc), + MgNode = make_node_name(mg), + d("start nodes: " + "~n MgcNode: ~p" + "~n MgNode: ~p", + [MgcNode, MgNode]), + + MgMid = {deviceName,"mg"}, + + ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE), + + + d("[MGC] start the simulator "), + {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode), + + d("[MGC] create the event sequence"), + MgcEvSeq = otp72923_mgc_event_sequence(text, udp, MgMid), + + i("wait some time before starting the MGC simulation"), + sleep(1000), + + d("[MGC] start the simulation"), + {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq), + + i("wait some time before starting the MG simulator"), + sleep(1000), + + d("[MG] start the simulator (generator)"), + {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode), + + d("[MG] create the event sequence"), + MgEvSeq = otp72923_mg_event_sequence(text, udp, MgMid), + + i("wait some time before starting the MG simulation"), + sleep(1000), + + d("[MG] start the simulation"), + {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq), + + d("await the generator(s) completion"), + await_completion([MgcId, MgId], 60000), + + %% Tell Mgc to stop + i("[MGC] stop generator"), + megaco_test_megaco_generator:stop(Mgc), + + %% Tell Mg to stop + i("[MG] stop generator"), + megaco_test_megaco_generator:stop(Mg), + + i("done", []), + ok. + + +%% +%% MGC generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp72923_mgc_verify_handle_connect_fun(), + {?MODULE, otp72923_mgc_verify_handle_connect, []}). +-define(otp72923_mgc_verify_service_change_req_fun(Mid), + {?MODULE, otp72923_mgc_verify_service_change_req, [Mid]}). +-define(otp72923_mgc_verify_notify_req_fun(), + {?MODULE, otp72923_mgc_verify_notify_request, []}). +-define(otp72923_mgc_verify_notify_reply_fun(), + {?MODULE, otp72923_mgc_verify_notify_reply, []}). +-define(otp72923_mgc_verify_ack_fun(), + {?MODULE, otp72923_mgc_verify_ack, []}). +-define(otp72923_mgc_verify_handle_disconnect_fun(), + {?MODULE, otp72923_mgc_verify_handle_disconnect, []}). +-else. +-define(otp72923_mgc_verify_handle_connect_fun(), + fun otp72923_mgc_verify_handle_connect/1). +-define(otp72923_mgc_verify_service_change_req_fun(Mid), + otp72923_mgc_verify_service_change_req_fun(Mid)). +-define(otp72923_mgc_verify_notify_req_fun(), + otp72923_mgc_verify_notify_request_fun()). +-define(otp72923_mgc_verify_notify_reply_fun(), + fun otp72923_mgc_verify_notify_reply/1). +-define(otp72923_mgc_verify_ack_fun(), + fun otp72923_mgc_verify_ack/1). +-define(otp72923_mgc_verify_handle_disconnect_fun(), + fun otp72923_mgc_verify_handle_disconnect/1). +-endif. + +otp72923_mgc_event_sequence(text, udp, MgMid) -> + Mid = {deviceName, "ctrl"}, + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_udp} + ], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [otp72923_mgc_notify_request_ar(Rid, Tid, Cid)] + end, + LocalConnectVerify = ?otp72923_mgc_verify_handle_connect_fun(), + ServiceChangeReqVerify = ?otp72923_mgc_verify_service_change_req_fun(Mid), + NotifyReqVerify = ?otp72923_mgc_verify_notify_req_fun(), + NotifyReplyVerify = ?otp72923_mgc_verify_notify_reply_fun(), + AckVerify = ?otp72923_mgc_verify_ack_fun(), + %% DiscoVerify = ?otp72923_mgc_verify_handle_disconnect_fun(), + EvSeq = [ + {debug, true}, + {megaco_trace, max}, + %% {megaco_trace, disable}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + listen, + {megaco_connect, MgMid}, + {megaco_callback, handle_connect, LocalConnectVerify}, + {megaco_callback, handle_trans_request, ServiceChangeReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_update_conn_info, request_timer, 1000}, + {megaco_cast, NR(1,1), []}, + + {megaco_callback, [{handle_trans_ack, 3, AckVerify}, + {handle_trans_request, 3, NotifyReqVerify}, + {handle_trans_reply, 1, NotifyReplyVerify}]}, + %% {megaco_callback, handle_disconnect, DiscoVerify}, + {sleep, 1000}, + megaco_stop_user, + megaco_stop + ], + EvSeq. + + +otp72923_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("otp72923_mgc_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, timer:seconds(2), CH, ok}; +otp72923_mgc_verify_handle_connect(Else) -> + io:format("otp72923_mgc_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp72923_mgc_verify_service_change_req_fun(Mid) -> + fun(Ev) -> + otp72923_mgc_verify_service_change_req(Ev, Mid) + end. + +otp72923_mgc_verify_service_change_req( + {handle_trans_request, _, ?VERSION, [AR]}, Mid) -> + io:format("otp72923_mgc_verify_service_change_req -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{commandRequests = [CR]} -> + case CR of + #'CommandRequest'{command = Cmd} -> + case Cmd of + {serviceChangeReq, + #'ServiceChangeRequest'{terminationID = [Tid], + serviceChangeParms = Parms}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Parms of + #'ServiceChangeParm'{ + serviceChangeMethod = restart, + serviceChangeReason = [[$9,$0,$1|_]]} -> + Reply = + {discard_ack, + [otp72923_mgc_service_change_reply_ar(Mid, 1)]}, + {ok, AR, Reply}; + _ -> + Err = {invalid_SCP, Parms}, + ED = otp72923_err_desc(Parms), + ErrReply = {discard_ack, + ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_termination_id, Tid}, + ED = otp72923_err_desc(Tid), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command, Cmd}, + ED = otp72923_err_desc(Cmd), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_command_request, CR}, + ED = otp72923_err_desc(CR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; + _ -> + Err = {invalid_action_request, AR}, + ED = otp72923_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, Err, ErrReply} + end; +otp72923_mgc_verify_service_change_req(Else, _Mid) -> + io:format("otp72923_mgc_verify_service_change_req -> unknown" + "~n Else: ~p~n", [Else]), + ED = otp72923_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +otp72923_mgc_verify_notify_request_fun() -> + fun(Ev) -> + otp72923_mgc_verify_notify_request(Ev) + end. + +otp72923_mgc_verify_notify_request( + {handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("otp72923_mgc_verify_notify_request -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + HandleAck = {handle_sloppy_ack, kalle}, + Reply = {HandleAck, + [otp72923_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + #'ActionRequest'{contextId = 2 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [otp72923_mgc_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = otp72923_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +otp72923_mgc_verify_notify_request(Else) -> + io:format("otp72923_mgc_verify_notify_request -> unknown" + "~n Else: ~p~n", [Else]), + ED = otp72923_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +otp72923_mgc_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("otp72923_mgc_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +otp72923_mgc_verify_notify_reply({handle_trans_reply, CH, ?VERSION, + UnknownResult, _}) -> + io:format("otp72923_mgc_verify_notify_reply -> unknown result" + "~n UnknownResult: ~p~n", [UnknownResult]), + {error, {unknown_reply_result, UnknownResult, CH}, ok}; +otp72923_mgc_verify_notify_reply(Else) -> + io:format("otp72923_mgc_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, {unknown_reply, Else}, ok}. + +otp72923_mgc_verify_ack({handle_trans_ack, CH, ?VERSION, ok, kalle}) -> + io:format("otp72923_mgc_verify_ack -> ok" + "~n CH: ~p" + "~n", [CH]), + {ok, CH, ok}; +otp72923_mgc_verify_ack(Else) -> + io:format("otp72923_mgc_verify_ack -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +%% otp72923_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, R}) -> +%% io:format("otp72923_mgc_verify_handle_disconnect -> ok" +%% "~n CH: ~p" +%% "~n R: ~p" +%% "~n", [CH, R]), +%% {ok, CH, ok}; +%% otp72923_mgc_verify_handle_disconnect(Else) -> +%% io:format("otp72923_mgc_verify_handle_disconnect -> unknown" +%% "~n Else: ~p~n", [Else]), +%% {error, Else, ok}. + + +otp72923_mgc_service_change_reply_ar(Mid, Cid) -> + SCRP = cre_serviceChangeResParm(Mid), + SCRes = cre_serviceChangeResult(SCRP), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReply([Root], SCRes), + CR = cre_cmdReply(SCR), + cre_actionReply(Cid, [CR]). + +otp72923_mgc_service_change_reply_msg(Mid, TransId, Cid) -> + AR = otp72923_mgc_service_change_reply_ar(Mid, Cid), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +otp72923_mgc_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "44000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp72923_mgc_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +otp72923_mgc_notify_reply(Mid, TransId, Cid, TermId) -> + AR = otp72923_mgc_notify_reply_ar(Cid, TermId), + TRes = cre_transResult([AR]), + TR = cre_transReply(TransId, TRes), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% MG generator stuff +%% +-ifdef(megaco_hipe_special). +-define(otp72923_mg_verify_handle_connect_fun(), + {?MODULE, otp72923_mg_verify_handle_connect, []}). +-define(otp72923_mg_verify_service_change_reply_fun(), + {?MODULE, otp72923_mg_verify_service_change_reply, []}). +-define(otp72923_mg_verify_notify_req_fun(), + {?MODULE, otp72923_mgc_verify_notify_request, []}). +-define(otp72923_mg_verify_notify_reply_fun(), + {?MODULE, otp72923_mg_verify_notify_reply, []}). +-else. +-define(otp72923_mg_verify_handle_connect_fun(), + fun otp72923_mg_verify_handle_connect/1). +-define(otp72923_mg_verify_service_change_reply_fun(), + fun otp72923_mg_verify_service_change_reply/1). +-define(otp72923_mg_verify_notify_req_fun(), + otp72923_mgc_verify_notify_request_fun()). +-define(otp72923_mg_verify_notify_reply_fun(), + fun otp72923_mg_verify_notify_reply/1). +-endif. + +otp72923_mg_event_sequence(text, udp, Mid) -> + RI = [ + {port, 2944}, + {encoding_module, megaco_pretty_text_encoder}, + {encoding_config, []}, + {transport_module, megaco_udp} + ], + ServiceChangeReq = [otp72923_mg_service_change_request_ar(Mid, 1)], + Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]}, + NR = fun(Cid, Rid) -> + [otp72923_mg_notify_request_ar(Rid, Tid, Cid)] + end, + ConnectVerify = ?otp72923_mg_verify_handle_connect_fun(), + ServiceChangeReplyVerify = ?otp72923_mg_verify_service_change_reply_fun(), + NotifyReqVerify = ?otp72923_mg_verify_notify_req_fun(), + NotifyReplyVerify = ?otp72923_mg_verify_notify_reply_fun(), + EvSeq = [ + %% {debug, true}, + {debug, false}, + megaco_start, + {megaco_start_user, Mid, RI, []}, + start_transport, + %% {megaco_trace, max}, + {megaco_trace, disable}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + connect, + {megaco_callback, handle_connect, ConnectVerify}, + megaco_connect, + {megaco_cast, ServiceChangeReq, []}, + {megaco_callback, handle_connect, ConnectVerify}, + {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify}, + {sleep, 1000}, + {megaco_system_info, users}, + {megaco_system_info, connections}, + {sleep, 1000}, + {megaco_update_conn_info, auto_ack, true}, + {megaco_update_conn_info, trans_ack_maxcount, 10}, + {megaco_update_conn_info, trans_req_maxcount, 10}, + {megaco_update_conn_info, trans_timer, 1000}, + {megaco_update_conn_info, trans_ack, true}, + {megaco_update_conn_info, trans_req, true}, + {megaco_conn_info, all}, + {megaco_cast, NR(1,1), []}, + {megaco_cast, NR(1,2), []}, + {megaco_cast, NR(1,3), []}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_update_conn_info, trans_timer, 120000}, + {megaco_cast, NR(2,1), []}, + {megaco_cast, NR(2,2), []}, + {megaco_cast, NR(2,3), []}, + {megaco_callback, handle_trans_request, NotifyReqVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {megaco_callback, handle_trans_reply, NotifyReplyVerify}, + {sleep, 3000}, + megaco_stop_user, + megaco_stop, + {sleep, 1000} + ], + EvSeq. + +otp72923_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) -> + io:format("otp72923_mg_verify_handle_connect -> ok" + "~n CH: ~p~n", [CH]), + {ok, CH, ok}; +otp72923_mg_verify_handle_connect(Else) -> + io:format("otp72923_mg_verify_handle_connect -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp72923_mg_verify_service_change_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("otp72923_mg_verify_service_change_reply -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionReply'{commandReply = [SCR]} -> + case SCR of + {serviceChangeReply, + #'ServiceChangeReply'{terminationID = [Tid], + serviceChangeResult = Res}} -> + case Tid of + #megaco_term_id{contains_wildcards = false, + id = ["root"]} -> + case Res of + {serviceChangeResParms, + #'ServiceChangeResParm'{ + serviceChangeMgcId = _RemoteMid}} -> + {ok, AR, ok}; + {Tag, Val} -> + Err = {invalid_service_change_result, + Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_termination_id, Tid}, + {error, Err, ok} + end; + {Tag, Val} -> + Err = {invalid_command_reply, Tag, Val}, + {error, Err, ok} + end; + _ -> + Err = {invalid_action_reply, AR}, + {error, Err, ok} + end; +otp72923_mg_verify_service_change_reply(Else) -> + io:format("otp72923_mg_verify_service_change_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp72923_mg_verify_notify_request_fun() -> + fun(Ev) -> + otp72923_mg_verify_notify_request(Ev) + end. + +otp72923_mg_verify_notify_request( + {handle_trans_request, _, ?VERSION, [AR]}) -> + io:format("otp72923_mg_verify_notify_request -> ok" + "~n AR: ~p~n", [AR]), + case AR of + #'ActionRequest'{contextId = 1 = Cid, + commandRequests = [CR]} -> + #'CommandRequest'{command = Cmd} = CR, + {notifyReq, NR} = Cmd, + #'NotifyRequest'{terminationID = [Tid], + observedEventsDescriptor = OED, + errorDescriptor = asn1_NOVALUE} = NR, + #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED, + #'ObservedEvent'{eventName = "al/of"} = OE, + Reply = {discard_ack, [otp72923_mg_notify_reply_ar(Cid, Tid)]}, + {ok, AR, Reply}; + _ -> + ED = otp72923_err_desc(AR), + ErrReply = {discard_ack, ED}, + {error, AR, ErrReply} + end; +otp72923_mg_verify_notify_request(Else) -> + io:format("otp72923_mg_verify_notify_request -> unknown" + "~n Else: ~p~n", [Else]), + ED = otp72923_err_desc(Else), + ErrReply = {discard_ack, ED}, + {error, Else, ErrReply}. + +otp72923_mg_verify_notify_reply({handle_trans_reply, _CH, ?VERSION, + {ok, [AR]}, _}) -> + io:format("otp72923_mg_verify_notify_reply -> ok" + "~n AR: ~p~n", [AR]), + {ok, AR, ok}; +otp72923_mg_verify_notify_reply(Else) -> + io:format("otp72923_mg_verify_notify_reply -> unknown" + "~n Else: ~p~n", [Else]), + {error, Else, ok}. + +otp72923_mg_service_change_request_ar(_Mid, Cid) -> + Prof = cre_serviceChangeProf("resgw", 1), + SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof), + Root = #megaco_term_id{id = ["root"]}, + SCR = cre_serviceChangeReq([Root], SCP), + CMD = cre_command(SCR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp72923_mg_service_change_request_msg(Mid, TransId, Cid) -> + AR = otp72923_mg_service_change_request_ar(Mid, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + +otp72923_mg_notify_reply_ar(Cid, TermId) -> + NR = cre_notifyReply([TermId]), + CR = cre_cmdReply(NR), + cre_actionReply(Cid, [CR]). + +otp72923_mg_notify_request_ar(Rid, Tid, Cid) -> + TT = cre_timeNotation("19990729", "22000000"), + Ev = cre_obsEvent("al/of", TT), + EvsDesc = cre_obsEvsDesc(Rid, [Ev]), + NR = cre_notifyReq([Tid], EvsDesc), + CMD = cre_command(NR), + CR = cre_cmdReq(CMD), + cre_actionReq(Cid, [CR]). + +otp72923_notify_request_msg(Mid, TransId, Rid, TermId, Cid) -> + AR = otp72923_mg_notify_request_ar(Rid, TermId, Cid), + TR = cre_transReq(TransId, [AR]), + Trans = cre_transaction(TR), + Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])), + cre_megacoMessage(Mess). + + +%% +%% Common functions for the multi_trans_req_timeout test case +%% + +otp72923_err_desc(T) -> + EC = ?megaco_internal_gateway_error, + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% +%% Common message creation functions +%% + +cre_ErrDesc(T) -> + cre_ErrDesc(?megaco_internal_gateway_error, T). + +cre_ErrDesc(EC, T) -> + ET = lists:flatten(io_lib:format("~w",[T])), + #'ErrorDescriptor'{errorCode = EC, errorText = ET}. + +cre_serviceChangeParm(M,R,P) -> + #'ServiceChangeParm'{serviceChangeMethod = M, + serviceChangeReason = R, + serviceChangeProfile = P}. + +cre_serviceChangeReq(Tid, Parms) -> + #'ServiceChangeRequest'{terminationID = Tid, + serviceChangeParms = Parms}. + +cre_timeNotation(D,T) -> + #'TimeNotation'{date = D, time = T}. + +cre_obsEvent(Name, Not) -> + #'ObservedEvent'{eventName = Name, + timeNotation = Not}. +cre_obsEvent(Name, Not, Par) -> + #'ObservedEvent'{eventName = Name, + timeNotation = Not, + eventParList = Par}. + +cre_obsEvsDesc(Id, EvList) -> + #'ObservedEventsDescriptor'{requestId = Id, + observedEventLst = EvList}. + +cre_notifyReq(Tid, EvsDesc) -> + #'NotifyRequest'{terminationID = Tid, + observedEventsDescriptor = EvsDesc}. + +cre_command(R) when is_record(R, 'NotifyRequest') -> + {notifyReq, R}; +cre_command(R) when is_record(R, 'ServiceChangeRequest') -> + {serviceChangeReq, R}. + +cre_cmdReq(Cmd) -> + #'CommandRequest'{command = Cmd}. + +cre_actionReq(CtxId, CmdReqs) when is_list(CmdReqs) -> + #'ActionRequest'{contextId = CtxId, + commandRequests = CmdReqs}. + +cre_transReq(TransId, ARs) when is_list(ARs) -> + #'TransactionRequest'{transactionId = TransId, + actions = ARs}. + +%% -- + +cre_serviceChangeResParm(Mid) -> + #'ServiceChangeResParm'{serviceChangeMgcId = Mid}. + +cre_serviceChangeResult(SCRP) when is_record(SCRP, 'ServiceChangeResParm') -> + {serviceChangeResParms, SCRP}; +cre_serviceChangeResult(ED) when is_record(ED, 'ErrorDescriptor') -> + {errorDescriptor, ED}. + +cre_serviceChangeReply(Tid, Res) -> + #'ServiceChangeReply'{terminationID = Tid, + serviceChangeResult = Res}. + +cre_cmdReply(R) when is_record(R, 'NotifyReply') -> + {notifyReply, R}; +cre_cmdReply(R) when is_record(R, 'ServiceChangeReply') -> + {serviceChangeReply, R}. + +cre_notifyReply(Tid) -> + #'NotifyReply'{terminationID = Tid}. + +cre_actionReply(CtxId, CmdRep) -> + #'ActionReply'{contextId = CtxId, + commandReply = CmdRep}. + +cre_transResult(ED) when is_record(ED, 'ErrorDescriptor') -> + {transactionError, ED}; +cre_transResult([AR|_] = ARs) when is_record(AR, 'ActionReply') -> + {actionReplies, ARs}. + +cre_transReply(TransId, Res) -> + #'TransactionReply'{transactionId = TransId, + transactionResult = Res}. + + +%% -- + +cre_serviceChangeProf(Name, Ver) when is_list(Name) andalso is_integer(Ver) -> + #'ServiceChangeProfile'{profileName = Name, + version = Ver}. + +cre_transaction(Trans) when is_record(Trans, 'TransactionRequest') -> + {transactionRequest, Trans}; +cre_transaction(Trans) when is_record(Trans, 'TransactionPending') -> + {transactionPending, Trans}; +cre_transaction(Trans) when is_record(Trans, 'TransactionReply') -> + {transactionReply, Trans}; +cre_transaction(Trans) when is_record(Trans, 'TransactionAck') -> + {transactionResponseAck, Trans}. + +cre_transactions(Trans) when is_list(Trans) -> + {transactions, Trans}. + +cre_message(Version, Mid, Body) -> + #'Message'{version = Version, + mId = Mid, + messageBody = Body}. + +cre_megacoMessage(Mess) -> + #'MegacoMessage'{mess = Mess}. + + +%% +%% Common functions +%% + +encode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:encode_message(Conf, M) + end. +encode_msg_fun(Mod, Conf, Ver) -> + fun(M) -> + Mod:encode_message(Conf, Ver, M) + end. + +decode_msg_fun(Mod, Conf) -> + fun(M) -> + Mod:decode_message(Conf, M) + end. +decode_msg_fun(Mod, Conf, Ver) -> + fun(M) -> + Mod:decode_message(Conf, Ver, M) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +await_ack(_User, 0, Timeout, _Expected) -> + d("await_ack -> done when Timeout = ~p", [Timeout]), + ok; +await_ack(User, N, Timeout, Expected) when (N > 0) andalso is_integer(Timeout) -> + d("await_ack -> entry with N: ~p, Timeout: ~p", [N,Timeout]), + T = tim(), + receive + {ack_received, User, Expected} -> + d("await_ack -> received another ack"), + await_ack(User, N-1, Timeout - (tim() - T), Expected); + {ack_received, User, UnExpected} -> + d("await_ack -> unexpected ack result: ~p", [UnExpected]), + exit({unexpected_ack_result, UnExpected, Expected}) + after Timeout -> + exit({await_ack_timeout, N}) + end; +await_ack(User, N, infinity, Expected) when N > 0 -> + d("await_ack -> entry with N: ~p", [N]), + receive + {ack_received, User, Expected} -> + d("await_ack -> received another ack"), + await_ack(User, N-1, infinity, Expected); + {ack_received, User, UnExpected} -> + d("await_ack -> unexpected ack result: ~p", [UnExpected]), + exit({unexpected_ack_result, UnExpected, Expected}) + end. + +await_req(_User, 0, Timeout) -> + d("await_req -> done when Timeout = ~p", [Timeout]), + ok; +await_req(User, N, Timeout) when (N > 0) andalso is_integer(Timeout) -> + d("await_req -> entry with N: ~p, Timeout: ~p", [N,Timeout]), + T = tim(), + receive + {req_received, User, ARs} -> + d("await_req -> received req(s) when N = ~w", [N]), + N1 = await_req1(N, ARs), + await_req(User, N1, Timeout - (tim() - T)) + after Timeout -> + exit({await_req_timeout, N}) + end; +await_req(User, N, infinity) when N > 0 -> + d("await_req -> entry with N: ~p", [N]), + receive + {req_received, User, ARs} -> + d("await_req -> received req(s) when N = ~2",[N]), + N1 = await_req1(N, ARs), + await_req(User, N1, infinity) + end. + +await_req1(N, []) when N >= 0 -> + N; +await_req1(N, [AR|ARs]) when (N > 0) andalso is_record(AR, 'ActionRequest') -> + await_req1(N-1, ARs); +await_req1(N, ARs) -> + exit({unexpected_req_result, N, ARs}). + +% await_rep(_User, 0, Timeout) -> +% d("await_rep -> done when Timeout = ~p", [Timeout]), +% ok; +% await_rep(User, N, Timeout) when N > 0, integer(Timeout) -> +% d("await_rep -> entry with N: ~p, Timeout: ~p", [N,Timeout]), +% T = tim(), +% receive +% {rep_received, User, ARs} -> +% d("await_rep -> received rep(s)"), +% N1 = await_rep1(N, ARs), +% await_rep(User, N1, Timeout - (tim() - T)) +% after Timeout -> +% exit({await_rep_timeout, N}) +% end; +% await_rep(User, N, infinity) when N > 0 -> +% d("await_rep -> entry with N: ~p", [N]), +% receive +% {rep_received, User, ARs} -> +% d("await_rep -> received rep(s)"), +% N1 = await_rep1(N, ARs), +% await_rep(User, N1, infinity) +% end. + +% await_rep1(N, []) when N >= 0 -> +% N; +% await_rep1(N, [AR|ARs]) when N > 0, record(AR, 'ActionReply') -> +% await_rep1(N-1, ARs); +% await_rep1(N, ARs) -> +% exit({unexpected_rep_result, N, ARs}). + +tim() -> + {A,B,C} = erlang:now(), + A*1000000000+B*1000+(C div 1000). + + +make_node_name(Name) -> + case string:tokens(atom_to_list(node()), [$@]) of + [_,Host] -> + list_to_atom(lists:concat([atom_to_list(Name) ++ "@" ++ Host])); + _ -> + exit("Test node must be started with '-sname'") + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +await_completion(Ids) -> + case megaco_test_generator_lib:await_completion(Ids) of + {ok, Reply} -> + d("OK => Reply: ~n~p", [Reply]), + ok; + {error, Reply} -> + d("ERROR => Reply: ~n~p", [Reply]), + ?ERROR({failed, Reply}) + end. + +await_completion(Ids, Timeout) -> + case megaco_test_generator_lib:await_completion(Ids, Timeout) of + {ok, Reply} -> + d("OK => Reply: ~n~p", [Reply]), + ok; + {error, Reply} -> + d("ERROR => Reply: ~n~p", [Reply]), + ?ERROR({failed, Reply}) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +sleep(X) -> receive after X -> ok end. + +error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +i(F) -> + i(F, []). + +i(F, A) -> + print(info, get(verbosity), now(), get(tc), "INF", F, A). + + +d(F) -> + d(F, []). + +d(F, A) -> + print(debug, get(verbosity), now(), get(tc), "DBG", F, A). + + +printable(_, debug) -> true; +printable(info, info) -> true; +printable(_,_) -> false. + +print(Severity, Verbosity, Ts, Tc, P, F, A) -> + print(printable(Severity,Verbosity), Ts, Tc, P, F, A). + +print(true, Ts, Tc, P, F, A) -> + io:format("*** [~s] ~s ~p ~s:~w ***" + "~n " ++ F ++ "~n", + [format_timestamp(Ts), P, self(), get(tc), Tc | A]); +print(_, _, _, _, _, _) -> + ok. + + +p(F, A) -> + io:format("*** [~s] ***" + "~n " ++ F ++ "~n", + [format_timestamp(now()) | A]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +random_init() -> + {A,B,C} = now(), + random:seed(A,B,C). + +random() -> + 10 * random:uniform(50). + +apply_load_timer() -> + erlang:send_after(random(), self(), apply_load_timeout). + + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). + diff --git a/lib/megaco/test/megaco_udp_test.erl b/lib/megaco/test/megaco_udp_test.erl new file mode 100644 index 0000000000..2e2f5465dd --- /dev/null +++ b/lib/megaco/test/megaco_udp_test.erl @@ -0,0 +1,1251 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: +%%---------------------------------------------------------------------- +-module(megaco_udp_test). + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include_lib("megaco/src/udp/megaco_udp.hrl"). +-include("megaco_test_lib.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([ + all/1, + + start/1, + start_normal/1, + start_invalid_opt/1, + start_and_stop/1, + + sending/1, + sendreceive/1, + block_unblock/1, + + errors/1, + socket_failure/1, + + init_per_testcase/2, fin_per_testcase/2, + + t/0, t/1 + ]). + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- +-export([ + receive_message/4, + process_received_message/4 + ]). + + +%%---------------------------------------------------------------------- +%% Macros +%%---------------------------------------------------------------------- + +%%---------------------------------------------------------------------- +%% Records +%%---------------------------------------------------------------------- + +-record(command, {id, desc, cmd}). +-record(server, {parent, transport_ref, control_pid, handle, remote}). +-record(client, {parent, transport_ref, control_pid, handle, remote}). + + +%%====================================================================== +%% External functions +%%====================================================================== +%%---------------------------------------------------------------------- +%% Function: t/0 +%% Description: Run all test cases +%%---------------------------------------------------------------------- +t() -> megaco_test_lib:t(?MODULE). + + +%%---------------------------------------------------------------------- +%% Function: t/1 +%% Description: Run the specified test cases +%%---------------------------------------------------------------------- +t(Case) -> megaco_test_lib:t({?MODULE, Case}). + + +%%====================================================================== +%% Test server callbacks +%%====================================================================== +%%---------------------------------------------------------------------- +%% Function: init_per_testcase/2 +%% Description: +%%---------------------------------------------------------------------- +init_per_testcase(Case, Config) -> + megaco_test_lib:init_per_testcase(Case, Config). + + +%%---------------------------------------------------------------------- +%% Function: fin_per_testcase/2 +%% Description: +%%---------------------------------------------------------------------- +fin_per_testcase(Case, Config) -> + megaco_test_lib:fin_per_testcase(Case, Config). + + +%%====================================================================== +%% Test case definitions +%%====================================================================== + +all(suite) -> + [ + start, + sending, + errors + ]. + +start(suite) -> + [ + start_normal, + start_invalid_opt, + start_and_stop + ]. + +sending(suite) -> + [ + sendreceive, + block_unblock + + ]. + +errors(suite) -> + [ + socket_failure + ]. + + +%% ================================================= +%% +%% ------------------ start ------------------------ +%% +%% ================================================= + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_normal(suite) -> + []; +start_normal(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Opts = [{port, 0}, {receive_handle, apa}], + {ok, Pid} = start_case(Opts, ok), + megaco_udp:stop_transport(Pid), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_invalid_opt(suite) -> + []; +start_invalid_opt(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + Opts = [{port, 0}, {receivehandle, apa}], + start_case(Opts, error). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_and_stop(suite) -> + []; +start_and_stop(doc) -> + ["This test case sets up a connection and then cloises it. " + "No data is sent. "]; +start_and_stop(Config) when is_list(Config) -> + put(sname, "start_and_stop"), + p("BEGIN TEST-CASE"), + + process_flag(trap_exit, true), + + p("create nodes"), + ServerNode = make_node_name(server), + ClientNode = make_node_name(client), + Nodes = [ServerNode, ClientNode], + ok = megaco_test_lib:start_nodes(Nodes, ?FILE, ?LINE), + + %% Create command sequences + p("create command sequences"), + ServerPort = 2944, + ServerCmds = start_and_stop_server_commands(ServerPort), + {ok, ServerHost} = inet:gethostname(), + ClientCmds = start_and_stop_client_commands(ServerPort, ServerHost), + + %% Start the test procs used in the test-case, one for each node + p("start command handlers"), + Server = server_start_command_handler(ServerNode, ServerCmds), + p("server command handler started: ~p", [Server]), + Client = client_start_command_handler(ClientNode, ClientCmds), + p("client command handler started: ~p", [Client]), + + ok = + receive + {operational, Server} -> + p("received listening message from server [~p] => " + "send continue to client [~p]~n", [Server, Client]), + Client ! {continue, self()}, + ok; + {'EXIT', Server, {skip, Reason}} -> + ?SKIP(Reason); + {'EXIT', Client, {skip, Reason}} -> + ?SKIP(Reason) + after 5000 -> + {error, server_timeout} + end, + + ok = await_command_handler_completion([Server, Client], timer:seconds(20)), + p("done"), + ok. + + +start_and_stop_server_commands(Port) -> + Opts = [{port, Port}], + Self = self(), + [ + #command{id = 1, + desc = "Command sequence init", + cmd = fun(State) -> + {ok, State#server{parent = Self}} + end}, + + #command{id = 2, + desc = "Start transport", + cmd = fun(State) -> + server_start_transport(State) + end}, + + #command{id = 3, + desc = "Open", + cmd = fun(State) -> + server_open(State, Opts) + end}, + + #command{id = 4, + desc = "Notify operational", + cmd = fun(State) -> + server_notify_operational(State) + end}, + + #command{id = 5, + desc = "Await nothing", + cmd = fun(State) -> + server_await_nothing(State, 5000) + end}, + + #command{id = 6, + desc = "Close", + cmd = fun(State) -> + server_close(State) + end}, + + #command{id = 7, + desc = "Stop", + cmd = fun(State) -> + server_stop_transport(State) + end} + + ]. + +start_and_stop_client_commands(ServerPort, _ServerHost) -> + Opts = [{port, ServerPort}], + Self = self(), + [ + #command{id = 1, + desc = "Command sequence init", + cmd = fun(State) -> + {ok, State#client{parent = Self}} + end}, + + #command{id = 2, + desc = "Start transport", + cmd = fun(State) -> + client_start_transport(State) + end}, + + #command{id = 3, + desc = "Open", + cmd = fun(State) -> + client_open(State, Opts) + end}, + + #command{id = 4, + desc = "Await continue", + cmd = fun(State) -> + client_await_continue_signal(State, 5000) + end}, + + #command{id = 5, + desc = "Await nothing", + cmd = fun(State) -> + client_await_nothing(State, 5000) + end}, + + #command{id = 6, + desc = "Close", + cmd = fun(State) -> + client_close(State) + end}, + + #command{id = 7, + desc = "Stop transport", + cmd = fun(State) -> + client_stop_transport(State) + end} + ]. + + + +%% ================================================= +%% +%% ------------------ sending ------------------------ +%% +%% ================================================= + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +sendreceive(suite) -> + []; +sendreceive(doc) -> + ["Test send and receive with the UDP transport. "]; +sendreceive(Config) when is_list(Config) -> + put(sname, "sendreceive"), + p("BEGIN TEST-CASE"), + + process_flag(trap_exit, true), + + p("create nodes"), + ServerNode = make_node_name(server), + ClientNode = make_node_name(client), + Nodes = [ServerNode, ClientNode], + ok = megaco_test_lib:start_nodes(Nodes, ?FILE, ?LINE), + + %% Create command sequences + p("create command sequences"), + ServerPort = 2944, + ServerCmds = sendreceive_server_commands(ServerPort), + {ok, ServerHost} = inet:gethostname(), + ClientCmds = sendreceive_client_commands(ServerPort, ServerHost), + + %% Start the test procs used in the test-case, one for each node + p("start command handlers"), + Server = server_start_command_handler(ServerNode, ServerCmds), + p("server command handler started: ~p", [Server]), + Client = client_start_command_handler(ClientNode, ClientCmds), + p("client command handler started: ~p", [Client]), + + ok = + receive + {operational, Server} -> + p("received operational message from server [~p] => " + "send continue to client [~p]~n", [Server, Client]), + Client ! {continue, self()}, + ok; + {'EXIT', Server, {skip, Reason}} -> + ?SKIP(Reason); + {'EXIT', Client, {skip, Reason}} -> + ?SKIP(Reason) + after 5000 -> + {error, server_timeout} + end, + + ok = await_command_handler_completion([Server, Client], timer:seconds(20)), + p("done"), + ok. + + +sendreceive_server_commands(Port) -> + Opts = [{port, Port}], + Self = self(), + [ + #command{id = 1, + desc = "Command sequence init", + cmd = fun(State) -> + {ok, State#server{parent = Self}} + end}, + + #command{id = 2, + desc = "Start transport", + cmd = fun(State) -> + server_start_transport(State) + end}, + + #command{id = 3, + desc = "Open", + cmd = fun(State) -> + server_open(State, Opts) + end}, + + #command{id = 4, + desc = "Notify operational", + cmd = fun(State) -> + server_notify_operational(State) + end}, + + #command{id = 5, + desc = "Await initial message (ping)", + cmd = fun(State) -> + server_await_initial_message(State, "ping", 5000) + end}, + + #command{id = 6, + desc = "Send reply (pong) to initial message", + cmd = fun(State) -> + server_send_message(State, "pong") + end}, + + #command{id = 7, + desc = "Await nothing before sending a message (hejsan)", + cmd = fun(State) -> + server_await_nothing(State, 1000) + end}, + + #command{id = 8, + desc = "Send message (hejsan)", + cmd = fun(State) -> + server_send_message(State, "hejsan") + end}, + + #command{id = 9, + desc = "Await reply (hoppsan) to message", + cmd = fun(State) -> + server_await_message(State, "hoppsan", 1000) + end}, + + #command{id = 10, + desc = "Await nothing before closing", + cmd = fun(State) -> + server_await_nothing(State, 1000) + end}, + + #command{id = 11, + desc = "Close", + cmd = fun(State) -> + server_close(State) + end}, + + #command{id = 12, + desc = "Await nothing before stopping transport", + cmd = fun(State) -> + server_await_nothing(State, 1000) + end}, + + #command{id = 13, + desc = "Stop", + cmd = fun(State) -> + server_stop_transport(State) + end} + + ]. + +sendreceive_client_commands(ServerPort, ServerHost) -> + OwnPort = ServerPort+1, + Opts = [{port, OwnPort}], + Self = self(), + [ + #command{id = 1, + desc = "Command sequence init", + cmd = fun(State) -> + {ok, State#client{parent = Self}} + end}, + + #command{id = 2, + desc = "Start transport", + cmd = fun(State) -> + client_start_transport(State) + end}, + + #command{id = 3, + desc = "Open", + cmd = fun(State) -> + client_open(State, Opts) + end}, + + #command{id = 4, + desc = "Await continue", + cmd = fun(State) -> + client_await_continue_signal(State, 5000) + end}, + + #command{id = 5, + desc = "Connect", + cmd = fun(State) -> + client_connect(State, ServerHost, ServerPort) + end}, + + #command{id = 6, + desc = "Send initial message (ping)", + cmd = fun(State) -> + client_send_message(State, "ping") + end}, + + #command{id = 7, + desc = "Await reply (pong) to initial message", + cmd = fun(State) -> + client_await_message(State, "pong", 1000) + end}, + + #command{id = 8, + desc = "Await message (hejsan)", + cmd = fun(State) -> + client_await_message(State, "hejsan", 5000) + end}, + + #command{id = 9, + desc = "Send reply (hoppsan) to message", + cmd = fun(State) -> + client_send_message(State, "hoppsan") + end}, + + #command{id = 10, + desc = "Await nothing before closing", + cmd = fun(State) -> + client_await_nothing(State, 1000) + end}, + + #command{id = 11, + desc = "Close", + cmd = fun(State) -> + client_close(State) + end}, + + #command{id = 12, + desc = "Await nothing before stopping transport", + cmd = fun(State) -> + client_await_nothing(State, 1000) + end}, + + #command{id = 13, + desc = "Stop transport", + cmd = fun(State) -> + client_stop_transport(State) + end} + ]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +block_unblock(suite) -> + []; +block_unblock(doc) -> + ["Test the block/unblock functions of the UDP transport. "]; +block_unblock(Config) when is_list(Config) -> + put(sname, "block_unblock"), + p("BEGIN TEST-CASE"), + + process_flag(trap_exit, true), + + p("create nodes"), + ServerNode = make_node_name(server), + ClientNode = make_node_name(client), + Nodes = [ServerNode, ClientNode], + ok = megaco_test_lib:start_nodes(Nodes, ?FILE, ?LINE), + + %% Create command sequences + p("create command sequences"), + ServerPort = 2944, + ServerCmds = block_unblock_server_commands(ServerPort), + {ok, ServerHost} = inet:gethostname(), + ClientCmds = block_unblock_client_commands(ServerPort, ServerHost), + + %% Start the test procs used in the test-case, one for each node + p("start command handlers"), + Server = server_start_command_handler(ServerNode, ServerCmds), + p("server command handler started: ~p", [Server]), + Client = client_start_command_handler(ClientNode, ClientCmds), + p("client command handler started: ~p", [Client]), + + %% Wait for the server to become ready for operation + %% and then tell the client to continue + ok = + receive + {operational, Server} -> + p("received operational message from server [~p] => " + "send continue to client [~p]~n", [Server, Client]), + Client ! {continue, self()}, + ok; + {'EXIT', Server, {skip, Reason1}} -> + ?SKIP(Reason1); + {'EXIT', Client, {skip, Reason2}} -> + ?SKIP(Reason2) + after 5000 -> + {error, server_timeout} + end, + + %% Wait for the client to become blocked + %% and then tell the server to continue + ok = + receive + {blocked, Client} -> + p("received blocked message from client [~p] => " + "send continue to server [~p]~n", [Client, Server]), + Server ! {continue, self()}, + ok; + {'EXIT', Server, {skip, Reason3}} -> + ?SKIP(Reason3); + {'EXIT', Client, {skip, Reason4}} -> + ?SKIP(Reason4) + after 5000 -> + {error, timeout} + end, + + ok = await_command_handler_completion([Server, Client], timer:seconds(20)), + p("done"), + ok. + + +block_unblock_server_commands(Port) -> + Opts = [{port, Port}], + Self = self(), + [ + #command{id = 1, + desc = "Command sequence init", + cmd = fun(State) -> + {ok, State#server{parent = Self}} + end}, + + #command{id = 2, + desc = "Start transport", + cmd = fun(State) -> + server_start_transport(State) + end}, + + #command{id = 3, + desc = "Open", + cmd = fun(State) -> + server_open(State, Opts) + end}, + + #command{id = 4, + desc = "Notify operational", + cmd = fun(State) -> + server_notify_operational(State) + end}, + + #command{id = 5, + desc = "Await initial message (ping)", + cmd = fun(State) -> + server_await_initial_message(State, "ping", 5000) + end}, + + #command{id = 6, + desc = "Send reply (pong) to initial message", + cmd = fun(State) -> + server_send_message(State, "pong") + end}, + + #command{id = 7, + desc = "Await continue", + cmd = fun(State) -> + server_await_continue_signal(State, 5000) + end}, + + #command{id = 8, + desc = "Send message (hejsan)", + cmd = fun(State) -> + server_send_message(State, "hejsan") + end}, + + #command{id = 9, + desc = "Await nothing before receiving (hoppsan) reply", + cmd = fun(State) -> + server_await_nothing(State, 4000) + end}, + + #command{id = 10, + desc = "Await reply (hoppsan) to message", + cmd = fun(State) -> + server_await_message(State, "hoppsan", 2000) + end}, + + #command{id = 11, + desc = "Await nothing before closing", + cmd = fun(State) -> + server_await_nothing(State, 1000) + end}, + + #command{id = 12, + desc = "Close", + cmd = fun(State) -> + server_close(State) + end}, + + #command{id = 13, + desc = "Await nothing before stopping transport", + cmd = fun(State) -> + server_await_nothing(State, 1000) + end}, + + #command{id = 14, + desc = "Stop", + cmd = fun(State) -> + server_stop_transport(State) + end} + + ]. + +block_unblock_client_commands(ServerPort, ServerHost) -> + OwnPort = ServerPort+1, + Opts = [{port, OwnPort}], + Self = self(), + [ + #command{id = 1, + desc = "Command sequence init", + cmd = fun(State) -> + {ok, State#client{parent = Self}} + end}, + + #command{id = 2, + desc = "Start transport", + cmd = fun(State) -> + client_start_transport(State) + end}, + + #command{id = 3, + desc = "Open", + cmd = fun(State) -> + client_open(State, Opts) + end}, + + #command{id = 4, + desc = "Await continue", + cmd = fun(State) -> + client_await_continue_signal(State, 5000) + end}, + + #command{id = 5, + desc = "[pseudo] Connect", + cmd = fun(State) -> + client_connect(State, ServerHost, ServerPort) + end}, + + #command{id = 6, + desc = "Send initial message (ping)", + cmd = fun(State) -> + client_send_message(State, "ping") + end}, + + #command{id = 7, + desc = "Await reply (pong) to initial message", + cmd = fun(State) -> + client_await_message(State, "pong", 1000) + end}, + + #command{id = 8, + desc = "Block", + cmd = fun(State) -> + client_block(State) + end}, + + #command{id = 9, + desc = "Notify blocked", + cmd = fun(State) -> + client_notify_blocked(State) + end}, + + #command{id = 10, + desc = "Await nothing before unblocking", + cmd = fun(State) -> + client_await_nothing(State, 5000) + end}, + + #command{id = 11, + desc = "Unblock", + cmd = fun(State) -> + client_unblock(State) + end}, + + #command{id = 8, + desc = "Await message (hejsan)", + cmd = fun(State) -> + client_await_message(State, "hejsan", 5000) + end}, + + #command{id = 9, + desc = "Send reply (hoppsan) to message", + cmd = fun(State) -> + client_send_message(State, "hoppsan") + end}, + + #command{id = 10, + desc = "Await nothing before closing", + cmd = fun(State) -> + client_await_nothing(State, 1000) + end}, + + #command{id = 11, + desc = "Close", + cmd = fun(State) -> + client_close(State) + end}, + + #command{id = 12, + desc = "Await nothing before stopping transport", + cmd = fun(State) -> + client_await_nothing(State, 1000) + end}, + + #command{id = 13, + desc = "Stop transport", + cmd = fun(State) -> + client_stop_transport(State) + end} + ]. + + +%% ================================================= +%% +%% ------------------ errors ------------------------ +%% +%% ================================================= + +socket_failure(suite) -> + []; +socket_failure(Config) when is_list(Config) -> + ?ACQUIRE_NODES(1, Config), + failing_socket(). + + +%%====================================================================== +%% Test functions +%%====================================================================== + +start_case(Opts, Expect) -> + case (catch megaco_udp:start_transport()) of + {ok, Pid} -> + case (catch megaco_udp:open(Pid, Opts)) of + {ok, _Handle, _CtrlPid} when Expect =:= ok -> + {ok, Pid}; + {ok, Handle, CtrlPid} -> + megaco_udp:stop_transport(Pid), + ?ERROR({unexpected_start_sucesss, Handle, CtrlPid}); + {error, _Reason} when Expect =:= error -> + megaco_udp:stop_transport(Pid), + ok; + {error, Reason} -> + megaco_udp:stop_transport(Pid), + ?ERROR({unexpected_start_failure, Reason}); + Error -> + ?ERROR({unexpected_result, Error}) + end; + {error, Reason} -> + ?ERROR({failed_starting_transport, Reason}) + end. + + +failing_socket() -> + ?SKIP(not_yet_implemented). + + + +%%---------------------------------------------------------------------- +%% Message Callback functions +%%---------------------------------------------------------------------- + +receive_message(ReceiveHandle, ControlPid, SendHandle, BinMsg) + when is_pid(ReceiveHandle) andalso is_binary(BinMsg) -> + Msg = binary_to_list(BinMsg), + ReceiveHandle ! {receive_message, {ControlPid, SendHandle, Msg}}, + ok. + +process_received_message(ReceiveHandle, ControlPid, SendHandle, BinMsg) + when is_pid(ReceiveHandle) andalso is_binary(BinMsg) -> + Msg = binary_to_list(BinMsg), + ReceiveHandle ! {process_received_message, {ControlPid, SendHandle, Msg}}, + ok. + + +%%====================================================================== +%% Internal functions +%%====================================================================== + +%% ------- Server command handler and utility functions ---------- + +server_start_command_handler(Node, Commands) -> + start_command_handler(Node, Commands, #server{}, "server"). + +server_start_transport(State) when is_record(State, server) -> + case (catch megaco_udp:start_transport()) of + {ok, Ref} -> + {ok, State#server{transport_ref = Ref}}; + Error -> + Error + end. + +server_open(#server{transport_ref = Ref} = State, Options) + when is_record(State, server) andalso is_list(Options) -> + Opts = [{receive_handle, self()}, {module, ?MODULE} | Options], + case (catch megaco_udp:open(Ref, Opts)) of + {ok, Socket, ControlPid} -> + {ok, State#server{handle = {socket, Socket}, % Temporary + control_pid = ControlPid}}; + {error, {could_not_open_udp_port, eaddrinuse}} -> + {skip, {server, eaddrinuse}}; + Error -> + Error + end. + +server_notify_operational(#server{parent = Parent} = State) + when is_record(State, server) -> + Parent ! {operational, self()}, + {ok, State}. + +server_await_continue_signal(#server{parent = Parent} = State, Timeout) -> + receive + {continue, Parent} -> + {ok, State} + after Timeout -> + {error, timeout} + end. + +server_await_initial_message(State, InitialMessage, Timeout) + when is_record(State, server) -> + receive + {receive_message, {ControlPid, Handle, InitialMessage}} -> + p("received expected event with: " + "~n ControlPid: ~p" + "~n Handle: ~p", [ControlPid, Handle]), + NewState = State#server{handle = Handle}, + {ok, NewState}; + + Any -> + p("received unexpected event: ~p", [Any]), + {error, {unexpected_event, Any}} + + after Timeout -> + {error, timeout} + end. + +server_send_message(#server{handle = Handle} = State, Message) -> + Bin = if + is_list(Message) -> + list_to_binary(Message); + true -> + Message + end, + megaco_udp:send_message(Handle, Bin), + {ok, State}. + +server_await_nothing(State, Timeout) + when is_record(State, server) -> + receive + Any -> + p("received unexpected event: ~p", [Any]), + {error, {unexpected_event, Any}} + + after Timeout -> + {ok, State} + end. + + +server_await_message(State, ExpectMessage, Timeout) + when is_record(State, server) -> + receive + {receive_message, {_, _, ExpectMessage}} -> + p("received expected message [~p]", [ExpectMessage]), + {ok, State}; + + Any -> + p("received unexpected event: ~p", [Any]), + {error, {unexpected_event, Any}} + + after Timeout -> + {error, timeout} + end. + +server_close(#server{handle = {socket, Socket}} = State) -> + megaco_udp:close(Socket), + {ok, State#server{handle = undefined, control_pid = undefined}}; +server_close(#server{handle = Handle} = State) + when (Handle =/= undefined) -> + megaco_udp:close(Handle), + {ok, State#server{handle = undefined, control_pid = undefined}}. + +%% server_block(#server{handle = Handle} = State) +%% when (Handle =/= undefined) -> +%% megaco_udp:block(Handle), +%% {ok, State}. + +%% server_unblock(#server{handle = Handle} = State) +%% when (Handle =/= undefined) -> +%% megaco_udp:unblock(Handle), +%% {ok, State}. + +server_stop_transport(#server{transport_ref = Ref} = State) + when (Ref =/= undefined) -> + megaco_udp:stop_transport(Ref), + {ok, State#server{transport_ref = undefined}}. + + +%% ------- Client command handler and utility functions ---------- + +client_start_command_handler(Node, Commands) -> + start_command_handler(Node, Commands, #client{}, "client"). + +client_start_transport(State) when is_record(State, client) -> + case (catch megaco_udp:start_transport()) of + {ok, Ref} -> + {ok, State#client{transport_ref = Ref}}; + Error -> + Error + end. + +client_open(#client{transport_ref = Ref} = State, Options) + when is_record(State, client) andalso is_list(Options) -> + Opts = [{receive_handle, self()}, {module, ?MODULE} | Options], + case (catch megaco_udp:open(Ref, Opts)) of + {ok, Socket, ControlPid} -> + {ok, State#client{handle = {socket, Socket}, + control_pid = ControlPid}}; + {error, {could_not_open_udp_port, eaddrinuse}} -> + {skip, {client, eaddrinuse}}; + Error -> + Error + end. + +client_await_continue_signal(#client{parent = Parent} = State, Timeout) -> + receive + {continue, Parent} -> + {ok, State} + after Timeout -> + {error, timeout} + end. + +client_notify_blocked(#client{parent = Parent} = State) -> + Parent ! {blocked, self()}, + {ok, State}. + +client_await_nothing(State, Timeout) + when is_record(State, client) -> + receive + Any -> + p("received unexpected event: ~p", [Any]), + {error, {unexpected_event, Any}} + after Timeout -> + {ok, State} + end. + +client_connect(#client{handle = {socket, Socket}} = State, Host, Port) -> + Handle = megaco_udp:create_send_handle(Socket, Host, Port), + {ok, State#client{handle = Handle}}. + +client_send_message(#client{handle = Handle} = State, Message) -> + Bin = if + is_list(Message) -> + list_to_binary(Message); + true -> + Message + end, + megaco_udp:send_message(Handle, Bin), + {ok, State}. + +client_await_message(State, ExpectMessage, Timeout) + when is_record(State, client) -> + receive + {receive_message, {_, _, ExpectMessage}} -> + {ok, State}; + + Any -> + p("received unexpected event: ~p", [Any]), + {error, {unexpected_event, Any}} + + after Timeout -> + {error, timeout} + end. + +client_block(#client{handle = Handle} = State) + when (Handle =/= undefined) -> + megaco_udp:block(Handle), + {ok, State}. + +client_unblock(#client{handle = Handle} = State) + when (Handle =/= undefined) -> + megaco_udp:unblock(Handle), + {ok, State}. + +client_close(#client{handle = {socket, Socket}} = State) -> + megaco_udp:close(Socket), + {ok, State#client{handle = undefined, control_pid = undefined}}; +client_close(#client{handle = Handle} = State) + when (Handle =/= undefined) -> + megaco_udp:close(Handle), + {ok, State#client{handle = undefined, control_pid = undefined}}. + +client_stop_transport(#client{transport_ref = Ref} = State) + when (Ref =/= undefined) -> + megaco_udp:stop_transport(Ref), + {ok, State#client{transport_ref = undefined}}. + + +%% -------- Command handler --------- + +start_command_handler(Node, Commands, State, ShortName) -> + Fun = fun() -> + put(sname, ShortName), + process_flag(trap_exit, true), + Result = (catch command_handler(Commands, State)), + p("command handler terminated with: " + "~n Result: ~p", [Result]), + exit(Result) + end, + erlang:spawn_link(Node, Fun). + +command_handler([], State) -> + p("command_handler -> entry when done with" + "~n State: ~p", [State]), + {ok, State}; +command_handler([#command{id = Id, + desc = Desc, + cmd = Cmd}|Commands], State) -> + p("command_handler -> entry with" + "~n Id: ~p" + "~n Desc: ~p", [Id, Desc]), + case (catch Cmd(State)) of + {ok, NewState} -> + p("command_handler -> cmd ~w ok", [Id]), + command_handler(Commands, NewState); + {skip, _} = SKIP -> + p("command_handler -> cmd ~w skip", [Id]), + SKIP; + {error, Reason} -> + p("command_handler -> cmd ~w error: " + "~n Reason: ~p", [Id, Reason]), + {error, {cmd_error, Reason}}; + {'EXIT', Reason} -> + p("command_handler -> cmv ~w exit: " + "~n Reason: ~p", [Id, Reason]), + {error, {cmd_exit, Reason}}; + Error -> + p("command_handler -> cmd ~w failure: " + "~n Error: ~p", [Id, Error]), + {error, {cmd_failure, Error}} + end. + + +await_command_handler_completion(Pids, Timeout) -> + await_command_handler_completion(Pids, [], [], Timeout). + +await_command_handler_completion([], [], _Good, _Timeout) -> + p("await_command_handler_completion -> entry when done"), + ok; +await_command_handler_completion([], Bad, Good, _Timeout) -> + p("await_command_handler_completion -> entry when done with bad result: " + "~n Bad: ~p" + "~n Good: ~p", [Bad, Good]), + {error, Bad, Good}; +await_command_handler_completion(Pids, Bad, Good, Timeout) -> + p("await_command_handler_completion -> entry when waiting for" + "~n Pids: ~p" + "~n Bad: ~p" + "~n Good: ~p" + "~n Timeout: ~p", [Pids, Bad, Good, Timeout]), + Begin = ms(), + receive + {'EXIT', Pid, {ok, FinalState}} -> + p("await_command_handler_completion -> " + "received ok EXIT signal from ~p", [Pid]), + case lists:delete(Pid, Pids) of + Pids -> + await_command_handler_completion(Pids, Bad, Good, + Timeout - (ms() - Begin)); + Pids2 -> + p("await_command_handler_completion -> ~p done", [Pid]), + await_command_handler_completion(Pids2, + Bad, + [{Pid, FinalState}|Good], + Timeout - (ms() - Begin)) + end; + + {'EXIT', Pid, {error, Reason}} -> + p("await_command_handler_completion -> " + "received error EXIT signal from ~p", [Pid]), + case lists:delete(Pid, Pids) of + Pids -> + await_command_handler_completion(Pids, Bad, Good, + Timeout - (ms() - Begin)); + Pids2 -> + p("await_command_handler_completion -> ~p done with" + "~n ~p", [Pid, Reason]), + await_command_handler_completion(Pids2, + [{Pid, Reason}|Bad], + Good, + Timeout - (ms() - Begin)) + end; + + {'EXIT', Pid, {skip, Reason}} -> + p("await_command_handler_completion -> " + "received skip EXIT signal from ~p with" + "~p", [Pid, Reason]), + ?SKIP(Reason) + + after Timeout -> + p("await_command_handler_completion -> timeout"), + exit({timeout, Pids}) + end. + + + +%% ------- Misc functions -------- + +make_node_name(Name) -> + case string:tokens(atom_to_list(node()), [$@]) of + [_,Host] -> + list_to_atom(lists:concat([atom_to_list(Name) ++ "@" ++ Host])); + _ -> + exit("Test node must be started with '-sname'") + end. + + +p(F) -> + p(F, []). + +p(F, A) -> + p(get(sname), F, A). + +p(S, F, A) when is_list(S) -> + io:format("*** [~s] ~p ~s ***" + "~n " ++ F ++ "~n", + [format_timestamp(now()), self(), S | A]); +p(_S, F, A) -> + io:format("*** [~s] ~p ~s *** " + "~n " ++ F ++ "~n", + [format_timestamp(now()), self(), "undefined" | A]). + + +ms() -> + {A,B,C} = erlang:now(), + A*1000000000+B*1000+(C div 1000). + + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). diff --git a/lib/megaco/test/modules.mk b/lib/megaco/test/modules.mk new file mode 100644 index 0000000000..0186a84c26 --- /dev/null +++ b/lib/megaco/test/modules.mk @@ -0,0 +1,82 @@ +#-*-makefile-*- ; force emacs to enter makefile-mode + +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% + +TEST_SPEC_FILE = megaco.spec + +BEHAVIOUR_MODULES = \ + megaco_test_generator + +MODULES = \ + $(BEHAVIOUR_MODULES) \ + megaco_SUITE \ + megaco_app_test \ + megaco_appup_test \ + megaco_actions_test \ + megaco_binary_term_id_test \ + megaco_call_flow_test \ + megaco_codec_test \ + megaco_codec_test_lib \ + megaco_codec_flex_lib \ + megaco_codec_v1_test \ + megaco_codec_v2_test \ + megaco_codec_prev3a_test \ + megaco_codec_prev3b_test \ + megaco_codec_prev3c_test \ + megaco_codec_v3_test \ + megaco_codec_mini_test \ + megaco_config_test \ + megaco_digit_map_test \ + megaco_examples_test \ + megaco_flex_test \ + megaco_load_test \ + megaco_mess_test \ + megaco_mess_user_test \ + megaco_mess_otp8212_test \ + megaco_mib_test \ + megaco_mreq_test \ + megaco_pending_limit_test \ + megaco_profile \ + megaco_segment_test \ + megaco_sdp_test \ + megaco_tc_controller \ + megaco_tcp_test \ + megaco_timer_test \ + megaco_trans_test \ + megaco_udp_test \ + megaco_test_generator_lib \ + megaco_test_megaco_generator \ + megaco_test_tcp_generator \ + megaco_test_deliver \ + megaco_test_generic_transport \ + megaco_test_mgc \ + megaco_test_mg \ + megaco_test_msg_v1_lib \ + megaco_test_msg_v2_lib \ + megaco_test_msg_prev3a_lib \ + megaco_test_msg_prev3b_lib \ + megaco_test_msg_prev3c_lib \ + megaco_test_msg_v3_lib \ + megaco_test_lib + + +INTERNAL_HRL_FILES = \ + megaco_test_lib.hrl + + + |