1 #include "nbbio.h"
2 #include <assert.h>
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <sys/stat.h>
9 #include <sys/types.h>
10 #include <unistd.h>
11
12 #ifndef TRUE
13 #define TRUE 1
14 #define FALSE 0
15 #endif
16
17 #define NVECTORS 3
18
check(int d,int e,int line)19 void check(int d, int e, int line)
20 {
21 if (d != e) {
22 printf("check: %d != %d at line %d\n", d, e, line);
23 exit(1);
24 }
25 }
26 #define CHECK(d, e) check(d, e, __LINE__)
27
dumpBuf(const void * p,int len)28 static void dumpBuf(const void *p, int len)
29 {
30 int i;
31 for (i=0; i<len; i++) {
32 printf("%02d ", 0xff & ((unsigned const char *)p)[i]);
33 if ((i & 31) == 31)
34 puts("");
35 }
36 puts("");
37 }
38
main()39 int main()
40 {
41 nbbio nb;
42 int err;
43 char buf[nbbio_BUFLEN];
44 char buf2[nbbio_BUFLEN];
45 int i;
46 int bytesused;
47 int len;
48 int c;
49
50 /* Sanity checks */
51 CHECK( nb.bytesUsed(), 0 );
52 CHECK( nb.contigBytesUsed(), 0 );
53 CHECK( nb.bytesFree(), nbbio_BUFLEN-1 );
54 CHECK( nb.contigBytesFree(), nbbio_BUFLEN-1 );
55 CHECK( nb.isEmpty(), TRUE );
56 CHECK( nb.isFull(), FALSE );
57
58 /* Fill a buffer with three lines, piecemeal */
59 const char *vectors[NVECTORS] = { "Hi", "there", "cutie" };
60 bytesused=0;
61 for (i=0; i < NVECTORS; i++) {
62 err = nb.put(vectors[i], 1);
63 bytesused++;
64 if (err) {
65 printf("Failed at line %d: %s\n", __LINE__, strerror(err));
66 exit(1);
67 }
68 err = nb.put(vectors[i]+1, strlen(vectors[i])-1);
69 bytesused+=strlen(vectors[i])-1;
70 if (err) {
71 printf("Failed at line %d\n", __LINE__);
72 exit(1);
73 }
74 if (i & 1) {
75 err = nb.put("\r\n", 2);
76 bytesused+=2;
77 } else {
78 err = nb.put("\n", 1);
79 bytesused++;
80 }
81 if (err) {
82 printf("Failed at line %d\n", __LINE__);
83 exit(1);
84 }
85 }
86
87 /* Sanity checks */
88 CHECK( nb.bytesUsed(), bytesused );
89 CHECK( nb.contigBytesUsed(), bytesused ); /* assume no wrap yet */
90 CHECK( nb.bytesFree(), nbbio_BUFLEN-1 - bytesused );
91 CHECK( nb.contigBytesFree(), nbbio_BUFLEN-1 - bytesused );
92 CHECK( nb.isEmpty(), FALSE );
93 CHECK( nb.isFull(), FALSE );
94
95 /* make sure we can get them out */
96 for (i=0; i < NVECTORS; i++) {
97 err = nb.readline(buf, sizeof(buf));
98 if (err) {
99 printf("Failed at line %d; can't read line %d\n", __LINE__, i);
100 exit(1);
101 }
102 if (strcmp(buf, vectors[i])) {
103 printf("Bad data; failed at line %d\n", __LINE__);
104 exit(1);
105 }
106 }
107
108 /* Sanity checks */
109 CHECK( nb.bytesUsed(), 0 );
110 CHECK( nb.contigBytesUsed(), 0 );
111 CHECK( nb.bytesFree(), nbbio_BUFLEN-1 );
112 CHECK( nb.contigBytesFree(), nbbio_BUFLEN - bytesused );
113 CHECK( nb.isEmpty(), TRUE ); /* assume last line ended in \n only */
114 CHECK( nb.isFull(), FALSE );
115
116 /* Fill it to the brim with one long line */
117 for (i=0; i<nbbio_BUFLEN-1; i++)
118 buf2[i] = 32 + (i & 63);
119 err = nb.put(buf2, nbbio_BUFLEN-1);
120 if (err) {
121 printf("Failed at line %d; can't put big line\n", __LINE__);
122 exit(1);
123 }
124
125 /* Sanity checks */
126 CHECK( nb.bytesUsed(), nbbio_BUFLEN-1 );
127 CHECK( nb.contigBytesUsed(), nbbio_BUFLEN-bytesused ); /* -old m_putTo */
128 CHECK( nb.bytesFree(), 0 );
129 CHECK( nb.contigBytesFree(), 0 );
130 CHECK( nb.isEmpty(), FALSE );
131 CHECK( nb.isFull(), TRUE );
132
133 for (i=0; i<nbbio_BUFLEN-1; i++) {
134 if (nb.isEmpty()) {
135 printf("Failed at line %d\n", __LINE__);
136 exit(1);
137 }
138 c = nb.readc();
139 int wanted = (32 + (i & 63));
140 if (c != wanted) {
141 printf("Failed at line %d: bad value; i = %d, wanted %d, got %d\n", __LINE__, i, wanted, c);
142 exit(1);
143 }
144 }
145
146 /* Sanity checks */
147 CHECK( nb.bytesUsed(), 0 );
148 CHECK( nb.contigBytesUsed(), 0 );
149 CHECK( nb.bytesFree(), nbbio_BUFLEN-1 );
150 CHECK( nb.contigBytesFree(), nbbio_BUFLEN-bytesused+1 );
151 CHECK( nb.isEmpty(), TRUE );
152 CHECK( nb.isFull(), FALSE );
153
154 /* File I/O */
155 int wfd = open("nbbiotest.dat", O_CREAT|O_TRUNC|O_RDWR, 0664);
156 if (wfd < 0) {
157 printf("Failed at line %d; can't create nbbiotest.dat\n", __LINE__);
158 perror("open");
159 exit(1);
160 }
161 bytesused=0;
162 for (i=0; i < NVECTORS; i++) {
163 err = nb.put(vectors[i], 1);
164 bytesused++;
165 if (err) {
166 printf("Failed at line %d: %s\n", __LINE__, strerror(err));
167 exit(1);
168 }
169 err = nb.put(vectors[i]+1, strlen(vectors[i])-1);
170 bytesused+=strlen(vectors[i])-1;
171 if (err) {
172 printf("Failed at line %d\n", __LINE__);
173 exit(1);
174 }
175 if (i & 1) {
176 err = nb.put("\r\n", 2);
177 bytesused+=2;
178 } else {
179 err = nb.put("\n", 1);
180 bytesused++;
181 }
182 if (err) {
183 printf("Failed at line %d\n", __LINE__);
184 exit(1);
185 }
186 }
187 err = nb.flushTo(wfd);
188 if (err) {
189 printf("Failed at line %d\n", __LINE__);
190 exit(1);
191 }
192 close(wfd);
193
194 /* Sanity checks */
195 CHECK( nb.bytesUsed(), 0 );
196 CHECK( nb.contigBytesUsed(), 0 );
197 CHECK( nb.bytesFree(), nbbio_BUFLEN-1 );
198 CHECK( nb.contigBytesFree(), nbbio_BUFLEN - 2 * bytesused + 1);
199 CHECK( nb.isEmpty(), TRUE );
200 CHECK( nb.isFull(), FALSE );
201
202 int rfd = open("nbbiotest.dat", O_RDONLY);
203 if (rfd < 0) {
204 printf("Failed at line %d; can't open nbbiotest.dat\n", __LINE__);
205 perror("open");
206 exit(1);
207 }
208 err = nb.fillFrom(rfd);
209 if (err) {
210 printf("Failed at line %d\n", __LINE__);
211 exit(1);
212 }
213
214 /* make sure we can get them out */
215 for (i=0; i < NVECTORS; i++) {
216 err = nb.readline(buf, sizeof(buf));
217 if (err) {
218 printf("Failed at line %d; can't read line %d\n", __LINE__, i);
219 exit(1);
220 }
221 if (strcmp(buf, vectors[i])) {
222 printf("Bad data; failed at line %d\n", __LINE__);
223 exit(1);
224 }
225 }
226
227 /* Check "fillFrom when # of bytes readable == # of contig bytes left",
228 * which could cause a premature EOF due to 2nd read() returning 0
229 * Thanks to Tom Emersoni <TOMEMERSON at ms.globalpay.com> for finding that one
230 */
231
232 /* 1. Create a file with a single line of C's, len nbbio_BUFLEN/2 (inc CRLF) */
233 wfd = open("nbbiotest.dat", O_CREAT|O_TRUNC|O_RDWR, 0664);
234 if (wfd < 0) {
235 printf("Failed at line %d; can't create nbbiotest.dat\n", __LINE__);
236 perror("open");
237 exit(1);
238 }
239 memset(buf, 'C', nbbio_BUFLEN/2 - 2);
240 buf[nbbio_BUFLEN/2 - 2] = '\r';
241 buf[nbbio_BUFLEN/2 - 1] = '\n';
242 int nwrite = write(wfd, buf, nbbio_BUFLEN/2);
243 CHECK(nbbio_BUFLEN/2, nwrite);
244 err = close(wfd);
245 CHECK(err, 0);
246
247 /* 2. Rotate buf so there's two bytes of free space at the beginning,
248 * then fill buf with a line of B's until there's exactly nbbio_BUFLEN/2 contigFree
249 */
250 nb.init();
251 CHECK(nb.contigBytesFree(), nbbio_BUFLEN-1);
252 CHECK(nb.bytesFree(), nbbio_BUFLEN-1);
253 nb.put("AZ", 2);
254 c = nb.readc();
255 CHECK(c, 'A');
256 c = nb.readc();
257 CHECK(c, 'Z');
258 CHECK(nb.contigBytesFree(), nbbio_BUFLEN-2); /* because putTo is 2 */
259 CHECK(nb.bytesFree(), nbbio_BUFLEN-1);
260 while (nb.contigBytesFree() > nbbio_BUFLEN/2 + 2) {
261 nb.put("B", 1);
262 CHECK(nb.contigBytesFree(), nb.bytesFree()-1);
263 }
264 nb.put("\r\n", 2);
265 CHECK(nb.contigBytesFree(), nbbio_BUFLEN/2);
266 CHECK(nb.bytesFree(), nbbio_BUFLEN/2+1);
267
268 /* 3. Fill buf from the file. Make sure it doesn't barf because
269 * we hit EOF.
270 */
271 rfd = open("nbbiotest.dat", O_RDONLY);
272 if (rfd < 0) {
273 printf("Failed at line %d; can't open nbbiotest.dat\n", __LINE__);
274 perror("open");
275 exit(1);
276 }
277 err = nb.fillFrom(rfd);
278 CHECK(err, 0);
279 close(rfd);
280
281 /* 4. Make sure we can read both lines. */
282 memset(buf2, 255, sizeof(buf2));
283 err = nb.readline(buf2, sizeof(buf2));
284 CHECK(err, 0);
285 len = strlen(buf2);
286 CHECK(len, nbbio_BUFLEN/2 - 2 - 2);
287 CHECK(buf2[0], 'B'); /* first line all B's */
288
289 err = nb.readline(buf2, sizeof(buf2));
290 CHECK(err, 0);
291 CHECK(buf2[0], 'C'); /* 2nd line all C's */
292 err = memcmp(buf, buf2, nbbio_BUFLEN/2 - 2);
293 if (err) {
294 printf("got:");
295 dumpBuf(buf2, nbbio_BUFLEN/2-2);
296 printf("wanted:");
297 dumpBuf(buf, nbbio_BUFLEN/2-2);
298 }
299 CHECK(err, 0);
300 len = strlen(buf2);
301 if (len != nbbio_BUFLEN/2 - 2) {
302 printf("got:");
303 dumpBuf(buf2, len);
304 printf("wanted:");
305 dumpBuf(buf, nbbio_BUFLEN/2-2);
306 }
307 CHECK(len, nbbio_BUFLEN/2 - 2);
308
309 /* Whew. */
310 unlink("nbbiotest.dat");
311
312 printf("Test passed\n");
313 exit(0);
314 }
315