Stasis: Update unittest for channel snapshots
[asterisk/asterisk.git] / tests / test_stasis_channels.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Matt Jordan <mjordan@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 \brief Test Stasis Channel messages and objects
21  *
22  * \author\verbatim Matt Jordan <mjordan@digium.com> \endverbatim
23  *
24  * \ingroup tests
25  */
26
27 /*** MODULEINFO
28         <depend>TEST_FRAMEWORK</depend>
29         <support_level>core</support_level>
30  ***/
31
32 #include "asterisk.h"
33
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
35
36 #include "asterisk/astobj2.h"
37 #include "asterisk/module.h"
38 #include "asterisk/stasis.h"
39 #include "asterisk/stasis_message_router.h"
40 #include "asterisk/test.h"
41 #include "asterisk/stasis_channels.h"
42 #include "asterisk/channel.h"
43
44 static const char *test_category = "/stasis/channels/";
45
46 static void safe_channel_release(struct ast_channel *chan)
47 {
48         if (!chan) {
49                 return;
50         }
51         ast_channel_release(chan);
52 }
53
54 AST_TEST_DEFINE(channel_blob_create)
55 {
56         struct ast_channel_blob *blob;
57         RAII_VAR(struct stasis_message_type *, type, NULL, ao2_cleanup);
58         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
59         RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
60         RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
61         RAII_VAR(struct ast_json *, bad_json, NULL, ast_json_unref);
62
63         switch (cmd) {
64         case TEST_INIT:
65                 info->name = __func__;
66                 info->category = test_category;
67                 info->summary = "Test creation of ast_channel_blob objects";
68                 info->description = "Test creation of ast_channel_blob objects";
69                 return AST_TEST_NOT_RUN;
70         case TEST_EXECUTE:
71                 break;
72         }
73
74         ast_test_validate(test, stasis_message_type_create("test-type", NULL, &type) == STASIS_MESSAGE_TYPE_SUCCESS);
75         chan = ast_channel_alloc(0, AST_STATE_DOWN, "100", "Alice", "100", "100", "default", NULL, NULL, 0, "TEST/Alice");
76         ast_channel_unlock(chan);
77         json = ast_json_pack("{s: s}",
78                      "foo", "bar");
79
80         /* Off nominal creation */
81         ast_channel_lock(chan);
82         ast_test_validate(test, NULL == ast_channel_blob_create(chan, NULL, json));
83
84         /* Test for single channel */
85         msg = ast_channel_blob_create(chan, type, json);
86         ast_channel_unlock(chan);
87         ast_test_validate(test, NULL != msg);
88         blob = stasis_message_data(msg);
89         ast_test_validate(test, NULL != blob);
90         ast_test_validate(test, NULL != blob->snapshot);
91         ast_test_validate(test, NULL != blob->blob);
92         ast_test_validate(test, type == stasis_message_type(msg));
93
94         ast_test_validate(test, 1 == ao2_ref(msg, 0));
95         ao2_cleanup(msg);
96
97         /* Test for global channels */
98         msg = ast_channel_blob_create(NULL, type, json);
99         ast_test_validate(test, NULL != msg);
100         blob = stasis_message_data(msg);
101         ast_test_validate(test, NULL != blob);
102         ast_test_validate(test, NULL == blob->snapshot);
103         ast_test_validate(test, NULL != blob->blob);
104         ast_test_validate(test, type == stasis_message_type(msg));
105
106         return AST_TEST_PASS;
107 }
108
109 AST_TEST_DEFINE(null_blob)
110 {
111         struct ast_channel_blob *blob;
112         RAII_VAR(struct stasis_message_type *, type, NULL, ao2_cleanup);
113         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
114         RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
115         RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
116         RAII_VAR(struct ast_json *, bad_json, NULL, ast_json_unref);
117
118         switch (cmd) {
119         case TEST_INIT:
120                 info->name = __func__;
121                 info->category = test_category;
122                 info->summary = "Test creation of ast_channel_blob objects";
123                 info->description = "Test creation of ast_channel_blob objects";
124                 return AST_TEST_NOT_RUN;
125         case TEST_EXECUTE:
126                 break;
127         }
128
129         ast_test_validate(test, stasis_message_type_create("test-type", NULL, &type) == STASIS_MESSAGE_TYPE_SUCCESS);
130         chan = ast_channel_alloc(0, AST_STATE_DOWN, "100", "Alice", "100", "100", "default", NULL, NULL, 0, "TEST/Alice");
131         ast_channel_unlock(chan);
132         json = ast_json_pack("{s: s}",
133                      "foo", "bar");
134
135         /* Test for single channel */
136         ast_channel_lock(chan);
137         msg = ast_channel_blob_create(chan, type, NULL);
138         ast_channel_unlock(chan);
139         ast_test_validate(test, NULL != msg);
140         blob = stasis_message_data(msg);
141         ast_test_validate(test, NULL != blob);
142         ast_test_validate(test, NULL != blob->snapshot);
143         ast_test_validate(test, ast_json_null() == blob->blob);
144         ast_test_validate(test, type == stasis_message_type(msg));
145
146         return AST_TEST_PASS;
147 }
148
149 AST_TEST_DEFINE(multi_channel_blob_create)
150 {
151         RAII_VAR(struct ast_multi_channel_blob *, blob, NULL, ao2_cleanup);
152         RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
153         RAII_VAR(struct ast_json *, bad_json, NULL, ast_json_unref);
154
155         switch (cmd) {
156         case TEST_INIT:
157                 info->name = __func__;
158                 info->category = test_category;
159                 info->summary = "Test creation of ast_multi_channel_blob objects";
160                 info->description = "Test creation of ast_multi_channel_blob objects";
161                 return AST_TEST_NOT_RUN;
162         case TEST_EXECUTE:
163                 break;
164         }
165
166         json = ast_json_pack("{s: s}",
167                      "foo", "bar");
168
169         /* Test for single channel */
170         blob = ast_multi_channel_blob_create(json);
171         ast_test_validate(test, NULL != blob);
172         ast_test_validate(test, NULL != ast_multi_channel_blob_get_json(blob));
173
174         return AST_TEST_PASS;
175 }
176
177 AST_TEST_DEFINE(multi_channel_blob_snapshots)
178 {
179         RAII_VAR(struct ast_multi_channel_blob *, blob, NULL, ao2_cleanup);
180         RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
181         RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
182         RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
183         RAII_VAR(struct ast_channel *, chan_charlie, NULL, safe_channel_release);
184         struct ast_channel_snapshot *snapshot;
185         struct ao2_container *matches;
186
187         switch (cmd) {
188         case TEST_INIT:
189                 info->name = __func__;
190                 info->category = test_category;
191                 info->summary = "Test creation of ast_multi_channel_blob objects";
192                 info->description = "Test creation of ast_multi_channel_blob objects";
193                 return AST_TEST_NOT_RUN;
194         case TEST_EXECUTE:
195                 break;
196         }
197
198         json = ast_json_pack("{s: s}",
199                      "type", "test");
200         chan_alice = ast_channel_alloc(0, AST_STATE_DOWN, "100", "Alice", "100", "100", "default", NULL, NULL, 0, "TEST/Alice");
201         ast_channel_unlock(chan_alice);
202         chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, "200", "Bob", "200", "200", "default", NULL, NULL, 0, "TEST/Bob");
203         ast_channel_unlock(chan_bob);
204         chan_charlie = ast_channel_alloc(0, AST_STATE_DOWN, "300", "Bob", "300", "300", "default", NULL, NULL, 0, "TEST/Charlie");
205         ast_channel_unlock(chan_charlie);
206
207         blob = ast_multi_channel_blob_create(json);
208         ast_channel_lock(chan_alice);
209         ast_multi_channel_blob_add_channel(blob, "Caller", ast_channel_snapshot_create(chan_alice));
210         ast_channel_unlock(chan_alice);
211         ast_channel_lock(chan_bob);
212         ast_multi_channel_blob_add_channel(blob, "Peer", ast_channel_snapshot_create(chan_bob));
213         ast_channel_unlock(chan_bob);
214         ast_channel_lock(chan_charlie);
215         ast_multi_channel_blob_add_channel(blob, "Peer", ast_channel_snapshot_create(chan_charlie));
216         ast_channel_unlock(chan_charlie);
217
218         /* Test for unknown role */
219         ast_test_validate(test, NULL == ast_multi_channel_blob_get_channel(blob, "Foobar"));
220
221         /* Test for single match */
222         snapshot = ast_multi_channel_blob_get_channel(blob, "Caller");
223         ast_test_validate(test, NULL != snapshot);
224         ast_test_validate(test, 0 == strcmp("TEST/Alice", snapshot->name));
225
226         /* Test for single match, multiple possibilities */
227         snapshot = ast_multi_channel_blob_get_channel(blob, "Peer");
228         ast_test_validate(test, NULL != snapshot);
229         ast_test_validate(test, 0 != strcmp("TEST/Alice", snapshot->name));
230
231         /* Multi-match */
232         matches = ast_multi_channel_blob_get_channels(blob, "Peer");
233         ast_test_validate(test, NULL != matches);
234         ast_test_validate(test, 2 == ao2_container_count(matches));
235         snapshot = ao2_find(matches, "TEST/Bob", OBJ_KEY);
236         ast_test_validate(test, NULL != snapshot);
237         ao2_cleanup(snapshot);
238         snapshot = ao2_find(matches, "TEST/Charlie", OBJ_KEY);
239         ast_test_validate(test, NULL != snapshot);
240         ao2_cleanup(snapshot);
241         ast_test_validate(test, 1 == ao2_ref(matches, 0));
242         ao2_cleanup(matches);
243
244         return AST_TEST_PASS;
245 }
246
247 AST_TEST_DEFINE(channel_snapshot_json)
248 {
249         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
250         RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
251         RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
252         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
253         RAII_VAR(struct ast_json *, actual, NULL, ast_json_unref);
254
255         switch (cmd) {
256         case TEST_INIT:
257                 info->name = __func__;
258                 info->category = test_category;
259                 info->summary = "Test creation of ast_channel_blob objects";
260                 info->description = "Test creation of ast_channel_blob objects";
261                 return AST_TEST_NOT_RUN;
262         case TEST_EXECUTE:
263                 break;
264         }
265
266         ast_test_validate(test, NULL == ast_channel_snapshot_to_json(NULL, NULL));
267
268         chan = ast_channel_alloc(0, AST_STATE_DOWN, "cid_num", "cid_name", "acctcode", "exten", "context", NULL, NULL, 0, "TEST/name");
269         ast_channel_unlock(chan);
270         ast_test_validate(test, NULL != chan);
271         ast_channel_lock(chan);
272         snapshot = ast_channel_snapshot_create(chan);
273         ast_channel_unlock(chan);
274         ast_test_validate(test, NULL != snapshot);
275
276         actual = ast_channel_snapshot_to_json(snapshot, NULL);
277         expected = ast_json_pack("{ s: s, s: s, s: s, s: s,"
278                                  "  s: { s: s, s: s, s: i },"
279                                  "  s: { s: s, s: s },"
280                                  "  s: { s: s, s: s },"
281                                  "  s: s"
282                                  "  s: o"
283                                  "}",
284                                  "name", "TEST/name",
285                                  "state", "Down",
286                                  "accountcode", "acctcode",
287                                  "id", ast_channel_uniqueid(chan),
288                                  "dialplan",
289                                  "context", "context",
290                                  "exten", "exten",
291                                  "priority", 1,
292                                  "caller",
293                                  "name", "cid_name",
294                                  "number", "cid_num",
295                                  "connected",
296                                  "name", "",
297                                  "number", "",
298                                  "language", "en",
299                                  "creationtime",
300                                  ast_json_timeval(
301                                          ast_channel_creationtime(chan), NULL));
302
303         ast_test_validate(test, ast_json_equal(expected, actual));
304
305         return AST_TEST_PASS;
306 }
307
308 static int unload_module(void)
309 {
310         AST_TEST_UNREGISTER(channel_blob_create);
311         AST_TEST_UNREGISTER(null_blob);
312         AST_TEST_UNREGISTER(multi_channel_blob_create);
313         AST_TEST_UNREGISTER(multi_channel_blob_snapshots);
314         AST_TEST_UNREGISTER(channel_snapshot_json);
315
316         return 0;
317 }
318
319 static int load_module(void)
320 {
321         AST_TEST_REGISTER(channel_blob_create);
322         AST_TEST_REGISTER(null_blob);
323         AST_TEST_REGISTER(multi_channel_blob_create);
324         AST_TEST_REGISTER(multi_channel_blob_snapshots);
325         AST_TEST_REGISTER(channel_snapshot_json);
326
327         return AST_MODULE_LOAD_SUCCESS;
328 }
329
330 AST_MODULE_INFO(ASTERISK_GPL_KEY, 0, "Stasis Channel Testing",
331                 .load = load_module,
332                 .unload = unload_module
333         );