Path: blob/main/lib/libc/tests/stdlib/strfmon_test.c
39530 views
/*-1* Copyright (C) 2018 Conrad Meyer <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526#include <sys/param.h>2728#include <locale.h>29#include <monetary.h>30#include <stdio.h>3132#include <atf-c.h>3334ATF_TC_WITHOUT_HEAD(strfmon_locale_thousands);35ATF_TC_BODY(strfmon_locale_thousands, tc)36{37char actual[40], expected[40];38struct lconv *lc;39const char *ts;40double n;4142setlocale(LC_MONETARY, "sv_SE.UTF-8");4344lc = localeconv();4546ts = lc->mon_thousands_sep;47if (strlen(ts) == 0)48ts = lc->thousands_sep;4950if (strlen(ts) < 2)51atf_tc_skip("multi-byte thousands-separator not found");5253n = 1234.56;54strfmon(actual, sizeof(actual) - 1, "%i", n);5556strcpy(expected, "1");57strlcat(expected, ts, sizeof(expected));58strlcat(expected, "234", sizeof(expected));5960/* We're just testing the thousands separator, not all of strfmon. */61actual[strlen(expected)] = '\0';62ATF_CHECK_STREQ(expected, actual);63}6465ATF_TC_WITHOUT_HEAD(strfmon_examples);66ATF_TC_BODY(strfmon_examples, tc)67{68const struct {69const char *format;70const char *expected;71} tests[] = {72{ "%n", "[$123.45] [-$123.45] [$3,456.78]" },73{ "%11n", "[ $123.45] [ -$123.45] [ $3,456.78]" },74{ "%#5n", "[ $ 123.45] [-$ 123.45] [ $ 3,456.78]" },75{ "%=*#5n", "[ $***123.45] [-$***123.45] [ $*3,456.78]" },76{ "%=0#5n", "[ $000123.45] [-$000123.45] [ $03,456.78]" },77{ "%^#5n", "[ $ 123.45] [-$ 123.45] [ $ 3456.78]" },78{ "%^#5.0n", "[ $ 123] [-$ 123] [ $ 3457]" },79{ "%^#5.4n", "[ $ 123.4500] [-$ 123.4500] [ $ 3456.7810]" },80{ "%(#5n", "[ $ 123.45 ] [($ 123.45)] [ $ 3,456.78 ]" },81{ "%!(#5n", "[ 123.45 ] [( 123.45)] [ 3,456.78 ]" },82{ "%-14#5.4n", "[ $ 123.4500 ] [-$ 123.4500 ] [ $ 3,456.7810 ]" },83{ "%14#5.4n", "[ $ 123.4500] [ -$ 123.4500] [ $ 3,456.7810]" },84};85size_t i;86char actual[100], format[50];8788if (setlocale(LC_MONETARY, "en_US.UTF-8") == NULL)89atf_tc_skip("unable to setlocale()");9091for (i = 0; i < nitems(tests); ++i) {92snprintf(format, sizeof(format), "[%s] [%s] [%s]",93tests[i].format, tests[i].format, tests[i].format);94strfmon(actual, sizeof(actual) - 1, format,95123.45, -123.45, 3456.781);96ATF_CHECK_STREQ_MSG(tests[i].expected, actual,97"[%s]", tests[i].format);98}99}100101ATF_TC(strfmon_cs_precedes_0);102ATF_TC_HEAD(strfmon_cs_precedes_0, tc)103{104atf_tc_set_md_var(tc, "descr",105"sep_by_space x sign_posn when cs_precedes = 0");106}107ATF_TC_BODY(strfmon_cs_precedes_0, tc)108{109const struct {110const char *expected;111} tests[] = {112/* sep_by_space x sign_posn */113{ "[(123.00$)] [-123.00$] [123.00$-] [123.00-$] [123.00$-]" },114{ "[(123.00 $)] [-123.00 $] [123.00 $-] [123.00 -$] [123.00 $-]" },115{ "[(123.00$)] [- 123.00$] [123.00$ -] [123.00- $] [123.00$ -]" },116};117size_t i, j;118struct lconv *lc;119char actual[100], buf[100];120121if (setlocale(LC_MONETARY, "en_US.UTF-8") == NULL)122atf_tc_skip("unable to setlocale()");123124lc = localeconv();125lc->n_cs_precedes = 0;126127for (i = 0; i < nitems(tests); ++i) {128actual[0] = '\0';129lc->n_sep_by_space = i;130131for (j = 0; j < 5; ++j) {132lc->n_sign_posn = j;133134strfmon(buf, sizeof(buf) - 1, "[%n] ", -123.0);135strlcat(actual, buf, sizeof(actual));136}137138actual[strlen(actual) - 1] = '\0';139ATF_CHECK_STREQ_MSG(tests[i].expected, actual,140"sep_by_space = %zu", i);141}142}143144ATF_TC(strfmon_cs_precedes_1);145ATF_TC_HEAD(strfmon_cs_precedes_1, tc)146{147atf_tc_set_md_var(tc, "descr",148"sep_by_space x sign_posn when cs_precedes = 1");149}150ATF_TC_BODY(strfmon_cs_precedes_1, tc)151{152const struct {153const char *expected;154} tests[] = {155/* sep_by_space x sign_posn */156{ "[($123.00)] [-$123.00] [$123.00-] [-$123.00] [$-123.00]" },157{ "[($ 123.00)] [-$ 123.00] [$ 123.00-] [-$ 123.00] [$- 123.00]" },158{ "[($123.00)] [- $123.00] [$123.00 -] [- $123.00] [$ -123.00]" },159};160size_t i, j;161struct lconv *lc;162char actual[100], buf[100];163164if (setlocale(LC_MONETARY, "en_US.UTF-8") == NULL)165atf_tc_skip("unable to setlocale()");166167lc = localeconv();168lc->n_cs_precedes = 1;169170for (i = 0; i < nitems(tests); ++i) {171actual[0] = '\0';172lc->n_sep_by_space = i;173174for (j = 0; j < 5; ++j) {175lc->n_sign_posn = j;176177strfmon(buf, sizeof(buf) - 1, "[%n] ", -123.0);178strlcat(actual, buf, sizeof(actual));179}180181actual[strlen(actual) - 1] = '\0';182ATF_CHECK_STREQ_MSG(tests[i].expected, actual,183"sep_by_space = %zu", i);184}185}186187ATF_TC_WITHOUT_HEAD(strfmon_international_currency_code);188ATF_TC_BODY(strfmon_international_currency_code, tc)189{190const struct {191const char *locale;192const char *expected;193} tests[] = {194{ "en_US.UTF-8", "[USD123.45]" },195{ "de_DE.UTF-8", "[123,45 EUR]" },196{ "C", "[123.45]" },197};198size_t i;199char actual[100];200201for (i = 0; i < nitems(tests); ++i) {202if (setlocale(LC_MONETARY, tests[i].locale) == NULL)203atf_tc_skip("unable to setlocale()");204205strfmon(actual, sizeof(actual) - 1, "[%i]", 123.45);206ATF_CHECK_STREQ(tests[i].expected, actual);207}208}209210ATF_TC(strfmon_l);211ATF_TC_HEAD(strfmon_l, tc)212{213atf_tc_set_md_var(tc, "descr",214"checks strfmon_l under different locales");215}216ATF_TC_BODY(strfmon_l, tc)217{218const struct {219const char *locale;220const char *expected;221} tests[] = {222{ "C", "[ **1234.57 ] [ **1234.57 ]" },223{ "de_DE.UTF-8", "[ **1234,57 €] [ **1.234,57 EUR]" },224{ "en_GB.UTF-8", "[ £**1234.57] [ GBP**1,234.57]" },225};226locale_t loc;227size_t i;228char buf[100];229230for (i = 0; i < nitems(tests); ++i) {231loc = newlocale(LC_MONETARY_MASK, tests[i].locale, NULL);232ATF_REQUIRE(loc != NULL);233234strfmon_l(buf, sizeof(buf) - 1, loc, "[%^=*#6n] [%=*#6i]",2351234.567, 1234.567);236ATF_REQUIRE_STREQ(tests[i].expected, buf);237238freelocale(loc);239}240}241242ATF_TP_ADD_TCS(tp)243{244ATF_TP_ADD_TC(tp, strfmon_locale_thousands);245ATF_TP_ADD_TC(tp, strfmon_examples);246ATF_TP_ADD_TC(tp, strfmon_cs_precedes_0);247ATF_TP_ADD_TC(tp, strfmon_cs_precedes_1);248ATF_TP_ADD_TC(tp, strfmon_international_currency_code);249ATF_TP_ADD_TC(tp, strfmon_l);250return (atf_no_error());251}252253254