|  | /* fmemopen tests. | 
|  | Copyright (C) 2015-2016 Free Software Foundation, Inc. | 
|  | This file is part of the GNU C Library. | 
|  |  | 
|  | The GNU C Library is free software; you can redistribute it and/or | 
|  | modify it under the terms of the GNU Lesser General Public | 
|  | License as published by the Free Software Foundation; either | 
|  | version 2.1 of the License, or (at your option) any later version. | 
|  |  | 
|  | The GNU C Library is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | Lesser General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU Lesser General Public | 
|  | License along with the GNU C Library; if not, see | 
|  | <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  |  | 
|  | #include <assert.h> | 
|  | #include <stdio.h> | 
|  | #include <string.h> | 
|  | #include <sys/types.h> | 
|  | #include <errno.h> | 
|  |  | 
|  | /* Check fmemopen with user provided buffer open for write.  */ | 
|  | static int | 
|  | do_test_with_buffer (void) | 
|  | { | 
|  | int result = 0; | 
|  | char buf[100]; | 
|  | const size_t nbuf = sizeof (buf); | 
|  |  | 
|  | FILE *fp = fmemopen (buf, nbuf, "w"); | 
|  | if (fp == NULL) | 
|  | { | 
|  | printf ("FAIL: fmemopen failed (%s)\n", __FUNCTION__); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | /* Default write operation, check if file position is correct after it.  */ | 
|  | static const char str[] = "hello world"; | 
|  | const size_t nstr = sizeof (str) - 1; | 
|  | fputs (str, fp); | 
|  | off_t o = ftello (fp); | 
|  | if (o != nstr) | 
|  | { | 
|  | printf ("FAIL: first ftello returned %jd, expected %zu\n", | 
|  | (intmax_t)o, nstr); | 
|  | result = 1; | 
|  | } | 
|  |  | 
|  | /* Rewind stream and seek tests, the position size should be equal to | 
|  | buffer size provided in open function.  */ | 
|  | rewind (fp); | 
|  | o = ftello (fp); | 
|  | if (o != 0) | 
|  | { | 
|  | printf ("FAIL: second ftello returned %jd, expected 0\n", | 
|  | (intmax_t)o); | 
|  | result = 1; | 
|  | } | 
|  | if (fseeko (fp, 0, SEEK_END) != 0) | 
|  | { | 
|  | printf ("FAIL: fseeko failed\n"); | 
|  | result = 1; | 
|  | } | 
|  | o = ftello (fp); | 
|  | if (o != nstr) | 
|  | { | 
|  | printf ("FAIL: third ftello returned %jd, expected %zu\n", | 
|  | (intmax_t)o, nstr); | 
|  | result = 1; | 
|  | } | 
|  |  | 
|  | /* Rewind the stream and recheck by using a shorter string.  */ | 
|  | rewind (fp); | 
|  | static const char str2[] = "just hello"; | 
|  | const size_t nstr2 = sizeof (str2) - 1; | 
|  | assert (nstr2 < nstr); | 
|  | fputs (str2, fp); | 
|  | o = ftello (fp); | 
|  | if (o != nstr2) | 
|  | { | 
|  | printf ("FAIL: fourth ftello returned %jd, expected %zu\n", | 
|  | (intmax_t)o, nstr2); | 
|  | result = 1; | 
|  | } | 
|  | fclose (fp); | 
|  |  | 
|  | /* Again, but now with a larger string.  */ | 
|  | static const char str3[] = "just hellod"; | 
|  | if (strcmp (buf, str3) != 0) | 
|  | { | 
|  | printf ("FAIL: final string is \"%s\", expected \"%s\"\n", | 
|  | buf, str3); | 
|  | result = 1; | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /* Check fmemopen without user provided buffer open for write.  */ | 
|  | static int | 
|  | do_test_without_buffer (void) | 
|  | { | 
|  | int result = 0; | 
|  | const size_t nbuf = 100; | 
|  |  | 
|  | FILE *fp = fmemopen (NULL, nbuf, "w"); | 
|  | if (fp == NULL) | 
|  | { | 
|  | printf ("FAIL: fmemopen failed (%s)\n", __FUNCTION__); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | static const char str[] = "hello world"; | 
|  | const size_t nstr = sizeof (str) - 1; | 
|  |  | 
|  | /* Default write operation, check if file position is correct after it.  */ | 
|  | fputs (str, fp); | 
|  | off_t o = ftello (fp); | 
|  | if (o != nstr) | 
|  | { | 
|  | printf ("FAIL: first ftello returned %jd, expected %zu\n", | 
|  | (intmax_t) o, nstr); | 
|  | result = 1; | 
|  | } | 
|  | if (fseeko (fp, 0, SEEK_END) != 0) | 
|  | { | 
|  | printf ("FAIL: fseeko failed\n"); | 
|  | result = 1; | 
|  | } | 
|  | o = ftello (fp); | 
|  | if (o != nstr) | 
|  | { | 
|  | printf ("FAIL: second ftello returned %jd, expected %zu\n", | 
|  | (intmax_t) o, nbuf); | 
|  | result = 1; | 
|  | } | 
|  |  | 
|  | /* Rewind the stream and recheck by using a shorter string.  */ | 
|  | rewind (fp); | 
|  | static const char str2[] = "just hello"; | 
|  | const size_t nstr2 = sizeof (str2) - 1; | 
|  | assert (nstr2 < nstr); | 
|  | fputs (str2, fp); | 
|  | o = ftello (fp); | 
|  | if (o != nstr2) | 
|  | { | 
|  | printf ("FAIL: third ftello returned %jd, expected %zu\n", | 
|  | (intmax_t) o, nstr2); | 
|  | result = 1; | 
|  | } | 
|  | fclose (fp); | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /* Check fmemopen with a buffer lenght of zero.  */ | 
|  | static int | 
|  | do_test_length_zero (void) | 
|  | { | 
|  | int result = 0; | 
|  | FILE *fp; | 
|  | #define BUFCONTENTS "testing buffer" | 
|  | char buf[100] = BUFCONTENTS; | 
|  | const size_t nbuf = 0; | 
|  | int r; | 
|  |  | 
|  | fp = fmemopen (buf, nbuf, "r"); | 
|  | if (fp == NULL) | 
|  | { | 
|  | printf ("FAIL: fmemopen failed (%s)\n", __FUNCTION__); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | /* Reading any data on a zero-length buffer should return EOF.  */ | 
|  | if ((r = fgetc (fp)) != EOF) | 
|  | { | 
|  | printf ("FAIL: fgetc on a zero-length returned: %d\n", r); | 
|  | result = 1; | 
|  | } | 
|  | off_t o = ftello (fp); | 
|  | if (o != 0) | 
|  | { | 
|  | printf ("FAIL: first ftello returned %jd, expected 0\n", | 
|  | (intmax_t) o); | 
|  | result = 1; | 
|  | } | 
|  | fclose (fp); | 
|  |  | 
|  | /* Writing any data shall start at current position and shall not pass | 
|  | current buffer size beyond the size in fmemopen call.  */ | 
|  | fp = fmemopen (buf, nbuf, "w"); | 
|  | if (fp == NULL) | 
|  | { | 
|  | printf ("FAIL: second fmemopen failed (%s)\n", __FUNCTION__); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | static const char str[] = "hello world"; | 
|  | /* Because of buffering, the fputs call itself will not fail. However the | 
|  | final buffer should be not changed because length 0 was passed to the | 
|  | fmemopen call.  */ | 
|  | fputs (str, fp); | 
|  | r = 0; | 
|  | errno = 0; | 
|  | if (fflush (fp) != EOF) | 
|  | { | 
|  | printf ("FAIL: fflush did not return EOF\n"); | 
|  | fclose (fp); | 
|  | return 1; | 
|  | } | 
|  | if (errno != ENOSPC) | 
|  | { | 
|  | printf ("FAIL: errno is %i (expected ENOSPC)\n", errno); | 
|  | fclose (fp); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | fclose (fp); | 
|  |  | 
|  | if (strcmp (buf, BUFCONTENTS) != 0) | 
|  | { | 
|  | printf ("FAIL: strcmp (%s, %s) failed\n", buf, BUFCONTENTS); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | /* Different than 'w' mode, 'w+' truncates the buffer.  */ | 
|  | fp = fmemopen (buf, nbuf, "w+"); | 
|  | if (fp == NULL) | 
|  | { | 
|  | printf ("FAIL: third fmemopen failed (%s)\n", __FUNCTION__); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | fclose (fp); | 
|  |  | 
|  | if (strcmp (buf, "") != 0) | 
|  | { | 
|  | printf ("FAIL: strcmp (%s, \"\") failed\n", buf); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | static int | 
|  | do_test (void) | 
|  | { | 
|  | int ret = 0; | 
|  |  | 
|  | ret += do_test_with_buffer (); | 
|  | ret += do_test_without_buffer (); | 
|  | ret += do_test_length_zero (); | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | #define TEST_FUNCTION do_test () | 
|  | #include "../test-skeleton.c" |