Path: blob/main/lib/libc/tests/gen/fnmatch_test.c
105246 views
/*-1* Copyright (c) 2010 Jilles Tjoelker2* 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>27#include <errno.h>28#include <locale.h>29#include <stdio.h>30#include <stdlib.h>31#include <string.h>32#include <unistd.h>3334#include <atf-c.h>3536#include "fnmatch_testcases.h"3738static const char *39flags_to_string(int flags)40{41static const int flagvalues[] = { FNM_NOESCAPE, FNM_PATHNAME,42FNM_PERIOD, FNM_LEADING_DIR, FNM_CASEFOLD, 0 };43static const char flagnames[] = "FNM_NOESCAPE\0FNM_PATHNAME\0FNM_PERIOD\0FNM_LEADING_DIR\0FNM_CASEFOLD\0";44static char result[sizeof(flagnames) + 3 * sizeof(int) + 2];45char *p;46size_t i, len;47const char *fp;4849p = result;50fp = flagnames;51for (i = 0; flagvalues[i] != 0; i++) {52len = strlen(fp);53if (flags & flagvalues[i]) {54if (p != result)55*p++ = '|';56memcpy(p, fp, len);57p += len;58flags &= ~flagvalues[i];59}60fp += len + 1;61}62if (p == result)63memcpy(p, "0", 2);64else if (flags != 0)65sprintf(p, "%d", flags);66else67*p = '\0';68return result;69}7071ATF_TC_WITHOUT_HEAD(fnmatch_test);72ATF_TC_BODY(fnmatch_test, tc)73{74size_t i;75int flags, result;76struct testcase *t;7778for (i = 0; i < nitems(testcases); i++) {79t = &testcases[i];80flags = t->flags;81do {82result = fnmatch(t->pattern, t->string, flags);83if (result != t->result)84break;85if (strchr(t->pattern, '\\') == NULL &&86!(flags & FNM_NOESCAPE)) {87flags |= FNM_NOESCAPE;88result = fnmatch(t->pattern, t->string, flags);89if (result != t->result)90break;91flags = t->flags;92}93if (strchr(t->pattern, '\\') != NULL &&94strchr(t->string, '\\') == NULL &&95t->result == FNM_NOMATCH &&96!(flags & (FNM_NOESCAPE | FNM_LEADING_DIR))) {97flags |= FNM_NOESCAPE;98result = fnmatch(t->pattern, t->string, flags);99if (result != t->result)100break;101flags = t->flags;102}103if ((t->string[0] != '.' || t->pattern[0] == '.' ||104t->result == FNM_NOMATCH) &&105!(flags & (FNM_PATHNAME | FNM_PERIOD))) {106flags |= FNM_PERIOD;107result = fnmatch(t->pattern, t->string, flags);108if (result != t->result)109break;110flags = t->flags;111}112if ((strchr(t->string, '/') == NULL ||113t->result == FNM_NOMATCH) &&114!(flags & FNM_PATHNAME)) {115flags |= FNM_PATHNAME;116result = fnmatch(t->pattern, t->string, flags);117if (result != t->result)118break;119flags = t->flags;120}121if ((((t->string[0] != '.' || t->pattern[0] == '.') &&122strstr(t->string, "/.") == NULL) ||123t->result == FNM_NOMATCH) &&124flags & FNM_PATHNAME && !(flags & FNM_PERIOD)) {125flags |= FNM_PERIOD;126result = fnmatch(t->pattern, t->string, flags);127if (result != t->result)128break;129flags = t->flags;130}131if ((((t->string[0] != '.' || t->pattern[0] == '.') &&132strchr(t->string, '/') == NULL) ||133t->result == FNM_NOMATCH) &&134!(flags & (FNM_PATHNAME | FNM_PERIOD))) {135flags |= FNM_PATHNAME | FNM_PERIOD;136result = fnmatch(t->pattern, t->string, flags);137if (result != t->result)138break;139flags = t->flags;140}141if ((strchr(t->string, '/') == NULL || t->result == 0)142&& !(flags & FNM_LEADING_DIR)) {143flags |= FNM_LEADING_DIR;144result = fnmatch(t->pattern, t->string, flags);145if (result != t->result)146break;147flags = t->flags;148}149if (t->result == 0 && !(flags & FNM_CASEFOLD)) {150flags |= FNM_CASEFOLD;151result = fnmatch(t->pattern, t->string, flags);152if (result != t->result)153break;154flags = t->flags;155}156if (strchr(t->pattern, '\\') == NULL &&157t->result == 0 &&158!(flags & (FNM_NOESCAPE | FNM_CASEFOLD))) {159flags |= FNM_NOESCAPE | FNM_CASEFOLD;160result = fnmatch(t->pattern, t->string, flags);161if (result != t->result)162break;163flags = t->flags;164}165} while (0);166167ATF_CHECK(result == t->result);168if (result == t->result)169printf("fnmatch(\"%s\", \"%s\", %s) == %d\n",170t->pattern, t->string, flags_to_string(flags), result);171else172printf("fnmatch(\"%s\", \"%s\", %s) != %d (was %d)\n",173t->pattern, t->string, flags_to_string(flags),174t->result, result);175}176177}178179ATF_TC(fnmatch_characterclass);180ATF_TC_HEAD(fnmatch_characterclass, tc)181{182atf_tc_set_md_var(tc, "descr", "Test fnmatch with character classes");183}184185ATF_TC_BODY(fnmatch_characterclass, tc)186{187ATF_CHECK(fnmatch("[[:alnum:]]", "a", 0) == 0);188ATF_CHECK(fnmatch("[[:cntrl:]]", "\a", 0) == 0);189ATF_CHECK(fnmatch("[[:lower:]]", "a", 0) == 0);190ATF_CHECK(fnmatch("[[:space:]]", " ", 0) == 0);191ATF_CHECK(fnmatch("[[:alpha:]]", "a", 0) == 0);192ATF_CHECK(fnmatch("[[:digit:]]", "0", 0) == 0);193ATF_CHECK(fnmatch("[[:print:]]", "a", 0) == 0);194ATF_CHECK(fnmatch("[[:upper:]]", "A", 0) == 0);195ATF_CHECK(fnmatch("[[:blank:]]", " ", 0) == 0);196ATF_CHECK(fnmatch("[[:graph:]]", "a", 0) == 0);197ATF_CHECK(fnmatch("[[:punct:]]", ".", 0) == 0);198ATF_CHECK(fnmatch("[[:xdigit:]]", "f", 0) == 0);199200/*201* POSIX.1, section 9.3.5. states that '[:' and ':]'202* should be interpreted as character classes symbol only203* when part of a bracket expression.204*/205ATF_CHECK(fnmatch("[:alnum:]", "a", 0) == 0);206ATF_CHECK(fnmatch("[:alnum:]", ":", 0) == 0);207ATF_CHECK(fnmatch("[:alnum:]", "1", 0) != 0);208}209210ATF_TC(fnmatch_collsym);211ATF_TC_HEAD(fnmatch_collsym, tc)212{213atf_tc_set_md_var(tc, "descr", "Test fnmatch with collating symbols");214}215216ATF_TC_BODY(fnmatch_collsym, tc)217{218setlocale(LC_ALL, "cs_CZ.UTF-8");219ATF_CHECK(fnmatch("[ch]", "ch", 0) != 0);220ATF_CHECK(fnmatch("[[.ch.]]", "ch", 0) == 0);221ATF_CHECK(fnmatch("[[.ch.]]h", "chh", 0) == 0);222223/*224* POSIX.1, section 9.3.5. states that '[.' and '.]'225* should be interpreted as a collating symbol only226* when part of a bracket expression.227*/228ATF_CHECK(fnmatch("[.ch.]", "c", 0) == 0);229ATF_CHECK(fnmatch("[.ch.]", "h", 0) == 0);230ATF_CHECK(fnmatch("[.ch.]", ".", 0) == 0);231}232233ATF_TC(fnmatch_equivclass);234ATF_TC_HEAD(fnmatch_equivclass, tc)235{236atf_tc_set_md_var(tc, "descr", "Test fnmatch with equivalence classes");237}238239ATF_TC_BODY(fnmatch_equivclass, tc)240{241setlocale(LC_ALL, "en_US.UTF-8");242ATF_CHECK(fnmatch("[[=a=]]b", "ab", 0) == 0);243ATF_CHECK(fnmatch("[[=a=]]b", "Ab", 0) == 0);244ATF_CHECK(fnmatch("[[=à=]]b", "ab", 0) == 0);245ATF_CHECK(fnmatch("[[=a=]]b", "àb", 0) == 0);246247/*248* POSIX.1, section 9.3.5. states that '[=' and '=]'249* should be interpreted as an equivalence class only250* when part of a bracket expression.251*/252ATF_CHECK(fnmatch("[=a=]b", "=b", 0) == 0);253ATF_CHECK(fnmatch("[=a=]b", "ab", 0) == 0);254}255256ATF_TP_ADD_TCS(tp)257{258259ATF_TP_ADD_TC(tp, fnmatch_test);260ATF_TP_ADD_TC(tp, fnmatch_collsym);261ATF_TP_ADD_TC(tp, fnmatch_characterclass);262ATF_TP_ADD_TC(tp, fnmatch_equivclass);263264return (atf_no_error());265}266267268