]> git.draconx.ca Git - dxcommon.git/blob - t/getline.c
dx_getline: Fix EOF handling in standard C fallback.
[dxcommon.git] / t / getline.c
1 /*
2  * Copyright © 2024 Nick Bowler
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17
18 void tap_diag(const char *fmt, ...);
19
20 #undef HAVE_GETLINE
21 #define DX_GETLINE_INITIAL_ALLOC 2
22 #include "getline.h"
23 #include "tap.h"
24
25 #include <errno.h>
26
27 #define LONGLINE "this line is pretty long and may require scaling the buffer multiple times"
28
29 static const char testdata[] =
30         "\n"
31         LONGLINE "\n"
32         LONGLINE "\n"
33         LONGLINE "\n"
34         "hellorld\n";
35
36 int main(void)
37 {
38         char *line = NULL;
39         size_t long_size;
40         size_t n = 0;
41         FILE *f;
42         int rc;
43
44         if (!(f = tmpfile()))
45                 tap_bail_out("tmpfile failed: %s\n", strerror(errno));
46
47         if (fwrite(testdata, sizeof testdata-1, 1, f) != 1)
48                 tap_bail_out("fwrite failed: %s\n", strerror(errno));
49
50         if (fflush(f) != 0)
51                 tap_bail_out("fflush failed: %s\n", strerror(errno));
52
53         if (fseek(f, 0, SEEK_SET) != 0)
54                 tap_bail_out("fseek failed: %s\n", strerror(errno));
55
56         /* First line: empty */
57         rc = dx_getline(&line, &n, f);
58         if (!tap_result(rc == DX_GETLINE_OK, "dx_getline")) {
59                 tap_diag("Failed, unexpected result");
60                 tap_diag("   Received: %d", rc);
61                 tap_diag("   Expected: %d (DX_GETLINE_OK)", DX_GETLINE_OK);
62         }
63         if (!tap_result(n == 2, "alloc size")) {
64                 tap_diag("Failed, unexpected result");
65                 tap_diag("   Received: %lu", (unsigned long)n);
66                 tap_diag("   Expected: 2");
67         }
68         if (!tap_result(line[0] == 0, "returned string")) {
69                 tap_diag("Failed, unexpected result");
70                 tap_diag("   Received: \"%.*s\"", (int)n, line);
71                 tap_diag("   Expected: \"\"");
72         }
73
74         /* Next line: long line (buffer needs expanding) */
75         rc = dx_getline(&line, &n, f);
76         if (!tap_result(rc == DX_GETLINE_OK, "dx_getline")) {
77                 tap_diag("Failed, unexpected result");
78                 tap_diag("   Received: %d", rc);
79                 tap_diag("   Expected: %d (DX_GETLINE_OK)", DX_GETLINE_OK);
80         }
81         if (!tap_result(n > sizeof LONGLINE, "alloc size")) {
82                 tap_diag("Failed, unexpected result");
83                 tap_diag("   Received: %lu", (unsigned long)n);
84                 tap_diag("   Expected: >%u", (unsigned)(sizeof LONGLINE));
85         }
86         if (!tap_result(!strcmp(line, LONGLINE), "returned string")) {
87                 tap_diag("Failed, unexpected result");
88                 tap_diag("   Received: \"%.*s\"", (int)n, line);
89                 tap_diag("   Expected: \"" LONGLINE "\"");
90         }
91
92         /* Next line: long line (buffer does not need expanding) */
93         long_size = n;
94         rc = dx_getline(&line, &n, f);
95         if (!tap_result(rc == DX_GETLINE_OK, "dx_getline")) {
96                 tap_diag("Failed, unexpected result");
97                 tap_diag("   Received: %d", rc);
98                 tap_diag("   Expected: %d (DX_GETLINE_OK)", DX_GETLINE_OK);
99         }
100         if (!tap_result(n == long_size, "alloc size")) {
101                 tap_diag("Failed, unexpected result");
102                 tap_diag("   Received: %lu", (unsigned long)n);
103                 tap_diag("   Expected: %lu", (unsigned long)long_size);
104         }
105         if (!tap_result(!strcmp(line, LONGLINE), "returned string")) {
106                 tap_diag("Failed, unexpected result");
107                 tap_diag("   Received: \"%.*s\"", (int)n, line);
108                 tap_diag("   Expected: \"" LONGLINE "\"");
109         }
110
111         /* Next line: long line (new buffer allocation) */
112         free(line); line = NULL; n = 0;
113         rc = dx_getline(&line, &n, f);
114         if (!tap_result(rc == DX_GETLINE_OK, "dx_getline")) {
115                 tap_diag("Failed, unexpected result");
116                 tap_diag("   Received: %d", rc);
117                 tap_diag("   Expected: %d (DX_GETLINE_OK)", DX_GETLINE_OK);
118         }
119         if (!tap_result(n == long_size, "alloc size")) {
120                 tap_diag("Failed, unexpected result");
121                 tap_diag("   Received: %lu", (unsigned long)n);
122                 tap_diag("   Expected: %lu", (unsigned long)long_size);
123         }
124         if (!tap_result(!strcmp(line, LONGLINE), "returned string")) {
125                 tap_diag("Failed, unexpected result");
126                 tap_diag("   Received: \"%.*s\"", (int)n, line);
127                 tap_diag("   Expected: \"" LONGLINE "\"");
128         }
129
130         /* Next line: short line */
131         rc = dx_getline(&line, &n, f);
132         if (!tap_result(rc == DX_GETLINE_OK, "dx_getline")) {
133                 tap_diag("Failed, unexpected result");
134                 tap_diag("   Received: %d", rc);
135                 tap_diag("   Expected: %d (DX_GETLINE_OK)", DX_GETLINE_OK);
136         }
137         if (!tap_result(n == long_size, "alloc size")) {
138                 tap_diag("Failed, unexpected result");
139                 tap_diag("   Received: %lu", (unsigned long)n);
140                 tap_diag("   Expected: %lu", (unsigned long)long_size);
141         }
142         if (!tap_result(!strcmp(line, "hellorld"), "returned string")) {
143                 tap_diag("Failed, unexpected result");
144                 tap_diag("   Received: \"%.*s\"", (int)n, line);
145                 tap_diag("   Expected: \"hellorld\"");
146         }
147
148         /* Next line: end of file */
149         rc = dx_getline(&line, &n, f);
150         if (!tap_result(rc == DX_GETLINE_EOF, "dx_getline (end of file)")) {
151                 tap_diag("Failed, unexpected result");
152                 tap_diag("   Received: %d", rc);
153                 tap_diag("   Expected: %d (DX_GETLINE_EOF)", DX_GETLINE_EOF);
154         }
155         if (!tap_result(n == long_size, "alloc size")) {
156                 tap_diag("Failed, unexpected result");
157                 tap_diag("   Received: %lu", (unsigned long)n);
158                 tap_diag("   Expected: %lu", (unsigned long)long_size);
159         }
160
161         tap_done();
162 }