push 212f1dad91f15aefd8e676124180e0b86d7c9ee6
[wine/hacks.git] / dlls / msvcrt / tests / file.c
blob91effe92aea40101b66cf2ce06c2dbfec033aa7d
1 /*
2 * Unit test suite for file functions
4 * Copyright 2002 Bill Currie
5 * Copyright 2005 Paul Rupe
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/test.h"
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 #include <share.h>
28 #include <sys/stat.h>
29 #include <io.h>
30 #include <direct.h>
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winnls.h>
34 #include <process.h>
35 #include <errno.h>
37 static HANDLE proc_handles[2];
39 static void test_fdopen( void )
41 static const char buffer[] = {0,1,2,3,4,5,6,7,8,9};
42 char ibuf[10];
43 int fd;
44 FILE *file;
46 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
47 write (fd, buffer, sizeof (buffer));
48 close (fd);
50 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
51 lseek (fd, 5, SEEK_SET);
52 file = fdopen (fd, "rb");
53 ok (fread (ibuf, 1, sizeof (buffer), file) == 5, "read wrong byte count\n");
54 ok (memcmp (ibuf, buffer + 5, 5) == 0, "read wrong bytes\n");
55 fclose (file);
56 unlink ("fdopen.tst");
59 static void test_fileops( void )
61 static const char outbuffer[] = "0,1,2,3,4,5,6,7,8,9";
62 char buffer[256];
63 WCHAR wbuffer[256];
64 int fd;
65 FILE *file;
66 fpos_t pos;
67 int i, c;
69 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
70 write (fd, outbuffer, sizeof (outbuffer));
71 close (fd);
73 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
74 file = fdopen (fd, "rb");
75 ok(strlen(outbuffer) == (sizeof(outbuffer)-1),"strlen/sizeof error\n");
76 ok(fgets(buffer,sizeof(buffer),file) !=0,"fgets failed unexpected\n");
77 ok(fgets(buffer,sizeof(buffer),file) ==0,"fgets didn't signal EOF\n");
78 ok(feof(file) !=0,"feof doesn't signal EOF\n");
79 rewind(file);
80 ok(fgets(buffer,strlen(outbuffer),file) !=0,"fgets failed unexpected\n");
81 ok(lstrlenA(buffer) == lstrlenA(outbuffer) -1,"fgets didn't read right size\n");
82 ok(fgets(buffer,sizeof(outbuffer),file) !=0,"fgets failed unexpected\n");
83 ok(strlen(buffer) == 1,"fgets dropped chars\n");
84 ok(buffer[0] == outbuffer[strlen(outbuffer)-1],"fgets exchanged chars\n");
86 rewind(file);
87 for (i = 0, c = EOF; i < sizeof(outbuffer); i++)
89 ok((c = fgetc(file)) == outbuffer[i], "fgetc returned wrong data\n");
91 ok((c = fgetc(file)) == EOF, "getc did not return EOF\n");
92 ok(feof(file), "feof did not return EOF\n");
93 ok(ungetc(c, file) == EOF, "ungetc(EOF) did not return EOF\n");
94 ok(feof(file), "feof after ungetc(EOF) did not return EOF\n");
95 ok((c = fgetc(file)) == EOF, "getc did not return EOF\n");
96 c = outbuffer[sizeof(outbuffer) - 1];
97 ok(ungetc(c, file) == c, "ungetc did not return its input\n");
98 ok(!feof(file), "feof after ungetc returned EOF\n");
99 ok((c = fgetc(file)) != EOF, "getc after ungetc returned EOF\n");
100 ok(c == outbuffer[sizeof(outbuffer) - 1],
101 "getc did not return ungetc'd data\n");
102 ok(!feof(file), "feof after getc returned EOF prematurely\n");
103 ok((c = fgetc(file)) == EOF, "getc did not return EOF\n");
104 ok(feof(file), "feof after getc did not return EOF\n");
106 rewind(file);
107 ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected\n");
108 ok(pos == 0, "Unexpected result of fgetpos %x%08x\n", (DWORD)(pos >> 32), (DWORD)pos);
109 pos = sizeof (outbuffer);
110 ok(fsetpos(file, &pos) == 0, "fsetpos failed unexpected\n");
111 ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected\n");
112 ok(pos == sizeof (outbuffer), "Unexpected result of fgetpos %x%08x\n", (DWORD)(pos >> 32), (DWORD)pos);
114 fclose (file);
115 fd = open ("fdopen.tst", O_RDONLY | O_TEXT);
116 file = fdopen (fd, "rt"); /* open in TEXT mode */
117 ok(fgetws(wbuffer,sizeof(wbuffer)/sizeof(wbuffer[0]),file) !=0,"fgetws failed unexpected\n");
118 ok(fgetws(wbuffer,sizeof(wbuffer)/sizeof(wbuffer[0]),file) ==0,"fgetws didn't signal EOF\n");
119 ok(feof(file) !=0,"feof doesn't signal EOF\n");
120 rewind(file);
121 ok(fgetws(wbuffer,strlen(outbuffer),file) !=0,"fgetws failed unexpected\n");
122 ok(lstrlenW(wbuffer) == (lstrlenA(outbuffer) -1),"fgetws didn't read right size\n");
123 ok(fgetws(wbuffer,sizeof(outbuffer)/sizeof(outbuffer[0]),file) !=0,"fgets failed unexpected\n");
124 ok(lstrlenW(wbuffer) == 1,"fgets dropped chars\n");
125 fclose (file);
127 file = fopen("fdopen.tst", "rb");
128 ok( file != NULL, "fopen failed\n");
129 /* sizeof(buffer) > content of file */
130 ok(fread(buffer, sizeof(buffer), 1, file) == 0, "fread test failed\n");
131 /* feof should be set now */
132 ok(feof(file), "feof after fread failed\n");
133 fclose (file);
135 unlink ("fdopen.tst");
138 #define IOMODE (ao?"ascii mode":"binary mode")
139 static void test_readmode( BOOL ascii_mode )
141 static const char outbuffer[] = "0,1,2,3,4,5,6,7,8,9\r\n\r\nA,B,C,D,E\r\nX,Y,Z";
142 static const char padbuffer[] = "ghjghjghjghj";
143 static const char nlbuffer[] = "\r\n";
144 char buffer[2*BUFSIZ+256];
145 const char *optr;
146 int fd;
147 FILE *file;
148 const int *ip;
149 int i, j, m, ao, pl;
150 unsigned int fp;
151 long l;
153 fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
154 /* an internal buffer of BUFSIZ is maintained, so make a file big
155 * enough to test operations that cross the buffer boundary
157 j = (2*BUFSIZ-4)/strlen(padbuffer);
158 for (i=0; i<j; i++)
159 write (fd, padbuffer, strlen(padbuffer));
160 j = (2*BUFSIZ-4)%strlen(padbuffer);
161 for (i=0; i<j; i++)
162 write (fd, &padbuffer[i], 1);
163 write (fd, nlbuffer, strlen(nlbuffer));
164 write (fd, outbuffer, sizeof (outbuffer));
165 close (fd);
167 if (ascii_mode) {
168 /* Open file in ascii mode */
169 fd = open ("fdopen.tst", O_RDONLY);
170 file = fdopen (fd, "r");
171 ao = -1; /* on offset to account for carriage returns */
173 else {
174 fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
175 file = fdopen (fd, "rb");
176 ao = 0;
179 /* first is a test of fgets, ftell, fseek */
180 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
181 ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
182 l = ftell(file);
183 pl = 2*BUFSIZ-2;
184 ok(l == pl,"padding line ftell got %ld should be %d in %s\n", l, pl, IOMODE);
185 ok(lstrlenA(buffer) == pl+ao,"padding line fgets got size %d should be %d in %s\n",
186 lstrlenA(buffer), pl+ao, IOMODE);
187 for (fp=0; fp<strlen(outbuffer); fp++)
188 if (outbuffer[fp] == '\n') break;
189 fp++;
190 ok(fgets(buffer,256,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
191 l = ftell(file);
192 ok(l == pl+fp,"line 1 ftell got %ld should be %d in %s\n", l, pl+fp, IOMODE);
193 ok(lstrlenA(buffer) == fp+ao,"line 1 fgets got size %d should be %d in %s\n",
194 lstrlenA(buffer), fp+ao, IOMODE);
195 /* test a seek back across the buffer boundary */
196 l = pl;
197 ok(fseek(file,l,SEEK_SET)==0,"seek failure in %s\n", IOMODE);
198 l = ftell(file);
199 ok(l == pl,"ftell after seek got %ld should be %d in %s\n", l, pl, IOMODE);
200 ok(fgets(buffer,256,file) !=0,"second read of line 1 fgets failed unexpected in %s\n", IOMODE);
201 l = ftell(file);
202 ok(l == pl+fp,"second read of line 1 ftell got %ld should be %d in %s\n", l, pl+fp, IOMODE);
203 ok(lstrlenA(buffer) == fp+ao,"second read of line 1 fgets got size %d should be %d in %s\n",
204 lstrlenA(buffer), fp+ao, IOMODE);
205 ok(fgets(buffer,256,file) !=0,"line 2 fgets failed unexpected in %s\n", IOMODE);
206 fp += 2;
207 l = ftell(file);
208 ok(l == pl+fp,"line 2 ftell got %ld should be %d in %s\n", l, pl+fp, IOMODE);
209 ok(lstrlenA(buffer) == 2+ao,"line 2 fgets got size %d should be %d in %s\n",
210 lstrlenA(buffer), 2+ao, IOMODE);
212 /* test fread across buffer boundary */
213 rewind(file);
214 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
215 ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
216 j=strlen(outbuffer);
217 i=fread(buffer,1,BUFSIZ+strlen(outbuffer),file);
218 ok(i==BUFSIZ+j,"fread failed, expected %d got %d in %s\n", BUFSIZ+j, i, IOMODE);
219 l = ftell(file);
220 ok(l == pl+j-(ao*4)-5,"ftell after fread got %ld should be %d in %s\n", l, pl+j-(ao*4)-5, IOMODE);
221 for (m=0; m<3; m++)
222 ok(buffer[m]==padbuffer[m+(BUFSIZ-4)%strlen(padbuffer)],"expected %c got %c\n", padbuffer[m], buffer[m]);
223 m+=BUFSIZ+2+ao;
224 optr = outbuffer;
225 for (; m<i; m++) {
226 ok(buffer[m]==*optr,"char %d expected %c got %c in %s\n", m, *optr, buffer[m], IOMODE);
227 optr++;
228 if (ao && (*optr == '\r'))
229 optr++;
231 /* fread should return the requested number of bytes if available */
232 rewind(file);
233 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
234 ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
235 j = fp+10;
236 i=fread(buffer,1,j,file);
237 ok(i==j,"fread failed, expected %d got %d in %s\n", j, i, IOMODE);
238 /* test fread eof */
239 ok(fseek(file,0,SEEK_END)==0,"seek failure in %s\n", IOMODE);
240 ok(feof(file)==0,"feof failure in %s\n", IOMODE);
241 ok(fread(buffer,1,1,file)==0,"fread failure in %s\n", IOMODE);
242 ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
243 ok(fseek(file,-3,SEEK_CUR)==0,"seek failure in %s\n", IOMODE);
244 ok(feof(file)==0,"feof failure in %s\n", IOMODE);
245 ok(fread(buffer,2,1,file)==1,"fread failed in %s\n", IOMODE);
246 ok(feof(file)==0,"feof failure in %s\n", IOMODE);
247 ok(fread(buffer,2,1,file)==0,"fread failure in %s\n",IOMODE);
248 ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
250 /* test some additional functions */
251 rewind(file);
252 ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
253 ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
254 i = _getw(file);
255 ip = (const int *)outbuffer;
256 ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
257 for (fp=0; fp<strlen(outbuffer); fp++)
258 if (outbuffer[fp] == '\n') break;
259 fp++;
260 /* this will cause the next _getw to cross carriage return characters */
261 ok(fgets(buffer,fp-6,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
262 for (i=0, j=0; i<6; i++) {
263 if (ao==0 || outbuffer[fp-3+i] != '\r')
264 buffer[j++] = outbuffer[fp-3+i];
266 i = _getw(file);
267 ip = (int *)buffer;
268 ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
270 fclose (file);
271 unlink ("fdopen.tst");
274 static void test_asciimode(void)
276 FILE *fp;
277 char buf[64];
279 /* Simple test of CR CR LF handling. Test both fgets and fread code paths, they're different! */
280 fp = fopen("ascii.tst", "wb");
281 fputs("\r\r\n", fp);
282 fclose(fp);
283 fp = fopen("ascii.tst", "rt");
284 ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets\n");
285 ok(0 == strcmp(buf, "\r\n"), "CR CR LF not read as CR LF\n");
286 rewind(fp);
287 ok((fread(buf, 1, sizeof(buf), fp) == 2) && (0 == strcmp(buf, "\r\n")), "CR CR LF not read as CR LF\n");
288 fclose(fp);
289 unlink("ascii.tst");
291 /* Simple test of foo ^Z [more than one block] bar handling */
292 fp = fopen("ascii.tst", "wb");
293 fputs("foo\032", fp); /* foo, logical EOF, ... */
294 fseek(fp, 65536L, SEEK_SET); /* ... more than MSVCRT_BUFSIZ, ... */
295 fputs("bar", fp); /* ... bar */
296 fclose(fp);
297 fp = fopen("ascii.tst", "rt");
298 ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets foo\n");
299 ok(0 == strcmp(buf, "foo"), "foo ^Z not read as foo by fgets\n");
300 ok(fgets(buf, sizeof(buf), fp) == NULL, "fgets after logical EOF\n");
301 rewind(fp);
302 ok((fread(buf, 1, sizeof(buf), fp) == 3) && (0 == strcmp(buf, "foo")), "foo ^Z not read as foo by fread\n");
303 ok((fread(buf, 1, sizeof(buf), fp) == 0), "fread after logical EOF\n");
304 fclose(fp);
306 unlink("ascii.tst");
309 static void test_asciimode2(void)
311 /* Error sequence from one app was getchar followed by small fread
312 * with one \r removed had last byte of buffer filled with
313 * next byte of *unbuffered* data rather than next byte from buffer
314 * Test case is a short string of one byte followed by a newline
315 * followed by filler to fill out the sector, then a sector of
316 * some different byte.
319 FILE *fp;
320 char ibuf[4];
321 int i;
322 static const char obuf[] =
323 "00\n"
324 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
325 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
326 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
327 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
328 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
329 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
330 "000000000000000000\n"
331 "1111111111111111111";
333 fp = fopen("ascii2.tst", "wt");
334 fwrite(obuf, 1, sizeof(obuf), fp);
335 fclose(fp);
337 fp = fopen("ascii2.tst", "rt");
338 ok(getc(fp) == '0', "first char not 0\n");
339 memset(ibuf, 0, sizeof(ibuf));
340 i = fread(ibuf, 1, sizeof(ibuf), fp);
341 ok(i == sizeof(ibuf), "fread i %d != sizeof(ibuf)\n", i);
342 ok(0 == strncmp(ibuf, obuf+1, sizeof(ibuf)), "ibuf != obuf\n");
343 fclose(fp);
344 unlink("ascii2.tst");
347 static WCHAR* AtoW( const char* p )
349 WCHAR* buffer;
350 DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
351 buffer = malloc( len * sizeof(WCHAR) );
352 MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
353 return buffer;
356 static void test_fgetc( void )
358 char* tempf;
359 FILE *tempfh;
360 int ich=0xe0, ret;
362 tempf=_tempnam(".","wne");
363 tempfh = fopen(tempf,"w+");
364 fputc(ich, tempfh);
365 fputc(ich, tempfh);
366 rewind(tempfh);
367 ret = fgetc(tempfh);
368 ok(ich == ret, "First fgetc expected %x got %x\n", ich, ret);
369 ret = fgetc(tempfh);
370 ok(ich == ret, "Second fgetc expected %x got %x\n", ich, ret);
371 fclose(tempfh);
372 unlink(tempf);
375 static void test_fputc( void )
377 char* tempf;
378 FILE *tempfh;
379 int ret;
381 tempf=_tempnam(".","wne");
382 tempfh = fopen(tempf,"wb");
383 ret = fputc(0,tempfh);
384 ok(0 == ret, "fputc(0,tempfh) expected %x got %x\n", 0, ret);
385 ret = fputc(0xff,tempfh);
386 ok(0xff == ret, "fputc(0xff,tempfh) expected %x got %x\n", 0xff, ret);
387 ret = fputc(0xffffffff,tempfh);
388 ok(0xff == ret, "fputc(0xffffffff,tempfh) expected %x got %x\n", 0xff, ret);
389 fclose(tempfh);
391 tempfh = fopen(tempf,"rb");
392 ret = fputc(0,tempfh);
393 ok(EOF == ret, "fputc(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
394 fclose(tempfh);
396 unlink(tempf);
399 static void test_flsbuf( void )
401 char* tempf;
402 FILE *tempfh;
403 int ret;
404 int bufmode;
405 int bufmodes[] = {_IOFBF,_IONBF};
407 tempf=_tempnam(".","wne");
408 for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
410 tempfh = fopen(tempf,"wb");
411 setvbuf(tempfh,NULL,bufmodes[bufmode],2048);
412 ret = _flsbuf(0,tempfh);
413 ok(0 == ret, "_flsbuf(0,tempfh) with bufmode %x expected %x got %x\n",
414 bufmodes[bufmode], 0, ret);
415 ret = _flsbuf(0xff,tempfh);
416 ok(0xff == ret, "_flsbuf(0xff,tempfh) with bufmode %x expected %x got %x\n",
417 bufmodes[bufmode], 0, ret);
418 ret = _flsbuf(0xffffffff,tempfh);
419 ok(0xff == ret, "_flsbuf(0xffffffff,tempfh) with bufmode %x expected %x got %x\n",
420 bufmodes[bufmode], 0, ret);
421 fclose(tempfh);
424 tempfh = fopen(tempf,"rb");
425 ret = _flsbuf(0,tempfh);
426 ok(EOF == ret, "_flsbuf(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
427 fclose(tempfh);
429 unlink(tempf);
432 static void test_fgetwc( void )
434 #define LLEN 512
436 char* tempf;
437 FILE *tempfh;
438 static const char mytext[]= "This is test_fgetwc\r\n";
439 WCHAR wtextW[BUFSIZ+LLEN+1];
440 WCHAR *mytextW = NULL, *aptr, *wptr;
441 BOOL diff_found = FALSE;
442 int j;
443 unsigned int i;
444 long l;
446 tempf=_tempnam(".","wne");
447 tempfh = fopen(tempf,"wb");
448 j = 'a';
449 /* pad to almost the length of the internal buffer */
450 for (i=0; i<BUFSIZ-4; i++)
451 fputc(j,tempfh);
452 j = '\r';
453 fputc(j,tempfh);
454 j = '\n';
455 fputc(j,tempfh);
456 fputs(mytext,tempfh);
457 fclose(tempfh);
458 /* in text mode, getws/c expects multibyte characters */
459 /*currently Wine only supports plain ascii, and that is all that is tested here */
460 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
461 fgetws(wtextW,LLEN,tempfh);
462 l=ftell(tempfh);
463 ok(l==BUFSIZ-2, "ftell expected %d got %ld\n", BUFSIZ-2, l);
464 fgetws(wtextW,LLEN,tempfh);
465 l=ftell(tempfh);
466 ok(l==BUFSIZ-2+strlen(mytext), "ftell got %ld\n", l);
467 mytextW = AtoW (mytext);
468 aptr = mytextW;
469 wptr = wtextW;
470 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
472 diff_found |= (*aptr != *wptr);
474 ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
475 ok(*wptr == '\n', "Carriage return was not skipped\n");
476 fclose(tempfh);
477 unlink(tempf);
479 tempfh = fopen(tempf,"wb");
480 j = 'a';
481 /* pad to almost the length of the internal buffer. Use an odd number of bytes
482 to test that we can read wchars that are split across the internal buffer
483 boundary */
484 for (i=0; i<BUFSIZ-3-strlen(mytext)*sizeof(WCHAR); i++)
485 fputc(j,tempfh);
486 j = '\r';
487 fputwc(j,tempfh);
488 j = '\n';
489 fputwc(j,tempfh);
490 fputws(wtextW,tempfh);
491 fputws(wtextW,tempfh);
492 fclose(tempfh);
493 /* in binary mode, getws/c expects wide characters */
494 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
495 j=(BUFSIZ-2)/sizeof(WCHAR)-strlen(mytext);
496 fgetws(wtextW,j,tempfh);
497 l=ftell(tempfh);
498 j=(j-1)*sizeof(WCHAR);
499 ok(l==j, "ftell expected %d got %ld\n", j, l);
500 i=fgetc(tempfh);
501 ok(i=='a', "fgetc expected %d got %d\n", 0x61, i);
502 l=ftell(tempfh);
503 j++;
504 ok(l==j, "ftell expected %d got %ld\n", j, l);
505 fgetws(wtextW,3,tempfh);
506 ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]);
507 ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]);
508 l=ftell(tempfh);
509 j += 4;
510 ok(l==j, "ftell expected %d got %ld\n", j, l);
511 for(i=0; i<strlen(mytext); i++)
512 wtextW[i] = 0;
513 /* the first time we get the string, it should be entirely within the local buffer */
514 fgetws(wtextW,LLEN,tempfh);
515 l=ftell(tempfh);
516 j += (strlen(mytext)-1)*sizeof(WCHAR);
517 ok(l==j, "ftell expected %d got %ld\n", j, l);
518 diff_found = FALSE;
519 aptr = mytextW;
520 wptr = wtextW;
521 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
523 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
524 diff_found |= (*aptr != *wptr);
526 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
527 ok(*wptr == '\n', "Should get newline\n");
528 for(i=0; i<strlen(mytext); i++)
529 wtextW[i] = 0;
530 /* the second time we get the string, it should cross the local buffer boundary.
531 One of the wchars should be split across the boundary */
532 fgetws(wtextW,LLEN,tempfh);
533 diff_found = FALSE;
534 aptr = mytextW;
535 wptr = wtextW;
536 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
538 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
539 diff_found |= (*aptr != *wptr);
541 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
542 ok(*wptr == '\n', "Should get newline\n");
544 free(mytextW);
545 fclose(tempfh);
546 unlink(tempf);
549 static void test_ctrlz( void )
551 char* tempf;
552 FILE *tempfh;
553 static const char mytext[]= "This is test_ctrlz";
554 char buffer[256];
555 int i, j;
556 long l;
558 tempf=_tempnam(".","wne");
559 tempfh = fopen(tempf,"wb");
560 fputs(mytext,tempfh);
561 j = 0x1a; /* a ctrl-z character signals EOF in text mode */
562 fputc(j,tempfh);
563 j = '\r';
564 fputc(j,tempfh);
565 j = '\n';
566 fputc(j,tempfh);
567 j = 'a';
568 fputc(j,tempfh);
569 fclose(tempfh);
570 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
571 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
572 i=strlen(buffer);
573 j=strlen(mytext);
574 ok(i==j, "returned string length expected %d got %d\n", j, i);
575 j+=4; /* ftell should indicate the true end of file */
576 l=ftell(tempfh);
577 ok(l==j, "ftell expected %d got %ld\n", j, l);
578 ok(feof(tempfh), "did not get EOF\n");
579 fclose(tempfh);
581 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
582 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
583 i=strlen(buffer);
584 j=strlen(mytext)+3; /* should get through newline */
585 ok(i==j, "returned string length expected %d got %d\n", j, i);
586 l=ftell(tempfh);
587 ok(l==j, "ftell expected %d got %ld\n", j, l);
588 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
589 i=strlen(buffer);
590 ok(i==1, "returned string length expected %d got %d\n", 1, i);
591 ok(feof(tempfh), "did not get EOF\n");
592 fclose(tempfh);
593 unlink(tempf);
596 static void test_file_put_get( void )
598 char* tempf;
599 FILE *tempfh;
600 static const char mytext[]= "This is a test_file_put_get\n";
601 static const char dostext[]= "This is a test_file_put_get\r\n";
602 char btext[LLEN];
603 WCHAR wtextW[LLEN+1];
604 WCHAR *mytextW = NULL, *aptr, *wptr;
605 BOOL diff_found = FALSE;
606 unsigned int i;
608 tempf=_tempnam(".","wne");
609 tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
610 fputs(mytext,tempfh);
611 fclose(tempfh);
612 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
613 fgets(btext,LLEN,tempfh);
614 ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
615 ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
616 fclose(tempfh);
617 tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
618 fputs(dostext,tempfh);
619 fclose(tempfh);
620 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
621 fgets(btext,LLEN,tempfh);
622 ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
623 fclose(tempfh);
624 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
625 fgets(btext,LLEN,tempfh);
626 ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
628 fclose(tempfh);
629 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
630 fgetws(wtextW,LLEN,tempfh);
631 mytextW = AtoW (mytext);
632 aptr = mytextW;
633 wptr = wtextW;
635 for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
637 diff_found |= (*aptr != *wptr);
639 ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
640 free(mytextW);
641 fclose(tempfh);
642 unlink(tempf);
645 static void test_file_write_read( void )
647 char* tempf;
648 int tempfd;
649 static const char mytext[]= "This is test_file_write_read\nsecond line\n";
650 static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
651 char btext[LLEN];
652 int ret, i;
654 tempf=_tempnam(".","wne");
655 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,
656 _S_IREAD | _S_IWRITE);
657 ok( tempfd != -1,
658 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
659 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
660 "_write _O_BINARY bad return value\n");
661 _close(tempfd);
662 i = lstrlenA(mytext);
663 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
664 ok(_read(tempfd,btext,i) == i,
665 "_read _O_BINARY got bad length\n");
666 ok( memcmp(dostext,btext,i) == 0,
667 "problems with _O_BINARY _write / _read\n");
668 _close(tempfd);
669 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
670 ok(_read(tempfd,btext,i) == i-1,
671 "_read _O_TEXT got bad length\n");
672 ok( memcmp(mytext,btext,i-1) == 0,
673 "problems with _O_BINARY _write / _O_TEXT _read\n");
674 _close(tempfd);
675 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
676 _S_IREAD | _S_IWRITE);
677 ok( tempfd != -1,
678 "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
679 ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
680 "_write _O_TEXT bad return value\n");
681 _close(tempfd);
682 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
683 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
684 "_read _O_BINARY got bad length\n");
685 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
686 "problems with _O_TEXT _write / _O_BINARY _read\n");
687 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
688 _close(tempfd);
689 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
690 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
691 "_read _O_TEXT got bad length\n");
692 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
693 "problems with _O_TEXT _write / _read\n");
694 _close(tempfd);
696 memset(btext, 0, LLEN);
697 tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */
698 ok(tell(tempfd) == 0, "bad position %lu expecting 0\n", tell(tempfd));
699 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n");
700 ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n");
701 _close(tempfd);
703 /* Test reading only \n or \r */
704 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
705 _lseek(tempfd, -1, FILE_END);
706 ret = _read(tempfd,btext,LLEN);
707 ok(ret == 1, "_read expected 1 got bad length: %d\n", ret);
708 _lseek(tempfd, -2, FILE_END);
709 ret = _read(tempfd,btext,LLEN);
710 ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
711 _lseek(tempfd, -3, FILE_END);
712 ret = _read(tempfd,btext,2);
713 ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
714 ok(tell(tempfd) == 42, "bad position %lu expecting 42\n", tell(tempfd));
715 _close(tempfd);
717 ret = unlink(tempf);
718 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
720 tempf=_tempnam(".","wne");
721 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,0);
722 ok( tempfd != -1,
723 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
724 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
725 "_write _O_BINARY bad return value\n");
726 _close(tempfd);
727 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
728 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
729 "_read _O_BINARY got bad length\n");
730 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
731 "problems with _O_BINARY _write / _read\n");
732 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
733 _close(tempfd);
734 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
735 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
736 "_read _O_TEXT got bad length\n");
737 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
738 "problems with _O_BINARY _write / _O_TEXT _read\n");
739 _close(tempfd);
741 ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
742 ok( ret == 0,
743 "Can't chmod '%s' to read-write: %d\n", tempf, errno);
744 ret = unlink(tempf);
745 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
748 static void test_file_inherit_child(const char* fd_s)
750 int fd = atoi(fd_s);
751 char buffer[32];
752 int ret;
754 ret =write(fd, "Success", 8);
755 ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
756 lseek(fd, 0, SEEK_SET);
757 ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
758 ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
761 static void test_file_inherit_child_no(const char* fd_s)
763 int fd = atoi(fd_s);
764 int ret;
766 ret = write(fd, "Success", 8);
767 ok( ret == -1 && errno == EBADF,
768 "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
771 static void test_file_inherit( const char* selfname )
773 int fd;
774 const char* arg_v[5];
775 char buffer[16];
777 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
778 ok(fd != -1, "Couldn't create test file\n");
779 arg_v[0] = selfname;
780 arg_v[1] = "tests/file.c";
781 arg_v[2] = "inherit";
782 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
783 arg_v[4] = 0;
784 _spawnvp(_P_WAIT, selfname, arg_v);
785 ok(tell(fd) == 8, "bad position %lu expecting 8\n", tell(fd));
786 lseek(fd, 0, SEEK_SET);
787 ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
788 close (fd);
789 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
791 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
792 ok(fd != -1, "Couldn't create test file\n");
793 arg_v[0] = selfname;
794 arg_v[1] = "tests/file.c";
795 arg_v[2] = "inherit_no";
796 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
797 arg_v[4] = 0;
798 _spawnvp(_P_WAIT, selfname, arg_v);
799 ok(tell(fd) == 0, "bad position %lu expecting 0\n", tell(fd));
800 ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
801 close (fd);
802 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
805 static void test_tmpnam( void )
807 char name[MAX_PATH] = "abc";
808 char *res;
810 res = tmpnam(NULL);
811 ok(res != NULL, "tmpnam returned NULL\n");
812 ok(res[0] == '\\', "first character is not a backslash\n");
813 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
814 ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
816 res = tmpnam(name);
817 ok(res != NULL, "tmpnam returned NULL\n");
818 ok(res == name, "supplied buffer was not used\n");
819 ok(res[0] == '\\', "first character is not a backslash\n");
820 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
821 ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
824 static void test_chsize( void )
826 int fd;
827 long cur, pos, count;
828 char temptext[] = "012345678";
829 char *tempfile = _tempnam( ".", "tst" );
831 ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
833 fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
834 ok( fd > 0, "Couldn't open test file\n" );
836 count = _write( fd, temptext, sizeof(temptext) );
837 ok( count > 0, "Couldn't write to test file\n" );
839 /* get current file pointer */
840 cur = _lseek( fd, 0, SEEK_CUR );
842 /* make the file smaller */
843 ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
845 pos = _lseek( fd, 0, SEEK_CUR );
846 ok( cur == pos, "File pointer changed from: %ld to: %ld\n", cur, pos );
847 ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
849 /* enlarge the file */
850 ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" );
852 pos = _lseek( fd, 0, SEEK_CUR );
853 ok( cur == pos, "File pointer changed from: %ld to: %ld\n", cur, pos );
854 ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
856 _close( fd );
857 _unlink( tempfile );
860 static void test_fopen_fclose_fcloseall( void )
862 char fname1[] = "empty1";
863 char fname2[] = "empty2";
864 char fname3[] = "empty3";
865 FILE *stream1, *stream2, *stream3, *stream4;
866 int ret, numclosed;
868 /* testing fopen() */
869 stream1 = fopen(fname1, "w+");
870 ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
871 stream2 = fopen(fname2, "w ");
872 ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
873 _unlink(fname3);
874 stream3 = fopen(fname3, "r");
875 ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
876 stream3 = fopen(fname3, "w+");
877 ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
878 errno = 0xfaceabad;
879 stream4 = fopen("", "w+");
880 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
881 "filename is empty, errno = %d (expected 2 or 22)\n", errno);
882 errno = 0xfaceabad;
883 stream4 = fopen(NULL, "w+");
884 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
885 "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
887 /* testing fclose() */
888 ret = fclose(stream2);
889 ok(ret == 0, "The file '%s' was not closed\n", fname2);
890 ret = fclose(stream3);
891 ok(ret == 0, "The file '%s' was not closed\n", fname3);
892 ret = fclose(stream2);
893 ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
894 ret = fclose(stream3);
895 ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
897 /* testing fcloseall() */
898 numclosed = _fcloseall();
899 /* fname1 should be closed here */
900 ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
901 numclosed = _fcloseall();
902 ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
904 ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
905 ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
906 ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
909 static void test_get_osfhandle(void)
911 int fd;
912 char fname[] = "t_get_osfhanle";
913 DWORD bytes_written;
914 HANDLE handle;
916 fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
917 handle = (HANDLE)_get_osfhandle(fd);
918 WriteFile(handle, "bar", 3, &bytes_written, NULL);
919 _close(fd);
920 fd = _open(fname, _O_RDONLY, 0);
921 ok(fd != -1, "Coudn't open '%s' after _get_osfhanle()\n", fname);
923 _close(fd);
924 _unlink(fname);
927 static void test_setmaxstdio(void)
929 ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
930 ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
933 static void test_stat(void)
935 int fd;
936 int pipes[2];
937 struct stat buf;
939 /* Tests for a file */
940 fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
941 if (fd >= 0)
943 ok(fstat(fd, &buf) == 0, "fstat failed: errno=%d\n", errno);
944 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
945 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
946 ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
947 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
948 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
949 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
951 ok(stat("stat.tst", &buf) == 0, "stat failed: errno=%d\n", errno);
952 ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
953 ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
954 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
955 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
956 ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
958 close(fd);
959 remove("stat.tst");
961 else
962 skip("open failed with errno %d\n", errno);
964 /* Tests for a char device */
965 if (_dup2(0, 10) == 0)
967 ok(fstat(10, &buf) == 0, "fstat(stdin) failed: errno=%d\n", errno);
968 if ((buf.st_mode & _S_IFMT) == _S_IFCHR)
970 ok(buf.st_mode == _S_IFCHR, "bad st_mode=%06o\n", buf.st_mode);
971 ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
972 ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
973 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
975 else
976 skip("stdin is not a char device? st_mode=%06o\n", buf.st_mode);
977 close(10);
979 else
980 skip("_dup2 failed with errno %d\n", errno);
982 /* Tests for pipes */
983 if (_pipe(pipes, 1024, O_BINARY) == 0)
985 ok(fstat(pipes[0], &buf) == 0, "fstat(pipe) failed: errno=%d\n", errno);
986 ok(buf.st_mode == _S_IFIFO, "bad st_mode=%06o\n", buf.st_mode);
987 ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n", buf.st_dev, pipes[0]);
988 ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n", buf.st_rdev, pipes[0]);
989 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
990 close(pipes[0]);
991 close(pipes[1]);
993 else
994 skip("pipe failed with errno %d\n", errno);
997 static const char* pipe_string="Hello world";
999 /* How many messages to transfer over the pipe */
1000 #define N_TEST_MESSAGES 3
1002 static void test_pipes_child(int argc, char** args)
1004 int fd;
1005 int nwritten;
1006 int i;
1008 if (argc < 5)
1010 ok(0, "not enough parameters: %d\n", argc);
1011 return;
1014 fd=atoi(args[3]);
1015 ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
1017 fd=atoi(args[4]);
1019 for (i=0; i<N_TEST_MESSAGES; i++) {
1020 nwritten=write(fd, pipe_string, strlen(pipe_string));
1021 ok(nwritten == strlen(pipe_string), "i %d, expected to write '%s' wrote %d\n", i, pipe_string, nwritten);
1022 /* let other process wake up so they can show off their "keep reading until EOF" behavior */
1023 if (i < N_TEST_MESSAGES-1)
1024 Sleep(100);
1027 ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
1030 static void test_pipes(const char* selfname)
1032 int pipes[2];
1033 char str_fdr[12], str_fdw[12];
1034 FILE* file;
1035 const char* arg_v[6];
1036 char buf[4096];
1037 char expected[4096];
1038 int r;
1039 int i;
1041 /* Test reading from a pipe with read() */
1042 if (_pipe(pipes, 1024, O_BINARY) < 0)
1044 ok(0, "pipe failed with errno %d\n", errno);
1045 return;
1048 arg_v[0] = selfname;
1049 arg_v[1] = "tests/file.c";
1050 arg_v[2] = "pipes";
1051 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1052 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1053 arg_v[5] = NULL;
1054 proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1055 ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
1057 for (i=0; i<N_TEST_MESSAGES; i++) {
1058 r=read(pipes[0], buf, sizeof(buf)-1);
1059 ok(r == strlen(pipe_string), "i %d, got %d\n", i, r);
1060 if (r > 0)
1061 buf[r]='\0';
1062 ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
1065 r=read(pipes[0], buf, sizeof(buf)-1);
1066 ok(r == 0, "expected to read 0 bytes, got %d\n", r);
1067 ok(close(pipes[0]) == 0, "unable to close %d: %d\n", pipes[0], errno);
1069 /* Test reading from a pipe with fread() */
1070 if (_pipe(pipes, 1024, O_BINARY) < 0)
1072 ok(0, "pipe failed with errno %d\n", errno);
1073 return;
1076 arg_v[0] = selfname;
1077 arg_v[1] = "tests/file.c";
1078 arg_v[2] = "pipes";
1079 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1080 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1081 arg_v[5] = NULL;
1082 proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1083 ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
1084 file=fdopen(pipes[0], "r");
1086 /* In blocking mode, fread will keep calling read() until it gets
1087 * enough bytes, or EOF, even on Unix. (If this were a Unix terminal
1088 * in cooked mode instead of a pipe, it would also stop on EOL.)
1090 expected[0] = 0;
1091 for (i=0; i<N_TEST_MESSAGES; i++)
1092 strcat(expected, pipe_string);
1093 r=fread(buf, 1, sizeof(buf)-1, file);
1094 ok(r == strlen(expected), "fread() returned %d: ferror=%d\n", r, ferror(file));
1095 if (r > 0)
1096 buf[r]='\0';
1097 ok(strcmp(buf, expected) == 0, "got '%s' expected '%s'\n", buf, expected);
1099 /* Let child close the file before we read, so we can sense EOF reliably */
1100 Sleep(100);
1101 r=fread(buf, 1, sizeof(buf)-1, file);
1102 ok(r == 0, "fread() returned %d instead of 0\n", r);
1103 ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
1104 ok(feof(file), "feof() is false!\n");
1106 ok(fclose(file) == 0, "unable to close the pipe: %d\n", errno);
1109 static void test_unlink(void)
1111 FILE* file;
1112 ok(mkdir("test_unlink") == 0, "unable to create test dir\n");
1113 file = fopen("test_unlink\\empty", "w");
1114 ok(file != NULL, "unable to create test file\n");
1115 if(file)
1116 fclose(file);
1117 ok(_unlink("test_unlink") != 0, "unlinking a non-empty directory must fail\n");
1118 unlink("test_unlink\\empty");
1119 rmdir("test_unlink");
1122 START_TEST(file)
1124 int arg_c;
1125 char** arg_v;
1127 arg_c = winetest_get_mainargs( &arg_v );
1129 /* testing low-level I/O */
1130 if (arg_c >= 3)
1132 if (strcmp(arg_v[2], "inherit") == 0)
1133 test_file_inherit_child(arg_v[3]);
1134 else if (strcmp(arg_v[2], "inherit_no") == 0)
1135 test_file_inherit_child_no(arg_v[3]);
1136 else if (strcmp(arg_v[2], "pipes") == 0)
1137 test_pipes_child(arg_c, arg_v);
1138 else
1139 ok(0, "invalid argument '%s'\n", arg_v[2]);
1140 return;
1142 test_file_inherit(arg_v[0]);
1143 test_file_write_read();
1144 test_chsize();
1145 test_stat();
1146 test_unlink();
1148 /* testing stream I/O */
1149 test_fdopen();
1150 test_fopen_fclose_fcloseall();
1151 test_fileops();
1152 test_asciimode();
1153 test_asciimode2();
1154 test_readmode(FALSE); /* binary mode */
1155 test_readmode(TRUE); /* ascii mode */
1156 test_fgetc();
1157 test_fputc();
1158 test_flsbuf();
1159 test_fgetwc();
1160 test_ctrlz();
1161 test_file_put_get();
1162 test_tmpnam();
1163 test_get_osfhandle();
1164 test_setmaxstdio();
1165 test_pipes(arg_v[0]);
1167 /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
1168 * file contains lines in the correct order
1170 WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);