Merged revisions 278023 via svnmerge from
[asterisk/asterisk.git] / tests / test_sched.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2009, Digium, Inc.
5  *
6  * Russell Bryant <russell@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 /*! \file
20  *
21  * \brief ast_sched performance test module
22  *
23  * \author Russell Bryant <russell@digium.com>
24  */
25
26 /*** MODULEINFO
27         <depend>TEST_FRAMEWORK</depend>
28  ***/
29
30 #include "asterisk.h"
31
32 #include <inttypes.h>
33
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
35
36 #include "asterisk/module.h"
37 #include "asterisk/utils.h"
38 #include "asterisk/sched.h"
39 #include "asterisk/test.h"
40 #include "asterisk/cli.h"
41
42 static int sched_cb(const void *data)
43 {
44         return 0;
45 }
46
47 AST_TEST_DEFINE(sched_test_order)
48 {
49         struct sched_context *con;
50         enum ast_test_result_state res = AST_TEST_FAIL;
51         int id1, id2, id3, wait;
52
53         switch (cmd) {
54         case TEST_INIT:
55                 info->name = "sched_test_order";
56                 info->category = "/main/sched/";
57                 info->summary = "Test ordering of events in the scheduler API";
58                 info->description =
59                         "This test ensures that events are properly ordered by the "
60                         "time they are scheduled to execute in the scheduler API.";
61                 return AST_TEST_NOT_RUN;
62         case TEST_EXECUTE:
63                 break;
64         }
65
66         if (!(con = sched_context_create())) {
67                 ast_test_status_update(test,
68                                 "Test failed - could not create scheduler context\n");
69                 return AST_TEST_FAIL;
70         }
71
72         /* Add 3 scheduler entries, and then remove them, ensuring that the result
73          * of ast_sched_wait() looks appropriate at each step along the way. */
74
75         if ((wait = ast_sched_wait(con)) != -1) {
76                 ast_test_status_update(test,
77                                 "ast_sched_wait() should have returned -1, returned '%d'\n",
78                                 wait);
79                 goto return_cleanup;
80         }
81
82         if ((id1 = ast_sched_add(con, 100000, sched_cb, NULL)) == -1) {
83                 ast_test_status_update(test, "Failed to add scheduler entry\n");
84                 goto return_cleanup;
85         }
86
87         if ((wait = ast_sched_wait(con)) > 100000) {
88                 ast_test_status_update(test,
89                                 "ast_sched_wait() should have returned <= 100000, returned '%d'\n",
90                                 wait);
91                 goto return_cleanup;
92         }
93
94         if ((id2 = ast_sched_add(con, 10000, sched_cb, NULL)) == -1) {
95                 ast_test_status_update(test, "Failed to add scheduler entry\n");
96                 goto return_cleanup;
97         }
98
99         if ((wait = ast_sched_wait(con)) > 10000) {
100                 ast_test_status_update(test,
101                                 "ast_sched_wait() should have returned <= 10000, returned '%d'\n",
102                                 wait);
103                 goto return_cleanup;
104         }
105
106         if ((id3 = ast_sched_add(con, 1000, sched_cb, NULL)) == -1) {
107                 ast_test_status_update(test, "Failed to add scheduler entry\n");
108                 goto return_cleanup;
109         }
110
111         if ((wait = ast_sched_wait(con)) > 1000) {
112                 ast_test_status_update(test,
113                                 "ast_sched_wait() should have returned <= 1000, returned '%d'\n",
114                                 wait);
115                 goto return_cleanup;
116         }
117
118         if (ast_sched_del(con, id3) == -1) {
119                 ast_test_status_update(test, "Failed to remove scheduler entry\n");
120                 goto return_cleanup;
121         }
122
123         if ((wait = ast_sched_wait(con)) <= 1000) {
124                 ast_test_status_update(test,
125                                 "ast_sched_wait() should have returned > 1000, returned '%d'\n",
126                                 wait);
127                 goto return_cleanup;
128         }
129
130         if (ast_sched_del(con, id2) == -1) {
131                 ast_test_status_update(test, "Failed to remove scheduler entry\n");
132                 goto return_cleanup;
133         }
134
135         if ((wait = ast_sched_wait(con)) <= 10000) {
136                 ast_test_status_update(test,
137                                 "ast_sched_wait() should have returned > 10000, returned '%d'\n",
138                                 wait);
139                 goto return_cleanup;
140         }
141
142         if (ast_sched_del(con, id1) == -1) {
143                 ast_test_status_update(test, "Failed to remove scheduler entry\n");
144                 goto return_cleanup;
145         }
146
147         if ((wait = ast_sched_wait(con)) != -1) {
148                 ast_test_status_update(test,
149                                 "ast_sched_wait() should have returned -1, returned '%d'\n",
150                                 wait);
151                 goto return_cleanup;
152         }
153
154         res = AST_TEST_PASS;
155
156 return_cleanup:
157         sched_context_destroy(con);
158
159         return res;
160 }
161
162 static char *handle_cli_sched_bench(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
163 {
164         struct sched_context *con;
165         struct timeval start;
166         unsigned int num, i;
167         int *sched_ids = NULL;
168
169         switch (cmd) {
170         case CLI_INIT:
171                 e->command = "sched benchmark";
172                 e->usage = ""
173                         "Usage: sched benchmark <num>\n"
174                         "";
175                 return NULL;
176         case CLI_GENERATE:
177                 return NULL;
178         }
179
180         if (a->argc != e->args + 1) {
181                 return CLI_SHOWUSAGE;
182         }
183
184         if (sscanf(a->argv[e->args], "%u", &num) != 1) {
185                 return CLI_SHOWUSAGE;
186         }
187
188         if (!(con = sched_context_create())) {
189                 ast_cli(a->fd, "Test failed - could not create scheduler context\n");
190                 return CLI_FAILURE;
191         }
192
193         if (!(sched_ids = ast_malloc(sizeof(*sched_ids) * num))) {
194                 ast_cli(a->fd, "Test failed - memory allocation failure\n");
195                 goto return_cleanup;
196         }
197
198         ast_cli(a->fd, "Testing ast_sched_add() performance - timing how long it takes "
199                         "to add %u entries at random time intervals from 0 to 60 seconds\n", num);
200
201         start = ast_tvnow();
202
203         for (i = 0; i < num; i++) {
204                 int when = abs(ast_random()) % 60000;
205                 if ((sched_ids[i] = ast_sched_add(con, when, sched_cb, NULL)) == -1) {
206                         ast_cli(a->fd, "Test failed - sched_add returned -1\n");
207                         goto return_cleanup;
208                 }
209         }
210
211         ast_cli(a->fd, "Test complete - %" PRIi64 " us\n", ast_tvdiff_us(ast_tvnow(), start));
212
213         ast_cli(a->fd, "Testing ast_sched_del() performance - timing how long it takes "
214                         "to delete %u entries with random time intervals from 0 to 60 seconds\n", num);
215
216         start = ast_tvnow();
217
218         for (i = 0; i < num; i++) {
219                 if (ast_sched_del(con, sched_ids[i]) == -1) {
220                         ast_cli(a->fd, "Test failed - sched_del returned -1\n");
221                         goto return_cleanup;
222                 }
223         }
224
225         ast_cli(a->fd, "Test complete - %" PRIi64 " us\n", ast_tvdiff_us(ast_tvnow(), start));
226
227 return_cleanup:
228         sched_context_destroy(con);
229         if (sched_ids) {
230                 ast_free(sched_ids);
231         }
232
233         return CLI_SUCCESS;
234 }
235
236 static struct ast_cli_entry cli_sched[] = {
237         AST_CLI_DEFINE(handle_cli_sched_bench, "Benchmark ast_sched add/del performance"),
238 };
239
240 static int unload_module(void)
241 {
242         AST_TEST_UNREGISTER(sched_test_order);
243         ast_cli_unregister_multiple(cli_sched, ARRAY_LEN(cli_sched));
244         return 0;
245 }
246
247 static int load_module(void)
248 {
249         AST_TEST_REGISTER(sched_test_order);
250         ast_cli_register_multiple(cli_sched, ARRAY_LEN(cli_sched));
251         return AST_MODULE_LOAD_SUCCESS;
252 }
253
254 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "ast_sched performance test module");