Asterisk - The Open Source Telephony Project GIT-master-b023714
Loading...
Searching...
No Matches
Macros | Functions | Variables
test_locale.c File Reference

Locale Test. More...

#include "asterisk.h"
#include <sys/types.h>
#include <dirent.h>
#include <locale.h>
#include "asterisk/cli.h"
#include "asterisk/linkedlists.h"
#include "asterisk/localtime.h"
#include "asterisk/utils.h"
#include "asterisk/module.h"
Include dependency graph for test_locale.c:

Go to the source code of this file.

Macros

#define __USE_GNU   1
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static char * handle_cli_test_locales (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int load_module (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Locale tests" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_cli_entry cli_locales []
 

Detailed Description

Locale Test.

Author
Tilghman Lesher <tlesher AT digium DOT com> 

Definition in file test_locale.c.

Macro Definition Documentation

◆ __USE_GNU

#define __USE_GNU   1

Definition at line 38 of file test_locale.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 186 of file test_locale.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 186 of file test_locale.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 186 of file test_locale.c.

◆ handle_cli_test_locales()

static char * handle_cli_test_locales ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 49 of file test_locale.c.

50{
51 DIR *localedir;
52 struct dirent *dent;
53 struct ast_tm atm;
54 struct timeval tv;
55 const char *orig_locale;
56 char origlocalformat[200] = "", localformat[200] = "";
57 struct test_locales {
58 AST_LIST_ENTRY(test_locales) list;
59 char *localformat;
60 char name[0];
61 } *tl = NULL;
62 AST_LIST_HEAD_NOLOCK(locales, test_locales) locales;
63 int varies = 0, all_successful = 1, count = 0, count_fail = 0;
64
65 switch (cmd) {
66 case CLI_INIT:
67 e->command = "test locale";
68 e->usage = ""
69 "Usage: test locale\n"
70 " Test thread safety of locale functions.\n";
71 return NULL;
72 case CLI_GENERATE:
73 return NULL;
74 }
75
76 if (a->argc != e->args) {
77 return CLI_SHOWUSAGE;
78 }
79
80 /* First we run a set of tests with the global locale, which isn't thread-safe. */
81 if (!(localedir = opendir(
82#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
83 "/usr/share/locale"
84#else /* Linux */
85 "/usr/lib/locale"
86#endif
87 ))) {
88 ast_cli(a->fd, "No locales seem to exist on this platform.\n");
89 return CLI_SUCCESS;
90 }
91
92 tv = ast_tvnow();
93 ast_localtime(&tv, &atm, NULL);
94 orig_locale = setlocale(LC_ALL, NULL);
96
97 /* Get something different, to compare against. */
98 ast_strftime(origlocalformat, sizeof(origlocalformat), "%c", &atm);
99
100 while ((dent = readdir(localedir))) {
101 size_t locallen;
102 size_t namelen;
103
104 if (dent->d_name[0] == '.') {
105 continue;
106 }
107
108 setlocale(LC_ALL, dent->d_name);
109 ast_strftime(localformat, sizeof(localformat), "%c", &atm);
110
111 locallen = strlen(localformat) + 1;
112 namelen = strlen(dent->d_name) + 1;
113
114 /* Store values */
115 if (!(tl = ast_calloc(1, sizeof(*tl) + locallen + namelen))) {
116 continue;
117 }
118
119 ast_copy_string(tl->name, dent->d_name, namelen); /* SAFE */
120 tl->localformat = tl->name + namelen;
121 ast_copy_string(tl->localformat, localformat, locallen); /* SAFE */
122
123 AST_LIST_INSERT_TAIL(&locales, tl, list);
124
125 /* Ensure that at least two entries differ, otherwise this test doesn't mean much. */
126 if (!varies && strcmp(AST_LIST_FIRST(&locales)->localformat, localformat)) {
127 varies = 1;
128 }
129 }
130
131 setlocale(LC_ALL, orig_locale);
132
133 closedir(localedir);
134
135 if (!varies) {
136 if (!strcmp(origlocalformat, localformat)) {
137 ast_cli(a->fd, "WARNING: the locales on your system don't differ. Install more locales if you want this test to mean something.\n");
138 }
139 }
140
141 orig_locale = ast_setlocale(AST_LIST_FIRST(&locales)->name);
142
143 while ((tl = AST_LIST_REMOVE_HEAD(&locales, list))) {
144 ast_setlocale(tl->name);
145 ast_strftime(localformat, sizeof(localformat), "%c", &atm);
146 if (strcmp(localformat, tl->localformat)) {
147 ast_cli(a->fd, "WARNING: locale test fails for locale %s\n", tl->name);
148 all_successful = 0;
149 count_fail++;
150 }
151 ast_free(tl);
152 count++;
153 }
154
155 ast_setlocale(orig_locale);
156
157 if (all_successful) {
158 ast_cli(a->fd, "All %d locale tests successful\n", count);
159 } else if (count_fail == count && count > 0) {
160 ast_cli(a->fd, "No locale tests successful out of %d tries\n", count);
161 } else if (count > 0) {
162 ast_cli(a->fd, "Partial failure (%d/%d) for a %.0f%% failure rate\n", count_fail, count, count_fail * 100.0 / count);
163 } else {
164 ast_cli(a->fd, "No locales tested. Install more locales.\n");
165 }
166
167 return CLI_SUCCESS;
168}
#define ast_free(a)
Definition astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#define CLI_SHOWUSAGE
Definition cli.h:45
#define CLI_SUCCESS
Definition cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition clicompat.c:6
@ CLI_INIT
Definition cli.h:152
@ CLI_GENERATE
Definition cli.h:153
static const char name[]
Definition format_mp3.c:68
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_HEAD_SET_NOLOCK(head, entry)
Initializes a list head structure with a specified first entry.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
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
const char * ast_setlocale(const char *locale)
Set the thread-local representation of the current locale.
Definition localtime.c:2420
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition localtime.c:2524
#define NULL
Definition resample.c:96
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
int args
This gets set in ast_cli_register()
Definition cli.h:185
char * command
Definition cli.h:186
const char * usage
Definition cli.h:177
const char * name
static struct test_val a
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition time.h:159

References a, ast_cli_entry::args, ast_calloc, ast_cli(), ast_copy_string(), ast_free, AST_LIST_ENTRY, AST_LIST_FIRST, AST_LIST_HEAD_NOLOCK, AST_LIST_HEAD_SET_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_localtime(), ast_setlocale(), ast_strftime(), ast_tvnow(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, name, test_val::name, NULL, and ast_cli_entry::usage.

◆ load_module()

static int load_module ( void  )
static

Definition at line 180 of file test_locale.c.

181{
184}
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition cli.h:265
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
static struct ast_cli_entry cli_locales[]
#define ARRAY_LEN(a)
Definition utils.h:703

References ARRAY_LEN, ast_cli_register_multiple, AST_MODULE_LOAD_SUCCESS, and cli_locales.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 174 of file test_locale.c.

175{
177 return 0;
178}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408

References ARRAY_LEN, ast_cli_unregister_multiple(), and cli_locales.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Locale tests" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 186 of file test_locale.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 186 of file test_locale.c.

◆ cli_locales

struct ast_cli_entry cli_locales[]
static
Initial value:
= {
{ .handler = handle_cli_test_locales , .summary = "Test locales for thread-safety" ,},
}
static char * handle_cli_test_locales(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition test_locale.c:49

Definition at line 170 of file test_locale.c.

170 {
171 AST_CLI_DEFINE(handle_cli_test_locales, "Test locales for thread-safety"),
172};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197

Referenced by load_module(), and unload_module().