afbb7594915012b9214b4a1ce5e6273bb1f89ad4
[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         <defaultenabled>no</defaultenabled>
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/cli.h"
38 #include "asterisk/utils.h"
39 #include "asterisk/sched.h"
40
41 static int sched_cb(const void *data)
42 {
43         return 0;
44 }
45
46 static char *handle_cli_sched_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
47 {
48         struct sched_context *con;
49         char *res = CLI_FAILURE;
50         int id1, id2, id3, wait;
51
52         switch (cmd) {
53         case CLI_INIT:
54                 e->command = "sched test";
55                 e->usage = ""
56                         "Usage: sched test\n"
57                         "   Test scheduler entry ordering.\n"
58                         "";
59                 return NULL;
60         case CLI_GENERATE:
61                 return NULL;
62         }
63
64         if (a->argc != e->args) {
65                 return CLI_SHOWUSAGE;
66         }
67
68         ast_cli(a->fd, "Testing scheduler entry ordering ...\n");
69
70         if (!(con = sched_context_create())) {
71                 ast_cli(a->fd, "Test failed - could not create scheduler context\n");
72                 return CLI_FAILURE;
73         }
74
75         /* Add 3 scheduler entries, and then remove them, ensuring that the result
76          * of ast_sched_wait() looks appropriate at each step along the way. */
77
78         if ((wait = ast_sched_wait(con)) != -1) {
79                 ast_cli(a->fd, "ast_sched_wait() should have returned -1, returned '%d'\n",
80                                 wait);
81                 goto return_cleanup;
82         }
83
84         if ((id1 = ast_sched_add(con, 100000, sched_cb, NULL)) == -1) {
85                 ast_cli(a->fd, "Failed to add scheduler entry\n");
86                 goto return_cleanup;
87         }
88
89         if ((wait = ast_sched_wait(con)) > 100000) {
90                 ast_cli(a->fd, "ast_sched_wait() should have returned <= 100000, returned '%d'\n",
91                                 wait);
92                 goto return_cleanup;
93         }
94
95         if ((id2 = ast_sched_add(con, 10000, sched_cb, NULL)) == -1) {
96                 ast_cli(a->fd, "Failed to add scheduler entry\n");
97                 goto return_cleanup;
98         }
99
100         if ((wait = ast_sched_wait(con)) > 10000) {
101                 ast_cli(a->fd, "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_cli(a->fd, "Failed to add scheduler entry\n");
108                 goto return_cleanup;
109         }
110
111         if ((wait = ast_sched_wait(con)) > 1000) {
112                 ast_cli(a->fd, "ast_sched_wait() should have returned <= 1000, returned '%d'\n",
113                                 wait);
114                 goto return_cleanup;
115         }
116
117         if (ast_sched_del(con, id3) == -1) {
118                 ast_cli(a->fd, "Failed to remove scheduler entry\n");
119                 goto return_cleanup;
120         }
121
122         if ((wait = ast_sched_wait(con)) <= 1000) {
123                 ast_cli(a->fd, "ast_sched_wait() should have returned > 1000, returned '%d'\n",
124                                 wait);
125                 goto return_cleanup;
126         }
127
128         if (ast_sched_del(con, id2) == -1) {
129                 ast_cli(a->fd, "Failed to remove scheduler entry\n");
130                 goto return_cleanup;
131         }
132
133         if ((wait = ast_sched_wait(con)) <= 10000) {
134                 ast_cli(a->fd, "ast_sched_wait() should have returned > 10000, returned '%d'\n",
135                                 wait);
136                 goto return_cleanup;
137         }
138
139         if (ast_sched_del(con, id1) == -1) {
140                 ast_cli(a->fd, "Failed to remove scheduler entry\n");
141                 goto return_cleanup;
142         }
143
144         if ((wait = ast_sched_wait(con)) != -1) {
145                 ast_cli(a->fd, "ast_sched_wait() should have returned -1, returned '%d'\n",
146                                 wait);
147                 goto return_cleanup;
148         }
149
150         res = CLI_SUCCESS;
151
152         ast_cli(a->fd, "Test passed!\n");
153
154 return_cleanup:
155         sched_context_destroy(con);
156
157         return res;
158 }
159
160 static char *handle_cli_sched_bench(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
161 {
162         struct sched_context *con;
163         struct timeval start;
164         unsigned int num, i;
165         int *sched_ids = NULL;
166
167         switch (cmd) {
168         case CLI_INIT:
169                 e->command = "sched benchmark";
170                 e->usage = ""
171                         "Usage: sched test <num>\n"
172                         "";
173                 return NULL;
174         case CLI_GENERATE:
175                 return NULL;
176         }
177
178         if (a->argc != e->args + 1) {
179                 return CLI_SHOWUSAGE;
180         }
181
182         if (sscanf(a->argv[e->args], "%u", &num) != 1) {
183                 return CLI_SHOWUSAGE;
184         }
185
186         if (!(con = sched_context_create())) {
187                 ast_cli(a->fd, "Test failed - could not create scheduler context\n");
188                 return CLI_FAILURE;
189         }
190
191         if (!(sched_ids = ast_malloc(sizeof(*sched_ids) * num))) {
192                 ast_cli(a->fd, "Test failed - memory allocation failure\n");
193                 goto return_cleanup;
194         }
195
196         ast_cli(a->fd, "Testing ast_sched_add() performance - timing how long it takes "
197                         "to add %u entries at random time intervals from 0 to 60 seconds\n", num);
198
199         start = ast_tvnow();
200
201         for (i = 0; i < num; i++) {
202                 int when = abs(ast_random()) % 60000;
203                 if ((sched_ids[i] = ast_sched_add(con, when, sched_cb, NULL)) == -1) {
204                         ast_cli(a->fd, "Test failed - sched_add returned -1\n");
205                         goto return_cleanup;
206                 }
207         }
208
209         ast_cli(a->fd, "Test complete - %" PRIi64 " us\n", ast_tvdiff_us(ast_tvnow(), start));
210
211         ast_cli(a->fd, "Testing ast_sched_del() performance - timing how long it takes "
212                         "to delete %u entries with random time intervals from 0 to 60 seconds\n", num);
213
214         start = ast_tvnow();
215
216         for (i = 0; i < num; i++) {
217                 if (ast_sched_del(con, sched_ids[i]) == -1) {
218                         ast_cli(a->fd, "Test failed - sched_del returned -1\n");
219                         goto return_cleanup;
220                 }
221         }
222
223         ast_cli(a->fd, "Test complete - %" PRIi64 " us\n", ast_tvdiff_us(ast_tvnow(), start));
224
225 return_cleanup:
226         sched_context_destroy(con);
227         if (sched_ids) {
228                 ast_free(sched_ids);
229         }
230
231         return CLI_SUCCESS;
232 }
233
234 static struct ast_cli_entry cli_sched[] = {
235         AST_CLI_DEFINE(handle_cli_sched_bench, "Benchmark ast_sched add/del performance"),
236         AST_CLI_DEFINE(handle_cli_sched_test, "Test scheduler entry ordering"),
237 };
238
239 static int unload_module(void)
240 {
241         ast_cli_unregister_multiple(cli_sched, ARRAY_LEN(cli_sched));
242         return 0;
243 }
244
245 static int load_module(void)
246 {
247         ast_cli_register_multiple(cli_sched, ARRAY_LEN(cli_sched));
248         return AST_MODULE_LOAD_SUCCESS;
249 }
250
251 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "ast_sched performance test module");