1 | /* Test for open_memstream implementation. |
2 | Copyright (C) 2016-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <mcheck.h> |
20 | #include <stdio.h> |
21 | #include <stdlib.h> |
22 | #include <string.h> |
23 | #include <stdarg.h> |
24 | #include <errno.h> |
25 | |
26 | |
27 | #ifndef CHAR_T |
28 | # define CHAR_T char |
29 | # define W(o) o |
30 | # define OPEN_MEMSTREAM open_memstream |
31 | # define PRINTF printf |
32 | # define FWRITE_FUNC fwrite |
33 | # define FPUTC fputc |
34 | # define STRCMP strcmp |
35 | #endif |
36 | |
37 | #define S(s) S1 (s) |
38 | #define S1(s) #s |
39 | |
40 | static void |
41 | mcheck_abort (enum mcheck_status ev) |
42 | { |
43 | printf (format: "mecheck failed with status %d\n" , (int) ev); |
44 | exit (1); |
45 | } |
46 | |
47 | static void |
48 | error_printf (int line, const char *fmt, ...) |
49 | { |
50 | va_list ap; |
51 | |
52 | printf (format: "error: %s:%i: " , __FILE__, line); |
53 | va_start (ap, fmt); |
54 | vprintf (fmt: fmt, arg: ap); |
55 | va_end (ap); |
56 | } |
57 | |
58 | #define ERROR_RET1(...) \ |
59 | { error_printf(__LINE__, __VA_ARGS__); return 1; } |
60 | |
61 | static int |
62 | do_test_bz18241 (void) |
63 | { |
64 | CHAR_T *buf; |
65 | size_t size; |
66 | |
67 | FILE *fp = OPEN_MEMSTREAM (bufloc: &buf, sizeloc: &size); |
68 | if (fp == NULL) |
69 | ERROR_RET1 ("%s failed\n" , S(OPEN_MEMSTREAM)); |
70 | |
71 | if (FPUTC (W('a'), stream: fp) != W('a')) |
72 | ERROR_RET1 ("%s failed (errno = %d)\n" , S(FPUTC), errno); |
73 | if (fflush (fp) != 0) |
74 | ERROR_RET1 ("fflush failed (errno = %d)\n" , errno); |
75 | if (fseek (fp, -2, SEEK_SET) != -1) |
76 | ERROR_RET1 ("fseek failed (errno = %d)\n" , errno); |
77 | if (errno != EINVAL) |
78 | ERROR_RET1 ("errno != EINVAL\n" ); |
79 | if (ftell (stream: fp) != 1) |
80 | ERROR_RET1 ("ftell failed (errno = %d)\n" , errno); |
81 | if (ferror (stream: fp) != 0) |
82 | ERROR_RET1 ("ferror != 0\n" ); |
83 | |
84 | if (fseek (fp, -1, SEEK_CUR) == -1) |
85 | ERROR_RET1 ("fseek failed (errno = %d)\n" , errno); |
86 | if (ftell (stream: fp) != 0) |
87 | ERROR_RET1 ("ftell failed (errno = %d)\n" , errno); |
88 | if (ferror (stream: fp) != 0) |
89 | ERROR_RET1 ("ferror != 0\n" ); |
90 | if (FPUTC (W('b'), stream: fp) != W('b')) |
91 | ERROR_RET1 ("%s failed (errno = %d)\n" , S(FPUTC), errno); |
92 | if (fflush (fp) != 0) |
93 | ERROR_RET1 ("fflush failed (errno = %d)\n" , errno); |
94 | |
95 | if (fclose (fp) != 0) |
96 | ERROR_RET1 ("fclose failed (errno = %d\n" , errno); |
97 | |
98 | if (STRCMP (buf, W("b" )) != 0) |
99 | ERROR_RET1 ("%s failed\n" , S(STRCMP)); |
100 | |
101 | free (ptr: buf); |
102 | |
103 | return 0; |
104 | } |
105 | |
106 | static int |
107 | do_test_bz20181 (void) |
108 | { |
109 | CHAR_T *buf; |
110 | size_t size; |
111 | size_t ret; |
112 | |
113 | FILE *fp = OPEN_MEMSTREAM (bufloc: &buf, sizeloc: &size); |
114 | if (fp == NULL) |
115 | ERROR_RET1 ("%s failed\n" , S(OPEN_MEMSTREAM)); |
116 | |
117 | if ((ret = FWRITE_FUNC (W("abc" ), 1, 3, fp)) != 3) |
118 | ERROR_RET1 ("%s failed (errno = %d)\n" , S(FWRITE_FUNC), errno); |
119 | |
120 | if (fseek (fp, 0, SEEK_SET) != 0) |
121 | ERROR_RET1 ("fseek failed (errno = %d)\n" , errno); |
122 | |
123 | if (FWRITE_FUNC (W("z" ), 1, 1, fp) != 1) |
124 | ERROR_RET1 ("%s failed (errno = %d)\n" , S(FWRITE_FUNC), errno); |
125 | |
126 | if (fflush (fp) != 0) |
127 | ERROR_RET1 ("fflush failed (errno = %d)\n" , errno); |
128 | |
129 | /* Avoid truncating the buffer on close. */ |
130 | if (fseek (fp, 3, SEEK_SET) != 0) |
131 | ERROR_RET1 ("fseek failed (errno = %d)\n" , errno); |
132 | |
133 | if (fclose (fp) != 0) |
134 | ERROR_RET1 ("fclose failed (errno = %d\n" , errno); |
135 | |
136 | if (size != 3) |
137 | ERROR_RET1 ("size != 3\n" ); |
138 | |
139 | if (buf[0] != W('z') |
140 | || buf[1] != W('b') |
141 | || buf[2] != W('c')) |
142 | { |
143 | PRINTF (W("error: buf {%c,%c,%c} != {z,b,c}\n" ), |
144 | buf[0], buf[1], buf[2]); |
145 | return 1; |
146 | } |
147 | |
148 | free (ptr: buf); |
149 | |
150 | return 0; |
151 | } |
152 | |
153 | static int |
154 | do_test (void) |
155 | { |
156 | int ret = 0; |
157 | |
158 | mcheck_pedantic (abortfunc: mcheck_abort); |
159 | |
160 | ret += do_test_bz18241 (); |
161 | ret += do_test_bz20181 (); |
162 | |
163 | return ret; |
164 | } |
165 | |
166 | #define TEST_FUNCTION do_test () |
167 | #include "../test-skeleton.c" |
168 | |