Asterisk - The Open Source Telephony Project  21.4.1
test_time.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2010, Digium, Inc.
5  *
6  * Tilghman Lesher <tlesher AT digium DOT 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 Timezone tests
22  *
23  * \author\verbatim Tilghman Lesher <tlesher AT digium DOT com> \endverbatim
24  *
25  * \ingroup tests
26  */
27 
28 /*** MODULEINFO
29  <depend>TEST_FRAMEWORK</depend>
30  <support_level>core</support_level>
31  ***/
32 
33 #include "asterisk.h"
34 
35 #include "asterisk/utils.h"
36 #include "asterisk/app.h"
37 #include "asterisk/module.h"
38 #include "asterisk/test.h"
39 
40 #ifndef TZDIR
41 #ifdef SOLARIS
42 #define TZDIR "/usr/share/lib/zoneinfo"
43 #else
44 #define TZDIR "/usr/share/zoneinfo"
45 #endif /* defined SOLARIS */
46 #endif /* !defined TZDIR */
47 
48 AST_TEST_DEFINE(test_timezone_watch)
49 {
50  const char *zones[] = { "America/Chicago", "America/New_York" };
51  int type, i, res = AST_TEST_PASS;
52  struct timeval tv = ast_tvnow();
53  struct ast_tm atm[ARRAY_LEN(zones)];
54  char tmpdir[] = "/tmp/timezone.XXXXXX";
55  char tzfile[50], syscmd[256];
56 
57  switch (cmd) {
58  case TEST_INIT:
59  info->name = "timezone_watch";
60  info->category = "/main/stdtime/";
61  info->summary = "Verify deleting timezone file purges cache";
62  info->description =
63  "Verifies that the caching engine properly destroys a timezone entry when its file is deleted.";
64  return AST_TEST_NOT_RUN;
65  case TEST_EXECUTE:
66  break;
67  }
68 
69  if (!mkdtemp(tmpdir)) {
70  ast_test_status_update(test, "Unable to create working directory: %s\n", strerror(errno));
71  return AST_TEST_NOT_RUN;
72  }
73  snprintf(tzfile, sizeof(tzfile), "%s/test", tmpdir);
74 
75  for (type = 0; type <
76 #ifdef SOLARIS
77  1 /* Solaris doesn't use symlinks for timezones */
78 #else
79  2
80 #endif
81  ; type++) {
82  ast_test_status_update(test, "Executing %s test...\n", type == 0 ? "deletion" : "symlink");
83  for (i = 0; i < ARRAY_LEN(zones); i++) {
84  int system_res;
85  snprintf(syscmd, sizeof(syscmd), "%s " TZDIR "/%s %s", type == 0 ? "cp" : "ln -sf", zones[i], tzfile);
86  if ((system_res = ast_safe_system(syscmd))) {
87  ast_log(LOG_WARNING, "system(%s) returned non-zero: %d\n", syscmd, system_res);
88  }
89  ast_localtime_wakeup_monitor(test);
90  ast_test_status_update(test, "Querying timezone %s\n", tzfile);
91  ast_localtime(&tv, &atm[i], tzfile);
92  if (i != 0) {
93  if (atm[i].tm_hour == atm[i - 1].tm_hour) {
94  if (atm[i].tm_isdst == atm[i - 1].tm_isdst) {
95  res = AST_TEST_FAIL;
96  ast_test_status_update(test, "Failed %s test: %d(%s) = %d(%s)\n", type == 0 ? "deletion" : "symlink", atm[i].tm_hour, zones[i], atm[i-1].tm_hour, zones[i-1]);
97  } else {
98  ast_log(LOG_WARNING, "DST transition during %s test: %d(%s/%d) != %d(%s/%d)\n", type == 0 ? "deletion" : "symlink", atm[i].tm_hour, zones[i], atm[i].tm_isdst, atm[i-1].tm_hour, zones[i-1], atm[i-1].tm_isdst);
99  }
100  }
101  }
102 
103  if (i + 1 != ARRAY_LEN(zones)) {
104  /* stat(2) only has resolution to 1 second - must wait, or the mtime is the same */
105  usleep(1100000);
106  }
107  }
108  }
109 
110  snprintf(syscmd, sizeof(syscmd), "rm -rf %s", tmpdir);
111  if (ast_safe_system(syscmd)) {
112  ast_log(LOG_WARNING, "system(%s) returned non-zero.\n", syscmd);
113  }
114 
115  return res;
116 }
117 
118 AST_TEST_DEFINE(test_time_str_to_unit)
119 {
120  switch (cmd) {
121  case TEST_INIT:
122  info->name = "time_str_to_unit";
123  info->category = "/main/stdtime/";
124  info->summary = "Verify string to time unit conversions";
125  info->description = info->summary;
126  return AST_TEST_NOT_RUN;
127  case TEST_EXECUTE:
128  break;
129  }
130 
131  /* Nominal */
132  ast_test_validate(test, ast_time_str_to_unit("ns") == TIME_UNIT_NANOSECOND);
133  ast_test_validate(test, ast_time_str_to_unit("us") == TIME_UNIT_MICROSECOND);
134  ast_test_validate(test, ast_time_str_to_unit("ms") == TIME_UNIT_MILLISECOND);
135  ast_test_validate(test, ast_time_str_to_unit("s") == TIME_UNIT_SECOND);
136  ast_test_validate(test, ast_time_str_to_unit("m") == TIME_UNIT_MINUTE);
137  ast_test_validate(test, ast_time_str_to_unit("h") == TIME_UNIT_HOUR);
138  ast_test_validate(test, ast_time_str_to_unit("d") == TIME_UNIT_DAY);
139  ast_test_validate(test, ast_time_str_to_unit("w") == TIME_UNIT_WEEK);
140  ast_test_validate(test, ast_time_str_to_unit("mo") == TIME_UNIT_MONTH);
141  ast_test_validate(test, ast_time_str_to_unit("y") == TIME_UNIT_YEAR);
142 
143  /* Plural */
144  ast_test_validate(test, ast_time_str_to_unit("nanoseconds") == TIME_UNIT_NANOSECOND);
145  ast_test_validate(test, ast_time_str_to_unit("microseconds") == TIME_UNIT_MICROSECOND);
146  ast_test_validate(test, ast_time_str_to_unit("milliseconds") == TIME_UNIT_MILLISECOND);
147  ast_test_validate(test, ast_time_str_to_unit("seconds") == TIME_UNIT_SECOND);
148  ast_test_validate(test, ast_time_str_to_unit("minutes") == TIME_UNIT_MINUTE);
149  ast_test_validate(test, ast_time_str_to_unit("hours") == TIME_UNIT_HOUR);
150  ast_test_validate(test, ast_time_str_to_unit("days") == TIME_UNIT_DAY);
151  ast_test_validate(test, ast_time_str_to_unit("weeks") == TIME_UNIT_WEEK);
152  ast_test_validate(test, ast_time_str_to_unit("months") == TIME_UNIT_MONTH);
153  ast_test_validate(test, ast_time_str_to_unit("years") == TIME_UNIT_YEAR);
154 
155  /* Case */
156  ast_test_validate(test, ast_time_str_to_unit("Nsec") == TIME_UNIT_NANOSECOND);
157  ast_test_validate(test, ast_time_str_to_unit("Usec") == TIME_UNIT_MICROSECOND);
158  ast_test_validate(test, ast_time_str_to_unit("Msec") == TIME_UNIT_MILLISECOND);
159  ast_test_validate(test, ast_time_str_to_unit("Sec") == TIME_UNIT_SECOND);
160  ast_test_validate(test, ast_time_str_to_unit("Min") == TIME_UNIT_MINUTE);
161  ast_test_validate(test, ast_time_str_to_unit("Hr") == TIME_UNIT_HOUR);
162  ast_test_validate(test, ast_time_str_to_unit("Day") == TIME_UNIT_DAY);
163  ast_test_validate(test, ast_time_str_to_unit("Wk") == TIME_UNIT_WEEK);
164  ast_test_validate(test, ast_time_str_to_unit("Mth") == TIME_UNIT_MONTH);
165  ast_test_validate(test, ast_time_str_to_unit("Yr") == TIME_UNIT_YEAR);
166 
167  return AST_TEST_PASS;
168 }
169 
170 AST_TEST_DEFINE(test_time_create_by_unit)
171 {
172  struct timeval tv;
173 
174  switch (cmd) {
175  case TEST_INIT:
176  info->name = "time_create_by_unit";
177  info->category = "/main/stdtime/";
178  info->summary = "Verify unit value to timeval conversions";
179  info->description = info->summary;
180  return AST_TEST_NOT_RUN;
181  case TEST_EXECUTE:
182  break;
183  }
184 
185  /* Nominal */
186  ast_test_validate(test, ast_time_create_by_unit(1000, TIME_UNIT_NANOSECOND).tv_usec == 1);
187  ast_test_validate(test, ast_time_create_by_unit(1, TIME_UNIT_MICROSECOND).tv_usec == 1);
188  ast_test_validate(test, ast_time_create_by_unit(1, TIME_UNIT_MILLISECOND).tv_usec == 1000);
189  ast_test_validate(test, ast_time_create_by_unit(1, TIME_UNIT_SECOND).tv_sec == 1);
190  ast_test_validate(test, ast_time_create_by_unit(1, TIME_UNIT_MINUTE).tv_sec == 60);
191  ast_test_validate(test, ast_time_create_by_unit(1, TIME_UNIT_HOUR).tv_sec == 3600);
192  ast_test_validate(test, ast_time_create_by_unit(1, TIME_UNIT_DAY).tv_sec == 86400);
193  ast_test_validate(test, ast_time_create_by_unit(1, TIME_UNIT_WEEK).tv_sec == 604800);
194  ast_test_validate(test, ast_time_create_by_unit(1, TIME_UNIT_MONTH).tv_sec == 2629746);
195  ast_test_validate(test, ast_time_create_by_unit(1, TIME_UNIT_YEAR).tv_sec == 31556952);
196 
197  /* timeval normalization */
198  tv = ast_time_create_by_unit(1500000000, TIME_UNIT_NANOSECOND);
199  ast_test_validate(test, tv.tv_sec == 1 && tv.tv_usec == 500000);
200 
201  tv = ast_time_create_by_unit(1500000, TIME_UNIT_MICROSECOND);
202  ast_test_validate(test, tv.tv_sec == 1 && tv.tv_usec == 500000);
203 
204  tv = ast_time_create_by_unit(1500, TIME_UNIT_MILLISECOND);
205  ast_test_validate(test, tv.tv_sec == 1 && tv.tv_usec == 500000);
206 
207  return AST_TEST_PASS;
208 }
209 
210 AST_TEST_DEFINE(test_time_create_by_unit_str)
211 {
212  struct timeval tv;
213 
214  switch (cmd) {
215  case TEST_INIT:
216  info->name = "time_create_by_unit_str";
217  info->category = "/main/stdtime/";
218  info->summary = "Verify value with unit as a string to timeval conversions";
219  info->description = info->summary;
220  return AST_TEST_NOT_RUN;
221  case TEST_EXECUTE:
222  break;
223  }
224 
225  /* Nominal */
226  ast_test_validate(test, ast_time_create_by_unit_str(1000, "ns").tv_usec == 1);
227  ast_test_validate(test, ast_time_create_by_unit_str(1, "us").tv_usec == 1);
228  ast_test_validate(test, ast_time_create_by_unit_str(1, "ms").tv_usec == 1000);
229  ast_test_validate(test, ast_time_create_by_unit_str(1, "s").tv_sec == 1);
230  ast_test_validate(test, ast_time_create_by_unit_str(1, "m").tv_sec == 60);
231  ast_test_validate(test, ast_time_create_by_unit_str(1, "h").tv_sec == 3600);
232  ast_test_validate(test, ast_time_create_by_unit_str(1, "d").tv_sec == 86400);
233  ast_test_validate(test, ast_time_create_by_unit_str(1, "w").tv_sec == 604800);
234  ast_test_validate(test, ast_time_create_by_unit_str(1, "mo").tv_sec == 2629746);
235  ast_test_validate(test, ast_time_create_by_unit_str(1, "yr").tv_sec == 31556952);
236 
237  /* timeval normalization */
238  tv = ast_time_create_by_unit_str(1500000000, "ns");
239  ast_test_validate(test, tv.tv_sec == 1 && tv.tv_usec == 500000);
240 
241  tv = ast_time_create_by_unit_str(1500000, "us");
242  ast_test_validate(test, tv.tv_sec == 1 && tv.tv_usec == 500000);
243 
244  tv = ast_time_create_by_unit_str(1500, "ms");
245  ast_test_validate(test, tv.tv_sec == 1 && tv.tv_usec == 500000);
246 
247  return AST_TEST_PASS;
248 }
249 
250 AST_TEST_DEFINE(test_time_tv_to_usec)
251 {
252  struct timeval tv;
253 
254  switch (cmd) {
255  case TEST_INIT:
256  info->name = "time_tv_to_usec";
257  info->category = "/main/stdtime/";
258  info->summary = "Verify conversion of a timeval structure to microseconds";
259  info->description = info->summary;
260  return AST_TEST_NOT_RUN;
261  case TEST_EXECUTE:
262  break;
263  }
264 
265  tv = ast_time_create(0, 0);
266  ast_test_validate(test, ast_time_tv_to_usec(&tv) == 0);
267 
268  tv = ast_time_create(0, 1);
269  ast_test_validate(test, ast_time_tv_to_usec(&tv) == 1);
270 
271  tv = ast_time_create(1, 0);
272  ast_test_validate(test, ast_time_tv_to_usec(&tv) == 1000000);
273 
274  tv = ast_time_create(1, 1);
275  ast_test_validate(test, ast_time_tv_to_usec(&tv) == 1000001);
276 
277  return AST_TEST_PASS;
278 }
279 
280 static int unload_module(void)
281 {
282  AST_TEST_UNREGISTER(test_time_create_by_unit_str);
283  AST_TEST_UNREGISTER(test_time_create_by_unit);
284  AST_TEST_UNREGISTER(test_time_str_to_unit);
285  AST_TEST_UNREGISTER(test_time_tv_to_usec);
286  AST_TEST_UNREGISTER(test_timezone_watch);
287  return 0;
288 }
289 
290 static int load_module(void)
291 {
292  AST_TEST_REGISTER(test_timezone_watch);
293  AST_TEST_REGISTER(test_time_tv_to_usec);
294  AST_TEST_REGISTER(test_time_str_to_unit);
295  AST_TEST_REGISTER(test_time_create_by_unit);
296  AST_TEST_REGISTER(test_time_create_by_unit_str);
298 }
299 
300 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Time Tests");
Asterisk main include file. File version handling, generic pbx functions.
ast_suseconds_t ast_time_tv_to_usec(const struct timeval *tv)
Convert a timeval structure to microseconds.
Definition: time.c:90
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
struct timeval ast_time_create_by_unit_str(unsigned long val, const char *unit)
Convert the given unit value, and create a timeval object from it.
Definition: time.c:143
Test Framework API.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
Utility functions.
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
struct timeval ast_time_create(ast_time_t sec, ast_suseconds_t usec)
Create a timeval object initialized to given values.
Definition: time.c:95
int tm_hour
Definition: localtime.h:38
enum TIME_UNIT ast_time_str_to_unit(const char *unit)
Convert a string to a time unit enumeration value.
Definition: time.c:66
int tm_isdst
Definition: localtime.h:44
#define AST_TEST_DEFINE(hdr)
Definition: test.h:126
struct timeval ast_time_create_by_unit(unsigned long val, enum TIME_UNIT unit)
Convert the given unit value, and create a timeval object from it.
Definition: time.c:113
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...