msvcrt/tests: Wait for spawned processes to finish.
[wine/multimedia.git] / dlls / msvcrt / tests / file.c
blobbdf0d0ac1e45701575cd2b065bdc1c1dc028848c
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 0x%Lx\n", pos);
109 pos = (ULONGLONG)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 == (ULONGLONG)sizeof (outbuffer), "Unexpected result of fgetpos 0x%Lx\n", 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),file) !=0,"fgetws failed unexpected\n");
118 ok(fgetws(wbuffer,sizeof(wbuffer),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),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 todo_wine 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");
275 static WCHAR* AtoW( const char* p )
277 WCHAR* buffer;
278 DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
279 buffer = malloc( len * sizeof(WCHAR) );
280 MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
281 return buffer;
284 static void test_fgetc( void )
286 char* tempf;
287 FILE *tempfh;
288 int ich=0xe0, ret;
290 tempf=_tempnam(".","wne");
291 tempfh = fopen(tempf,"w+");
292 fputc(ich, tempfh);
293 fputc(ich, tempfh);
294 rewind(tempfh);
295 ret = fgetc(tempfh);
296 ok(ich == ret, "First fgetc expected %x got %x\n", ich, ret);
297 ret = fgetc(tempfh);
298 ok(ich == ret, "Second fgetc expected %x got %x\n", ich, ret);
299 fclose(tempfh);
300 unlink(tempf);
303 static void test_fgetwc( void )
305 #define LLEN 512
307 char* tempf;
308 FILE *tempfh;
309 static const char mytext[]= "This is test_fgetwc\r\n";
310 WCHAR wtextW[BUFSIZ+LLEN+1];
311 WCHAR *mytextW = NULL, *aptr, *wptr;
312 BOOL diff_found = FALSE;
313 int j;
314 unsigned int i;
315 long l;
317 tempf=_tempnam(".","wne");
318 tempfh = fopen(tempf,"wb");
319 j = 'a';
320 /* pad to almost the length of the internal buffer */
321 for (i=0; i<BUFSIZ-4; i++)
322 fputc(j,tempfh);
323 j = '\r';
324 fputc(j,tempfh);
325 j = '\n';
326 fputc(j,tempfh);
327 fputs(mytext,tempfh);
328 fclose(tempfh);
329 /* in text mode, getws/c expects multibyte characters */
330 /*currently Wine only supports plain ascii, and that is all that is tested here */
331 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
332 fgetws(wtextW,LLEN,tempfh);
333 l=ftell(tempfh);
334 ok(l==BUFSIZ-2, "ftell expected %d got %ld\n", BUFSIZ-2, l);
335 fgetws(wtextW,LLEN,tempfh);
336 l=ftell(tempfh);
337 ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %ld\n",
338 BUFSIZ-2+strlen(mytext), l);
339 mytextW = AtoW (mytext);
340 aptr = mytextW;
341 wptr = wtextW;
342 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
344 diff_found |= (*aptr != *wptr);
346 ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
347 ok(*wptr == '\n', "Carriage return was not skipped\n");
348 fclose(tempfh);
349 unlink(tempf);
351 tempfh = fopen(tempf,"wb");
352 j = 'a';
353 /* pad to almost the length of the internal buffer. Use an odd number of bytes
354 to test that we can read wchars that are split across the internal buffer
355 boundary */
356 for (i=0; i<BUFSIZ-3-strlen(mytext)*sizeof(WCHAR); i++)
357 fputc(j,tempfh);
358 j = '\r';
359 fputwc(j,tempfh);
360 j = '\n';
361 fputwc(j,tempfh);
362 fputws(wtextW,tempfh);
363 fputws(wtextW,tempfh);
364 fclose(tempfh);
365 /* in binary mode, getws/c expects wide characters */
366 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
367 j=(BUFSIZ-2)/sizeof(WCHAR)-strlen(mytext);
368 fgetws(wtextW,j,tempfh);
369 l=ftell(tempfh);
370 j=(j-1)*sizeof(WCHAR);
371 ok(l==j, "ftell expected %d got %ld\n", j, l);
372 i=fgetc(tempfh);
373 ok(i=='a', "fgetc expected %d got %d\n", 0x61, i);
374 l=ftell(tempfh);
375 j++;
376 ok(l==j, "ftell expected %d got %ld\n", j, l);
377 fgetws(wtextW,3,tempfh);
378 ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]);
379 ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]);
380 l=ftell(tempfh);
381 j += 4;
382 ok(l==j, "ftell expected %d got %ld\n", j, l);
383 for(i=0; i<strlen(mytext); i++)
384 wtextW[i] = 0;
385 /* the first time we get the string, it should be entirely within the local buffer */
386 fgetws(wtextW,LLEN,tempfh);
387 l=ftell(tempfh);
388 j += (strlen(mytext)-1)*sizeof(WCHAR);
389 ok(l==j, "ftell expected %d got %ld\n", j, l);
390 diff_found = FALSE;
391 aptr = mytextW;
392 wptr = wtextW;
393 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
395 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
396 diff_found |= (*aptr != *wptr);
398 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
399 ok(*wptr == '\n', "Should get newline\n");
400 for(i=0; i<strlen(mytext); i++)
401 wtextW[i] = 0;
402 /* the second time we get the string, it should cross the local buffer boundary.
403 One of the wchars should be split across the boundary */
404 fgetws(wtextW,LLEN,tempfh);
405 diff_found = FALSE;
406 aptr = mytextW;
407 wptr = wtextW;
408 for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
410 ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
411 diff_found |= (*aptr != *wptr);
413 ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
414 ok(*wptr == '\n', "Should get newline\n");
416 free(mytextW);
417 fclose(tempfh);
418 unlink(tempf);
421 static void test_ctrlz( void )
423 char* tempf;
424 FILE *tempfh;
425 static const char mytext[]= "This is test_ctrlz";
426 char buffer[256];
427 int i, j;
428 long l;
430 tempf=_tempnam(".","wne");
431 tempfh = fopen(tempf,"wb");
432 fputs(mytext,tempfh);
433 j = 0x1a; /* a ctrl-z character signals EOF in text mode */
434 fputc(j,tempfh);
435 j = '\r';
436 fputc(j,tempfh);
437 j = '\n';
438 fputc(j,tempfh);
439 j = 'a';
440 fputc(j,tempfh);
441 fclose(tempfh);
442 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
443 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
444 i=strlen(buffer);
445 j=strlen(mytext);
446 ok(i==j, "returned string length expected %d got %d\n", j, i);
447 j+=4; /* ftell should indicate the true end of file */
448 l=ftell(tempfh);
449 ok(l==j, "ftell expected %d got %ld\n", j, l);
450 ok(feof(tempfh), "did not get EOF\n");
451 fclose(tempfh);
453 tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
454 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
455 i=strlen(buffer);
456 j=strlen(mytext)+3; /* should get through newline */
457 ok(i==j, "returned string length expected %d got %d\n", j, i);
458 l=ftell(tempfh);
459 ok(l==j, "ftell expected %d got %ld\n", j, l);
460 ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
461 i=strlen(buffer);
462 ok(i==1, "returned string length expected %d got %d\n", 1, i);
463 ok(feof(tempfh), "did not get EOF\n");
464 fclose(tempfh);
465 unlink(tempf);
468 static void test_file_put_get( void )
470 char* tempf;
471 FILE *tempfh;
472 static const char mytext[]= "This is a test_file_put_get\n";
473 static const char dostext[]= "This is a test_file_put_get\r\n";
474 char btext[LLEN];
475 WCHAR wtextW[LLEN+1];
476 WCHAR *mytextW = NULL, *aptr, *wptr;
477 BOOL diff_found = FALSE;
478 unsigned int i;
480 tempf=_tempnam(".","wne");
481 tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
482 fputs(mytext,tempfh);
483 fclose(tempfh);
484 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
485 fgets(btext,LLEN,tempfh);
486 ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
487 ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
488 fclose(tempfh);
489 tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
490 fputs(dostext,tempfh);
491 fclose(tempfh);
492 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
493 fgets(btext,LLEN,tempfh);
494 ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
495 fclose(tempfh);
496 tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
497 fgets(btext,LLEN,tempfh);
498 ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
500 fclose(tempfh);
501 tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
502 fgetws(wtextW,LLEN,tempfh);
503 mytextW = AtoW (mytext);
504 aptr = mytextW;
505 wptr = wtextW;
507 for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
509 diff_found |= (*aptr != *wptr);
511 ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
512 free(mytextW);
513 fclose(tempfh);
514 unlink(tempf);
517 static void test_file_write_read( void )
519 char* tempf;
520 int tempfd;
521 static const char mytext[]= "This is test_file_write_read\nsecond line\n";
522 static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
523 char btext[LLEN];
524 int ret, i;
526 tempf=_tempnam(".","wne");
527 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,
528 _S_IREAD | _S_IWRITE);
529 ok( tempfd != -1,
530 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
531 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
532 "_write _O_BINARY bad return value\n");
533 _close(tempfd);
534 i = lstrlenA(mytext);
535 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
536 ok(_read(tempfd,btext,i) == i,
537 "_read _O_BINARY got bad length\n");
538 ok( memcmp(dostext,btext,i) == 0,
539 "problems with _O_BINARY _write / _read\n");
540 _close(tempfd);
541 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
542 ok(_read(tempfd,btext,i) == i-1,
543 "_read _O_TEXT got bad length\n");
544 ok( memcmp(mytext,btext,i-1) == 0,
545 "problems with _O_BINARY _write / _O_TEXT _read\n");
546 _close(tempfd);
547 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
548 _S_IREAD | _S_IWRITE);
549 ok( tempfd != -1,
550 "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
551 ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
552 "_write _O_TEXT bad return value\n");
553 _close(tempfd);
554 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
555 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
556 "_read _O_BINARY got bad length\n");
557 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
558 "problems with _O_TEXT _write / _O_BINARY _read\n");
559 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
560 _close(tempfd);
561 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
562 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
563 "_read _O_TEXT got bad length\n");
564 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
565 "problems with _O_TEXT _write / _read\n");
566 _close(tempfd);
568 memset(btext, 0, LLEN);
569 tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */
570 ok(tell(tempfd) == 0, "bad position %lu expecting 0\n", tell(tempfd));
571 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n");
572 ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n");
573 _close(tempfd);
575 /* Test reading only \n or \r */
576 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
577 _lseek(tempfd, -1, FILE_END);
578 ret = _read(tempfd,btext,LLEN);
579 ok(ret == 1, "_read expected 1 got bad length: %d\n", ret);
580 _lseek(tempfd, -2, FILE_END);
581 ret = _read(tempfd,btext,LLEN);
582 ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
583 _lseek(tempfd, -3, FILE_END);
584 ret = _read(tempfd,btext,2);
585 ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
586 ok(tell(tempfd) == 42, "bad position %lu expecting 42\n", tell(tempfd));
587 _close(tempfd);
589 ret = unlink(tempf);
590 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
592 tempf=_tempnam(".","wne");
593 tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,0);
594 ok( tempfd != -1,
595 "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
596 ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
597 "_write _O_BINARY bad return value\n");
598 _close(tempfd);
599 tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
600 ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
601 "_read _O_BINARY got bad length\n");
602 ok( memcmp(dostext,btext,strlen(dostext)) == 0,
603 "problems with _O_BINARY _write / _read\n");
604 ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
605 _close(tempfd);
606 tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
607 ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
608 "_read _O_TEXT got bad length\n");
609 ok( memcmp(mytext,btext,strlen(mytext)) == 0,
610 "problems with _O_BINARY _write / _O_TEXT _read\n");
611 _close(tempfd);
613 ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
614 ok( ret == 0,
615 "Can't chmod '%s' to read-write: %d\n", tempf, errno);
616 ret = unlink(tempf);
617 ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
620 static void test_file_inherit_child(const char* fd_s)
622 int fd = atoi(fd_s);
623 char buffer[32];
624 int ret;
626 ret =write(fd, "Success", 8);
627 ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
628 lseek(fd, 0, SEEK_SET);
629 ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
630 ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
633 static void test_file_inherit_child_no(const char* fd_s)
635 int fd = atoi(fd_s);
636 int ret;
638 ret = write(fd, "Success", 8);
639 ok( ret == -1 && errno == EBADF,
640 "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
643 static void test_file_inherit( const char* selfname )
645 int fd;
646 const char* arg_v[5];
647 char buffer[16];
649 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
650 ok(fd != -1, "Couldn't create test file\n");
651 arg_v[0] = selfname;
652 arg_v[1] = "tests/file.c";
653 arg_v[2] = "inherit";
654 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
655 arg_v[4] = 0;
656 _spawnvp(_P_WAIT, selfname, arg_v);
657 ok(tell(fd) == 8, "bad position %lu expecting 8\n", tell(fd));
658 lseek(fd, 0, SEEK_SET);
659 ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
660 close (fd);
661 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
663 fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
664 ok(fd != -1, "Couldn't create test file\n");
665 arg_v[0] = selfname;
666 arg_v[1] = "tests/file.c";
667 arg_v[2] = "inherit_no";
668 arg_v[3] = buffer; sprintf(buffer, "%d", fd);
669 arg_v[4] = 0;
670 _spawnvp(_P_WAIT, selfname, arg_v);
671 ok(tell(fd) == 0, "bad position %lu expecting 0\n", tell(fd));
672 ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
673 close (fd);
674 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
677 static void test_tmpnam( void )
679 char name[MAX_PATH] = "abc";
680 char *res;
682 res = tmpnam(NULL);
683 ok(res != NULL, "tmpnam returned NULL\n");
684 ok(res[0] == '\\', "first character is not a backslash\n");
685 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
686 ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
688 res = tmpnam(name);
689 ok(res != NULL, "tmpnam returned NULL\n");
690 ok(res == name, "supplied buffer was not used\n");
691 ok(res[0] == '\\', "first character is not a backslash\n");
692 ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
693 ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
696 static void test_chsize( void )
698 int fd;
699 long cur, pos, count;
700 char temptext[] = "012345678";
701 char *tempfile = _tempnam( ".", "tst" );
703 ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
705 fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
706 ok( fd > 0, "Couldn't open test file\n" );
708 count = _write( fd, temptext, sizeof(temptext) );
709 ok( count > 0, "Couldn't write to test file\n" );
711 /* get current file pointer */
712 cur = _lseek( fd, 0, SEEK_CUR );
714 /* make the file smaller */
715 ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
717 pos = _lseek( fd, 0, SEEK_CUR );
718 ok( cur == pos, "File pointer changed from: %ld to: %ld\n", cur, pos );
719 ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
721 /* enlarge the file */
722 ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" );
724 pos = _lseek( fd, 0, SEEK_CUR );
725 ok( cur == pos, "File pointer changed from: %ld to: %ld\n", cur, pos );
726 ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
728 _close( fd );
729 _unlink( tempfile );
732 static void test_fopen_fclose_fcloseall( void )
734 char fname1[] = "empty1";
735 char fname2[] = "empty2";
736 char fname3[] = "empty3";
737 FILE *stream1, *stream2, *stream3, *stream4;
738 int ret, numclosed;
740 /* testing fopen() */
741 stream1 = fopen(fname1, "w+");
742 ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
743 stream2 = fopen(fname2, "w ");
744 ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
745 _unlink(fname3);
746 stream3 = fopen(fname3, "r");
747 ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
748 stream3 = fopen(fname3, "w+");
749 ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
750 errno = 0xfaceabad;
751 stream4 = fopen("", "w+");
752 ok(stream4 == NULL && errno == ENOENT,
753 "filename is empty, errno = %d (expected 2)\n", errno);
754 errno = 0xfaceabad;
755 stream4 = fopen(NULL, "w+");
756 ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
757 "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
759 /* testing fclose() */
760 ret = fclose(stream2);
761 ok(ret == 0, "The file '%s' was not closed\n", fname2);
762 ret = fclose(stream3);
763 ok(ret == 0, "The file '%s' was not closed\n", fname3);
764 ret = fclose(stream2);
765 ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
766 ret = fclose(stream3);
767 ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
769 /* testing fcloseall() */
770 numclosed = _fcloseall();
771 /* fname1 should be closed here */
772 ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
773 numclosed = _fcloseall();
774 ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
776 ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
777 ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
778 ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
781 static void test_get_osfhandle(void)
783 int fd;
784 char fname[] = "t_get_osfhanle";
785 DWORD bytes_written;
786 HANDLE handle;
788 fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
789 handle = (HANDLE)_get_osfhandle(fd);
790 WriteFile(handle, "bar", 3, &bytes_written, NULL);
791 _close(fd);
792 fd = _open(fname, _O_RDONLY, 0);
793 ok(fd != -1, "Coudn't open '%s' after _get_osfhanle()\n", fname);
795 _close(fd);
796 _unlink(fname);
799 static void test_setmaxstdio(void)
801 ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
802 ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
805 static void test_stat(void)
807 int fd;
808 int pipes[2];
809 struct stat buf;
811 /* Tests for a file */
812 fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
813 if (fd >= 0)
815 if (fstat(fd, &buf) == 0)
817 if ((buf.st_mode & _S_IFMT) == _S_IFREG)
819 ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
820 ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n",
821 buf.st_dev, buf.st_rdev);
822 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n",
823 buf.st_nlink);
824 ok(buf.st_size == 0, "st_size is %d, expected 0\n",
825 buf.st_size);
827 else
828 skip("file is not a file?\n");
830 else
831 skip("fstat failed, errno %d\n", errno);
832 close(fd);
833 remove("stat.tst");
835 else
836 skip("open failed with errno %d\n", errno);
838 /* Tests for a char device */
839 if (_dup2(0, 10) == 0)
841 if (fstat(10, &buf) == 0)
843 if (buf.st_mode == _S_IFCHR)
845 ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
846 ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
847 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
849 else
850 skip("stdin is not a char device?\n");
852 else
853 skip("fstat failed with errno %d\n", errno);
854 close(10);
856 else
857 skip("_dup2 failed with errno %d\n", errno);
859 /* Tests for pipes */
860 if (_pipe(pipes, 1024, O_BINARY) == 0)
862 if (fstat(pipes[0], &buf) == 0)
864 if (buf.st_mode == _S_IFIFO)
866 ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n",
867 buf.st_dev, pipes[0]);
868 ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n",
869 buf.st_rdev, pipes[0]);
870 ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n",
871 buf.st_nlink);
873 else
874 skip("pipe() didn't make a pipe?\n");
876 else
877 skip("fstat failed with errno %d\n", errno);
878 close(pipes[0]);
879 close(pipes[1]);
881 else
882 skip("pipe failed with errno %d\n", errno);
885 static const char* pipe_string="Hello world";
887 static void test_pipes_child(int argc, char** args)
889 int fd;
891 if (argc < 5)
893 ok(0, "not enough parameters: %d\n", argc);
894 return;
897 fd=atoi(args[3]);
898 ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
900 fd=atoi(args[4]);
901 write(fd, pipe_string, strlen(pipe_string));
902 ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno);
905 static void test_pipes(const char* selfname)
907 int pipes[2];
908 char str_fdr[12], str_fdw[12];
909 FILE* file;
910 const char* arg_v[6];
911 char buf[4096];
912 int r;
914 /* Test reading from a pipe with read() */
915 if (_pipe(pipes, 1024, O_BINARY) < 0)
917 ok(0, "pipe failed with errno %d\n", errno);
918 return;
921 arg_v[0] = selfname;
922 arg_v[1] = "tests/file.c";
923 arg_v[2] = "pipes";
924 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
925 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
926 arg_v[5] = NULL;
927 proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
928 ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
930 r=read(pipes[0], buf, sizeof(buf)-1);
931 ok(r == strlen(pipe_string), "expected to read %d bytes, got %d\n", strlen(pipe_string)+1, r);
932 if (r > 0)
933 buf[r]='\0';
934 ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
935 r=read(pipes[0], buf, sizeof(buf)-1);
936 ok(r == 0, "expected to read 0 bytes, got %d\n", r);
937 ok(close(pipes[0]) == 0, "unable to close %d: %d\n", pipes[0], errno);
939 /* Test reading from a pipe with fread() */
940 if (_pipe(pipes, 1024, O_BINARY) < 0)
942 ok(0, "pipe failed with errno %d\n", errno);
943 return;
946 arg_v[0] = selfname;
947 arg_v[1] = "tests/file.c";
948 arg_v[2] = "pipes";
949 arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
950 arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
951 arg_v[5] = NULL;
952 proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
953 ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno);
954 file=fdopen(pipes[0], "r");
956 r=fread(buf, 1, sizeof(buf)-1, file);
957 ok(r == strlen(pipe_string), "fread() returned %d instead of %d: ferror=%d\n", r, strlen(pipe_string), ferror(file));
958 if (r > 0)
959 buf[r]='\0';
960 ok(strcmp(buf, pipe_string) == 0, "got '%s' expected '%s'\n", buf, pipe_string);
962 r=fread(buf, 1, sizeof(buf)-1, file);
963 ok(r == 0, "fread() returned %d instead of 0\n", r);
964 ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
965 ok(feof(file), "feof() is false!\n");
967 ok(fclose(file) == 0, "unable to close the pipe: %d\n", errno);
970 START_TEST(file)
972 int arg_c;
973 char** arg_v;
975 arg_c = winetest_get_mainargs( &arg_v );
977 /* testing low-level I/O */
978 if (arg_c >= 3)
980 if (strcmp(arg_v[2], "inherit") == 0)
981 test_file_inherit_child(arg_v[3]);
982 else if (strcmp(arg_v[2], "inherit_no") == 0)
983 test_file_inherit_child_no(arg_v[3]);
984 else if (strcmp(arg_v[2], "pipes") == 0)
985 test_pipes_child(arg_c, arg_v);
986 else
987 ok(0, "invalid argument '%s'\n", arg_v[2]);
988 return;
990 test_file_inherit(arg_v[0]);
991 test_file_write_read();
992 test_chsize();
993 test_stat();
995 /* testing stream I/O */
996 test_fdopen();
997 test_fopen_fclose_fcloseall();
998 test_fileops();
999 test_readmode(FALSE); /* binary mode */
1000 test_readmode(TRUE); /* ascii mode */
1001 test_fgetc();
1002 test_fgetwc();
1003 test_ctrlz();
1004 test_file_put_get();
1005 test_tmpnam();
1006 test_get_osfhandle();
1007 test_setmaxstdio();
1008 test_pipes(arg_v[0]);
1010 /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
1011 * file contains lines in the correct order
1013 WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);