doxygen: Fix doxygen errors
[asterisk/asterisk.git] / tests / test_stasis_endpoints.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * David M. Lee, II <dlee@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*!
20  * \file
21  * \brief Test endpoints.
22  *
23  * \author\verbatim David M. Lee, II <dlee@digium.com> \endverbatim
24  *
25  * \ingroup tests
26  */
27
28 /*** MODULEINFO
29         <depend>TEST_FRAMEWORK</depend>
30         <depend>res_stasis_test</depend>
31         <support_level>core</support_level>
32  ***/
33
34 #include "asterisk.h"
35
36 ASTERISK_REGISTER_FILE()
37
38 #include "asterisk/astobj2.h"
39 #include "asterisk/channel.h"
40 #include "asterisk/endpoints.h"
41 #include "asterisk/module.h"
42 #include "asterisk/stasis_channels.h"
43 #include "asterisk/stasis_endpoints.h"
44 #include "asterisk/stasis_test.h"
45 #include "asterisk/test.h"
46
47 static const char *test_category = "/stasis/endpoints/";
48
49 /*! \brief Message matcher looking for cache update messages */
50 static int cache_update(struct stasis_message *msg, const void *data) {
51         struct stasis_cache_update *update;
52         struct ast_endpoint_snapshot *snapshot;
53         const char *name = data;
54
55         if (stasis_cache_update_type() != stasis_message_type(msg)) {
56                 return 0;
57         }
58
59         update = stasis_message_data(msg);
60         if (ast_endpoint_snapshot_type() != update->type) {
61                 return 0;
62         }
63
64         snapshot = stasis_message_data(update->old_snapshot);
65         if (!snapshot) {
66                 snapshot = stasis_message_data(update->new_snapshot);
67         }
68
69         return 0 == strcmp(name, snapshot->resource);
70 }
71
72 AST_TEST_DEFINE(state_changes)
73 {
74         RAII_VAR(struct ast_endpoint *, uut, NULL, ast_endpoint_shutdown);
75         RAII_VAR(struct ast_channel *, chan, NULL, ast_hangup);
76         RAII_VAR(struct stasis_message_sink *, sink, NULL, ao2_cleanup);
77         RAII_VAR(struct stasis_subscription *, sub, NULL, stasis_unsubscribe);
78         struct stasis_message *msg;
79         struct stasis_message_type *type;
80         struct ast_endpoint_snapshot *actual_snapshot;
81         int actual_count;
82
83         switch (cmd) {
84         case TEST_INIT:
85                 info->name = __func__;
86                 info->category = test_category;
87                 info->summary = "Test endpoint updates as its state changes";
88                 info->description =
89                         "Test endpoint updates as its state changes";
90                 return AST_TEST_NOT_RUN;
91         case TEST_EXECUTE:
92                 break;
93         }
94
95         uut = ast_endpoint_create("TEST", __func__);
96         ast_test_validate(test, NULL != uut);
97
98         sink = stasis_message_sink_create();
99         ast_test_validate(test, NULL != sink);
100
101         sub = stasis_subscribe(ast_endpoint_topic(uut),
102                 stasis_message_sink_cb(), sink);
103         ast_test_validate(test, NULL != sub);
104
105         ast_endpoint_set_state(uut, AST_ENDPOINT_OFFLINE);
106         actual_count = stasis_message_sink_wait_for_count(sink, 1,
107                 STASIS_SINK_DEFAULT_WAIT);
108         ast_test_validate(test, 1 == actual_count);
109         msg = sink->messages[0];
110         type = stasis_message_type(msg);
111         ast_test_validate(test, ast_endpoint_snapshot_type() == type);
112         actual_snapshot = stasis_message_data(msg);
113         ast_test_validate(test, AST_ENDPOINT_OFFLINE == actual_snapshot->state);
114
115         ast_endpoint_set_max_channels(uut, 8675309);
116         actual_count = stasis_message_sink_wait_for_count(sink, 2,
117                 STASIS_SINK_DEFAULT_WAIT);
118         ast_test_validate(test, 2 == actual_count);
119         msg = sink->messages[1];
120         type = stasis_message_type(msg);
121         ast_test_validate(test, ast_endpoint_snapshot_type() == type);
122         actual_snapshot = stasis_message_data(msg);
123         ast_test_validate(test, 8675309 == actual_snapshot->max_channels);
124
125         return AST_TEST_PASS;
126 }
127
128 AST_TEST_DEFINE(cache_clear)
129 {
130         RAII_VAR(struct ast_endpoint *, uut, NULL, ast_endpoint_shutdown);
131         RAII_VAR(struct ast_channel *, chan, NULL, ast_hangup);
132         RAII_VAR(struct stasis_message_sink *, sink, NULL, ao2_cleanup);
133         RAII_VAR(struct stasis_subscription *, sub, NULL, stasis_unsubscribe);
134         struct stasis_message *msg;
135         struct stasis_message_type *type;
136         struct ast_endpoint_snapshot *actual_snapshot;
137         struct stasis_cache_update *update;
138         int message_index;
139
140         switch (cmd) {
141         case TEST_INIT:
142                 info->name = __func__;
143                 info->category = test_category;
144                 info->summary = "Test endpoint state change messages";
145                 info->description = "Test endpoint state change messages";
146                 return AST_TEST_NOT_RUN;
147         case TEST_EXECUTE:
148                 break;
149         }
150
151         /* Subscribe to the cache topic */
152         sink = stasis_message_sink_create();
153         ast_test_validate(test, NULL != sink);
154
155         sub = stasis_subscribe(
156                 ast_endpoint_topic_all_cached(),
157                 stasis_message_sink_cb(), sink);
158         ast_test_validate(test, NULL != sub);
159
160         uut = ast_endpoint_create("TEST", __func__);
161         ast_test_validate(test, NULL != uut);
162
163         /* Since the cache topic is a singleton (ew), it may have messages from
164          * elsewheres that it's processing, or maybe even some final messages
165          * from the prior test. We've got to wait_for our specific message,
166          * instead of wait_for_count.
167          */
168         message_index = stasis_message_sink_wait_for(sink, 0,
169                 cache_update, __func__, STASIS_SINK_DEFAULT_WAIT);
170         ast_test_validate(test, 0 <= message_index);
171
172         /* First message should be a cache creation entry for our endpoint */
173         msg = sink->messages[message_index];
174         type = stasis_message_type(msg);
175         ast_test_validate(test, stasis_cache_update_type() == type);
176         update = stasis_message_data(msg);
177         ast_test_validate(test, ast_endpoint_snapshot_type() == update->type);
178         ast_test_validate(test, NULL == update->old_snapshot);
179         actual_snapshot = stasis_message_data(update->new_snapshot);
180         ast_test_validate(test, 0 == strcmp("TEST", actual_snapshot->tech));
181         ast_test_validate(test,
182                 0 == strcmp(__func__, actual_snapshot->resource));
183
184         ast_endpoint_shutdown(uut);
185         uut = NULL;
186
187         /* Note: there's a few messages between the creation and the clear.
188          * Wait for all of them... */
189         message_index = stasis_message_sink_wait_for(sink, message_index + 4,
190                 cache_update, __func__, STASIS_SINK_DEFAULT_WAIT);
191         ast_test_validate(test, 0 <= message_index);
192         /* Now we should have a cache removal entry */
193         msg = sink->messages[message_index];
194         type = stasis_message_type(msg);
195         ast_test_validate(test, stasis_cache_update_type() == type);
196         update = stasis_message_data(msg);
197         ast_test_validate(test, ast_endpoint_snapshot_type() == update->type);
198         actual_snapshot = stasis_message_data(update->old_snapshot);
199         ast_test_validate(test, 0 == strcmp("TEST", actual_snapshot->tech));
200         ast_test_validate(test,
201                 0 == strcmp(__func__, actual_snapshot->resource));
202         ast_test_validate(test, NULL == update->new_snapshot);
203
204         return AST_TEST_PASS;
205 }
206
207 AST_TEST_DEFINE(channel_messages)
208 {
209         RAII_VAR(struct ast_endpoint *, uut, NULL, ast_endpoint_shutdown);
210         RAII_VAR(struct ast_channel *, chan, NULL, ast_hangup);
211         RAII_VAR(struct stasis_message_sink *, sink, NULL, ao2_cleanup);
212         RAII_VAR(struct stasis_subscription *, sub, NULL, stasis_unsubscribe);
213         struct stasis_message *msg;
214         struct stasis_message_type *type;
215         struct ast_endpoint_snapshot *actual_snapshot;
216         int actual_count;
217
218         switch (cmd) {
219         case TEST_INIT:
220                 info->name = __func__;
221                 info->category = test_category;
222                 info->summary = "Test channel messages on an endpoint topic";
223                 info->description =
224                         "Test channel messages on an endpoint topic";
225                 return AST_TEST_NOT_RUN;
226         case TEST_EXECUTE:
227                 break;
228         }
229
230         uut = ast_endpoint_create("TEST", __func__);
231         ast_test_validate(test, NULL != uut);
232
233         sink = stasis_message_sink_create();
234         ast_test_validate(test, NULL != sink);
235
236         sub = stasis_subscribe(ast_endpoint_topic(uut),
237                 stasis_message_sink_cb(), sink);
238         ast_test_validate(test, NULL != sub);
239
240         chan = ast_channel_alloc(0, AST_STATE_DOWN, "100", __func__, "100",
241                 "100", "default", NULL, NULL, 0, "TEST/test_res");
242         ast_test_validate(test, NULL != chan);
243
244         ast_endpoint_add_channel(uut, chan);
245
246         actual_count = stasis_message_sink_wait_for_count(sink, 1,
247                 STASIS_SINK_DEFAULT_WAIT);
248         ast_test_validate(test, 1 == actual_count);
249
250         msg = sink->messages[0];
251         type = stasis_message_type(msg);
252         ast_test_validate(test, ast_endpoint_snapshot_type() == type);
253         actual_snapshot = stasis_message_data(msg);
254         ast_test_validate(test, 1 == actual_snapshot->num_channels);
255
256         ast_hangup(chan);
257         chan = NULL;
258
259         actual_count = stasis_message_sink_wait_for_count(sink, 6,
260                 STASIS_SINK_DEFAULT_WAIT);
261         ast_test_validate(test, 6 == actual_count);
262
263         msg = sink->messages[1];
264         type = stasis_message_type(msg);
265         ast_test_validate(test, stasis_cache_update_type() == type);
266
267         msg = sink->messages[2];
268         type = stasis_message_type(msg);
269         ast_test_validate(test, ast_channel_snapshot_type() == type);
270
271         msg = sink->messages[3];
272         type = stasis_message_type(msg);
273         ast_test_validate(test, stasis_cache_update_type() == type);
274
275         /* The ordering of the cache clear and endpoint snapshot are
276          * unspecified */
277         msg = sink->messages[4];
278         if (stasis_message_type(msg) == stasis_cache_clear_type()) {
279                 /* Okay; the next message should be the endpoint snapshot */
280                 msg = sink->messages[5];
281         }
282
283         type = stasis_message_type(msg);
284         ast_test_validate(test, ast_endpoint_snapshot_type() == type);
285         actual_snapshot = stasis_message_data(msg);
286         ast_test_validate(test, 0 == actual_snapshot->num_channels);
287
288         return AST_TEST_PASS;
289 }
290
291 static int unload_module(void)
292 {
293         AST_TEST_UNREGISTER(state_changes);
294         AST_TEST_UNREGISTER(cache_clear);
295         AST_TEST_UNREGISTER(channel_messages);
296         return 0;
297 }
298
299 static int load_module(void)
300 {
301         AST_TEST_REGISTER(state_changes);
302         AST_TEST_REGISTER(cache_clear);
303         AST_TEST_REGISTER(channel_messages);
304         return AST_MODULE_LOAD_SUCCESS;
305 }
306
307 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Endpoint stasis-related testing",
308         .load = load_module,
309         .unload = unload_module,
310         .nonoptreq = "res_stasis_test",
311 );