1272343Sngie/* $NetBSD: t_strcat.c,v 1.2 2011/07/14 05:46:04 jruoho Exp $ */
2272343Sngie
3272343Sngie/*
4272343Sngie * Written by J.T. Conklin <jtc@acorntoolworks.com>
5272343Sngie * Public domain.
6272343Sngie */
7272343Sngie
8272343Sngie#include <atf-c.h>
9272343Sngie#include <string.h>
10272343Sngie#include <unistd.h>
11272343Sngie#include <stdio.h>
12272343Sngie#include <stdlib.h>
13272343Sngie
14272343SngieATF_TC(strcat_basic);
15272343SngieATF_TC_HEAD(strcat_basic, tc)
16272343Sngie{
17272343Sngie        atf_tc_set_md_var(tc, "descr", "Test strcat(3) results");
18272343Sngie}
19272343Sngie
20272343SngieATF_TC_BODY(strcat_basic, tc)
21272343Sngie{
22272343Sngie	/* try to trick the compiler */
23272343Sngie	char * (*f)(char *, const char *s) = strcat;
24272343Sngie
25272343Sngie	unsigned int a0, a1, t0, t1;
26272343Sngie	char buf0[64];
27272343Sngie	char buf1[64];
28272343Sngie	char *ret;
29272343Sngie
30272343Sngie	struct tab {
31272343Sngie		const char*	val;
32272343Sngie		size_t		len;
33272343Sngie	};
34272343Sngie
35272343Sngie	const struct tab tab[] = {
36272343Sngie	/*
37272343Sngie	 * patterns that check for all combinations of leading and
38272343Sngie	 * trailing unaligned characters (on a 64 bit processor)
39272343Sngie	 */
40272343Sngie
41272343Sngie		{ "",				0 },
42272343Sngie		{ "a",				1 },
43272343Sngie		{ "ab",				2 },
44272343Sngie		{ "abc",			3 },
45272343Sngie		{ "abcd",			4 },
46272343Sngie		{ "abcde",			5 },
47272343Sngie		{ "abcdef",			6 },
48272343Sngie		{ "abcdefg",			7 },
49272343Sngie		{ "abcdefgh",			8 },
50272343Sngie		{ "abcdefghi",			9 },
51272343Sngie		{ "abcdefghij",			10 },
52272343Sngie		{ "abcdefghijk",		11 },
53272343Sngie		{ "abcdefghijkl",		12 },
54272343Sngie		{ "abcdefghijklm",		13 },
55272343Sngie		{ "abcdefghijklmn",		14 },
56272343Sngie		{ "abcdefghijklmno",		15 },
57272343Sngie		{ "abcdefghijklmnop",		16 },
58272343Sngie		{ "abcdefghijklmnopq",		17 },
59272343Sngie		{ "abcdefghijklmnopqr",		18 },
60272343Sngie		{ "abcdefghijklmnopqrs",	19 },
61272343Sngie		{ "abcdefghijklmnopqrst",	20 },
62272343Sngie		{ "abcdefghijklmnopqrstu",	21 },
63272343Sngie		{ "abcdefghijklmnopqrstuv",	22 },
64272343Sngie		{ "abcdefghijklmnopqrstuvw",	23 },
65272343Sngie
66272343Sngie		/*
67272343Sngie		 * patterns that check for the cases where the expression:
68272343Sngie		 *
69272343Sngie		 *	((word - 0x7f7f..7f) & 0x8080..80)
70272343Sngie		 *
71272343Sngie		 * returns non-zero even though there are no zero bytes in
72272343Sngie		 * the word.
73272343Sngie		 */
74272343Sngie
75272343Sngie		{ "" "\xff\xff\xff\xff\xff\xff\xff\xff" "abcdefgh",	16 },
76272343Sngie		{ "a" "\xff\xff\xff\xff\xff\xff\xff\xff" "bcdefgh",	16 },
77272343Sngie		{ "ab" "\xff\xff\xff\xff\xff\xff\xff\xff" "cdefgh",	16 },
78272343Sngie		{ "abc" "\xff\xff\xff\xff\xff\xff\xff\xff" "defgh",	16 },
79272343Sngie		{ "abcd" "\xff\xff\xff\xff\xff\xff\xff\xff" "efgh",	16 },
80272343Sngie		{ "abcde" "\xff\xff\xff\xff\xff\xff\xff\xff" "fgh",	16 },
81272343Sngie		{ "abcdef" "\xff\xff\xff\xff\xff\xff\xff\xff" "gh",	16 },
82272343Sngie		{ "abcdefg" "\xff\xff\xff\xff\xff\xff\xff\xff" "h",	16 },
83272343Sngie		{ "abcdefgh" "\xff\xff\xff\xff\xff\xff\xff\xff" "",	16 },
84272343Sngie	};
85272343Sngie
86272343Sngie	for (a0 = 0; a0 < sizeof(long); ++a0) {
87272343Sngie		for (a1 = 0; a1 < sizeof(long); ++a1) {
88272343Sngie			for (t0 = 0; t0 < __arraycount(tab); ++t0) {
89272343Sngie				for (t1 = 0; t1 < __arraycount(tab); ++t1) {
90272343Sngie
91272343Sngie					memcpy(&buf0[a0], tab[t0].val,
92272343Sngie					    tab[t0].len + 1);
93272343Sngie					memcpy(&buf1[a1], tab[t1].val,
94272343Sngie					    tab[t1].len + 1);
95272343Sngie
96272343Sngie					ret = f(&buf0[a0], &buf1[a1]);
97272343Sngie
98272343Sngie					/*
99272343Sngie					 * verify strcat returns address
100272343Sngie					 * of first parameter
101272343Sngie					 */
102272343Sngie					if (&buf0[a0] != ret) {
103272343Sngie						fprintf(stderr, "a0 %d, a1 %d, "
104272343Sngie						    "t0 %d, t1 %d\n",
105272343Sngie						    a0, a1, t0, t1);
106272343Sngie						atf_tc_fail("strcat did not "
107272343Sngie						    "return its first arg");
108272343Sngie					}
109272343Sngie
110272343Sngie					/* verify string copied correctly */
111272343Sngie					if (memcmp(&buf0[a0] + tab[t0].len,
112272343Sngie						   &buf1[a1],
113272343Sngie						   tab[t1].len + 1) != 0) {
114272343Sngie						fprintf(stderr, "a0 %d, a1 %d, "
115272343Sngie						    "t0 %d, t1 %d\n",
116272343Sngie						    a0, a1, t0, t1);
117272343Sngie						atf_tc_fail("string not copied "
118272343Sngie						    "correctly");
119272343Sngie					}
120272343Sngie				}
121272343Sngie			}
122272343Sngie		}
123272343Sngie	}
124272343Sngie}
125272343Sngie
126272343SngieATF_TC(strncat_simple);
127272343SngieATF_TC_HEAD(strncat_simple, tc)
128272343Sngie{
129272343Sngie        atf_tc_set_md_var(tc, "descr", "Test strncat(3) results");
130272343Sngie}
131272343Sngie
132272343SngieATF_TC_BODY(strncat_simple, tc)
133272343Sngie{
134272343Sngie	char buf[100] = "abcdefg";
135272343Sngie
136272343Sngie	ATF_CHECK(strncat(buf, "xxx", 0) == buf);
137272343Sngie	ATF_CHECK(strcmp(buf, "abcdefg") == 0);
138272343Sngie	ATF_CHECK(strncat(buf, "xxx", 1) == buf);
139272343Sngie	ATF_CHECK(strcmp(buf, "abcdefgx") == 0);
140272343Sngie	ATF_CHECK(strncat(buf, "xxx", 2) == buf);
141272343Sngie	ATF_CHECK(strcmp(buf, "abcdefgxxx") == 0);
142272343Sngie	ATF_CHECK(strncat(buf, "\0", 1) == buf);
143272343Sngie	ATF_CHECK(strcmp(buf, "abcdefgxxx") == 0);
144272343Sngie}
145272343Sngie
146272343SngieATF_TP_ADD_TCS(tp)
147272343Sngie{
148272343Sngie
149272343Sngie	ATF_TP_ADD_TC(tp, strcat_basic);
150272343Sngie	ATF_TP_ADD_TC(tp, strncat_simple);
151272343Sngie
152272343Sngie	return atf_no_error();
153272343Sngie}
154