summaryrefslogtreecommitdiff
path: root/cesar/cp/eoc/cco/action/test/utest_mcast
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/cp/eoc/cco/action/test/utest_mcast')
-rw-r--r--cesar/cp/eoc/cco/action/test/utest_mcast/Config19
-rw-r--r--cesar/cp/eoc/cco/action/test/utest_mcast/Makefile18
-rw-r--r--cesar/cp/eoc/cco/action/test/utest_mcast/inc/scenario_defs.h160
-rw-r--r--cesar/cp/eoc/cco/action/test/utest_mcast/inc/test_cco_action.h46
-rw-r--r--cesar/cp/eoc/cco/action/test/utest_mcast/override/cp/inc/context.h90
-rw-r--r--cesar/cp/eoc/cco/action/test/utest_mcast/override/cp/sta/core/defs.h57
-rw-r--r--cesar/cp/eoc/cco/action/test/utest_mcast/override/cyg/kernel/kapi.h37
-rw-r--r--cesar/cp/eoc/cco/action/test/utest_mcast/override/mac/sar/inc/context.h24
-rw-r--r--cesar/cp/eoc/cco/action/test/utest_mcast/src/cl_mcast.c60
-rw-r--r--cesar/cp/eoc/cco/action/test/utest_mcast/src/fsm_stub.c55
-rw-r--r--cesar/cp/eoc/cco/action/test/utest_mcast/src/msg_stub.c289
-rw-r--r--cesar/cp/eoc/cco/action/test/utest_mcast/src/scenario_actions.c72
-rw-r--r--cesar/cp/eoc/cco/action/test/utest_mcast/src/test_cco_action.c75
-rw-r--r--cesar/cp/eoc/cco/action/test/utest_mcast/src/test_mcast_suite.c97
14 files changed, 1099 insertions, 0 deletions
diff --git a/cesar/cp/eoc/cco/action/test/utest_mcast/Config b/cesar/cp/eoc/cco/action/test/utest_mcast/Config
new file mode 100644
index 0000000000..4660a4c5b7
--- /dev/null
+++ b/cesar/cp/eoc/cco/action/test/utest_mcast/Config
@@ -0,0 +1,19 @@
+CONFIG_CP_EOC = y
+CONFIG_TRACE = n
+CONFIG_MAC_COMMON_EOC_SCHED = y
+CONFIG_CP_EOC_SCHEDULER = y
+CONFIG_CP_EOC_MULTI_STA_FSM_DEF="cp/eoc/multi_sta_fsm/src/fsm/multi_sta.fsm"
+CONFIG_CP_EOC_IS_MASTER = y
+CONFIG_CP_STA_MGR_CCO_EOC = y
+CONFIG_CP_FSM_DEF = "cp/eoc/fsm/src/fsm/cp_eoc_cco.fsm"
+CONFIG_CP_MSG_EOC_MULTI_STA_MME = y
+CONFIG_CL_EOC_CLASSIFY = y
+CONFIG_CP_EOC_BEACON_SPC_CENTRAL = y
+CONFIG_CL_EOC_ROUTE = y
+CONFIG_CP_MSG_EOC_DRV_MME = y
+CONFIG_CP_EOC_CCO_ACTION_WL_ALLOWED = y
+CONFIG_CP_STA_ACTION_MISC_EOC = y
+CONFIG_CP_EOC_DBG_PRINT_LEVEL = 1
+CONFIG_AV_ONLY_MODE = y
+CONFIG_CP_EOC_CCO_ACTION_CON_ALLOWED = n
+CONFIG_MAC_COMMON_EOC_TEI = y
diff --git a/cesar/cp/eoc/cco/action/test/utest_mcast/Makefile b/cesar/cp/eoc/cco/action/test/utest_mcast/Makefile
new file mode 100644
index 0000000000..8fc6f16a77
--- /dev/null
+++ b/cesar/cp/eoc/cco/action/test/utest_mcast/Makefile
@@ -0,0 +1,18 @@
+BASE = ../../../../../..
+
+INCLUDES = cp/eoc/cco/action/test/utest_mcast/override \
+ cp/eoc/cco/action/test/utest_mcast
+
+HOST_PROGRAMS = test_cco_action
+test_cco_action_SOURCES = test_cco_action.c test_mcast_suite.c \
+ scenario_actions.c fsm_stub.c msg_stub.c cl_mcast.c
+test_cco_action_MODULES = lib lib/scenario cp/eoc/fsm/stub mac/common \
+ cp/eoc/cco/action cp/eoc/cco/bw/stub cl/stub \
+ cp/eoc/sta/mgr cp/eoc/sta/action/stub cp/sta/core/stub \
+ cp/eoc/multi_sta_fsm cp/eoc/multi_sta/action/stub \
+ cp/eoc/beacon/stub cp/eoc/msg/stub bsu/stub cp/secu/stub \
+ mac/sar/stub mac/pbproc/stub mac/ca/stub ce/rx/stub \
+ hal/ipmbox/stub bufmgr/stub
+test_cco_action_CONFIG_MODULES = cp/eoc cl mac/sar
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/cp/eoc/cco/action/test/utest_mcast/inc/scenario_defs.h b/cesar/cp/eoc/cco/action/test/utest_mcast/inc/scenario_defs.h
new file mode 100644
index 0000000000..1806228271
--- /dev/null
+++ b/cesar/cp/eoc/cco/action/test/utest_mcast/inc/scenario_defs.h
@@ -0,0 +1,160 @@
+#ifndef inc_scenario_defs_h
+#define inc_scenario_defs_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/scenario_defs.h
+ * \brief Scenario definitions.
+ * \ingroup test
+ */
+#include "cp/fsm/fsm.h"
+
+/* Scenario globals. */
+#define SCENARIO_DEFS_GLOBALS \
+ cp_t *cp; \
+ u16 prn; \
+ u32 my_nonce; \
+ u32 your_nonce; \
+ cp_mme_tx_t *mme;
+
+/* Scenario actions. */
+#define SCENARIO_DEFS_ACTIONS \
+ drv__drv_mcast_set_list_req
+
+/* Actions without parameter. */
+#define __0(action) \
+typedef scenario_empty_t scenario_action_ ## action ## _t; \
+void \
+scenario_action_ ## action ## _cb ( \
+ scenario_globals_t *globals, scenario_params_t *params);
+
+/* Actions with parameters. */
+#define __n(action, param...) \
+typedef struct \
+{ \
+ PREPROC_FOR_EACH (__n_, param) \
+} scenario_action_ ## action ## _t; \
+void \
+scenario_action_ ## action ## _cb ( \
+ scenario_globals_t *globals, scenario_params_t *params);
+#define __n_(param) param;
+
+/* Actions with MME and parameters. */
+#define __m(action, param...) \
+typedef struct \
+{ \
+ cp_mme_peer_t peer; \
+ PREPROC_FOR_EACH (__m_, param) \
+} scenario_action_ ## action ## _t; \
+void \
+scenario_action_ ## action ## _cb ( \
+ scenario_globals_t *globals, scenario_params_t *params);
+#define __m_(param) param;
+
+__m (drv__drv_mcast_set_list_req)
+
+#undef __0
+#undef __n
+#undef __n_
+#undef __m
+#undef __m_
+
+/* Scenario events. */
+#define SCENARIO_DEFS_EVENTS \
+ cp_fsm_event_bare_new, \
+ cp_fsm_event_mme_new, \
+ cp_fsm_branch, \
+ cp_msg_drv_mcast_set_list_req_receive
+
+/* MME send event. */
+#define __ms(event, param...) \
+typedef struct \
+{ \
+ cp_mme_peer_t peer; \
+ PREPROC_FOR_EACH (__p_, ## param) \
+} scenario_event_ ## event ## _t;
+
+/* MME send event complex. */
+#define __msc(event, param...) \
+typedef struct \
+{ \
+ PREPROC_FOR_EACH (__p_, ## param) \
+} scenario_event_ ## event ## _t;
+
+/* MME send event with encryption information. */
+#define __msk(event, param...) \
+typedef struct \
+{ \
+ cp_mme_peer_t peer; \
+ cp_mme_peks_t peks; \
+ u8 pid; \
+ u8 pmn; \
+ PREPROC_FOR_EACH (__p_, ## param) \
+} scenario_event_ ## event ## _t;
+
+/* MME send event for CC_RELAY.IND. */
+#define __msr(event, param...) \
+typedef struct \
+{ \
+ mac_t mac_fa; \
+ cp_tei_t ftei; \
+ PREPROC_FOR_EACH (__p_, ## param) \
+} scenario_event_ ## event ## _t;
+
+/* MME receive event. */
+#define __mr(event, param...) \
+typedef struct \
+{ \
+ bool ok; \
+ PREPROC_FOR_EACH (__p_, ## param) \
+} scenario_event_ ## event ## _t;
+
+/* MME receive event with encryption information. */
+#define __mrk(event, param...) \
+typedef struct \
+{ \
+ bool ok; \
+ cp_mme_peks_t peks; \
+ u8 pid; \
+ u8 pmn; \
+ bool new_prn; \
+ bool new_my_nonce; \
+ bool new_your_nonce; \
+ PREPROC_FOR_EACH (__p_, ## param) \
+} scenario_event_ ## event ## _t;
+
+#define __p_(param) param;
+
+__mr (cp_msg_drv_mcast_set_list_req_receive,
+ int nb_groups,
+ mac_t* groups, uint* nb_members,
+ mac_t* members)
+
+#undef __ms
+#undef __msk
+#undef __msr
+#undef __mr
+#undef __mrk
+#undef __msc
+
+/* Any event. */
+#define __e(event, param...) \
+typedef struct \
+{ \
+ PREPROC_FOR_EACH (__p_, ## param) \
+} scenario_event_ ## event ## _t;
+
+__e (cp_fsm_event_bare_new, cp_fsm_event_type_t type)
+__e (cp_fsm_event_mme_new, cp_fsm_event_type_t type)
+__e (cp_fsm_branch, cp_fsm_branch_t branch)
+
+#undef __e
+
+#undef __p_
+
+#endif /* inc_scenario_defs_h */
diff --git a/cesar/cp/eoc/cco/action/test/utest_mcast/inc/test_cco_action.h b/cesar/cp/eoc/cco/action/test/utest_mcast/inc/test_cco_action.h
new file mode 100644
index 0000000000..06213c752d
--- /dev/null
+++ b/cesar/cp/eoc/cco/action/test/utest_mcast/inc/test_cco_action.h
@@ -0,0 +1,46 @@
+#ifndef inc_test_cco_action_h
+#define inc_test_cco_action_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/test_cco_action.h
+ * \brief Test cco/action.
+ * \ingroup test
+ */
+#include "cp/inc/context.h"
+
+/** Contexts used in tests. */
+struct test_cco_action_t
+{
+ cp_t cp;
+ mac_config_t mac_config;
+};
+typedef struct test_cco_action_t test_cco_action_t;
+
+/**
+ * Initialise test contexts.
+ * \param ctx test context
+ */
+void
+test_cco_action_init (test_cco_action_t *ctx);
+
+/**
+ * Uninitialise test contexts.
+ * \param ctx test context
+ */
+void
+test_cco_action_uninit (test_cco_action_t *ctx);
+
+/**
+ * Reset test contexts.
+ * \param ctx test context
+ */
+void
+test_cco_action_reset (test_cco_action_t *ctx);
+
+#endif /* inc_test_cco_action_h */
diff --git a/cesar/cp/eoc/cco/action/test/utest_mcast/override/cp/inc/context.h b/cesar/cp/eoc/cco/action/test/utest_mcast/override/cp/inc/context.h
new file mode 100644
index 0000000000..af86ef23f3
--- /dev/null
+++ b/cesar/cp/eoc/cco/action/test/utest_mcast/override/cp/inc/context.h
@@ -0,0 +1,90 @@
+#ifndef override_cp_inc_context_h
+#define override_cp_inc_context_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file override/cp/inc/context.h
+ * \brief Control plane context override.
+ * \ingroup test
+ */
+#include "cp/types.h"
+#include "cp/eoc/cco/action/inc/cco_action.h"
+#include "cp/cco/action/inc/cco_action.h"
+#include "cp/sta/action/inc/context.h"
+#include "cp/eoc/beacon/inc/beacon.h"
+#include "cp/eoc/beacon/beacon.h"
+#include "cp/sta/mgr/sta_mgr.h"
+#include "cp/sta/mgr/inc/sta_mgr.h"
+#include "cp/cco/region/inc/context.h"
+#include "cp/cco/bw/bw.h"
+#include "cp/cco/bw/inc/context.h"
+#include "cl/cl.h"
+#include "mac/common/config.h"
+#include "mac/common/store.h"
+#include "mac/sar/sar.h"
+#include "mac/pbproc/pbproc.h"
+#include "lib/rnd.h"
+#include "lib/trace.h"
+#include "cp/eoc/cco/bw/inc/bw.h"
+#include "cp/inc/trace.h"
+#include "cp/fsm/fsm.h"
+#include "cp/fsm/inc/context.h"
+
+enum cp_handover_reason_t
+{
+ CP_HANDOVER_REASON_CCO_SELECTION,
+ CP_HANDOVER_REASON_CCO_LEAVING,
+ CP_HANDOVER_REASON_USER_APPOINT,
+ CP_HANDOVER_REASON_NB,
+};
+
+enum cp_handover_soft_hard_t
+{
+ CP_HANDOVER_SOFT_HARD_SOFT,
+ CP_HANDOVER_SOFT_HARD_HARD,
+ CP_HANDOVER_NB,
+};
+
+struct cp_handover_t
+{
+ /** Handover timeout. */
+ cp_sta_core_timed_event_def_t handover_timeout;
+
+ /** handover reason. */
+ enum cp_handover_reason_t reason;
+
+ /** Handover soft hard */
+ enum cp_handover_soft_hard_t soft_hard;
+};
+
+struct cp_t
+{
+ cp_fsm_t fsm;
+ cp_cco_action_t cco_action;
+ cp_sta_action_t sta_action;
+ cp_sta_mgr_t sta_mgr;
+ cp_beacon_t beacon;
+ lib_rnd_t rnd;
+ cl_t *cl;
+ mac_config_t *mac_config;
+ mac_store_t *mac_store;
+ sar_t *sar;
+ ca_t *ca;
+ pbproc_t *pbproc;
+ struct cp_handover_t handover;
+ struct cp_cco_region_t region;
+ struct cp_cco_bw_t bw;
+ bsu_t *bsu;
+ cp_eoc_cco_bw_sched_t schedule;
+
+#if CONFIG_TRACE
+ trace_buffer_t trace;
+#endif
+};
+
+#endif /* override_cp_inc_context_h */
diff --git a/cesar/cp/eoc/cco/action/test/utest_mcast/override/cp/sta/core/defs.h b/cesar/cp/eoc/cco/action/test/utest_mcast/override/cp/sta/core/defs.h
new file mode 100644
index 0000000000..9698b44e93
--- /dev/null
+++ b/cesar/cp/eoc/cco/action/test/utest_mcast/override/cp/sta/core/defs.h
@@ -0,0 +1,57 @@
+#ifndef cp_sta_core_defs_h
+#define cp_sta_core_defs_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/sta/core/defs.h
+ * \brief Sta core defs.
+ * \ingroup cp/sta/core
+ *
+ */
+#include "cp/fsm/forward.h"
+
+/** Forward declaration. */
+typedef struct cp_sta_core_t cp_sta_core_t;
+
+/*
+ * the sta core event flags
+ * these are some flags, so take care to give a value with all bits set to 0 but one.
+ */
+enum cp_sta_core_event_flag_t
+{
+ CP_STA_CORE_EVENT_FLAG_RECV_BEACON = 0x1,
+ CP_STA_CORE_EVENT_FLAG_RECV_MME = 0x2,
+ CP_STA_CORE_EVENT_FLAG_FSM = 0x4,
+ CP_STA_CORE_EVENT_FLAG_GARBAGE = 0x8,
+ CP_STA_CORE_EVENT_FLAG_TERMINATE = 0x10
+};
+typedef enum cp_sta_core_event_flag_t cp_sta_core_event_flag_t;
+
+/** Definition of alarm info structure
+ * (applications should not use it directly but use "alias" defined just below) */
+struct cp_sta_core_timed_event_def_t
+{
+ /* eCos alarm. */
+ uint alarm;
+ /* eCos alarm handle. */
+ uint alarm_handle;
+ /* the sta core event flag to set
+ * (auto or user-specified when creating/launching timer alarm). */
+ cp_sta_core_event_flag_t event_flag;
+ /* FSM event specified when creating/launching timer alarm
+ * (set if the previous flag is CP_STA_CORE_EVENT_FLAG_FSM). */
+ cp_fsm_event_t *fsm_event;
+ /* flag indicating a periodic alarm (if set to true)
+ * or one-shot alarm (if set to false). */
+ bool cyclic_alarm;
+ /* pointer to CP context. */
+ cp_t *cp_ctx;
+};
+typedef struct cp_sta_core_timed_event_def_t cp_sta_core_timed_event_def_t;
+
+#endif /* cp_sta_core_defs_h */
diff --git a/cesar/cp/eoc/cco/action/test/utest_mcast/override/cyg/kernel/kapi.h b/cesar/cp/eoc/cco/action/test/utest_mcast/override/cyg/kernel/kapi.h
new file mode 100644
index 0000000000..019e5d3a07
--- /dev/null
+++ b/cesar/cp/eoc/cco/action/test/utest_mcast/override/cyg/kernel/kapi.h
@@ -0,0 +1,37 @@
+#ifndef override_cyg_kernel_kapi_h
+#define override_cyg_kernel_kapi_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2010 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file override/cyg/kernel/kapi.h
+ * \brief override some kernel api from <cyg/kernel/kapi.h>.
+ * \ingroup cp_msg
+ *
+ *
+ */
+
+struct cyg_resolution_t
+{
+ u32 dividend;
+ u32 divisor;
+} ;
+
+typedef struct cyg_resolution_t cyg_resolution_t;
+
+typedef u64 cyg_tick_count_t;
+
+int
+cyg_real_time_clock (void);
+
+cyg_resolution_t
+cyg_clock_get_resolution (int clock);
+
+cyg_tick_count_t
+cyg_current_time (void);
+
+#endif
diff --git a/cesar/cp/eoc/cco/action/test/utest_mcast/override/mac/sar/inc/context.h b/cesar/cp/eoc/cco/action/test/utest_mcast/override/mac/sar/inc/context.h
new file mode 100644
index 0000000000..3cf70530df
--- /dev/null
+++ b/cesar/cp/eoc/cco/action/test/utest_mcast/override/mac/sar/inc/context.h
@@ -0,0 +1,24 @@
+#ifndef override_mac_sar_inc_context_h
+#define override_mac_sar_inc_context_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file override/mac/sar/inc/context.h
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+#include "mac/common/store.h"
+
+struct sar_t
+{
+ mac_store_t *mac_store;
+};
+
+#endif /* override_mac_sar_inc_context_h */
diff --git a/cesar/cp/eoc/cco/action/test/utest_mcast/src/cl_mcast.c b/cesar/cp/eoc/cco/action/test/utest_mcast/src/cl_mcast.c
new file mode 100644
index 0000000000..6eb9f07fd2
--- /dev/null
+++ b/cesar/cp/eoc/cco/action/test/utest_mcast/src/cl_mcast.c
@@ -0,0 +1,60 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/eoc/cco/action/test/scenario/src/cl_mcast.c
+ * \brief Multicast.
+ * \ingroup cp_eoc_cco_action_test_scenario
+ */
+#include "common/std.h"
+#include "cl/cl.h"
+#include "cl/mcast.h"
+#include "config/cl/eoc/route.h"
+#include "cl/inc/context.h"
+
+igmp_groups_t*
+cl_get_igmp_groups (cl_t *ctx)
+{
+ dbg_assert (ctx);
+ return &ctx->groups;
+}
+
+void
+cl_update_igmp_groups (cl_t *ctx)
+{
+ dbg_assert (ctx);
+ uint g;
+ uint m;
+ for (g = 0; g < ctx->groups.nb; g++)
+ {
+ uint tei = MAC_TEI_UNASSOCIATED;
+ ctx->groups.nb_actual_members[g] = 0;
+
+ for (m = 0; m < ctx->groups.nb_total_members[g]; m++)
+# if CONFIG_CL_EOC_ROUTE
+ {
+ tei = cl_eoc_mactotei_find_tei (
+ ctx, ctx->groups.member_mac[g][m]);
+ if (MAC_TEI_IS_EOC_STA (tei))
+ ctx->groups.member_tei[g][ctx->groups.nb_actual_members[g]++] =
+ tei;
+ }
+ if (ctx->groups.nb_actual_members[g] == 0)
+ ctx->groups.member_tei[g][0] = MAC_TEI_UNASSOCIATED;
+#else
+ {
+ tei = cl_mactotei_table_find_tei_from_mac (
+ ctx, ctx->groups.member_mac[g][m]);
+ if (MAC_TEI_IS_STA(tei))
+ ctx->groups.member_tei[g][ctx->groups.nb_actual_members[g]++] =
+ tei;
+ }
+ if (ctx->groups.nb_actual_members[g] == 0)
+ ctx->groups.member_tei[g][0] = MAC_TEI_BCAST;
+#endif
+ }
+}
diff --git a/cesar/cp/eoc/cco/action/test/utest_mcast/src/fsm_stub.c b/cesar/cp/eoc/cco/action/test/utest_mcast/src/fsm_stub.c
new file mode 100644
index 0000000000..993bffaaaa
--- /dev/null
+++ b/cesar/cp/eoc/cco/action/test/utest_mcast/src/fsm_stub.c
@@ -0,0 +1,55 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/fsm_stub.c
+ * \brief FSM stub.
+ * \ingroup test
+ */
+#include "common/std.h"
+#include "cp/fsm/fsm.h"
+
+#include "lib/scenario/scenario.h"
+
+cp_fsm_event_t *
+cp_fsm_event_bare_new (cp_t *ctx, cp_fsm_event_type_t type)
+{
+ dbg_assert (ctx);
+ switch (type)
+ {
+ case CP_FSM_EVENT_TYPE_net_list_empty:
+ /* Ignore. */
+ return INVALID_PTR;
+ case CP_FSM_EVENT_TYPE_sta_status_changed:
+ if (!scenario.current ||
+ (scenario.current->params.event_cp_fsm_event_bare_new.type != type))
+ return INVALID_PTR;
+
+ default:
+ ;
+ }
+ scenario_event (cp_fsm_event_bare_new, param);
+ test_fail_unless (type == param->type);
+ return INVALID_PTR;
+}
+
+cp_fsm_event_t *
+cp_fsm_event_mme_new (cp_t *ctx, cp_fsm_event_type_t type, cp_mme_rx_t *mme)
+{
+ dbg_assert (ctx);
+ scenario_event (cp_fsm_event_mme_new, param);
+ test_fail_unless (type == param->type);
+ return INVALID_PTR;
+}
+
+void
+cp_fsm_branch_ (cp_t *ctx, cp_fsm_branch_t branch)
+{
+ dbg_assert (ctx);
+ scenario_event (cp_fsm_branch, param);
+ test_fail_unless (branch == param->branch);
+}
diff --git a/cesar/cp/eoc/cco/action/test/utest_mcast/src/msg_stub.c b/cesar/cp/eoc/cco/action/test/utest_mcast/src/msg_stub.c
new file mode 100644
index 0000000000..c9beef391b
--- /dev/null
+++ b/cesar/cp/eoc/cco/action/test/utest_mcast/src/msg_stub.c
@@ -0,0 +1,289 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/msg_stub.c
+ * \brief cp_msg_stub functions.
+ * \ingroup cp_msg
+ */
+#include "common/std.h"
+#include "lib/scenario/scenario.h"
+#include "cp/inc/context.h"
+#include "cp/msg/msg.h"
+
+#define __ptr_(TYPE) PASTE_EXPAND (__ptr__, TYPE)
+#define __ptr__assign *
+#define __ptr__string
+#define __ptr__array
+#define __ptr__string_or_null
+#define __ptr__tonemask
+#define __ptr__hash_key
+
+#define __dim_(TYPE, DIM...) PASTE_EXPAND (__dim__, TYPE) (DIM)
+#define __dim__assign()
+#define __dim__string()
+#define __dim__array(DIM) DIM
+#define __dim__string_or_null()
+#define __dim__tonemask()
+#define __dim__hash_key()
+
+/* Code for MME transmission. */
+#define __ms(EVENT, PARAMS...) \
+void \
+EVENT (cp_t *ctx, cp_mme_peer_t *peer \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_pdecl_, ## PARAMS)) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (peer); \
+ scenario_event (EVENT, param); \
+ __ms_test_peer \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_test_, ## PARAMS) \
+}
+
+/* Code for MME transmission complex with a begin. */
+#define __mscb(EVENT, PARAMS...) \
+cp_mme_tx_t * \
+EVENT (cp_t *ctx, cp_mme_peer_t *peer \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_pdecl_, ## PARAMS)) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (peer); \
+ scenario_event (EVENT, param, global); \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_test_, ## PARAMS) \
+ return global->mme; \
+}
+
+/* Code for MME transmission complex (with or without an end). */
+#define __msc(EVENT, PARAMS...) \
+void \
+EVENT (cp_t *ctx, cp_mme_tx_t *mme \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_pdecl_, ## PARAMS)) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (mme); \
+ scenario_event (EVENT, param); \
+ test_fail_unless (param); \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_test_, ## PARAMS) \
+}
+
+#define __msdc(EVENT, DATA, PARAMS...) \
+void \
+EVENT (cp_t *ctx, cp_mme_tx_t *mme, const DATA *data) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (mme); \
+ dbg_assert (data); \
+ scenario_event (EVENT, param); \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __msd_test_, ## PARAMS) \
+}
+
+#define __ms_pdecl_(TYPE, PARAM, KIND) , TYPE PARAM
+#define __ms_test_(TYPE, PARAM, KIND) \
+ PASTE_EXPAND (__ms_test__, KIND) (PARAM)
+#define __ms_test__assign(PARAM) \
+ test_fail_unless (PARAM == param->PARAM);
+#define __ms_test__ignore_pointer(PARAM)
+#define __ms_test__string(PARAM) \
+ test_fail_unless (strcmp (PARAM, param->PARAM) == 0);
+#define __ms_test_peer \
+ test_fail_unless (peer->mac == param->peer.mac); \
+ test_fail_unless (peer->eth_type == param->peer.eth_type); \
+ test_fail_unless (peer->vlan_tci == param->peer.vlan_tci); \
+ test_fail_unless (peer->tei == param->peer.tei); \
+
+/* Code for MME transmission with a data structure. */
+#define __msd(EVENT, DATA, PARAMS...) \
+void \
+EVENT (cp_t *ctx, cp_mme_peer_t *peer, const DATA *data) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (peer); \
+ dbg_assert (data); \
+ scenario_event (EVENT, param); \
+ __ms_test_peer \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __msd_test_, ## PARAMS) \
+}
+
+#define __msd_test_(TYPE, PARAM, KIND) \
+ PASTE_EXPAND (__msd_test__, KIND) (PARAM)
+#define __msd_test__assign(PARAM) \
+ test_fail_unless (data->PARAM == param->PARAM);
+#define __msd_test__string(PARAM) \
+ test_fail_unless (strcmp (data->PARAM, param->PARAM) == 0);
+#define __msd_test__hash_key(PARAM) \
+ test_fail_unless (!param->PARAM || memcmp (data->PARAM, param->PARAM, \
+ CP_HASH_KEY_SIZE) == 0);
+#define __msd_test__key(PARAM) \
+ test_fail_unless (memcmp (&data->PARAM, &param->PARAM, \
+ sizeof (cp_key_t)) == 0);
+#define __ms_test__key(PARAM) \
+ test_fail_unless (memcmp (&PARAM, &param->PARAM, \
+ sizeof (cp_key_t)) == 0);
+#define __msd_test__sub_assign(PARAM) \
+ __msd_test__sub_assign_ PARAM
+#define __msd_test__sub_assign_(PARAM, SUBNAME) \
+ test_fail_unless (data->SUBNAME.PARAM == param->PARAM);
+#define __msd_test__ignore_pointer(PARAM) ;
+
+#define __msd_test__array(PARAM) \
+ __msd_test__array_ PARAM
+#define __msd_test__array_(PARAM, SIZE) \
+ test_fail_unless (memcmp (data->PARAM, param->PARAM, SIZE) == 0);
+
+/* Code for MME transmission with a data structure with encryption
+ * information. */
+#define __msk(EVENT, DATA, PARAMS...) \
+void \
+EVENT (cp_t *ctx, cp_mme_peer_t *peer, cp_mme_peks_t peks, \
+ const cp_secu_protocol_run_t *prun, const DATA *data) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (peer); \
+ dbg_assert (data); \
+ scenario_event (EVENT, param, global); \
+ __ms_test_peer \
+ test_fail_unless (peks == param->peks); \
+ test_fail_unless (prun->pid == param->pid); \
+ test_fail_unless (prun->pmn == param->pmn); \
+ global->prn = prun->prn; \
+ global->my_nonce = prun->my_nonce; \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __msd_test_, ## PARAMS) \
+}
+
+/* Code for MME transmission for CC_RELAY.IND. */
+#define __msr(EVENT, PARAMS...) \
+void \
+EVENT (cp_t *ctx, cp_mme_rx_t *mme \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_pdecl_, ## PARAMS)) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (mme); \
+ scenario_event (EVENT, param); \
+ test_fail_unless (mme->relay.mac_fa == param->mac_fa); \
+ test_fail_unless (mme->relay.ftei == param->ftei); \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_test_, ## PARAMS) \
+}
+
+
+/* Code for MME reception. */
+#define __mr(EVENT, PARAMS...) \
+bool \
+EVENT (cp_t *ctx, cp_mme_rx_t *mme \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mr_pdecl_, ## PARAMS)) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (mme); \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mr_assert_, ## PARAMS) \
+ scenario_event (EVENT, param); \
+ if (param->ok) \
+ { \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mr_copy_, ## PARAMS) \
+ return true; \
+ } \
+ else \
+ return false; \
+}
+
+#define __mr_pdecl_(TYPE, PARAM, KIND, DIM...) \
+ , TYPE __ptr_ (KIND) PARAM __dim_ (KIND, ## DIM)
+#define __mr_assert_(TYPE, PARAM, KIND, DIM...) dbg_assert_ptr (PARAM);
+#define __mr_copy_(TYPE, PARAM, KIND, DIM...) \
+ PASTE_EXPAND (__mr_copy__, KIND) (PARAM, TYPE, ## DIM)
+
+#define __mr_copy__assign(PARAM, TYPE) *PARAM = param->PARAM;
+#define __mr_copy__string(PARAM, TYPE) strcpy (PARAM, param->PARAM);
+#define __mr_copy__string_or_null(PARAM, TYPE) \
+ if (param->PARAM) strcpy (PARAM, param->PARAM);
+#define __mr_copy__tonemask(PARAM, TYPE) \
+ memcpy (PARAM, param->PARAM, PHY_TONEMASK_SIZE);
+#define __mr_copy__array(PARAM, TYPE, DIM) \
+ memcpy (PARAM, param->PARAM, sizeof(TYPE DIM));
+
+/* Code for MME reception with a data structure. */
+#define __mrd(EVENT, DATA, PARAMS...) \
+bool \
+EVENT (cp_t *ctx, cp_mme_rx_t *mme, DATA *data) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (mme); \
+ dbg_assert (data); \
+ scenario_event (EVENT, param); \
+ if (param->ok) \
+ { \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mrd_copy_, PARAMS) \
+ return true; \
+ } \
+ else \
+ return false; \
+}
+
+#define __mrd_copy_(TYPE, PARAM, KIND) \
+ PASTE_EXPAND (__mrd_copy__, KIND) (PARAM)
+
+#define __mrd_copy__assign(PARAM) data->PARAM = param->PARAM;
+#define __mrd_copy__string(PARAM) strcpy (data->PARAM, param->PARAM);
+#define __mrd_copy__tonemask(PARAM) \
+ memcpy (data->PARAM, param->PARAM, PHY_TONEMASK_SIZE);
+#define __mrd_copy__hash_key(PARAM) \
+ if (param->PARAM) memcpy (data->PARAM, param->PARAM, CP_HASH_KEY_SIZE);
+#define __mrd_copy__assign_deref(PARAM) \
+ if (param->PARAM) data->PARAM = *param->PARAM;
+
+/* Code for MME reception with a data structure with encryption
+ * information. */
+#define __mrk(EVENT, DATA, PARAMS...) \
+bool \
+EVENT (cp_t *ctx, cp_mme_rx_t *mme, DATA *data) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (mme); \
+ dbg_assert (data); \
+ scenario_event (EVENT, param, g); \
+ if (param->ok) \
+ { \
+ mme->peks = param->peks; \
+ if (param->new_prn) g->prn = lib_rnd32 (&ctx->rnd) & 0xffff; \
+ if (param->new_my_nonce) g->my_nonce = lib_rnd32 (&ctx->rnd); \
+ if (param->new_your_nonce) g->your_nonce = lib_rnd32 (&ctx->rnd); \
+ mme->prun.pid = param->pid; \
+ mme->prun.pmn = param->pmn; \
+ mme->prun.prn = g->prn; \
+ mme->prun.my_nonce = g->my_nonce; \
+ mme->prun.your_nonce = g->your_nonce; \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mrd_copy_, PARAMS) \
+ return true; \
+ } \
+ else \
+ return false; \
+}
+
+/* Code for MME reception for CC_RELAY.REQ. */
+#define __mrr(EVENT, PARAMS...) \
+bool \
+EVENT (cp_t *ctx, cp_mme_rx_t *mme \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mr_pdecl_, ## PARAMS)) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (mme); \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mr_assert_, ## PARAMS) \
+ scenario_event (EVENT, param); \
+ if (param->ok) \
+ { \
+ mme->relay.mac_fa = param->mac_fa; \
+ mme->relay.ftei = param->ftei; \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mr_copy_, ## PARAMS) \
+ return true; \
+ } \
+ else \
+ return false; \
+}
+
+__mr (cp_msg_drv_mcast_set_list_req_receive,
+ (uint, nb_groups, assign),
+ (mac_t, groups, array, [MCAST_GROUP_MAX_NB]),
+ (uint, nb_members, array, [MCAST_GROUP_MAX_NB]),
+ (mac_t, members, array, [MCAST_GROUP_MAX_NB][MCAST_MEMBER_MAX_NB]))
diff --git a/cesar/cp/eoc/cco/action/test/utest_mcast/src/scenario_actions.c b/cesar/cp/eoc/cco/action/test/utest_mcast/src/scenario_actions.c
new file mode 100644
index 0000000000..edcd638f3b
--- /dev/null
+++ b/cesar/cp/eoc/cco/action/test/utest_mcast/src/scenario_actions.c
@@ -0,0 +1,72 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/scenario_actions.c
+ * \brief Scenario actions.
+ * \ingroup test
+ */
+#include "common/std.h"
+#include "cp/eoc/cco/action/cco_action.h"
+#include "lib/scenario/scenario.h"
+
+#define __m(ACTION) \
+void \
+scenario_action_ ## ACTION ## _cb (scenario_globals_t *globals, \
+ scenario_params_t *params) \
+{ \
+ static cp_mme_rx_t mme; \
+ mme.peer = params->action_ ## ACTION.peer; \
+ cp_eoc_cco_action_ ## ACTION (globals->cp, &mme); \
+}
+
+#define __mp(ACTION) \
+void \
+scenario_action_ ## ACTION ## _cb (scenario_globals_t *globals, \
+ scenario_params_t *params) \
+{ \
+ ccotic cp_mme_rx_t mme; \
+ mme.peer = params->action_ ## ACTION.peer; \
+ mme.prun.pid = params->action_ ## ACTION.pid; \
+ cp_eoc_cco_action_ ## ACTION (globals->cp, &mme); \
+}
+
+#define __me(ACTION) \
+void \
+scenario_action_ ## ACTION ## _cb (scenario_globals_t *globals, \
+ scenario_params_t *params) \
+{ \
+ ccotic cp_mme_rx_t mme; \
+ mme.peer = params->action_ ## ACTION.peer; \
+ mme.encrypt = params->action_ ## ACTION.encrypt; \
+ cp_eoc_cco_action_ ## ACTION (globals->cp, &mme); \
+}
+
+#define __0(ACTION) \
+void \
+scenario_action_ ## ACTION ## _cb (scenario_globals_t *globals, \
+ scenario_params_t *params) \
+{ \
+ cp_eoc_cco_action_ ## ACTION (globals->cp); \
+}
+
+#define __n(ACTION, PARAMS...) \
+void \
+scenario_action_ ## ACTION ## _cb (scenario_globals_t *globals, \
+ scenario_params_t *params) \
+{ \
+ scenario_action_ ## ACTION ## _t *p = &params->action_ ## ACTION; \
+ cp_eoc_cco_action_ ## ACTION (globals->cp \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, \
+ __n_args, ## PARAMS) \
+ ); \
+}
+
+#define __n_args(TYPE, PARAM) \
+ , p->PARAM
+
+__m (drv__drv_mcast_set_list_req)
diff --git a/cesar/cp/eoc/cco/action/test/utest_mcast/src/test_cco_action.c b/cesar/cp/eoc/cco/action/test/utest_mcast/src/test_cco_action.c
new file mode 100644
index 0000000000..8659c74c13
--- /dev/null
+++ b/cesar/cp/eoc/cco/action/test/utest_mcast/src/test_cco_action.c
@@ -0,0 +1,75 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_sta_action.c
+ * \brief Test sta/action.
+ * \ingroup test
+ */
+#include "common/std.h"
+#include "lib/test.h"
+#include "cp/eoc/multi_sta_fsm/forward.h"
+#include "cl/inc/context.h"
+#include "mac/sar/inc/context.h"
+#include "inc/test_cco_action.h"
+
+void
+test_suite_mcast (test_t test);
+
+void
+test_cco_action_init (test_cco_action_t *ctx)
+{
+ static sar_t sar;
+ static cl_t cl;
+ memset (&cl, 0, sizeof (cl_t));
+
+ lib_rnd_init (&ctx->cp.rnd, 1234);
+ ctx->cp.mac_config = &ctx->mac_config;
+ ctx->cp.mac_store = mac_store_init ();
+ ctx->cp.sar = &sar;
+ ctx->cp.cl = &cl;
+ sar.mac_store = ctx->cp.mac_store;
+ ctx->cp.pbproc = NULL;
+ cp_eoc_sta_mgr_init (&ctx->cp);
+}
+
+void
+test_cco_action_uninit (test_cco_action_t *ctx)
+{
+ cp_sta_mgr_uninit (&ctx->cp);
+ mac_store_uninit (ctx->cp.mac_store);
+}
+
+void
+test_cco_action_reset (test_cco_action_t *ctx)
+{
+ cp_sta_mgr_uninit (&ctx->cp);
+ mac_store_uninit (ctx->cp.mac_store);
+ ctx->cp.mac_store = mac_store_init ();
+ cp_eoc_sta_mgr_init (&ctx->cp);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init (t, argc, argv);
+ trace_init ();
+ lib_stats_init ();
+ test_suite_mcast (t);
+ lib_stats_uninit ();
+ trace_uninit ();
+ test_case_begin (t, "Memory allocation");
+ test_begin (t, "memory leaks")
+ {
+ test_fail_if (blk_check_memory () != true, "Memory leaks");
+ }
+ test_end;
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
+
diff --git a/cesar/cp/eoc/cco/action/test/utest_mcast/src/test_mcast_suite.c b/cesar/cp/eoc/cco/action/test/utest_mcast/src/test_mcast_suite.c
new file mode 100644
index 0000000000..2352da0115
--- /dev/null
+++ b/cesar/cp/eoc/cco/action/test/utest_mcast/src/test_mcast_suite.c
@@ -0,0 +1,97 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/mcast.c
+ * \brief Multicast test.
+ * \ingroup cp_eoc
+ */
+#include "common/std.h"
+#include "lib/test.h"
+#include "lib/scenario/scenario.h"
+#include "inc/test_cco_action.h"
+#include "cl/mcast.h"
+
+void
+test_suite_mcast (test_t test)
+{
+ test_cco_action_t ctx;
+ test_cco_action_init (&ctx);
+ cp_cco_action_init (&ctx.cp);
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+
+ test_suite_begin (test, "Multicast");
+ test_case_begin (test, "No groups");
+ test_begin (test, "MME received with errors")
+ {
+ igmp_groups_t *igmp = cl_get_igmp_groups (ctx.cp.cl);
+ igmp->nb = 10;
+ scenario_entry_t entry [] = {
+ SCENARIO_ACTION (drv__drv_mcast_set_list_req,
+ .peer = CP_MME_PEER (3, 3)),
+ SCENARIO_EVENT (cp_msg_drv_mcast_set_list_req_receive,
+ .ok = false),
+ SCENARIO_END
+ };
+ scenario_run (test, entry, &globals);
+ test_fail_unless (igmp->nb == 0);
+ }
+ test_end;
+ test_begin (test, "Test all groups cases")
+ {
+ igmp_groups_t *igmp = cl_get_igmp_groups (ctx.cp.cl);
+ igmp->nb = 0;
+ uint nb_groups;
+ mac_t groups[MCAST_GROUP_MAX_NB];
+ uint nb_members[MCAST_GROUP_MAX_NB];
+ mac_t members[MCAST_GROUP_MAX_NB][MCAST_MEMBER_MAX_NB];
+
+ mac_t gmac = 0xAA0000000000ll;
+ mac_t mmac = 0xFF0000000000ll;
+ for (nb_groups = 0; nb_groups < MCAST_GROUP_MAX_NB; nb_groups++)
+ {
+ groups[nb_groups] = gmac + nb_groups;
+ for (nb_members[nb_groups] = 0;
+ nb_members[nb_groups] < MCAST_MEMBER_MAX_NB;
+ nb_members[nb_groups]++)
+ {
+ members[nb_groups][nb_members[nb_groups]] =
+ mmac | (nb_groups << 8) | nb_members[nb_groups];
+
+ scenario_entry_t entry [] = {
+ SCENARIO_ACTION (drv__drv_mcast_set_list_req,
+ .peer = CP_MME_PEER (3, 3)),
+ SCENARIO_EVENT (cp_msg_drv_mcast_set_list_req_receive,
+ .ok = true,
+ .nb_groups = nb_groups,
+ .groups = groups,
+ .nb_members = nb_members,
+ .members = (mac_t*)members),
+ SCENARIO_END
+ };
+ scenario_run (test, entry, &globals);
+ /* Verify. */
+ test_fail_unless (igmp->nb == nb_groups);
+ uint i, j;
+ for (i = 0; i < igmp->nb; i++)
+ {
+ test_fail_unless (igmp->group_mac[i] == gmac + i);
+ test_fail_unless (igmp->nb_total_members[i] == nb_members[i]);
+ for (j = 0; j < nb_members[i]; j++)
+ {
+ test_fail_unless (igmp->member_mac[i][j] ==
+ (mmac | (i << 8) | j));
+ }
+ }
+ }
+ }
+ }
+ test_end;
+ test_cco_action_uninit (&ctx);
+}