Asterisk - The Open Source Telephony Project  18.5.0
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 = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .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.

References __APPLE__, ast_cli_args::argc, 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, ast_cli_args::fd, name, NULL, and ast_cli_entry::usage.

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);
95  AST_LIST_HEAD_SET_NOLOCK(&locales, 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_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
#define __APPLE__
Definition: mpool.c:316
const int argc
Definition: cli.h:160
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
Definition: cli.h:152
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const int fd
Definition: cli.h:159
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
AST_LIST_HEAD_NOLOCK(contactliststruct, contact)
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
#define AST_LIST_HEAD_SET_NOLOCK(head, entry)
Initializes a list head structure with a specified first entry.
Definition: linkedlists.h:387
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
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
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ load_module()

static int load_module ( void  )
static

Definition at line 180 of file test_locale.c.

References ARRAY_LEN, ast_cli_register_multiple, and AST_MODULE_LOAD_SUCCESS.

181 {
184 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static struct ast_cli_entry cli_locales[]
Definition: test_locale.c:170

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 174 of file test_locale.c.

References ARRAY_LEN, and ast_cli_unregister_multiple().

175 {
177  return 0;
178 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
static struct ast_cli_entry cli_locales[]
Definition: test_locale.c:170

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Locale tests" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .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.