1 /* Test for fgetsgent_r and buffer sizes.
2 Copyright (C) 2020-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
19 #include <array_length.h>
24 #include <support/check.h>
25 #include <support/support.h>
26 #include <support/temp_file.h>
27 #include <support/xmemstream.h>
28 #include <support/xstdio.h>
30 /* Turn a parsed struct back into a line string. The returned string
33 format_ent (const struct sgrp
*e
)
35 struct xmemstream stream
;
36 xopen_memstream (&stream
);
37 TEST_COMPARE (putsgent (e
, stream
.out
), 0);
38 xfclose_memstream (&stream
);
42 /* An entry in the input file along with the expected output. */
45 const char *line
; /* Line in the file. */
46 const char *expected
; /* Expected output. NULL if skipped. */
49 const struct input inputs
[] =
51 /* Regular entries. */
52 { "g1:x1::\n", "g1:x1::\n" },
53 { "g2:x2:a1:\n", "g2:x2:a1:\n" },
54 { "g3:x3:a2:u1\n", "g3:x3:a2:u1\n" },
55 { "g4:x4:a3,a4:u2,u3,u4\n", "g4:x4:a3,a4:u2,u3,u4\n" },
57 /* Comments and empty lines. */
62 { " #g:x::\n", NULL
},
63 { "\t#g:x::\n", NULL
},
64 { " \t#g:x::\n", NULL
},
66 /* Marker for synchronization. */
67 { "g5:x5::\n", "g5:x5::\n" },
69 /* Leading whitespace. */
70 { " g6:x6::\n", "g6:x6::\n" },
71 { "\tg7:x7::\n", "g7:x7::\n" },
73 /* This is expected to trigger buffer exhaustion during parsing
76 "g8:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:u5,u6,u7,u8,u9:\n",
77 "g8:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:u5,u6,u7,u8,u9:\n",
80 "g9:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx::a5,a6,a7,a8,a9,a10\n",
81 "g9:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx::a5,a6,a7,a8,a9,a10\n",
85 /* Writes the test data to a temporary file and returns its name. The
86 returned pointer should be freed. */
88 create_test_file (void)
91 int fd
= create_temp_file ("tst-fgetsgent_r-", &path
);
92 FILE *fp
= fdopen (fd
, "w");
93 TEST_VERIFY_EXIT (fp
!= NULL
);
95 for (size_t i
= 0; i
< array_length (inputs
); ++i
)
96 fputs (inputs
[i
].line
, fp
);
102 /* Read the test file with the indicated start buffer size. Return
103 true if the buffer size had to be increased during reading. */
105 run_test (const char *path
, size_t buffer_size
)
107 bool resized
= false;
108 FILE *fp
= xfopen (path
, "r");
110 /* This avoids repeated lseek system calls (bug 26257). */
111 TEST_COMPARE (fseeko64 (fp
, 0, SEEK_SET
), 0);
116 /* Skip over unused expected entries. */
117 while (i
< array_length (inputs
) && inputs
[i
].expected
== NULL
)
120 /* Store the data on the heap, to help valgrind to detect
122 struct sgrp
*result_storage
= xmalloc (sizeof (*result_storage
));
123 char *buffer
= xmalloc (buffer_size
);
124 struct sgrp
**result_pointer_storage
125 = xmalloc (sizeof (*result_pointer_storage
));
127 int ret
= fgetsgent_r (fp
, result_storage
, buffer
, buffer_size
,
128 result_pointer_storage
);
131 TEST_VERIFY (*result_pointer_storage
!= NULL
);
132 TEST_VERIFY (i
< array_length (inputs
));
133 if (*result_pointer_storage
!= NULL
134 && i
< array_length (inputs
))
136 char * actual
= format_ent (*result_pointer_storage
);
137 TEST_COMPARE_STRING (inputs
[i
].expected
, actual
);
146 TEST_VERIFY (*result_pointer_storage
== NULL
);
147 TEST_COMPARE (ret
, errno
);
151 TEST_COMPARE (i
, array_length (inputs
));
152 free (result_pointer_storage
);
154 free (result_storage
);
157 else if (ret
== ERANGE
)
163 FAIL_EXIT1 ("read failure: %m");
166 free (result_pointer_storage
);
168 free (result_storage
);
178 char *path
= create_test_file ();
180 for (size_t buffer_size
= 3; ; ++buffer_size
)
182 bool resized
= run_test (path
, buffer_size
);
192 #include <support/test-driver.c>