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