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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/test.h"
35 static void test_fdopen( void )
37 static const char buffer
[] = {0,1,2,3,4,5,6,7,8,9};
42 fd
= open ("fdopen.tst", O_WRONLY
| O_CREAT
| O_BINARY
, _S_IREAD
|_S_IWRITE
);
43 write (fd
, buffer
, sizeof (buffer
));
46 fd
= open ("fdopen.tst", O_RDONLY
| O_BINARY
);
47 lseek (fd
, 5, SEEK_SET
);
48 file
= fdopen (fd
, "rb");
49 ok (fread (ibuf
, 1, sizeof (buffer
), file
) == 5, "read wrong byte count\n");
50 ok (memcmp (ibuf
, buffer
+ 5, 5) == 0, "read wrong bytes\n");
52 unlink ("fdopen.tst");
55 static void test_fileops( void )
57 static const char outbuffer
[] = "0,1,2,3,4,5,6,7,8,9";
65 fd
= open ("fdopen.tst", O_WRONLY
| O_CREAT
| O_BINARY
, _S_IREAD
|_S_IWRITE
);
66 write (fd
, outbuffer
, sizeof (outbuffer
));
69 fd
= open ("fdopen.tst", O_RDONLY
| O_BINARY
);
70 file
= fdopen (fd
, "rb");
71 ok(strlen(outbuffer
) == (sizeof(outbuffer
)-1),"strlen/sizeof error\n");
72 ok(fgets(buffer
,sizeof(buffer
),file
) !=0,"fgets failed unexpected\n");
73 ok(fgets(buffer
,sizeof(buffer
),file
) ==0,"fgets didn't signal EOF\n");
74 ok(feof(file
) !=0,"feof doesn't signal EOF\n");
76 ok(fgets(buffer
,strlen(outbuffer
),file
) !=0,"fgets failed unexpected\n");
77 ok(lstrlenA(buffer
) == lstrlenA(outbuffer
) -1,"fgets didn't read right size\n");
78 ok(fgets(buffer
,sizeof(outbuffer
),file
) !=0,"fgets failed unexpected\n");
79 ok(strlen(buffer
) == 1,"fgets dropped chars\n");
80 ok(buffer
[0] == outbuffer
[strlen(outbuffer
)-1],"fgets exchanged chars\n");
83 for (i
= 0, c
= EOF
; i
< sizeof(outbuffer
); i
++)
85 ok((c
= fgetc(file
)) == outbuffer
[i
], "fgetc returned wrong data\n");
87 ok((c
= fgetc(file
)) == EOF
, "getc did not return EOF\n");
88 ok(feof(file
), "feof did not return EOF\n");
89 ok(ungetc(c
, file
) == EOF
, "ungetc(EOF) did not return EOF\n");
90 ok(feof(file
), "feof after ungetc(EOF) did not return EOF\n");
91 ok((c
= fgetc(file
)) == EOF
, "getc did not return EOF\n");
92 c
= outbuffer
[sizeof(outbuffer
) - 1];
93 ok(ungetc(c
, file
) == c
, "ungetc did not return its input\n");
94 ok(!feof(file
), "feof after ungetc returned EOF\n");
95 ok((c
= fgetc(file
)) != EOF
, "getc after ungetc returned EOF\n");
96 ok(c
== outbuffer
[sizeof(outbuffer
) - 1],
97 "getc did not return ungetc'd data\n");
98 ok(!feof(file
), "feof after getc returned EOF prematurely\n");
99 ok((c
= fgetc(file
)) == EOF
, "getc did not return EOF\n");
100 ok(feof(file
), "feof after getc did not return EOF\n");
103 ok(fgetpos(file
,&pos
) == 0, "fgetpos failed unexpected\n");
104 ok(pos
== 0, "Unexpected result of fgetpos 0x%Lx\n", pos
);
105 pos
= (ULONGLONG
)sizeof (outbuffer
);
106 ok(fsetpos(file
, &pos
) == 0, "fsetpos failed unexpected\n");
107 ok(fgetpos(file
,&pos
) == 0, "fgetpos failed unexpected\n");
108 ok(pos
== (ULONGLONG
)sizeof (outbuffer
), "Unexpected result of fgetpos 0x%Lx\n", pos
);
111 fd
= open ("fdopen.tst", O_RDONLY
| O_TEXT
);
112 file
= fdopen (fd
, "rt"); /* open in TEXT mode */
113 ok(fgetws(wbuffer
,sizeof(wbuffer
),file
) !=0,"fgetws failed unexpected\n");
114 ok(fgetws(wbuffer
,sizeof(wbuffer
),file
) ==0,"fgetws didn't signal EOF\n");
115 ok(feof(file
) !=0,"feof doesn't signal EOF\n");
117 ok(fgetws(wbuffer
,strlen(outbuffer
),file
) !=0,"fgetws failed unexpected\n");
118 ok(lstrlenW(wbuffer
) == (lstrlenA(outbuffer
) -1),"fgetws didn't read right size\n");
119 ok(fgetws(wbuffer
,sizeof(outbuffer
),file
) !=0,"fgets failed unexpected\n");
120 ok(lstrlenW(wbuffer
) == 1,"fgets dropped chars\n");
123 file
= fopen("fdopen.tst", "rb");
124 ok( file
!= NULL
, "fopen failed\n");
125 /* sizeof(buffer) > content of file */
126 ok(fread(buffer
, sizeof(buffer
), 1, file
) == 0, "fread test failed\n");
127 /* feof should be set now */
128 ok(feof(file
), "feof after fread failed\n");
131 unlink ("fdopen.tst");
134 static WCHAR
* AtoW( char* p
)
137 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, p
, -1, NULL
, 0 );
138 buffer
= malloc( len
* sizeof(WCHAR
) );
139 MultiByteToWideChar( CP_ACP
, 0, p
, -1, buffer
, len
);
143 static void test_fgetwc( void )
149 static const char mytext
[]= "This is test_fgetwc\n";
150 WCHAR wtextW
[LLEN
+1];
151 WCHAR
*mytextW
= NULL
, *aptr
, *wptr
;
152 BOOL diff_found
= FALSE
;
155 tempf
=_tempnam(".","wne");
156 tempfh
= fopen(tempf
,"wt"); /* open in TEXT mode */
157 fputs(mytext
,tempfh
);
159 tempfh
= fopen(tempf
,"rt");
160 fgetws(wtextW
,LLEN
,tempfh
);
161 mytextW
= AtoW ((char*)mytext
);
165 for (i
=0; i
<strlen(mytext
); i
++, aptr
++, wptr
++)
167 diff_found
|= (*aptr
!= *wptr
);
169 ok(!(diff_found
), "fgetwc difference found in TEXT mode\n");
170 if(mytextW
) free (mytextW
);
175 static void test_file_put_get( void )
179 static const char mytext
[]= "This is a test_file_put_get\n";
180 static const char dostext
[]= "This is a test_file_put_get\r\n";
182 WCHAR wtextW
[LLEN
+1];
183 WCHAR
*mytextW
= NULL
, *aptr
, *wptr
;
184 BOOL diff_found
= FALSE
;
187 tempf
=_tempnam(".","wne");
188 tempfh
= fopen(tempf
,"wt"); /* open in TEXT mode */
189 fputs(mytext
,tempfh
);
191 tempfh
= fopen(tempf
,"rb"); /* open in TEXT mode */
192 fgets(btext
,LLEN
,tempfh
);
193 ok( strlen(mytext
) + 1 == strlen(btext
),"TEXT/BINARY mode not handled for write\n");
194 ok( btext
[strlen(mytext
)-1] == '\r', "CR not written\n");
196 tempfh
= fopen(tempf
,"wb"); /* open in BINARY mode */
197 fputs(dostext
,tempfh
);
199 tempfh
= fopen(tempf
,"rt"); /* open in TEXT mode */
200 fgets(btext
,LLEN
,tempfh
);
201 ok(strcmp(btext
, mytext
) == 0,"_O_TEXT read doesn't strip CR\n");
203 tempfh
= fopen(tempf
,"rb"); /* open in TEXT mode */
204 fgets(btext
,LLEN
,tempfh
);
205 ok(strcmp(btext
, dostext
) == 0,"_O_BINARY read doesn't preserve CR\n");
208 tempfh
= fopen(tempf
,"rt"); /* open in TEXT mode */
209 fgetws(wtextW
,LLEN
,tempfh
);
210 mytextW
= AtoW ((char*)mytext
);
214 for (i
=0; i
<strlen(mytext
); i
++, aptr
++, wptr
++)
216 diff_found
|= (*aptr
!= *wptr
);
218 ok(!(diff_found
), "fgetwc doesn't strip CR in TEXT mode\n");
219 if(mytextW
) free (mytextW
);
224 static void test_file_write_read( void )
228 static const char mytext
[]= "This is test_file_write_read\nsecond line\n";
229 static const char dostext
[]= "This is test_file_write_read\r\nsecond line\r\n";
233 tempf
=_tempnam(".","wne");
234 tempfd
= _open(tempf
,_O_CREAT
|_O_TRUNC
|_O_TEXT
|_O_RDWR
,
235 _S_IREAD
| _S_IWRITE
);
237 "Can't open '%s': %d\n", tempf
, errno
); /* open in TEXT mode */
238 ok(_write(tempfd
,mytext
,strlen(mytext
)) == lstrlenA(mytext
),
239 "_write _O_TEXT bad return value\n");
241 tempfd
= _open(tempf
,_O_RDONLY
|_O_BINARY
,0); /* open in BINARY mode */
242 ok(_read(tempfd
,btext
,LLEN
) == lstrlenA(dostext
),
243 "_read _O_BINARY got bad length\n");
244 ok( memcmp(dostext
,btext
,strlen(dostext
)) == 0,
245 "problems with _O_TEXT _write / _O_BINARY _read\n");
246 ok( btext
[strlen(dostext
)-2] == '\r', "CR not written or read\n");
248 tempfd
= _open(tempf
,_O_RDONLY
|_O_TEXT
); /* open in TEXT mode */
249 ok(_read(tempfd
,btext
,LLEN
) == lstrlenA(mytext
),
250 "_read _O_TEXT got bad length\n");
251 ok( memcmp(mytext
,btext
,strlen(mytext
)) == 0,
252 "problems with _O_TEXT _write / _read\n");
255 memset(btext
, 0, LLEN
);
256 tempfd
= _open(tempf
,_O_APPEND
|_O_RDWR
); /* open for APPEND in default mode */
257 ok(tell(tempfd
) == 0, "bad position %lu expecting 0\n", tell(tempfd
));
258 ok(_read(tempfd
,btext
,LLEN
) == lstrlenA(mytext
), "_read _O_APPEND got bad length\n");
259 ok( memcmp(mytext
,btext
,strlen(mytext
)) == 0, "problems with _O_APPEND _read\n");
262 /* Test reading only \n or \r */
263 tempfd
= _open(tempf
,_O_RDONLY
|_O_TEXT
); /* open in TEXT mode */
264 _lseek(tempfd
, -1, FILE_END
);
265 ret
= _read(tempfd
,btext
,LLEN
);
266 ok(ret
== 1, "_read expected 1 got bad length: %d\n", ret
);
267 _lseek(tempfd
, -2, FILE_END
);
268 ret
= _read(tempfd
,btext
,LLEN
);
269 ok(ret
== 1 && *btext
== '\n', "_read expected '\\n' got bad length: %d\n", ret
);
270 _lseek(tempfd
, -3, FILE_END
);
271 ret
= _read(tempfd
,btext
,2);
272 todo_wine
ok(ret
== 1 && *btext
== 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret
, btext
, ret
);
273 todo_wine
ok(tell(tempfd
) == 42, "bad position %lu expecting 42\n", tell(tempfd
));
277 ok( ret
== 0 ,"Can't unlink '%s': %d\n", tempf
, errno
);
279 tempf
=_tempnam(".","wne");
280 tempfd
= _open(tempf
,_O_CREAT
|_O_TRUNC
|_O_BINARY
|_O_RDWR
,0);
282 "Can't open '%s': %d\n", tempf
, errno
); /* open in BINARY mode */
283 ok(_write(tempfd
,dostext
,strlen(dostext
)) == lstrlenA(dostext
),
284 "_write _O_BINARY bad return value\n");
286 tempfd
= _open(tempf
,_O_RDONLY
|_O_BINARY
,0); /* open in BINARY mode */
287 ok(_read(tempfd
,btext
,LLEN
) == lstrlenA(dostext
),
288 "_read _O_BINARY got bad length\n");
289 ok( memcmp(dostext
,btext
,strlen(dostext
)) == 0,
290 "problems with _O_BINARY _write / _read\n");
291 ok( btext
[strlen(dostext
)-2] == '\r', "CR not written or read\n");
293 tempfd
= _open(tempf
,_O_RDONLY
|_O_TEXT
); /* open in TEXT mode */
294 ok(_read(tempfd
,btext
,LLEN
) == lstrlenA(mytext
),
295 "_read _O_TEXT got bad length\n");
296 ok( memcmp(mytext
,btext
,strlen(mytext
)) == 0,
297 "problems with _O_BINARY _write / _O_TEXT _read\n");
300 ret
=_chmod (tempf
, _S_IREAD
| _S_IWRITE
);
302 "Can't chmod '%s' to read-write: %d\n", tempf
, errno
);
304 ok( ret
== 0 ,"Can't unlink '%s': %d\n", tempf
, errno
);
307 static void test_file_inherit_child(const char* fd_s
)
313 ret
=write(fd
, "Success", 8);
314 ok( ret
== 8, "Couldn't write in child process on %d (%s)\n", fd
, strerror(errno
));
315 lseek(fd
, 0, SEEK_SET
);
316 ok(read(fd
, buffer
, sizeof (buffer
)) == 8, "Couldn't read back the data\n");
317 ok(memcmp(buffer
, "Success", 8) == 0, "Couldn't read back the data\n");
320 static void test_file_inherit_child_no(const char* fd_s
)
325 ret
= write(fd
, "Success", 8);
326 ok( ret
== -1 && errno
== EBADF
,
327 "Wrong write result in child process on %d (%s)\n", fd
, strerror(errno
));
330 static void test_file_inherit( const char* selfname
)
333 const char* arg_v
[5];
336 fd
= open ("fdopen.tst", O_CREAT
| O_RDWR
| O_BINARY
, _S_IREAD
|_S_IWRITE
);
337 ok(fd
!= -1, "Couldn't create test file\n");
339 arg_v
[1] = "tests/file.c";
340 arg_v
[2] = buffer
; sprintf(buffer
, "%d", fd
);
342 _spawnvp(_P_WAIT
, selfname
, arg_v
);
343 ok(tell(fd
) == 8, "bad position %lu expecting 8\n", tell(fd
));
344 lseek(fd
, 0, SEEK_SET
);
345 ok(read(fd
, buffer
, sizeof (buffer
)) == 8 && memcmp(buffer
, "Success", 8) == 0, "Couldn't read back the data\n");
347 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
349 fd
= open ("fdopen.tst", O_CREAT
| O_RDWR
| O_BINARY
| O_NOINHERIT
, _S_IREAD
|_S_IWRITE
);
350 ok(fd
!= -1, "Couldn't create test file\n");
352 arg_v
[1] = "tests/file.c";
353 arg_v
[2] = buffer
; sprintf(buffer
, "%d", fd
);
356 _spawnvp(_P_WAIT
, selfname
, arg_v
);
357 ok(tell(fd
) == 0, "bad position %lu expecting 0\n", tell(fd
));
358 ok(read(fd
, buffer
, sizeof (buffer
)) == 0, "Found unexpected data (%s)\n", buffer
);
360 ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
363 static void test_tmpnam( void )
365 char name
[MAX_PATH
] = "abc";
369 ok(res
!= NULL
, "tmpnam returned NULL\n");
370 ok(res
[0] == '\\', "first character is not a backslash\n");
371 ok(strchr(res
+1, '\\') == 0, "file not in the root directory\n");
372 ok(res
[strlen(res
)-1] == '.', "first call - last character is not a dot\n");
375 ok(res
!= NULL
, "tmpnam returned NULL\n");
376 ok(res
== name
, "supplied buffer was not used\n");
377 ok(res
[0] == '\\', "first character is not a backslash\n");
378 ok(strchr(res
+1, '\\') == 0, "file not in the root directory\n");
379 ok(res
[strlen(res
)-1] != '.', "second call - last character is a dot\n");
382 static void test_chsize( void )
385 long cur
, pos
, count
;
386 char temptext
[] = "012345678";
387 char *tempfile
= _tempnam( ".", "tst" );
389 ok( tempfile
!= NULL
, "Couldn't create test file: %s\n", tempfile
);
391 fd
= _open( tempfile
, _O_CREAT
|_O_TRUNC
|_O_RDWR
, _S_IREAD
|_S_IWRITE
);
392 ok( fd
> 0, "Couldn't open test file\n" );
394 count
= _write( fd
, temptext
, sizeof(temptext
) );
395 ok( count
> 0, "Couldn't write to test file\n" );
397 /* get current file pointer */
398 cur
= _lseek( fd
, 0, SEEK_CUR
);
400 /* make the file smaller */
401 ok( _chsize( fd
, sizeof(temptext
) / 2 ) == 0, "_chsize() failed\n" );
403 pos
= _lseek( fd
, 0, SEEK_CUR
);
404 ok( cur
== pos
, "File pointer changed from: %ld to: %ld\n", cur
, pos
);
405 ok( _filelength( fd
) == sizeof(temptext
) / 2, "Wrong file size\n" );
407 /* enlarge the file */
408 ok( _chsize( fd
, sizeof(temptext
) * 2 ) == 0, "_chsize() failed\n" );
410 pos
= _lseek( fd
, 0, SEEK_CUR
);
411 ok( cur
== pos
, "File pointer changed from: %ld to: %ld\n", cur
, pos
);
412 ok( _filelength( fd
) == sizeof(temptext
) * 2, "Wrong file size\n" );
418 static void test_fopen_fclose_fcloseall( void )
420 char fname1
[] = "empty1";
421 char fname2
[] = "empty2";
422 char fname3
[] = "empty3";
423 FILE *stream1
, *stream2
, *stream3
, *stream4
;
426 /* testing fopen() */
427 stream1
= fopen(fname1
, "w+");
428 ok(stream1
!= NULL
, "The file '%s' was not opened\n", fname1
);
429 stream2
= fopen(fname2
, "w ");
430 ok(stream2
!= NULL
, "The file '%s' was not opened\n", fname2
);
432 stream3
= fopen(fname3
, "r");
433 ok(stream3
== NULL
, "The file '%s' shouldn't exist before\n", fname3
);
434 stream3
= fopen(fname3
, "w+");
435 ok(stream3
!= NULL
, "The file '%s' should be opened now\n", fname3
);
437 stream4
= fopen("", "w+");
438 ok(stream4
== NULL
&& errno
== ENOENT
,
439 "filename is empty, errno = %d (expected 2)\n", errno
);
441 stream4
= fopen(NULL
, "w+");
442 ok(stream4
== NULL
&& (errno
== EINVAL
|| errno
== ENOENT
),
443 "filename is NULL, errno = %d (expected 2 or 22)\n", errno
);
445 /* testing fclose() */
446 ret
= fclose(stream2
);
447 ok(ret
== 0, "The file '%s' was not closed\n", fname2
);
448 ret
= fclose(stream3
);
449 ok(ret
== 0, "The file '%s' was not closed\n", fname3
);
450 ret
= fclose(stream2
);
451 ok(ret
== EOF
, "Closing file '%s' returned %d\n", fname2
, ret
);
452 ret
= fclose(stream3
);
453 ok(ret
== EOF
, "Closing file '%s' returned %d\n", fname3
, ret
);
455 /* testing fcloseall() */
456 numclosed
= _fcloseall();
457 /* fname1 should be closed here */
458 ok(numclosed
== 1, "Number of files closed by fcloseall(): %u\n", numclosed
);
459 numclosed
= _fcloseall();
460 ok(numclosed
== 0, "Number of files closed by fcloseall(): %u\n", numclosed
);
462 ok(_unlink(fname1
) == 0, "Couldn't unlink file named '%s'\n", fname1
);
463 ok(_unlink(fname2
) == 0, "Couldn't unlink file named '%s'\n", fname2
);
464 ok(_unlink(fname3
) == 0, "Couldn't unlink file named '%s'\n", fname3
);
472 arg_c
= winetest_get_mainargs( &arg_v
);
474 /* testing low-level I/O */
477 if (arg_c
== 3) test_file_inherit_child(arg_v
[2]);
478 else test_file_inherit_child_no(arg_v
[2]);
481 test_file_inherit(arg_v
[0]);
482 test_file_write_read();
485 /* testing stream I/O */
487 test_fopen_fclose_fcloseall();