summaryrefslogtreecommitdiff
path: root/usr/src/test
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2014-07-06 12:52:24 -0700
committerGarrett D'Amore <garrett@damore.org>2014-07-15 14:05:46 -0700
commit538aa54d819fa7751ca82bcc30d4ed8c57ec2ef2 (patch)
tree53b18be80f1470a87571c45a8a90cc4597d071bb /usr/src/test
parente42d205944d245bf5d1c4fc45261cbe09e28a7b9 (diff)
downloadillumos-joyent-538aa54d819fa7751ca82bcc30d4ed8c57ec2ef2.tar.gz
4964 nl_langinfo(CRNCYSTR) returns wrong alignment character
4999 libc test suite enhancements 4939 desire wcsnrtombs() function Reviewed by: Jason King <jason.brian.king@gmail.com> Reviewed by: Dan McDonald <danmcd@omniti.com> Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com> Approved by: Robert Mustacchi <rm@joyent.com>
Diffstat (limited to 'usr/src/test')
-rw-r--r--usr/src/test/libc-tests/doc/README12
-rw-r--r--usr/src/test/libc-tests/runfiles/default.run4
-rw-r--r--usr/src/test/libc-tests/tests/Makefile3
-rw-r--r--usr/src/test/libc-tests/tests/Makefile.com89
-rw-r--r--usr/src/test/libc-tests/tests/common/run_arch_tests.ksh65
-rw-r--r--usr/src/test/libc-tests/tests/common/test_common.c206
-rw-r--r--usr/src/test/libc-tests/tests/common/test_common.h41
-rw-r--r--usr/src/test/libc-tests/tests/newlocale/Makefile42
-rw-r--r--usr/src/test/libc-tests/tests/newlocale/newlocale_test.c192
-rw-r--r--usr/src/test/libc-tests/tests/nl_langinfo/Makefile21
-rw-r--r--usr/src/test/libc-tests/tests/nl_langinfo/nl_langinfo_test.c278
-rw-r--r--usr/src/test/libc-tests/tests/wcsrtombs/Makefile21
-rw-r--r--usr/src/test/libc-tests/tests/wcsrtombs/wcsrtombs_test.c388
13 files changed, 1253 insertions, 109 deletions
diff --git a/usr/src/test/libc-tests/doc/README b/usr/src/test/libc-tests/doc/README
index 60fc3b969a..f5640c58dd 100644
--- a/usr/src/test/libc-tests/doc/README
+++ b/usr/src/test/libc-tests/doc/README
@@ -25,7 +25,9 @@ libc Unit Test Suite README
1. What this Unit Test Suite tests
-This Unit Test Suite is for testing various libc interfaces.
+This Unit Test Suite is for testing various libc interfaces. The suite
+will test both 32 and 64 bit versions, provided that your kernel supports
+both.
2. Building and installing this Unit Test Suite
@@ -55,12 +57,12 @@ dependencies and will be automatically installed.
The pre-requisites for running the this Unit Test Suite are:
- Any user may perform these tests.
- - The en_US.UTF-8, ja_JP.UTF-8, de_DE.UTF-8, and ru_RU.UTF-8 locales
- must be installed.
+ - The en_US.UTF-8, en_GB.ISO8859-15, ja_JP.UTF-8, de_DE.UTF-8, and
+ ru_RU.UTF-8 locales must be installed.
-Once the pre-requisites are satisfied, simply run the ostest script:
+Once the pre-requisites are satisfied, simply run the libctest script:
- test_machine$ /opt/util-tests/bin/libctest
+ test_machine$ /opt/libc-tests/bin/libctest
4. Test results
diff --git a/usr/src/test/libc-tests/runfiles/default.run b/usr/src/test/libc-tests/runfiles/default.run
index 18f1475199..ae204ecccd 100644
--- a/usr/src/test/libc-tests/runfiles/default.run
+++ b/usr/src/test/libc-tests/runfiles/default.run
@@ -23,3 +23,7 @@ post =
outputdir = /var/tmp/test_results
[/opt/libc-tests/tests/newlocale_test]
+
+[/opt/libc-tests/tests/nl_langinfo_test]
+
+[/opt/libc-tests/tests/wcsrtombs_test]
diff --git a/usr/src/test/libc-tests/tests/Makefile b/usr/src/test/libc-tests/tests/Makefile
index 310dcf06a7..01207bd6d1 100644
--- a/usr/src/test/libc-tests/tests/Makefile
+++ b/usr/src/test/libc-tests/tests/Makefile
@@ -14,6 +14,7 @@
# Copyright 2014 Garrett D'Amore <garrett@damore.org>
#
-SUBDIRS = newlocale
+SUBDIRS = newlocale nl_langinfo wcsrtombs
+include $(SRC)/Makefile.master
include $(SRC)/test/Makefile.com
diff --git a/usr/src/test/libc-tests/tests/Makefile.com b/usr/src/test/libc-tests/tests/Makefile.com
new file mode 100644
index 0000000000..78f357257a
--- /dev/null
+++ b/usr/src/test/libc-tests/tests/Makefile.com
@@ -0,0 +1,89 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+#
+
+include $(SRC)/Makefile.master
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/test/Makefile.com
+
+$(OBJS_OVERRIDE)OBJS = $(PROG).o test_common.o
+OBJS32 = $(OBJS:%.o=%.$(MACH).o)
+PROG32 = $(PROG).$(MACH)
+
+$(BUILD64) OBJS64 = $(OBJS:%.o=%.$(MACH64).o)
+$(BUILD64) PROG64= $(PROG).$(MACH64)
+
+$(OBJS_OVERRIDE)SRCS = $(PROG).c ../common/test_common.c
+
+C99MODE = -xc99=%all
+LINTFLAGS += -I../common -DARCH=\"ARCH\" -DLINT
+CPPFLAGS += -I../common
+
+ROOTOPTPKG = $(ROOT)/opt/libc-tests
+TESTDIR = $(ROOTOPTPKG)/tests
+
+CMDS = $(PROG32:%=$(TESTDIR)/%) $(PROG64:%=$(TESTDIR)/%) \
+ $(KSHPROG:%=$(TESTDIR)/%) $(ARCHPROG:%=$(TESTDIR)/%)
+$(CMDS) := FILEMODE = 0555
+
+all: $(PROG32) $(PROG64) $(KSHPROG) $(ARCHPROG) $(SUBDIRS)
+
+$(PROG32): $(OBJS32)
+ $(LINK.c) $(OBJS32) -o $@ $(LDLIBS)
+ $(POST_PROCESS)
+
+$(PROG64): $(OBJS64)
+ $(LINK64.c) $(OBJS64) -o $@ $(LDLIBS64)
+ $(POST_PROCESS)
+
+$(KSHPROG): $(KSHPROG).ksh
+ $(RM) $@
+ $(CP) $(KSHPROG).ksh $(@)
+ $(CHMOD) +x $@
+
+$(ARCHPROG): ../common/run_arch_tests.ksh
+ $(RM) $@
+ $(CP) ../common/run_arch_tests.ksh $(@)
+ $(CHMOD) +x $@
+
+%.$(MACH).o: %.c
+ $(COMPILE.c) -o $@ $(CFLAGS_$(MACH)) -DARCH=\"$(MACH)\" $<
+
+%.$(MACH).o: ../common/%.c
+ $(COMPILE.c) -o $@ $(CFLAGS_$(MACH)) -DARCH=\"$(MACH)\" $<
+
+%.$(MACH64).o: %.c
+ $(COMPILE64.c) -o $@ $(CFLAGS_$(MACH64)) -DARCH=\"$(MACH64)\" $<
+
+%.$(MACH64).o: ../common/%.c
+ $(COMPILE64.c) -o $@ $(CFLAGS_$(MACH64)) -DARCH=\"$(MACH64)\" $<
+
+install: $(SUBDIRS) $(CMDS)
+
+lint: lint_SRCS
+
+clobber: clean
+ -$(RM) $(PROG32) $(PROG64) $(KSHPROG) $(ARCHPROG)
+
+clean:
+ -$(RM) $(OBJS32) $(OBJS64)
+
+$(CMDS): $(TESTDIR) $(PROG32) $(PROG64) $(KSHPROG) $(ARCHPROG)
+
+$(TESTDIR):
+ $(INS.dir)
+
+$(TESTDIR)/%: %
+ $(INS.file)
diff --git a/usr/src/test/libc-tests/tests/common/run_arch_tests.ksh b/usr/src/test/libc-tests/tests/common/run_arch_tests.ksh
new file mode 100644
index 0000000000..2598fc9d5b
--- /dev/null
+++ b/usr/src/test/libc-tests/tests/common/run_arch_tests.ksh
@@ -0,0 +1,65 @@
+#!/usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+#
+
+# First we set $dir to dirname $0, and $prog to basename $0 .ksh,
+# using efficient ksh builtins.
+case $0 in
+*/*)
+ dir=${0%/*}
+ prog=${0##*/}
+ ;;
+*)
+ dir=.
+ prog=${0}
+ ;;
+esac
+prog=${prog%.ksh}
+
+for a in $*
+do
+ if [[ $a == "-d" ]]
+ then
+ debug=yes
+ fi
+done
+
+# We look for architecture specific versions of the program,
+# searching in several candidate directories. We run each one as
+# we find it.
+for f in $(/usr/bin/isainfo)
+do
+ found=
+ [[ -n $debug ]] && print "Checking for arch $f:"
+ for p in \
+ ${dir}/${prog}.${f} \
+ ${dir}/${f}/${prog}.${f} \
+ ${dir}/${f}/${prog}
+ do
+ [[ -n $found ]] && continue
+ [[ -n $debug ]] && print -n " $p"
+ if [[ -f $p ]]; then
+ [[ -n $debug ]] && print " FOUND"
+ [[ -n $debug ]] && print "Executing $p $*"
+ found=yes
+ $p $* || exit 1
+ else
+ [[ -n $debug ]] && print
+ fi
+ done
+ [[ -z $found ]] && [[ -n $debug ]] && print "NOT PRESENT"
+done
+exit 0
diff --git a/usr/src/test/libc-tests/tests/common/test_common.c b/usr/src/test/libc-tests/tests/common/test_common.c
new file mode 100644
index 0000000000..21ecc018b9
--- /dev/null
+++ b/usr/src/test/libc-tests/tests/common/test_common.c
@@ -0,0 +1,206 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Garrett D'Amore <garrett@damore.org>
+ */
+
+/*
+ * Common handling for test programs.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include "test_common.h"
+
+static int debug = 0;
+static int force = 0;
+static pthread_mutex_t lk;
+
+struct test {
+ char *name;
+ int ntids;
+ pthread_t *tids;
+ int fails;
+ void *arg;
+ void (*func)(test_t t, void *);
+};
+
+void
+test_set_debug(void)
+{
+ debug++;
+}
+
+void
+test_set_force(void)
+{
+ force++;
+}
+
+test_t
+test_start(const char *format, ...)
+{
+ va_list args;
+ test_t t;
+ char *s;
+
+ t = calloc(1, sizeof (*t));
+ va_start(args, format);
+ (void) vasprintf(&s, format, args);
+ va_end(args);
+
+ (void) asprintf(&t->name, "%s (%s)", s, ARCH);
+ free(s);
+
+ (void) pthread_mutex_lock(&lk);
+ (void) printf("TEST STARTING %s:\n", t->name);
+ (void) fflush(stdout);
+ (void) pthread_mutex_unlock(&lk);
+
+#ifdef LINT
+ /* We inject references to make avoid name unused warnings */
+ test_run(0, NULL, NULL, NULL);
+ test_debugf(t, NULL);
+ test_failed(t, NULL);
+ test_passed(t);
+ test_set_debug();
+ test_set_force();
+#endif
+
+ return (t);
+
+}
+
+void
+test_failed(test_t t, const char *format, ...)
+{
+ va_list args;
+
+ (void) pthread_mutex_lock(&lk);
+ if (force || (t->ntids > 0)) {
+ (void) printf("TEST FAILING %s: ", t->name);
+ } else {
+ (void) printf("TEST FAILED %s: ", t->name);
+ }
+
+ va_start(args, format);
+ (void) vprintf(format, args);
+ va_end(args);
+ (void) printf("\n");
+ (void) fflush(stdout);
+ (void) pthread_mutex_unlock(&lk);
+
+ t->fails++;
+ if (!force) {
+ if (t->ntids > 0) {
+ pthread_exit(NULL);
+ } else {
+ (void) exit(EXIT_FAILURE);
+ }
+ }
+}
+
+void
+test_passed(test_t t)
+{
+ if (t->ntids > 0) {
+ if (debug) {
+ (void) pthread_mutex_lock(&lk);
+ (void) printf("TEST PASSING: %s\n", t->name);
+ (void) pthread_mutex_unlock(&lk);
+ }
+ return;
+ }
+ (void) pthread_mutex_lock(&lk);
+ if (t->fails == 0) {
+ (void) printf("TEST PASS: %s\n", t->name);
+ } else {
+ (void) printf("TEST FAILED: %d failures\n", t->fails);
+ }
+ (void) fflush(stdout);
+ (void) pthread_mutex_unlock(&lk);
+ free(t->name);
+ if (t->tids) {
+ free(t->tids);
+ }
+ free(t);
+}
+
+void
+test_debugf(test_t t, const char *format, ...)
+{
+ va_list args;
+
+ if (!debug)
+ return;
+
+ (void) pthread_mutex_lock(&lk);
+ (void) printf("TEST DEBUG %s: ", t->name);
+
+ va_start(args, format);
+ (void) vprintf(format, args);
+ va_end(args);
+ (void) printf("\n");
+ (void) fflush(stdout);
+ (void) pthread_mutex_unlock(&lk);
+}
+
+static void *
+test_thr_one(void *arg)
+{
+ test_t t = arg;
+ t->func(t, t->arg);
+ return (NULL);
+}
+
+void
+test_run(int nthr, void (*func)(test_t, void *), void *arg,
+ const char *tname, ...)
+{
+ test_t t;
+ char *s;
+ va_list args;
+
+ t = calloc(1, sizeof (*t));
+ t->ntids = nthr;
+ t->tids = calloc(nthr, sizeof (pthread_t));
+ t->func = func;
+ t->arg = arg;
+
+ va_start(args, tname);
+ (void) vasprintf(&s, tname, args);
+ va_end(args);
+
+ (void) asprintf(&t->name, "%s (%s)", s, ARCH);
+ free(s);
+
+ (void) pthread_mutex_lock(&lk);
+ (void) printf("TEST STARTING %s:\n", t->name);
+ (void) fflush(stdout);
+ (void) pthread_mutex_unlock(&lk);
+
+ test_debugf(t, "running %d threads", nthr);
+
+ for (int i = 0; i < nthr; i++) {
+ test_debugf(t, "started thread %d", i);
+ (void) pthread_create(&t->tids[i], NULL, test_thr_one, t);
+ }
+
+ for (int i = 0; i < nthr; i++) {
+ (void) pthread_join(t->tids[i], NULL);
+ test_debugf(t, "thread %d joined", i);
+ t->ntids--;
+ }
+ test_passed(t);
+}
diff --git a/usr/src/test/libc-tests/tests/common/test_common.h b/usr/src/test/libc-tests/tests/common/test_common.h
new file mode 100644
index 0000000000..9234bfac19
--- /dev/null
+++ b/usr/src/test/libc-tests/tests/common/test_common.h
@@ -0,0 +1,41 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Garrett D'Amore <garrett@damore.org>
+ */
+
+/*
+ * Common handling for test programs.
+ */
+
+#ifndef _TEST_COMMON_H
+#define _TEST_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct test *test_t;
+typedef void (*test_func_t)(test_t, void *);
+
+extern void test_set_debug(void);
+extern void test_set_force(void);
+extern test_t test_start(const char *name, ...);
+extern void test_failed(test_t, const char *format, ...);
+extern void test_passed(test_t);
+extern void test_debugf(test_t, const char *format, ...);
+extern void test_run(int nthr, test_func_t, void *arg, const char *, ...);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _TEST_COMMON_H */
diff --git a/usr/src/test/libc-tests/tests/newlocale/Makefile b/usr/src/test/libc-tests/tests/newlocale/Makefile
index 4f761595ca..480f7066d7 100644
--- a/usr/src/test/libc-tests/tests/newlocale/Makefile
+++ b/usr/src/test/libc-tests/tests/newlocale/Makefile
@@ -10,48 +10,12 @@
#
#
-# Copyright (c) 2012 by Delphix. All rights reserved.
# Copyright 2014 Garrett D'Amore <garrett@damore.org>
#
-include $(SRC)/cmd/Makefile.cmd
-include $(SRC)/test/Makefile.com
+include $(SRC)/Makefile.master
PROG = newlocale_test
-OBJS = $(PROG:%=%.o)
-SRCS = $(OBJS:%.o=%.c)
+ARCHPROG = newlocale_test
-C99MODE = -xc99=%all
-
-ROOTOPTPKG = $(ROOT)/opt/libc-tests
-TESTDIR = $(ROOTOPTPKG)/tests
-
-CMDS = $(PROG:%=$(TESTDIR)/%)
-$(CMDS) := FILEMODE = 0555
-
-all: $(PROG)
-
-$(PROG): $(OBJS)
- $(LINK.c) $(OBJS) -o $@ $(LDLIBS)
- $(POST_PROCESS)
-
-%.o: ../%.c
- $(COMPILE.c) $<
-
-install: all $(CMDS)
-
-lint: lint_SRCS
-
-clobber: clean
- -$(RM) $(PROG)
-
-clean:
- -$(RM) $(OBJS)
-
-$(CMDS): $(TESTDIR) $(PROG)
-
-$(TESTDIR):
- $(INS.dir)
-
-$(TESTDIR)/%: %
- $(INS.file)
+include ../Makefile.com
diff --git a/usr/src/test/libc-tests/tests/newlocale/newlocale_test.c b/usr/src/test/libc-tests/tests/newlocale/newlocale_test.c
index 214fa9fb19..22a23c5587 100644
--- a/usr/src/test/libc-tests/tests/newlocale/newlocale_test.c
+++ b/usr/src/test/libc-tests/tests/newlocale/newlocale_test.c
@@ -29,8 +29,8 @@
#include <err.h>
#include <unistd.h>
#include <pthread.h>
-
-int debug = 0;
+#include <note.h>
+#include "test_common.h"
/*
* Note that on some platforms, different symbols are used. For example,
@@ -53,47 +53,15 @@ struct ldata {
#define NUMTHR 20
#define NUMITR 200
-static void
-test_start(const char *testName, const char *format, ...)
-{
- va_list args;
-
- (void) printf("TEST STARTING %s: ", testName);
-
- va_start(args, format);
- (void) vprintf(format, args);
- va_end(args);
- (void) fflush(stdout);
-}
-
-static void
-test_failed(const char *testName, const char *format, ...)
-{
- va_list args;
-
- (void) printf("TEST FAILED %s: ", testName);
-
- va_start(args, format);
- (void) vprintf(format, args);
- va_end(args);
-
- (void) exit(-1);
-}
-
-static void
-test_passed(const char *testName)
-{
- (void) printf("TEST PASS: %s\n", testName);
- (void) fflush(stdout);
-}
+int extra_debug = 0;
-void *
-testlocale_thr(void *ptr)
+void
+testlocale_thr_one(test_t t, void *arg)
{
+ _NOTE(ARGUNUSED(arg));
locale_t cloc, loc;
struct lconv *lc;
char *day;
- char *tname = ptr;
for (int i = 0; i < NUMITR; i++) {
struct ldata *l = &ldata[i % NUM_LDATA];
@@ -101,24 +69,24 @@ testlocale_thr(void *ptr)
loc = newlocale(LC_ALL_MASK, l->locale, NULL);
if (loc == NULL) {
- test_failed("newlocale %s failed", l->locale);
+ test_failed(t, "newlocale %s failed", l->locale);
}
day = nl_langinfo_l(DAY_1, loc);
if (strcmp(day, l->day1) != 0) {
- test_failed(tname, "newlocale data mismatch (%s != %s)",
+ test_failed(t, "newlocale data mismatch (%s != %s)",
day, l->day1);
}
- if (debug)
- (void) printf("DAY1: %s\n", day);
+ if (extra_debug)
+ test_debugf(t, "DAY1: %s", day);
day = nl_langinfo(DAY_1);
if (strcmp(day, "Sunday") != 0) {
- test_failed(tname, "C locale day wrong %s != Sunday",
+ test_failed(t, "C locale day wrong %s != Sunday",
day);
}
lc = localeconv();
if (strcmp(lc->currency_symbol, "") != 0) {
- test_failed(tname, "C cursym mismatch (%s != %s)",
+ test_failed(t, "C cursym mismatch (%s != %s)",
lc->currency_symbol, "");
}
@@ -128,49 +96,135 @@ testlocale_thr(void *ptr)
(void) uselocale(loc);
day = nl_langinfo(DAY_1);
if (strcmp(day, l->day1) != 0) {
- test_failed(tname, "uselocale data mismatch (%s != %s)",
+ test_failed(t, "uselocale data mismatch (%s != %s)",
day, l->day1);
}
lc = localeconv();
if (strcmp(lc->currency_symbol, l->cursym) != 0) {
- test_failed(tname, "uselocal cursym %s != %s",
+ test_failed(t, "uselocal cursym %s != %s",
lc->currency_symbol, l->cursym);
}
- if (debug)
- (void) printf("CSYM: %s\n", lc->currency_symbol);
+ if (extra_debug)
+ test_debugf(t, "CSYM: %s", lc->currency_symbol);
/* we sleep a random bit to mix it up */
(void) usleep(rand() % 10);
if (uselocale(cloc) != loc) {
- test_failed(tname, "revert old locale mismatch");
+ test_failed(t, "revert old locale mismatch");
}
freelocale(loc);
if (uselocale(LC_GLOBAL_LOCALE) != cloc) {
- test_failed(tname, "revert GLOBAL_LOCALE mismatch");
+ test_failed(t, "revert GLOBAL_LOCALE mismatch");
}
}
- return (NULL);
+ test_passed(t);
}
void
-testlocale(void)
+test_newlocale_threaded(void)
{
- char *tname = "newlocale/uselocale";
- pthread_t tid[NUMTHR];
+ test_run(NUMTHR, testlocale_thr_one, NULL, "newlocale_threaded");
+}
- test_start(tname, "running %d threads %d iterations\n", NUMTHR, NUMITR);
+void
+test_newlocale_negative(void)
+{
+ locale_t loc, bad;
+ char *day;
+ char *tname = "newlocale_negative";
+ test_t t;
+
+ t = test_start(tname);
+ loc = newlocale(LC_ALL_MASK, "de_DE.UTF-8", NULL);
+ if (loc == NULL) {
+ test_failed(t, "cannot set de_DE.UTF-8");
+ }
+ day = nl_langinfo_l(DAY_1, loc);
+ if (strcmp(day, "Sonntag") != 0) {
+ test_failed(t, "incorrect Sonntag != %s", day);
+ }
- for (int i = 0; i < NUMTHR; i++) {
- (void) pthread_create(&tid[i], NULL, testlocale_thr, tname);
+ bad = newlocale(LC_ALL_MASK, "cn_US.BIZRRE", loc);
+ if (bad != NULL) {
+ test_failed(t, "passed setting bogus locale");
+ }
+ day = nl_langinfo_l(DAY_1, loc);
+ if (strcmp(day, "Sonntag") != 0) {
+ test_failed(t, "incorrect Sonntag != %s", day);
}
+ test_passed(t);
+}
- for (int i = 0; i < NUMTHR; i++) {
- (void) pthread_join(tid[i], NULL);
+void
+test_newlocale_categories(void)
+{
+ locale_t loc;
+ char *day, *cur, *yes;
+ char *tname = "newlocale_categories";
+ test_t t;
+
+ t = test_start(tname);
+
+ loc = NULL;
+ loc = newlocale(LC_TIME_MASK, "de_DE.UTF-8", loc);
+ loc = newlocale(LC_MESSAGES_MASK, "ru_RU.UTF-8", loc);
+ loc = newlocale(LC_MONETARY_MASK, "en_US.UTF-8", loc);
+
+ if (loc == NULL) {
+ test_failed(t, "failed to set locale");
+ }
+
+ day = nl_langinfo_l(DAY_1, loc);
+ if ((day == NULL) || (strcmp(day, "Sonntag") != 0)) {
+ test_failed(t, "day1 mismatch %s != %s", day, "Sonntag");
+ }
+ yes = nl_langinfo_l(YESSTR, loc);
+ if ((yes == NULL) || (strcmp(yes, "да") != 0)) {
+ test_failed(t, "currency mismatch");
}
- test_passed(tname);
+ cur = nl_langinfo_l(CRNCYSTR, loc);
+ if ((cur == NULL) || (strcmp(cur, "-$") != 0)) {
+ test_failed(t, "currency mismatch [%s] != [%s]", cur, "-$");
+ }
+
+ test_passed(t);
+}
+
+void
+test_newlocale_composite(void)
+{
+ locale_t loc;
+ char *day, *cur, *yes;
+ char *tname = "newlocale_composite";
+ test_t t;
+
+ t = test_start(tname);
+
+ /* order: CTYPE/NUMERIC/TIME/COLLATE/MONETARY/MESSAGES */
+ loc = newlocale(LC_ALL_MASK,
+ "C/C/de_DE.UTF-8/C/en_US.UTF-8/ru_RU.UTF-8", NULL);
+
+ if (loc == NULL) {
+ test_failed(t, "failed to set composite locale");
+ }
+
+ day = nl_langinfo_l(DAY_1, loc);
+ if ((day == NULL) || (strcmp(day, "Sonntag") != 0)) {
+ test_failed(t, "day1 mismatch %s != %s", day, "Sonntag");
+ }
+ yes = nl_langinfo_l(YESSTR, loc);
+ if ((yes == NULL) || (strcmp(yes, "да") != 0)) {
+ test_failed(t, "currency mismatch");
+ }
+ cur = nl_langinfo_l(CRNCYSTR, loc);
+ if ((cur == NULL) || (strcmp(cur, "-$") != 0)) {
+ test_failed(t, "currency mismatch [%s] != [%s]", cur, "-$");
+ }
+
+ test_passed(t);
}
int
@@ -178,18 +232,28 @@ main(int argc, char **argv)
{
int optc;
- while ((optc = getopt(argc, argv, "d")) != EOF) {
+ while ((optc = getopt(argc, argv, "Ddf")) != EOF) {
switch (optc) {
case 'd':
- debug++;
+ test_set_debug();
+ break;
+ case 'f':
+ test_set_force();
+ break;
+ case 'D':
+ test_set_debug();
+ extra_debug++;
break;
default:
- (void) fprintf(stderr, "Usage: %s [-d]\n", argv[0]);
+ (void) fprintf(stderr, "Usage: %s [-df]\n", argv[0]);
exit(1);
}
}
- testlocale();
+ test_newlocale_threaded();
+ test_newlocale_negative();
+ test_newlocale_categories();
+ test_newlocale_composite();
exit(0);
}
diff --git a/usr/src/test/libc-tests/tests/nl_langinfo/Makefile b/usr/src/test/libc-tests/tests/nl_langinfo/Makefile
new file mode 100644
index 0000000000..f58927159e
--- /dev/null
+++ b/usr/src/test/libc-tests/tests/nl_langinfo/Makefile
@@ -0,0 +1,21 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+#
+
+include $(SRC)/Makefile.master
+
+PROG = nl_langinfo_test
+ARCHPROG = nl_langinfo_test
+
+include ../Makefile.com
diff --git a/usr/src/test/libc-tests/tests/nl_langinfo/nl_langinfo_test.c b/usr/src/test/libc-tests/tests/nl_langinfo/nl_langinfo_test.c
new file mode 100644
index 0000000000..4488e18d41
--- /dev/null
+++ b/usr/src/test/libc-tests/tests/nl_langinfo/nl_langinfo_test.c
@@ -0,0 +1,278 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Garrett D'Amore <garrett@damore.org>
+ */
+
+/*
+ * This program tests that newlocale and uselocale work properly in
+ * multi-threaded programs. In order for it to work, it requires that
+ * some additional locales be installed.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <libintl.h>
+#include <langinfo.h>
+#include <nl_types.h>
+#include <err.h>
+#include <errno.h>
+#include <unistd.h>
+#include "test_common.h"
+
+/*
+ * Note that on some platforms, different symbols are used. For example,
+ * MacOS Mavericks uses "Eu" for Euro symbol, instead of €. If the locale
+ * data changes, then this program will need to update to reflect that.
+ *
+ * Note also that this file is easiest edited with a UTF-8 capable editor,
+ * as there are embedded UTF-8 symbols in some of the strings.
+ */
+struct langinfo_test {
+ nl_item param;
+ const char *value;
+};
+
+struct langinfo_test C_data[] = {
+ { CODESET, "646" },
+ { D_T_FMT, "%a %b %e %H:%M:%S %Y" },
+ { D_FMT, "%m/%d/%y" },
+ { T_FMT, "%H:%M:%S" },
+ { T_FMT_AMPM, "%I:%M:%S %p" },
+ { AM_STR, "AM" },
+ { PM_STR, "PM" },
+ { ERA, "" },
+ { ERA_D_FMT, "" },
+ { ERA_D_T_FMT, "" },
+ { ERA_T_FMT, "" },
+ { DAY_1, "Sunday" },
+ { DAY_7, "Saturday" },
+ { ABDAY_1, "Sun" },
+ { ABDAY_7, "Sat" },
+ { MON_1, "January" },
+ { MON_12, "December" },
+ { ABMON_1, "Jan" },
+ { ABMON_12, "Dec" },
+ { RADIXCHAR, "." },
+ { THOUSEP, "" },
+ { YESSTR, "yes" },
+ { NOSTR, "no" },
+ { YESEXPR, "^[yY]" },
+ { NOEXPR, "^[nN]" },
+ { CRNCYSTR, "" },
+ { -1, NULL }
+};
+
+struct langinfo_test en_us_utf8_data[] = {
+ { CODESET, "UTF-8" },
+ { D_T_FMT, "%B %e, %Y %I:%M:%S %p %Z" },
+ { D_FMT, "%m/%e/%y" },
+ { T_FMT, "%I:%M:%S %p" },
+ { T_FMT_AMPM, "%I:%M:%S %p" },
+ { AM_STR, "AM" },
+ { PM_STR, "PM" },
+ { ERA, "" },
+ { ERA_D_FMT, "" },
+ { ERA_D_T_FMT, "" },
+ { ERA_T_FMT, "" },
+ { DAY_1, "Sunday" },
+ { DAY_7, "Saturday" },
+ { ABDAY_1, "Sun" },
+ { ABDAY_7, "Sat" },
+ { MON_1, "January" },
+ { MON_12, "December" },
+ { ABMON_1, "Jan" },
+ { ABMON_12, "Dec" },
+ { RADIXCHAR, "." },
+ { THOUSEP, "," },
+ { YESSTR, "yes" },
+ { NOSTR, "no" },
+ { YESEXPR, "^(([yY]([eE][sS])?))" },
+ { NOEXPR, "^(([nN]([oO])?))" },
+ { CRNCYSTR, "-$" },
+ { -1, NULL }
+};
+
+struct langinfo_test en_gb_latin15_data[] = {
+ { CODESET, "ISO8859-15" },
+ { D_T_FMT, "%e %B %Y %H:%M:%S %Z" },
+ { D_FMT, "%d/%m/%Y" },
+ { T_FMT, "%H:%M:%S" },
+ { T_FMT_AMPM, "%I:%M:%S %p" },
+ { AM_STR, "AM" },
+ { PM_STR, "PM" },
+ { ERA, "" },
+ { ERA_D_FMT, "" },
+ { ERA_D_T_FMT, "" },
+ { ERA_T_FMT, "" },
+ { DAY_1, "Sunday" },
+ { DAY_7, "Saturday" },
+ { ABDAY_1, "Sun" },
+ { ABDAY_7, "Sat" },
+ { MON_1, "January" },
+ { MON_12, "December" },
+ { ABMON_1, "Jan" },
+ { ABMON_12, "Dec" },
+ { RADIXCHAR, "." },
+ { THOUSEP, "," },
+ { YESSTR, "yes" },
+ { NOSTR, "no" },
+ { YESEXPR, "^(([yY]([eE][sS])?))" },
+ { NOEXPR, "^(([nN]([oO])?))" },
+ { CRNCYSTR, "-\243" },
+ { -1, NULL }
+};
+
+struct langinfo_test ru_ru_utf8_data[] = {
+ { CODESET, "UTF-8" },
+ { D_T_FMT, "%e %B %Y г. %H:%M:%S %Z"},
+ { D_FMT, "%d.%m.%y" },
+ { T_FMT, "%H:%M:%S" },
+ { T_FMT_AMPM, "%I:%M:%S %p" },
+ { AM_STR, "до полудня" },
+ { PM_STR, "после полудня" },
+ { ERA, "" },
+ { ERA_D_FMT, "" },
+ { ERA_D_T_FMT, "" },
+ { ERA_T_FMT, "" },
+ { DAY_1, "воскресенье" },
+ { DAY_7, "суббота" },
+ { ABDAY_1, "вс" },
+ { ABDAY_7, "сб" },
+ { MON_1, "января" },
+ { MON_12, "декабря" },
+ { ABMON_1, "янв" },
+ { ABMON_12, "дек" },
+ { RADIXCHAR, "," },
+ { THOUSEP, " " },
+ { YESSTR, "да" },
+ { NOSTR, "нет" },
+ { YESEXPR, "^(([дД]([аА])?)|([yY]([eE][sS])?))" },
+ { NOEXPR, "^(([нН]([еЕ][тТ])?)|([nN]([oO])?))" },
+ { CRNCYSTR, "+руб." },
+ { -1, NULL }
+};
+
+struct {
+ const char *locale;
+ struct langinfo_test *loctest;
+} locales[] = {
+ { "C", C_data },
+ { "en_US.UTF-8", en_us_utf8_data },
+ { "en_GB.ISO8859-15", en_gb_latin15_data },
+ { "ru_RU.UTF-8", ru_ru_utf8_data },
+ { NULL, NULL }
+};
+
+void
+test_nl_langinfo_1(const char *locale, struct langinfo_test *test)
+{
+ char tname[128];
+ char *v;
+ test_t t;
+
+ (void) snprintf(tname, sizeof (tname), "nl_langinfo (locale %s)",
+ locale);
+ t = test_start(tname);
+
+ v = setlocale(LC_ALL, locale);
+ if (v == NULL) {
+ test_failed(t, "setlocale failed: %s", strerror(errno));
+ }
+ if (strcmp(v, locale) != 0) {
+ test_failed(t, "setlocale got %s instead of %s", v, locale);
+ }
+
+ for (int i = 0; test[i].value != NULL; i++) {
+ v = nl_langinfo(test[i].param);
+ test_debugf(t, "%d: expect [%s], got [%s]",
+ test[i].param, test[i].value, v);
+ if (strcmp(v, test[i].value) != 0) {
+ test_failed(t,
+ "param %d wrong, expected [%s], got [%s]",
+ test[i].param, test[i].value, v);
+ }
+ }
+ test_passed(t);
+}
+
+void
+test_nl_langinfo_l(const char *locale, struct langinfo_test *test)
+{
+ char tname[128];
+ char *v;
+ test_t t;
+ locale_t loc;
+
+ (void) snprintf(tname, sizeof (tname), "nl_langinfo_l (locale %s)",
+ locale);
+ t = test_start(tname);
+
+ v = setlocale(LC_ALL, "C");
+ if (v == NULL) {
+ test_failed(t, "setlocale failed: %s", strerror(errno));
+ }
+ if (strcmp(v, "C") != 0) {
+ test_failed(t, "setlocale got %s instead of %s", v, "C");
+ }
+
+ loc = newlocale(LC_ALL_MASK, locale, NULL);
+ if (loc == NULL) {
+ test_failed(t, "newlocale failed: %s", strerror(errno));
+ }
+
+ for (int i = 0; test[i].value != NULL; i++) {
+ v = nl_langinfo_l(test[i].param, loc);
+ test_debugf(t, "%d: expect [%s], got [%s]",
+ test[i].param, test[i].value, v);
+ if (strcmp(v, test[i].value) != 0) {
+ test_failed(t,
+ "param %d wrong, expected [%s], got [%s]",
+ test[i].param, test[i].value, v);
+ }
+ }
+ test_passed(t);
+}
+void
+test_nl_langinfo(void)
+{
+ for (int i = 0; locales[i].locale != NULL; i++) {
+ test_nl_langinfo_1(locales[i].locale, locales[i].loctest);
+ test_nl_langinfo_l(locales[i].locale, locales[i].loctest);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int optc;
+
+ while ((optc = getopt(argc, argv, "df")) != EOF) {
+ switch (optc) {
+ case 'd':
+ test_set_debug();
+ break;
+ case 'f':
+ test_set_force();
+ break;
+ default:
+ (void) fprintf(stderr, "Usage: %s [-df]\n", argv[0]);
+ exit(1);
+ }
+ }
+
+ test_nl_langinfo();
+
+ exit(0);
+}
diff --git a/usr/src/test/libc-tests/tests/wcsrtombs/Makefile b/usr/src/test/libc-tests/tests/wcsrtombs/Makefile
new file mode 100644
index 0000000000..657bb91696
--- /dev/null
+++ b/usr/src/test/libc-tests/tests/wcsrtombs/Makefile
@@ -0,0 +1,21 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+#
+
+include $(SRC)/Makefile.master
+
+PROG = wcsrtombs_test
+ARCHPROG = wcsrtombs_test
+
+include ../Makefile.com
diff --git a/usr/src/test/libc-tests/tests/wcsrtombs/wcsrtombs_test.c b/usr/src/test/libc-tests/tests/wcsrtombs/wcsrtombs_test.c
new file mode 100644
index 0000000000..f083254952
--- /dev/null
+++ b/usr/src/test/libc-tests/tests/wcsrtombs/wcsrtombs_test.c
@@ -0,0 +1,388 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Garrett D'Amore <garrett@damore.org>
+ */
+
+/*
+ * This program tests that wcsrtombs and friends work properly.
+ * In order for it to work, it requires that some additional locales
+ * be installed.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <wchar.h>
+#include <err.h>
+#include <errno.h>
+#include <unistd.h>
+#include <xlocale.h>
+#include <note.h>
+#include "test_common.h"
+
+int extra_debug = 0;
+
+#define NUMTHR 300
+#define NUMITR 300
+
+/*
+ * Note that this file is easiest edited with a UTF-8 capable editor,
+ * as there are embedded UTF-8 symbols in some of the strings.
+ */
+struct wcsrtombs_test {
+ char mbs[32];
+ wchar_t wcs[32];
+};
+
+#define TESTING_MBS "TESTING"
+#define TESTING_WCS { 'T', 'E', 'S', 'T', 'I', 'N', 'G', 0 }
+#define HELLO_RU_MBS "ПРИВЕТ"
+#define HELLO_RU_WCS { 1055, 1056, 1048, 1042, 1045, 1058, 0 }
+#define HELLO_EN_MBS "HELLO"
+#define HELLO_EN_WCS { 'H', 'E', 'L', 'L', 'O', 0 }
+
+/* Unicode values never have the high order bit set */
+#define BAD_WCS { 'B', 'A', 'D', (wchar_t)0xf000f000, 'W', 'C', 'S' }
+
+struct wcsrtombs_test C_data[] = {
+ { TESTING_MBS, TESTING_WCS },
+ { HELLO_EN_MBS, HELLO_EN_WCS },
+ { 0, 0 },
+};
+
+struct wcsrtombs_test utf8_data[] = {
+ { TESTING_MBS, TESTING_WCS },
+ { HELLO_EN_MBS, HELLO_EN_WCS },
+ { HELLO_RU_MBS, HELLO_RU_WCS },
+ { 0, 0 },
+};
+
+struct {
+ const char *locale;
+ struct wcsrtombs_test *test;
+} locales[] = {
+ { "C", C_data },
+ { "en_US.UTF-8", utf8_data },
+ { NULL, NULL }
+};
+
+void
+test_wcsrtombs_1(const char *locale, struct wcsrtombs_test *test)
+{
+ test_t t;
+ char *v;
+ mbstate_t ms;
+
+ t = test_start("wcsrtombs (locale %s)", locale);
+
+ v = setlocale(LC_ALL, locale);
+ if (v == NULL) {
+ test_failed(t, "setlocale failed: %s", strerror(errno));
+ }
+ if (strcmp(v, locale) != 0) {
+ test_failed(t, "setlocale got %s instead of %s", v, locale);
+ }
+
+ for (int i = 0; test[i].mbs[0] != 0; i++) {
+ char mbs[32];
+ const wchar_t *wcs = test[i].wcs;
+ size_t cnt;
+
+ (void) memset(&ms, 0, sizeof (ms));
+ (void) memset(mbs, 0, sizeof (mbs));
+ cnt = wcsrtombs(mbs, &wcs, sizeof (mbs), &ms);
+ if (cnt != strlen(test[i].mbs)) {
+ test_failed(t, "incorrect return value: %d != %d",
+ cnt, strlen(test[i].mbs));
+ }
+ if (strcmp(mbs, test[i].mbs) != 0) {
+ test_failed(t, "wrong result: %s != %s",
+ mbs, test[i].mbs);
+ }
+ if (extra_debug) {
+ test_debugf(t, "mbs is %s", mbs);
+ }
+ }
+ test_passed(t);
+}
+
+void
+test_wcsrtombs_l(const char *locale, struct wcsrtombs_test *test)
+{
+ test_t t;
+ locale_t loc;
+ char *v;
+ mbstate_t ms;
+
+ t = test_start("wcsrtombs_l (locale %s)", locale);
+
+ v = setlocale(LC_ALL, "C");
+ if (v == NULL) {
+ test_failed(t, "setlocale failed: %s", strerror(errno));
+ }
+ if (strcmp(v, "C") != 0) {
+ test_failed(t, "setlocale got %s instead of %s", v, "C");
+ }
+
+ loc = newlocale(LC_ALL_MASK, locale, NULL);
+ if (loc == NULL) {
+ test_failed(t, "newlocale failed: %s", strerror(errno));
+ }
+
+ for (int i = 0; test[i].mbs[0] != 0; i++) {
+ char mbs[32];
+ const wchar_t *wcs = test[i].wcs;
+ size_t cnt;
+
+ (void) memset(&ms, 0, sizeof (ms));
+ (void) memset(mbs, 0, sizeof (mbs));
+ cnt = wcsrtombs_l(mbs, &wcs, sizeof (mbs), &ms, loc);
+ if (cnt != strlen(test[i].mbs)) {
+ test_failed(t, "incorrect return value: %d != %d",
+ cnt, strlen(test[i].mbs));
+ }
+ if (strcmp(mbs, test[i].mbs) != 0) {
+ test_failed(t, "wrong result: %s != %s", mbs,
+ test[i].mbs);
+ }
+ if (extra_debug) {
+ test_debugf(t, "mbs is %s", mbs);
+ }
+ }
+ test_passed(t);
+}
+
+void
+test_wcsrtombs_thr_iter(test_t t, const char *locale,
+ struct wcsrtombs_test *test)
+{
+ locale_t loc;
+ mbstate_t ms;
+
+ loc = newlocale(LC_ALL_MASK, locale, NULL);
+ if (loc == NULL) {
+ test_failed(t, "newlocale failed: %s", strerror(errno));
+ }
+
+ for (int i = 0; test[i].mbs[0] != 0; i++) {
+ char mbs[32];
+ const wchar_t *wcs = test[i].wcs;
+ size_t cnt;
+
+ (void) memset(&ms, 0, sizeof (ms));
+ (void) memset(mbs, 0, sizeof (mbs));
+ cnt = wcsrtombs_l(mbs, &wcs, sizeof (mbs), &ms, loc);
+ if (cnt != strlen(test[i].mbs)) {
+ test_failed(t, "incorrect return value: %d != %d",
+ cnt, strlen(test[i].mbs));
+ }
+ if (strcmp(mbs, test[i].mbs) != 0) {
+ test_failed(t, "wrong result: %s != %s", mbs,
+ test[i].mbs);
+ }
+ if (extra_debug) {
+ test_debugf(t, "mbs is %s", mbs);
+ }
+ }
+
+ freelocale(loc);
+}
+
+void
+test_wcsrtombs_thr_work(test_t t, void *arg)
+{
+ _NOTE(ARGUNUSED(arg));
+ for (int j = 0; j < NUMITR; j++) {
+ test_debugf(t, "iteration %d", j);
+ for (int i = 0; locales[i].locale != NULL; i++) {
+ test_wcsrtombs_thr_iter(t, locales[i].locale,
+ locales[i].test);
+ }
+ }
+ test_passed(t);
+}
+
+void
+test_wcsrtombs_threaded(void)
+{
+ (void) setlocale(LC_ALL, "C");
+ test_run(NUMTHR, test_wcsrtombs_thr_work, NULL, "wcsrtombs_threaded");
+}
+
+void
+test_wcsrtombs_partial(void)
+{
+ test_t t;
+ mbstate_t ms;
+ wchar_t src[32] = HELLO_RU_WCS;
+ char mbs[32];
+ char *dst;
+ const wchar_t *wcs;
+ size_t cnt;
+
+
+ (void) memset(&ms, 0, sizeof (ms));
+ t = test_start("wcsrtombs_partial");
+
+ if (setlocale(LC_ALL, "ru_RU.UTF-8") == NULL) {
+ test_failed(t, "setlocale failed: %s", strerror(errno));
+ }
+
+ wcs = src;
+ dst = mbs;
+ cnt = wcsrtombs(dst, &wcs, 1, &ms);
+ if (cnt != 0) {
+ test_failed(t, "gave back a conversion cnt %d != 0", cnt);
+ }
+ if (wcs != src) {
+ test_failed(t, "incorrectly advanced wcs");
+ }
+
+ cnt = wcsrtombs(dst, &wcs, 2, &ms);
+ if (cnt != 2) {
+ test_failed(t, "gave back a conversion cnt %d != 2", cnt);
+ }
+ dst += cnt;
+
+ cnt = wcsrtombs(dst, &wcs, 4, &ms);
+ dst += cnt;
+
+ cnt = wcsrtombs(dst, &wcs, sizeof (mbs) - strlen(mbs), &ms);
+ if (extra_debug) {
+ test_debugf(t, "mbs is %s", mbs);
+ }
+ if (strcmp(mbs, HELLO_RU_MBS) != 0) {
+ test_failed(t, "wrong result: %s != %s", mbs, HELLO_RU_MBS);
+ }
+ test_passed(t);
+}
+
+void
+test_wcsrtombs_negative(void)
+{
+ mbstate_t ms;
+ const wchar_t *wcs;
+ char mbs[32];
+ char *dst;
+ int e;
+ wchar_t src[32] = BAD_WCS;
+ test_t t;
+ int cnt;
+
+ t = test_start("wcsrtombs_negative");
+
+ (void) memset(&ms, 0, sizeof (ms));
+ if (setlocale(LC_ALL, "ru_RU.UTF-8") == NULL) {
+ test_failed(t, "setlocale failed: %s", strerror(errno));
+ }
+
+ wcs = src;
+ dst = mbs;
+ cnt = wcsrtombs(dst, &wcs, sizeof (mbs), &ms);
+ if (cnt != -1) {
+ test_failed(t, "bogus success (%d)", cnt);
+ }
+ if ((e = errno) != EILSEQ) {
+ test_failed(t, "wrong errno, wanted %d (EILSEQ), got %d: %s",
+ EILSEQ, e, strerror(e));
+ }
+ test_passed(t);
+}
+
+void
+test_wcsnrtombs_partial(void)
+{
+ test_t t;
+ mbstate_t ms;
+ wchar_t src[32] = HELLO_RU_WCS;
+ char mbs[32];
+ char *dst;
+ const wchar_t *wcs;
+ size_t cnt;
+
+
+ (void) memset(&ms, 0, sizeof (ms));
+ t = test_start("wcsrntombs_partial");
+
+ if (setlocale(LC_ALL, "ru_RU.UTF-8") == NULL) {
+ test_failed(t, "setlocale failed: %s", strerror(errno));
+ }
+
+ wcs = src;
+ dst = mbs;
+ cnt = wcsnrtombs(dst, &wcs, 1, 1, &ms);
+ if (cnt != 0) {
+ test_failed(t, "gave back a conversion cnt %d != 0", cnt);
+ }
+ if (wcs != src) {
+ test_failed(t, "incorrectly advanced wcs");
+ }
+
+ /* we should get just 2 wide characters (expanding to 4 bytes) */
+ cnt = wcsnrtombs(dst, &wcs, 2, sizeof (mbs), &ms);
+ if (cnt != 4) {
+ test_failed(t, "gave back a conversion cnt %d != 4", cnt);
+ }
+ dst += cnt;
+
+ cnt = wcsnrtombs(dst, &wcs, 32, sizeof (mbs) - strlen(mbs), &ms);
+ if (extra_debug) {
+ test_debugf(t, "mbs is %s", mbs);
+ }
+ if (strcmp(mbs, HELLO_RU_MBS) != 0) {
+ test_failed(t, "wrong result: %s != %s", mbs, HELLO_RU_MBS);
+ }
+ test_passed(t);
+}
+
+void
+test_wcsrtombs(void)
+{
+ for (int i = 0; locales[i].locale != NULL; i++) {
+ test_wcsrtombs_1(locales[i].locale, locales[i].test);
+ test_wcsrtombs_l(locales[i].locale, locales[i].test);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int optc;
+
+ while ((optc = getopt(argc, argv, "dfD")) != EOF) {
+ switch (optc) {
+ case 'd':
+ test_set_debug();
+ break;
+ case 'f':
+ test_set_force();
+ break;
+ case 'D':
+ test_set_debug();
+ extra_debug++;
+ break;
+ default:
+ (void) fprintf(stderr, "Usage: %s [-dfD]\n", argv[0]);
+ exit(1);
+ }
+ }
+
+ test_wcsrtombs();
+ test_wcsrtombs_partial();
+ test_wcsrtombs_negative();
+ test_wcsrtombs_threaded();
+ test_wcsnrtombs_partial();
+
+ exit(0);
+}