/ tests / freebsd_open_wmemstream.c
freebsd_open_wmemstream.c
  1  /*-
  2   * Copyright (c) 2013 Hudson River Trading LLC
  3   * Written by: John H. Baldwin <jhb@FreeBSD.org>
  4   * All rights reserved.
  5   *
  6   * Redistribution and use in source and binary forms, with or without
  7   * modification, are permitted provided that the following conditions
  8   * are met:
  9   * 1. Redistributions of source code must retain the above copyright
 10   *    notice, this list of conditions and the following disclaimer.
 11   * 2. Redistributions in binary form must reproduce the above copyright
 12   *    notice, this list of conditions and the following disclaimer in the
 13   *    documentation and/or other materials provided with the distribution.
 14   *
 15   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 16   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 17   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 18   * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 19   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 20   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 21   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 22   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 23   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 24   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 25   * SUCH DAMAGE.
 26   */
 27  
 28  #include <sys/cdefs.h>
 29  
 30  #include <err.h>
 31  #include <errno.h>
 32  #include <limits.h>
 33  #include <stdint.h>
 34  #include <stdio.h>
 35  #include <stdlib.h>
 36  #include <string.h>
 37  #include <wchar.h>
 38  
 39  #include <darwintest.h>
 40  
 41  static wchar_t *buf;
 42  static size_t len;
 43  
 44  static void
 45  assert_stream(const wchar_t *contents)
 46  {
 47  	if (wcslen(contents) != len)
 48  		printf("bad length %zd for \"%ls\"\n", len, contents);
 49  	else if (wcsncmp(buf, contents, wcslen(contents)) != 0)
 50  		printf("bad buffer \"%ls\" for \"%ls\"\n", buf, contents);
 51  }
 52  
 53  T_DECL(freebsd_open_wmemstream_open_group_test, "")
 54  {
 55  	FILE *fp;
 56  	off_t eob;
 57  
 58  	fp = open_wmemstream(&buf, &len);
 59  	T_ASSERT_NOTNULL(fp, "open_wmemstream failed");
 60  
 61  	fwprintf(fp, L"hello my world");
 62  	fflush(fp);
 63  	assert_stream(L"hello my world");
 64  	eob = ftello(fp);
 65  	rewind(fp);
 66  	fwprintf(fp, L"good-bye");
 67  	fseeko(fp, eob, SEEK_SET);
 68  	fclose(fp);
 69  	assert_stream(L"good-bye world");
 70  	free(buf);
 71  }
 72  
 73  T_DECL(freebsd_open_wmemstream_simple_tests, "")
 74  {
 75  	static const wchar_t zerobuf[] =
 76  	    { L'f', L'o', L'o', 0, 0, 0, 0, L'b', L'a', L'r', 0 };
 77  	wchar_t c;
 78  	FILE *fp;
 79  
 80  	fp = open_wmemstream(&buf, NULL);
 81  	T_ASSERT_NULL(fp, "open_wmemstream did not fail");
 82  	T_ASSERT_EQ(errno, EINVAL, "open_wmemstream didn't fail with EINVAL");
 83  	fp = open_wmemstream(NULL, &len);
 84  	T_ASSERT_NULL(fp, "open_wmemstream did not fail");
 85  	T_ASSERT_EQ(errno, EINVAL, "open_wmemstream didn't fail with EINVAL");
 86  	fp = open_wmemstream(&buf, &len);
 87  	T_ASSERT_NOTNULL(fp, "open_memstream failed, errno=%d", errno);
 88  	fflush(fp);
 89  	assert_stream(L"");
 90  	if (fwide(fp, 0) <= 0)
 91  		printf("stream is not wide-oriented\n");
 92  
 93  	fwprintf(fp, L"fo");
 94  	fflush(fp);
 95  	assert_stream(L"fo");
 96  	fputwc(L'o', fp);
 97  	fflush(fp);
 98  	assert_stream(L"foo");
 99  	rewind(fp);
100  	fflush(fp);
101  	assert_stream(L"");
102  	fseek(fp, 0, SEEK_END);
103  	fflush(fp);
104  	assert_stream(L"foo");
105  
106  	/*
107  	 * Test seeking out past the current end.  Should zero-fill the
108  	 * intermediate area.
109  	 */
110  	fseek(fp, 4, SEEK_END);
111  	fwprintf(fp, L"bar");
112  	fflush(fp);
113  
114  	/*
115  	 * Can't use assert_stream() here since this should contain
116  	 * embedded null characters.
117  	 */
118  	if (len != 10)
119  		printf("bad length %zd for zero-fill test\n", len);
120  	else if (memcmp(buf, zerobuf, sizeof(zerobuf)) != 0)
121  		printf("bad buffer for zero-fill test\n");
122  
123  	fseek(fp, 3, SEEK_SET);
124  	fwprintf(fp, L" in ");
125  	fflush(fp);
126  	assert_stream(L"foo in ");
127  	fseek(fp, 0, SEEK_END);
128  	fflush(fp);
129  	assert_stream(L"foo in bar");
130  
131  	rewind(fp);
132  	if (fread(&c, sizeof(c), 1, fp) != 0)
133  		printf("fread did not fail\n");
134  	else if (!ferror(fp))
135  		printf("error indicator not set after fread\n");
136  	else
137  		clearerr(fp);
138  
139  	fseek(fp, 4, SEEK_SET);
140  	fwprintf(fp, L"bar baz");
141  	fclose(fp);
142  	assert_stream(L"foo bar baz");
143  	free(buf);
144  }
145  
146  T_DECL(freebsd_open_wmemstream_seek_tests, "")
147  {
148  	FILE *fp;
149  
150  	fp = open_wmemstream(&buf, &len);
151  	T_ASSERT_NOTNULL(fp, "open_wmemstream failed, errno=%d", errno);
152  
153  #define SEEK_FAIL(offset, whence, error) do {			\
154  	errno = 0;						\
155  	T_ASSERT_NE(fseeko(fp, (offset), (whence)), 0,	\
156  	    "fseeko(%s, %s) did not fail, set pos to %jd",	\
157  	    __STRING(offset), __STRING(whence), \
158  	    (intmax_t)ftello(fp));				\
159  	T_ASSERT_EQ(errno, (error),			\
160  	    "fseeko(%s, %s) failed with %d rather than %s",	\
161  	    __STRING(offset), __STRING(whence),	errno,		\
162  	    __STRING(error));					\
163  } while (0)
164  
165  #define SEEK_OK(offset, whence, result) do {			\
166  	T_ASSERT_EQ(fseeko(fp, (offset), (whence)), 0,	\
167  	    "fseeko(%s, %s) failed: %s",			\
168  	    __STRING(offset), __STRING(whence), strerror(errno)); \
169  	T_ASSERT_EQ(ftello(fp), (off_t)(result),			\
170  	    "fseeko(%s, %s) seeked to %jd rather than %s",	\
171  	    __STRING(offset), __STRING(whence),			\
172  	    (intmax_t)ftello(fp), __STRING(result));		\
173  } while (0)
174  
175  	SEEK_FAIL(-1, SEEK_SET, EINVAL);
176  	SEEK_FAIL(-1, SEEK_CUR, EINVAL);
177  	SEEK_FAIL(-1, SEEK_END, EINVAL);
178  	fwprintf(fp, L"foo");
179  	SEEK_OK(-1, SEEK_CUR, 2);
180  	SEEK_OK(0, SEEK_SET, 0);
181  	SEEK_OK(-1, SEEK_END, 2);
182  	SEEK_OK(OFF_MAX - 1, SEEK_SET, OFF_MAX - 1);
183  	SEEK_FAIL(2, SEEK_CUR, EOVERFLOW);
184  	fclose(fp);
185  }