test_astobj2_weaken: Fix source file registration.
[asterisk/asterisk.git] / tests / test_astobj2_weaken.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2015, CFWare, LLC
5  *
6  * Corey Farrell <git@cfware.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 astobj2 weakproxy test module
22  *
23  * \author Corey Farrell <git@cfware.com>
24  */
25
26 /*** MODULEINFO
27         <depend>TEST_FRAMEWORK</depend>
28         <support_level>core</support_level>
29  ***/
30
31 #include "asterisk.h"
32
33 ASTERISK_REGISTER_FILE()
34
35 #include "asterisk/utils.h"
36 #include "asterisk/module.h"
37 #include "asterisk/test.h"
38 #include "asterisk/astobj2.h"
39
40 static int destructor_called;
41 static int weakproxydestroyed;
42
43 static void test_obj_destructor(void *obj)
44 {
45         destructor_called++;
46 }
47
48 static void weakproxy_destructor(void *obj)
49 {
50         weakproxydestroyed++;
51 }
52
53 static void test_obj_destroy_notify(void *obj, void *data)
54 {
55         int *i = data;
56
57         ++*i;
58 }
59
60 struct my_weakproxy {
61         AO2_WEAKPROXY();
62         int f1;
63 };
64
65 AST_TEST_DEFINE(astobj2_weak1)
66 {
67         void *obj1 = NULL;
68         void *obj2 = NULL;
69         void *obj3 = NULL;
70         void *strong1 = NULL;
71         struct my_weakproxy *weakref1 = NULL;
72         struct my_weakproxy *weakref2 = NULL;
73         int notify0_called = 0;
74         int notify1_called = 0;
75         int notify2_called = 0;
76         int notify3_called = 0;
77
78         switch (cmd) {
79         case TEST_INIT:
80                 info->name = "astobj2_weak1";
81                 info->category = "/main/astobj2/";
82                 info->summary = "Test ao2 weak objects";
83                 info->description = "Test ao2 weak objects.";
84                 return AST_TEST_NOT_RUN;
85         case TEST_EXECUTE:
86                 break;
87         }
88
89         destructor_called = weakproxydestroyed = 0;
90         obj1 = ao2_t_alloc(0, test_obj_destructor, "obj1");
91         if (!obj1) {
92                 return AST_TEST_FAIL;
93         }
94
95         weakref1 = ao2_t_weakproxy_alloc(sizeof(*weakref1), weakproxy_destructor, "weakref1");
96         if (!weakref1) {
97                 ast_test_status_update(test, "Failed to allocate weakref1.\n");
98                 goto fail_cleanup;
99         }
100         weakref1->f1 = 5315;
101
102         if (ao2_weakproxy_subscribe(weakref1, test_obj_destroy_notify, &notify0_called, 0)) {
103                 ast_test_status_update(test, "Failed to subscribe to weakref1.\n");
104                 goto fail_cleanup;
105         }
106         if (!notify0_called) {
107                 ast_test_status_update(test, "Subscribe failed to immediately run callback for empty weakproxy.\n");
108                 goto fail_cleanup;
109         }
110
111         if (ao2_t_weakproxy_set_object(weakref1, obj1, 0, "set weakref1 to obj1")) {
112                 ast_test_status_update(test, "Failed to set obj1 on weakref1.\n");
113                 goto fail_cleanup;
114         }
115
116         if (ao2_weakproxy_subscribe(weakref1, test_obj_destroy_notify, &notify1_called, 0)) {
117                 ast_test_status_update(test, "Failed to add a subscription to weakref1.\n");
118                 goto fail_cleanup;
119         }
120
121         weakref2 = ao2_t_get_weakproxy(obj1, "get weakref2 from obj1");
122         if (weakref1 != weakref2) {
123                 ast_test_status_update(test, "weakref1 != weakref2.\n");
124                 goto fail_cleanup;
125         }
126
127         if (ao2_weakproxy_subscribe(weakref2, test_obj_destroy_notify, &notify2_called, 0)) {
128                 ast_test_status_update(test, "Failed to add a subscription to weakref2.\n");
129                 goto fail_cleanup;
130         }
131
132         if (ao2_weakproxy_subscribe(weakref2, test_obj_destroy_notify, &notify2_called, 0)) {
133                 ast_test_status_update(test, "Failed to add a duplicate subscription to weakref2.\n");
134                 goto fail_cleanup;
135         }
136
137         if (ao2_weakproxy_subscribe(weakref2, test_obj_destroy_notify, &notify2_called, 0)) {
138                 ast_test_status_update(test, "Failed to add a second duplicate subscription to weakref2.\n");
139                 goto fail_cleanup;
140         }
141
142         if (ao2_weakproxy_unsubscribe(weakref2, test_obj_destroy_notify, &notify2_called, 0) != 1) {
143                 ast_test_status_update(test, "Failed to remove a subscription to weakref2.\n");
144                 goto fail_cleanup;
145         }
146
147         ao2_t_cleanup(weakref1, "weakref1");
148         ao2_t_cleanup(weakref2, "weakref2");
149
150         weakref2 = ao2_t_get_weakproxy(obj1, "get weakref2 from obj1");
151         if (weakref1 != weakref2) {
152                 weakref1 = NULL;
153                 ast_test_status_update(test, "weakref1 != weakref2.\n");
154                 goto fail_cleanup;
155         }
156         weakref1 = NULL;
157
158         obj2 = ao2_t_alloc(0, NULL, "obj2");
159         if (obj2) {
160                 int ret = ao2_t_weakproxy_set_object(weakref2, obj2, 0, "set weakref2 to obj2");
161
162                 ao2_ref(obj2, -1);
163                 if (!ret) {
164                         ast_test_status_update(test, "Set obj2 to weakref2 when it already had an object.\n");
165                         goto fail_cleanup;
166                 }
167         }
168
169         if (ao2_weakproxy_subscribe(weakref2, test_obj_destroy_notify, &notify3_called, 0)) {
170                 ast_test_status_update(test, "Failed to add a subscription to weakref2.\n");
171                 goto fail_cleanup;
172         }
173
174         if (ao2_weakproxy_subscribe(weakref2, test_obj_destroy_notify, &notify3_called, 0)) {
175                 ast_test_status_update(test, "Failed to add a duplicate subscription to weakref2.\n");
176                 goto fail_cleanup;
177         }
178
179         if (ao2_weakproxy_unsubscribe(weakref2, test_obj_destroy_notify, &notify3_called, OBJ_MULTIPLE) != 2) {
180                 ast_test_status_update(test, "Failed to remove the correct number of subscriptions to weakref2.\n");
181                 goto fail_cleanup;
182         }
183
184         if (destructor_called || notify1_called || notify2_called || notify3_called) {
185                 ast_test_status_update(test, "Destructor or notifications called early.\n");
186                 goto fail_cleanup;
187         }
188
189         strong1 = ao2_t_weakproxy_get_object(weakref2, 0, "get strong1 from weakref2");
190         ao2_t_cleanup(strong1, "strong1");
191
192         if (obj1 != strong1) {
193                 ast_test_status_update(test, "obj1 != strong1.\n");
194                 goto fail_cleanup;
195         }
196
197         if (destructor_called || notify1_called || notify2_called || notify3_called) {
198                 ast_test_status_update(test, "Destructor or notification called early.\n");
199                 goto fail_cleanup;
200         }
201
202         ao2_t_ref(obj1, -1, "obj1");
203         obj1 = NULL;
204
205         if (destructor_called != 1 || notify1_called != 1 || notify2_called != 2 || notify3_called != 0) {
206                 ast_test_status_update(test, "Destructor or notification not called the expected number of times.\n");
207                 goto fail_cleanup;
208         }
209
210         if (ao2_t_weakproxy_get_object(weakref2, 0, "impossible get of weakref2") != NULL) {
211                 ast_test_status_update(test, "Get object on weakref2 worked when it shouldn't\n");
212                 goto fail_cleanup;
213         }
214
215         obj3 = ao2_t_alloc(0, test_obj_destructor, "obj3");
216         if (!obj3) {
217                 ast_test_status_update(test, "Failed to allocate obj3.\n");
218                 goto fail_cleanup;
219         }
220
221         if (ao2_t_weakproxy_set_object(weakref2, obj3, 0, "set weakref2 to obj3")) {
222                 ast_test_status_update(test, "Failed to set obj3 to weakref2.\n");
223                 goto fail_cleanup;
224         }
225
226         ao2_ref(obj3, -1);
227         ao2_t_ref(weakref2, -1, "weakref2");
228
229         if (!weakproxydestroyed) {
230                 ast_test_status_update(test, "Destructor never called for weakproxy, likely a leak.\n");
231                 return AST_TEST_FAIL;
232         }
233
234         return AST_TEST_PASS;
235
236 fail_cleanup:
237         ao2_cleanup(obj1);
238         ao2_cleanup(obj3);
239         ao2_cleanup(weakref1);
240         ao2_cleanup(weakref2);
241
242         return AST_TEST_FAIL;
243 }
244
245 static int unload_module(void)
246 {
247         AST_TEST_UNREGISTER(astobj2_weak1);
248
249         return 0;
250 }
251
252 static int load_module(void)
253 {
254         AST_TEST_REGISTER(astobj2_weak1);
255
256         return AST_MODULE_LOAD_SUCCESS;
257 }
258
259 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "ASTOBJ2 Weak Reference Unit Tests");