summaryrefslogtreecommitdiff
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
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>
-rw-r--r--usr/src/Makefile.master12
-rw-r--r--usr/src/Makefile.master.6410
-rw-r--r--usr/src/head/iso/wchar_iso.h14
-rw-r--r--usr/src/head/xlocale.h4
-rw-r--r--usr/src/lib/libc/port/llib-lc2
-rw-r--r--usr/src/lib/libc/port/locale/lmonetary.c4
-rw-r--r--usr/src/lib/libc/port/mapfile-vers6
-rw-r--r--usr/src/man/man3c/Makefile7
-rw-r--r--usr/src/man/man3c/wcsrtombs.3c47
-rw-r--r--usr/src/man/man3lib/libc.3lib1
-rw-r--r--usr/src/pkg/manifests/system-library.man3c.inc3
-rw-r--r--usr/src/pkg/manifests/system-test-libctest.mf15
-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
25 files changed, 1346 insertions, 141 deletions
diff --git a/usr/src/Makefile.master b/usr/src/Makefile.master
index 0d07b02880..ba737c51d4 100644
--- a/usr/src/Makefile.master
+++ b/usr/src/Makefile.master
@@ -22,6 +22,7 @@
#
# Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
#
#
@@ -657,8 +658,9 @@ MAPFILE.NGB = $(MAPFILE.NGB_$(MACH))
MAPFILE.INT = mapfile-intf
#
-# LDLIBS32 can be set in the environment to override the following assignment.
-# LDLIBS64 can be set to override the assignment made in Makefile.master.64.
+# LDLIBS32 and LDLIBS64 can be set in the environment to override the following
+# assignments.
+#
# These environment settings make sure that no libraries are searched outside
# of the local workspace proto area:
# LDLIBS32=-YP,$ROOT/lib:$ROOT/usr/lib
@@ -668,6 +670,12 @@ LDLIBS32 = $(ENVLDLIBS1) $(ENVLDLIBS2) $(ENVLDLIBS3)
LDLIBS32 += $(ADJUNCT_PROTO:%=-L%/usr/lib -L%/lib)
LDLIBS.cmd = $(LDLIBS32)
LDLIBS.lib = $(LDLIBS32)
+
+LDLIBS64 = $(ENVLDLIBS1:%=%/$(MACH64)) \
+ $(ENVLDLIBS2:%=%/$(MACH64)) \
+ $(ENVLDLIBS3:%=%/$(MACH64))
+LDLIBS64 += $(ADJUNCT_PROTO:%=-L%/usr/lib/$(MACH64) -L%/lib/$(MACH64))
+
#
# Define compilation macros.
#
diff --git a/usr/src/Makefile.master.64 b/usr/src/Makefile.master.64
index 09169831a1..79ed039f66 100644
--- a/usr/src/Makefile.master.64
+++ b/usr/src/Makefile.master.64
@@ -20,6 +20,7 @@
#
#
# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
#
# rebind basic build macros to 64-bit versions
@@ -42,15 +43,6 @@ CTF_FLAGS= $(CTF_FLAGS_64)
OFFSETS_CREATE= $(OFFSETS_CREATE64)
#
-# Some library path hackery, to allow building of partial workspaces
-# and properly set the 64-bit library paths with 'ws'
-#
-LDLIBS1= $(ENVLDLIBS1:%=%/$(MACH64))
-LDLIBS2= $(ENVLDLIBS2:%=%/$(MACH64))
-LDLIBS3= $(ENVLDLIBS3:%=%/$(MACH64))
-LDLIBS64 = $(LDLIBS1) $(LDLIBS2) $(LDLIBS3)
-LDLIBS64 += $(ADJUNCT_PROTO:%=-L%/usr/lib/$(MACH64) -L%/lib/$(MACH64))
-#
# Moved these up to the top level here, so they can be overridden
#
LDLIBS.cmd = $(LDLIBS64)
diff --git a/usr/src/head/iso/wchar_iso.h b/usr/src/head/iso/wchar_iso.h
index 698dc1e7a9..6830794381 100644
--- a/usr/src/head/iso/wchar_iso.h
+++ b/usr/src/head/iso/wchar_iso.h
@@ -25,6 +25,10 @@
*/
/*
+ * Copyright 2014 Garrett D'Amore <garrett@damore.org>
+ */
+
+/*
* An application should not include this header directly. Instead it
* should be included only through the inclusion of other Sun headers.
*
@@ -39,8 +43,6 @@
#ifndef _ISO_WCHAR_ISO_H
#define _ISO_WCHAR_ISO_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/feature_tests.h>
#include <stdio_tag.h>
#include <wchar_impl.h>
@@ -326,6 +328,10 @@ extern size_t wcrtomb(char *_RESTRICT_KYWD, wchar_t,
mbstate_t *_RESTRICT_KYWD);
extern size_t wcsrtombs(char *_RESTRICT_KYWD, const wchar_t **_RESTRICT_KYWD,
size_t, mbstate_t *_RESTRICT_KYWD);
+#if defined(_XPG7) || !defined(_STRICT_SYMBOLS)
+extern size_t wcsnrtombs(char *_RESTRICT_KYWD, const wchar_t **_RESTRICT_KYWD,
+ size_t, size_t, mbstate_t *_RESTRICT_KYWD);
+#endif
extern int wctob(wint_t);
extern int wmemcmp(const wchar_t *, const wchar_t *, size_t);
extern wchar_t *wmemcpy(wchar_t *_RESTRICT_KYWD,
@@ -420,6 +426,10 @@ extern int vwprintf();
extern int vswprintf();
extern size_t wcrtomb();
extern size_t wcsrtombs();
+#if defined(_XPG7) || !defined(_STRICT_SYMBOLS)
+extern size_t wcsnrtombs();
+#endif
+
extern wchar_t *wcsstr();
extern int wctob();
extern wchar_t *wmemchr();
diff --git a/usr/src/head/xlocale.h b/usr/src/head/xlocale.h
index 7393a31a15..9179cf9761 100644
--- a/usr/src/head/xlocale.h
+++ b/usr/src/head/xlocale.h
@@ -81,7 +81,9 @@ extern size_t mbrlen_l(const char *_RESTRICT_KYWD, size_t,
extern int mbtowc_l(wchar_t *_RESTRICT_KYWD, const char *_RESTRICT_KYWD, size_t,
locale_t);
extern size_t wcsrtombs_l(char *_RESTRICT_KYWD, const wchar_t **_RESTRICT_KYWD,
- size_t len, mbstate_t *_RESTRICT_KYWD, locale_t);
+ size_t, mbstate_t *_RESTRICT_KYWD, locale_t);
+extern size_t wcsnrtombs_l(char *_RESTRICT_KYWD, const wchar_t **_RESTRICT_KYWD,
+ size_t, size_t, mbstate_t *_RESTRICT_KYWD, locale_t);
extern size_t wcrtomb_l(char *_RESTRICT_KYWD, wchar_t,
mbstate_t *_RESTRICT_KYWD, locale_t);
extern size_t wcstombs_l(char *_RESTRICT_KYWD, const wchar_t *_RESTRICT_KYWD,
diff --git a/usr/src/lib/libc/port/llib-lc b/usr/src/lib/libc/port/llib-lc
index eb2fb4357b..9f493e21d4 100644
--- a/usr/src/lib/libc/port/llib-lc
+++ b/usr/src/lib/libc/port/llib-lc
@@ -24,6 +24,7 @@
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright 2013 OmniTI Computer Consulting, Inc. All rights reserved.
* Copyright (c) 2013 Gary Mills
+ * Copyright 2014 Garrett D'Amore <garrett@damore.org>
*/
/* LINTLIBRARY */
@@ -165,6 +166,7 @@
#if defined(__amd64)
#include <stack_unwind.h>
#endif
+#include <xlocale.h>
/*
* This really comes from the crt*.s startup modules.
diff --git a/usr/src/lib/libc/port/locale/lmonetary.c b/usr/src/lib/libc/port/locale/lmonetary.c
index 623abc6281..373583171b 100644
--- a/usr/src/lib/libc/port/locale/lmonetary.c
+++ b/usr/src/lib/libc/port/locale/lmonetary.c
@@ -156,10 +156,10 @@ __lc_monetary_load(const char *name)
char sign = '\0';
switch (lmon->p_cs_precedes[0]) {
case 0:
- sign = '-';
+ sign = '+';
break;
case 1:
- sign = '+';
+ sign = '-';
break;
case CHAR_MAX:
/*
diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers
index c07a40aaf5..6509cd1aad 100644
--- a/usr/src/lib/libc/port/mapfile-vers
+++ b/usr/src/lib/libc/port/mapfile-vers
@@ -93,6 +93,12 @@ $if _x86 && _ELF64
$add amd64
$endif
+SYMBOL_VERSION ILLUMOS_0.9 {
+ protected:
+ wcsnrtombs;
+ wcsnrtombs_l;
+} ILLUMOS_0.8;
+
SYMBOL_VERSION ILLUMOS_0.8 { # POSIX 2008 newlocale and friends
protected:
__global_locale;
diff --git a/usr/src/man/man3c/Makefile b/usr/src/man/man3c/Makefile
index 7e6a965ce8..5132755460 100644
--- a/usr/src/man/man3c/Makefile
+++ b/usr/src/man/man3c/Makefile
@@ -1242,8 +1242,11 @@ MANLINKS= FD_CLR.3c \
wcsncat.3c \
wcsncmp.3c \
wcsncpy.3c \
+ wcsnrtombs.3c \
+ wcsnrtombs_l.3c \
wcspbrk.3c \
wcsrchr.3c \
+ wcsrtombs_l.3c \
wcsspn.3c \
wcstof.3c \
wcstok.3c \
@@ -2226,6 +2229,10 @@ wcrtomb_l.3c := LINKSRC = wcrtomb.3c
wcscoll_l.3c := LINKSRC = wcscoll.3c
wscoll.3c := LINKSRC = wcscoll.3c
+wcsnrtombs.3c := LINKSRC = wcsrtombs.3c
+wcsnrtombs_l.3c := LINKSRC = wcsrtombs.3c
+wcsrtombs_l.3c := LINKSRC = wcsrtombs.3c
+
watof.3c := LINKSRC = wcstod.3c
wcstof.3c := LINKSRC = wcstod.3c
wcstold.3c := LINKSRC = wcstod.3c
diff --git a/usr/src/man/man3c/wcsrtombs.3c b/usr/src/man/man3c/wcsrtombs.3c
index 860f83b913..4068427f8a 100644
--- a/usr/src/man/man3c/wcsrtombs.3c
+++ b/usr/src/man/man3c/wcsrtombs.3c
@@ -8,27 +8,34 @@
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH WCSRTOMBS 3C "Jun 25, 2014"
+.TH WCSRTOMBS 3C "Jul 13, 2014"
.SH NAME
-wcsrtombs, wcsrtombs_l \- convert a wide-character string to a character string
+wcsnrtombs, wcsnrtombs_l, wcsrtombs, wcsrtombs_l \- convert a wide-character string to a character string
(restartable)
.SH SYNOPSIS
.LP
.nf
#include <wchar.h>
-\fBsize_t\fR \fBwcsrtombs\fR(\fBchar *restrict\fR \fIdst\fR,
- \fBconst wchar_t **restrict\fR \fIsrc\fR, \fBsize_t\fR \fIlen\fR,
- \fBmbstate_t *restrict\fR \fIps\fR);
+\fBsize_t\fR \fBwcsrtombs\fR(\fBchar *restrict\fR \fIdst\fR, \fBconst wchar_t **restrict\fR \fIsrc\fR,
+ \fBsize_t\fR \fIlen\fR, \fBmbstate_t *restrict\fR \fIps\fR);
.fi
.LP
.nf
+\fBsize_t\fR \fBwcsnrtombs\fR(\fBchar *restrict\fR \fIdst\fR, \fBconst wchar_t **restrict\fR \fIsrc\fR,
+ \fBsize_t\fR \fInwc\fR, \fBsize_t\fR \fIlen\fR, \fBmbstate_t *restrict\fR \fIps\fR);
+.LP
+.nf
#include <wchar.h>
#include <xlocale.h>
-\fBsize_t\fR \fBwcsrtombs_l\fR(\fBchar *restrict\fR \fIdst\fR,
- \fBconst wchar_t **restrict\fR \fIsrc\fR, \fBsize_t\fR \fIlen\fR,
- \fBmbstate_t *restrict\fR \fIps\fR, \fBlocale_t\fR \fIloc\fR);
+\fBsize_t\fR \fBwcsrtombs_l\fR(\fBchar *restrict\fR \fIdst\fR, \fBconst wchar_t **restrict\fR \fIsrc\fR,
+ \fBsize_t\fR \fIlen\fR, \fBmbstate_t *restrict\fR \fIps\fR, \fBlocale_t\fR \fIloc\fR);
+.fi
+.LP
+.nf
+\fBsize_t\fR \fBwcsnrtombs_l\fR(\fBchar *restrict\fR \fIdst\fR, \fBconst wchar_t **restrict\fR \fIsrc\fR,
+ \fBsize_t\fR \fInwc\fR, \fBsize_t\fR \fIlen\fR, \fBmbstate_t *restrict\fR \fIps\fR, \fBlocale_t\fR \fIloc\fR);
.fi
.SH DESCRIPTION
.LP
@@ -53,6 +60,13 @@ When the next character would exceed the limit of \fIlen\fR total bytes to be
stored in the array pointed to by \fIdst\fR (and \fIdst\fR is not a null
pointer).
.RE
+.RS +4
+.TP
+.ie t \(bu
+.el o
+In the case of \fBwcsnrtombs()\fR and \fBwcsnrtombs_l()\fR, when \fInwc\fR
+wide characters have been completely converted.
+.RE
.LP
Each conversion takes place as if by a call to the \fBwcrtomb()\fR function.
.LP
@@ -63,18 +77,19 @@ wide-character converted (if any). If conversion stopped due to reaching a
terminating null wide-character, the resulting state described is the initial
conversion state.
.LP
-If \fIps\fR is a null pointer, the \fBwcsrtombs()\fR function uses its own
+If \fIps\fR is a null pointer, these functions uses their own
internal \fBmbstate_t\fR object, which is initialized at program startup to the
initial conversion state. Otherwise, the \fBmbstate_t\fR object pointed to by
\fIps\fR is used to completely describe the current conversion state of the
associated character sequence. The system will behave as if no function defined
in the Reference Manual calls any of these functions.
.LP
-The behavior of \fBwcsrtombs()\fR is affected by the \fBLC_CTYPE\fR category of
-the current locale. See \fBenviron\fR(5).
+The behavior of \fBwcsrtombs()\fR and \fBwcsnrtombs()\fR are affected by the
+\fBLC_CTYPE\fR category of the current locale. See \fBenviron\fR(5).
.LP
-The function \fBwcsrtombs_l()\fR behaves identically to \fBwcsrtombs\fR, except
-instead of operating in the current locale, it operates in the locale
+The \fBwcsrtombs_l()\fR and \fBwcsnrtombs_l()\fR functions behave identically
+to \fBwcsrtombs()\fR and \fBwcsnrtombs()\fR respectively, except
+that instead of operating in the current locale, they operate in the locale
specified by \fIloc\fR.
.SH RETURN VALUES
.LP
@@ -86,7 +101,7 @@ the number of bytes in the resulting character sequence, not including the
terminating null (if any).
.SH ERRORS
.LP
-The \fBwcsrtombs()\fR and \fBwcsrtombs_l()\fR functions may fail if:
+These functions may fail if:
.sp
.ne 2
.na
@@ -120,8 +135,8 @@ MT-Level See below.
.TE
.LP
-The \fBwcsrtombs()\fR function is Standard. The \fBwcsrtombs_l()\fR
-function is Uncommitted.
+The \fBwcsrtombs()\fR and \fBwcsnrtombs()\fR functions are Standard. The
+\fBwcsrtombs_l()\fR and \fBwcsnrtombs_l()\fR functions are Uncommitted.
.LP
If \fIps\fR is a null pointer, these functions should be considered Unsafe
for use in multithreaded applications. Otherwise, they are MT-Safe.
diff --git a/usr/src/man/man3lib/libc.3lib b/usr/src/man/man3lib/libc.3lib
index 387ac1b007..8c75f79bfb 100644
--- a/usr/src/man/man3lib/libc.3lib
+++ b/usr/src/man/man3lib/libc.3lib
@@ -778,6 +778,7 @@ l l .
\fBwcscspn\fR \fBwcsftime\fR
\fBwcslen\fR \fBwcsncat\fR
\fBwcsncmp\fR \fBwcsncpy\fR
+\fBwcsnrtombs\fR \fBwcsnrtombs_l\fR
\fBwcspbrk\fR \fBwcsrchr\fR
\fBwcsrtombs\fR \fBwcsrtombs_l\fR
\fBwcsspn\fR
diff --git a/usr/src/pkg/manifests/system-library.man3c.inc b/usr/src/pkg/manifests/system-library.man3c.inc
index 2714097dc6..d9f6759bba 100644
--- a/usr/src/pkg/manifests/system-library.man3c.inc
+++ b/usr/src/pkg/manifests/system-library.man3c.inc
@@ -1312,8 +1312,11 @@ link path=usr/share/man/man3c/wcslen.3c target=wcstring.3c
link path=usr/share/man/man3c/wcsncat.3c target=wcstring.3c
link path=usr/share/man/man3c/wcsncmp.3c target=wcstring.3c
link path=usr/share/man/man3c/wcsncpy.3c target=wcstring.3c
+link path=usr/share/man/man3c/wcsnrtombs.3c target=wcsrtombs.3c
+link path=usr/share/man/man3c/wcsnrtombs_l.3c target=wcsrtombs.3c
link path=usr/share/man/man3c/wcspbrk.3c target=wcstring.3c
link path=usr/share/man/man3c/wcsrchr.3c target=wcstring.3c
+link path=usr/share/man/man3c/wcsrtombs_l.3c target=wcsrtombs.3c
link path=usr/share/man/man3c/wcsspn.3c target=wcstring.3c
link path=usr/share/man/man3c/wcstof.3c target=wcstod.3c
link path=usr/share/man/man3c/wcstok.3c target=wcstring.3c
diff --git a/usr/src/pkg/manifests/system-test-libctest.mf b/usr/src/pkg/manifests/system-test-libctest.mf
index 896141f517..c65250d7a5 100644
--- a/usr/src/pkg/manifests/system-test-libctest.mf
+++ b/usr/src/pkg/manifests/system-test-libctest.mf
@@ -29,9 +29,24 @@ file path=opt/libc-tests/README mode=0444
file path=opt/libc-tests/bin/libctest mode=0555
file path=opt/libc-tests/runfiles/default.run mode=0444
file path=opt/libc-tests/tests/newlocale_test mode=0555
+$(i386_ONLY)file path=opt/libc-tests/tests/newlocale_test.amd64 mode=0555
+$(i386_ONLY)file path=opt/libc-tests/tests/newlocale_test.i386 mode=0555
+$(sparc_ONLY)file path=opt/libc-tests/tests/newlocale_test.sparc mode=0555
+$(sparc_ONLY)file path=opt/libc-tests/tests/newlocale_test.sparcv9 mode=0555
+file path=opt/libc-tests/tests/nl_langinfo_test mode=0555
+$(i386_ONLY)file path=opt/libc-tests/tests/nl_langinfo_test.amd64 mode=0555
+$(i386_ONLY)file path=opt/libc-tests/tests/nl_langinfo_test.i386 mode=0555
+$(sparc_ONLY)file path=opt/libc-tests/tests/nl_langinfo_test.sparc mode=0555
+$(sparc_ONLY)file path=opt/libc-tests/tests/nl_langinfo_test.sparcv9 mode=0555
+file path=opt/libc-tests/tests/wcsrtombs_test mode=0555
+$(i386_ONLY)file path=opt/libc-tests/tests/wcsrtombs_test.amd64 mode=0555
+$(i386_ONLY)file path=opt/libc-tests/tests/wcsrtombs_test.i386 mode=0555
+$(sparc_ONLY)file path=opt/libc-tests/tests/wcsrtombs_test.sparc mode=0555
+$(sparc_ONLY)file path=opt/libc-tests/tests/wcsrtombs_test.sparcv9 mode=0555
license lic_CDDL license=lic_CDDL
depend fmri=locale/de type=require
depend fmri=locale/en type=require
+depend fmri=locale/en-extra type=require
depend fmri=locale/ja type=require
depend fmri=locale/ru type=require
depend fmri=system/test/testrunner type=require
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);
+}