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