fmemopen2_test.c revision 246206
1/*-
2Copyright (C) 2013 Pietro Cerutti <gahr@FreeBSD.org>
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions
6are met:
71. Redistributions of source code must retain the above copyright
8   notice, this list of conditions and the following disclaimer.
92. Redistributions in binary form must reproduce the above copyright
10   notice, this list of conditions and the following disclaimer in the
11   documentation and/or other materials provided with the distribution.
12
13THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23SUCH DAMAGE.
24*/
25
26/*
27 * Test basic FILE * functions (fread, fwrite, fseek, fclose) against
28 * a FILE * retrieved using fmemopen()
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/tools/regression/lib/libc/stdio/test-fmemopen.c 246206 2013-02-01 13:04:06Z gahr $");
33
34#include <assert.h>
35#include <errno.h>
36#include <stdio.h>
37#include <string.h>
38#include <strings.h>
39
40void
41test_preexisting()
42{
43	/*
44	 * Use a pre-existing buffer.
45	 */
46
47	char buf[512];
48	char buf2[512];
49	char str[]  = "Test writing some stuff";
50	char str2[] = "AAAAAAAAA";
51	char str3[] = "AAAA writing some stuff";
52	FILE *fp;
53	size_t nofw, nofr;
54	int rc;
55
56	/* Open a FILE * using fmemopen. */
57	fp = fmemopen(buf, sizeof(buf), "w");
58	assert(fp != NULL);
59
60	/* Write to the buffer. */
61	nofw = fwrite(str, 1, sizeof(str), fp);
62	assert(nofw == sizeof(str));
63
64	/* Close the FILE *. */
65	rc = fclose(fp);
66	assert(rc == 0);
67
68	/* Re-open the FILE * to read back the data. */
69	fp = fmemopen(buf, sizeof(buf), "r");
70	assert(fp != NULL);
71
72	/* Read from the buffer. */
73	bzero(buf2, sizeof(buf2));
74	nofr = fread(buf2, 1, sizeof(buf2), fp);
75	assert(nofr == sizeof(buf2));
76
77	/*
78	 * Since a write on a FILE * retrieved by fmemopen
79	 * will add a '\0' (if there's space), we can check
80	 * the strings for equality.
81	 */
82	assert(strcmp(str, buf2) == 0);
83
84	/* Close the FILE *. */
85	rc = fclose(fp);
86	assert(rc == 0);
87
88	/* Now open a FILE * on the first 4 bytes of the string. */
89	fp = fmemopen(str, 4, "w");
90	assert(fp != NULL);
91
92	/*
93	 * Try to write more bytes than we shoud, we'll get a short count (4).
94	 */
95	nofw = fwrite(str2, 1, sizeof(str2), fp);
96	assert(nofw == 4);
97
98	/* Close the FILE *. */
99	rc = fclose(fp);
100
101	/* Check that the string was not modified after the first 4 bytes. */
102	assert(strcmp(str, str3) == 0);
103}
104
105void
106test_autoalloc()
107{
108	/*
109	 * Let fmemopen allocate the buffer.
110	 */
111
112	char str[] = "A quick test";
113	FILE *fp;
114	long pos;
115	size_t nofw, nofr, i;
116	int rc;
117
118	/* Open a FILE * using fmemopen. */
119	fp = fmemopen(NULL, 512, "w+");
120	assert(fp != NULL);
121
122	/* fill the buffer */
123	for (i = 0; i < 512; i++) {
124		nofw = fwrite("a", 1, 1, fp);
125		assert(nofw == 1);
126	}
127
128	/* Get the current position into the stream. */
129	pos = ftell(fp);
130	assert(pos == 512);
131
132	/*
133	 * Try to write past the end, we should get a short object count (0)
134	 */
135	nofw = fwrite("a", 1, 1, fp);
136	assert(nofw == 0);
137
138	/* Close the FILE *. */
139	rc = fclose(fp);
140	assert(rc == 0);
141}
142
143void
144test_data_length()
145{
146	/*
147	 * Here we test that a read operation doesn't go past the end of the
148	 * data actually written, and that a SEEK_END seeks from the end of the
149	 * data, not of the whole buffer.
150	 */
151	FILE *fp;
152	char buf[512] = {'\0'};
153	char str[]  = "Test data length. ";
154	char str2[] = "Do we have two sentences?";
155	char str3[sizeof(str) + sizeof(str2) -1];
156	long pos;
157	size_t nofw, nofr;
158	int rc;
159
160	/* Open a FILE * for updating our buffer. */
161	fp = fmemopen(buf, sizeof(buf), "w+");
162	assert(fp != NULL);
163
164	/* Write our string into the buffer. */
165	nofw = fwrite(str, 1, sizeof(str), fp);
166	assert(nofw == sizeof(str));
167
168	/*
169	 * Now seek to the end and check that ftell
170	 * gives us sizeof(str).
171	 */
172	rc = fseek(fp, 0, SEEK_END);
173	assert(rc == 0);
174	pos = ftell(fp);
175	assert(pos == sizeof(str));
176
177	/* Close the FILE *. */
178	rc = fclose(fp);
179	assert(rc == 0);
180
181	/* Reopen the buffer for appending. */
182	fp = fmemopen(buf, sizeof(buf), "a+");
183	assert(fp != NULL);
184
185	/* We should now be writing after the first string. */
186	nofw = fwrite(str2, 1, sizeof(str2), fp);
187	assert(nofw == sizeof(str2));
188
189	/* Rewind the FILE *. */
190	rc = fseek(fp, 0, SEEK_SET);
191	assert(rc == 0);
192
193	/* Make sure we're at the beginning. */
194	pos = ftell(fp);
195	assert(pos == 0);
196
197	/* Read the whole buffer. */
198	nofr = fread(str3, 1, sizeof(buf), fp);
199	assert(nofr == sizeof(str3));
200
201	/* Make sure the two strings are there. */
202	assert(strncmp(str3, str, sizeof(str) - 1) == 0);
203	assert(strncmp(str3 + sizeof(str) - 1, str2, sizeof(str2)) == 0);
204
205	/* Close the FILE *. */
206	rc = fclose(fp);
207	assert(rc == 0);
208}
209
210void
211test_binary()
212{
213	/*
214	 * Make sure that NULL bytes are never appended when opening a buffer
215	 * in binary mode.
216	 */
217
218	FILE *fp;
219	char buf[20];
220	char str[] = "Test";
221	size_t nofw;
222	int rc, i;
223
224	/* Pre-fill the buffer. */
225	memset(buf, 'A', sizeof(buf));
226
227	/* Open a FILE * in binary mode. */
228	fp = fmemopen(buf, sizeof(buf), "w+b");
229	assert(fp != NULL);
230
231	/* Write some data into it. */
232	nofw = fwrite(str, 1, strlen(str), fp);
233	assert(nofw == strlen(str));
234
235	/* Make sure that the buffer doesn't contain any NULL bytes. */
236	for (i = 0; i < sizeof(buf); i++)
237		assert(buf[i] != '\0');
238
239	/* Close the FILE *. */
240	rc = fclose(fp);
241	assert(rc == 0);
242}
243
244int
245main(void)
246{
247	test_autoalloc();
248	test_preexisting();
249	test_data_length();
250	test_binary();
251	return (0);
252}
253