This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new 18faf8f13 testing/libc/locale: Add a test of setlocale() and gettext().
18faf8f13 is described below

commit 18faf8f13f1e1d7460630c502ffa80533bcd387d
Author: Marco Casaroli <[email protected]>
AuthorDate: Tue Nov 10 21:09:15 2026 +0100

    testing/libc/locale: Add a test of setlocale() and gettext().
    
    The test checks the locale names that setlocale() and newlocale()
    accept: "C", "POSIX", "", "C.UTF-8" and "C.utf8".  An unknown name must
    give an error, and the name that setlocale() returns must select the
    locale again.  It also checks that the C.UTF-8 locale uses UTF-8.
    
    With LIBC_LOCALE_GETTEXT, it checks that gettext() and the other
    <libintl.h> functions keep errno when there is no message catalog.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 testing/libc/locale/CMakeLists.txt |  35 +++++++
 testing/libc/locale/Kconfig        |  32 ++++++
 testing/libc/locale/Make.defs      |  25 +++++
 testing/libc/locale/Makefile       |  36 +++++++
 testing/libc/locale/locale_main.c  | 208 +++++++++++++++++++++++++++++++++++++
 5 files changed, 336 insertions(+)

diff --git a/testing/libc/locale/CMakeLists.txt 
b/testing/libc/locale/CMakeLists.txt
new file mode 100644
index 000000000..fd301dfee
--- /dev/null
+++ b/testing/libc/locale/CMakeLists.txt
@@ -0,0 +1,35 @@
+# 
##############################################################################
+# apps/testing/libc/locale/CMakeLists.txt
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more 
contributor
+# license agreements.  See the NOTICE file distributed with this work for
+# additional information regarding copyright ownership.  The ASF licenses this
+# file to you under the Apache License, Version 2.0 (the "License"); you may 
not
+# use this file except in compliance with the License.  You may obtain a copy 
of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations under
+# the License.
+#
+# 
##############################################################################
+
+if(CONFIG_TESTING_LOCALE)
+  nuttx_add_application(
+    NAME
+    ${CONFIG_TESTING_LOCALE_PROGNAME}
+    PRIORITY
+    ${CONFIG_TESTING_LOCALE_PRIORITY}
+    STACKSIZE
+    ${CONFIG_TESTING_LOCALE_STACKSIZE}
+    MODULE
+    ${CONFIG_TESTING_LOCALE}
+    SRCS
+    locale_main.c)
+endif()
diff --git a/testing/libc/locale/Kconfig b/testing/libc/locale/Kconfig
new file mode 100644
index 000000000..cbd9b6c93
--- /dev/null
+++ b/testing/libc/locale/Kconfig
@@ -0,0 +1,32 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config TESTING_LOCALE
+       tristate "Locale test"
+       default n
+       depends on LIBC_LOCALE
+       ---help---
+               Check the locale names that setlocale() and newlocale() accept,
+               and, with LIBC_LOCALE_GETTEXT, that gettext() and the other
+               <libintl.h> functions do not change errno.
+
+if TESTING_LOCALE
+
+config TESTING_LOCALE_PROGNAME
+       string "Program name"
+       default "locale_test"
+       ---help---
+               This is the name of the program that will be used when the NSH 
ELF
+               program is installed.
+
+config TESTING_LOCALE_PRIORITY
+       int "locale_test task priority"
+       default 100
+
+config TESTING_LOCALE_STACKSIZE
+       int "locale_test stack size"
+       default DEFAULT_TASK_STACKSIZE
+
+endif
diff --git a/testing/libc/locale/Make.defs b/testing/libc/locale/Make.defs
new file mode 100644
index 000000000..27081709c
--- /dev/null
+++ b/testing/libc/locale/Make.defs
@@ -0,0 +1,25 @@
+############################################################################
+# apps/testing/libc/locale/Make.defs
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifneq ($(CONFIG_TESTING_LOCALE),)
+CONFIGURED_APPS += $(APPDIR)/testing/libc/locale
+endif
diff --git a/testing/libc/locale/Makefile b/testing/libc/locale/Makefile
new file mode 100644
index 000000000..57569dc9b
--- /dev/null
+++ b/testing/libc/locale/Makefile
@@ -0,0 +1,36 @@
+############################################################################
+# apps/testing/libc/locale/Makefile
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+# locale test built-in application info
+
+PROGNAME  = $(CONFIG_TESTING_LOCALE_PROGNAME)
+PRIORITY  = $(CONFIG_TESTING_LOCALE_PRIORITY)
+STACKSIZE = $(CONFIG_TESTING_LOCALE_STACKSIZE)
+MODULE    = $(CONFIG_TESTING_LOCALE)
+
+# locale test files
+
+MAINSRC = locale_main.c
+
+include $(APPDIR)/Application.mk
diff --git a/testing/libc/locale/locale_main.c 
b/testing/libc/locale/locale_main.c
new file mode 100644
index 000000000..cd4db083e
--- /dev/null
+++ b/testing/libc/locale/locale_main.c
@@ -0,0 +1,208 @@
+/****************************************************************************
+ * apps/testing/libc/locale/locale_main.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/param.h>
+#include <errno.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef CONFIG_LIBC_LOCALE_GETTEXT
+#  include <libintl.h>
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct locale_name_s
+{
+  FAR const char *name;
+  bool valid;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* "" is the C locale when LANG and LC_* are not set.  The C locale uses
+ * UTF-8, so "C.UTF-8" and "C.utf8" are valid names too.
+ */
+
+static const struct locale_name_s g_names[] =
+{
+  { "C",           true  },
+  { "POSIX",       true  },
+  { "",            true  },
+  { "C.UTF-8",     true  },
+  { "C.utf8",      true  },
+  { "xx_XX.UTF-8", false },
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/* The functions return the number of errors */
+
+static int check(FAR const char *func, FAR const char *name, bool ok)
+{
+  if (!ok)
+    {
+      printf("ERROR: %s(\"%s\")\n", func, name);
+      return 1;
+    }
+
+  printf("%s(\"%s\"): OK\n", func, name);
+  return 0;
+}
+
+static int test_setlocale(FAR const struct locale_name_s *entry)
+{
+  char saved[64];
+  FAR char *ret;
+  bool ok;
+
+  ret = setlocale(LC_ALL, entry->name);
+  ok = (ret != NULL) == entry->valid;
+  if (ok && ret != NULL)
+    {
+      /* The returned name must select the same locale again */
+
+      strlcpy(saved, ret, sizeof(saved));
+      ok = setlocale(LC_ALL, saved) != NULL;
+    }
+
+  setlocale(LC_ALL, "C");
+  return check("setlocale", entry->name, ok);
+}
+
+static int test_newlocale(FAR const struct locale_name_s *entry)
+{
+  locale_t loc;
+
+  loc = newlocale(LC_ALL_MASK, entry->name, NULL);
+  if (loc != NULL)
+    {
+      freelocale(loc);
+    }
+
+  return check("newlocale", entry->name, (loc != NULL) == entry->valid);
+}
+
+static int test_codeset(void)
+{
+  bool ok;
+
+  ok = setlocale(LC_CTYPE, "C.UTF-8") != NULL &&
+       strcmp(nl_langinfo(CODESET), "UTF-8") == 0;
+  setlocale(LC_ALL, "C");
+  return check("nl_langinfo(CODESET) after setlocale", "C.UTF-8", ok);
+}
+
+#ifdef CONFIG_LIBC_LOCALE_GETTEXT
+/* A program calls gettext() for the text of an error message after the
+ * failed call and before it reads errno.  So these functions must keep
+ * errno, also when there is no message catalog.
+ */
+
+static int check_gettext(FAR const char *func, FAR const char *text,
+                         FAR const char *expect, int errcode)
+{
+  if (errcode != EPERM || strcmp(text, expect) != 0)
+    {
+      printf("ERROR: %s: errno %d (expected %d) text \"%s\"\n",
+             func, errcode, EPERM, text);
+      return 1;
+    }
+
+  printf("%s: OK\n", func);
+  return 0;
+}
+
+static int test_gettext(void)
+{
+  FAR const char *text;
+  int nerrors = 0;
+
+  errno = EPERM;
+  text = gettext("message");
+  nerrors += check_gettext("gettext", text, "message", errno);
+
+  errno = EPERM;
+  text = dgettext("locale_test", "message");
+  nerrors += check_gettext("dgettext", text, "message", errno);
+
+  errno = EPERM;
+  text = dcgettext("locale_test", "message", LC_MESSAGES);
+  nerrors += check_gettext("dcgettext", text, "message", errno);
+
+  errno = EPERM;
+  text = ngettext("one file", "files", 2);
+  nerrors += check_gettext("ngettext", text, "files", errno);
+
+  errno = EPERM;
+  text = dngettext("locale_test", "one file", "files", 2);
+  nerrors += check_gettext("dngettext", text, "files", errno);
+
+  errno = EPERM;
+  text = dcngettext("locale_test", "one file", "files", 1, LC_MESSAGES);
+  nerrors += check_gettext("dcngettext", text, "one file", errno);
+  return nerrors;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+  int nerrors = 0;
+  size_t i;
+
+  printf("locale test: locale names and errno\n");
+
+  for (i = 0; i < nitems(g_names); i++)
+    {
+      nerrors += test_setlocale(&g_names[i]);
+      nerrors += test_newlocale(&g_names[i]);
+    }
+
+  nerrors += test_codeset();
+
+#ifdef CONFIG_LIBC_LOCALE_GETTEXT
+  nerrors += test_gettext();
+#endif
+
+  printf("locale test: %d errors\n", nerrors);
+  return nerrors > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}

Reply via email to