Test passing sequential and random access hints to fopen and _open. Test that the underlying windows handle actually has the corresponding FILE_SEQUENTIAL_ONLY mode set correctly.
Signed-off-by: Luke Deller luke@deller.id.au --- v4: Adjust the test for the contradictory "rbRS" fopen mode, to match what Marvin testbot@winehq.org reported is the behaviour on Windows --- dlls/msvcrt/tests/file.c | 124 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+)
diff --git a/dlls/msvcrt/tests/file.c b/dlls/msvcrt/tests/file.c index fb242d81282..1117ac0f729 100644 --- a/dlls/msvcrt/tests/file.c +++ b/dlls/msvcrt/tests/file.c @@ -35,6 +35,7 @@ #include <process.h> #include <errno.h> #include <locale.h> +#include <winternl.h>
#define MSVCRT_FD_BLOCK_SIZE 32 typedef struct { @@ -2731,6 +2732,127 @@ static void test_lseek(void) DeleteFileA("_creat.tst"); }
+static BOOL has_sequential_hint(int fd) +{ + HANDLE handle; + FILE_MODE_INFORMATION mode_info; + IO_STATUS_BLOCK io; + NTSTATUS status; + + /* Check whether the file handle has the sequential access hint */ + handle = (HANDLE)_get_osfhandle(fd); + status = NtQueryInformationFile(handle, &io, &mode_info, sizeof(mode_info), + FileModeInformation); + ok(!status, "NtQueryInformationFile failed\n"); + return (mode_info.Mode & FILE_SEQUENTIAL_ONLY) != 0; +} + +static void test_fopen_hints(void) +{ + char *tempf; + FILE *fp; + int i; + + /* fopen modes to test */ + const char *fopen_modes[] = { + "rb", "rbS", "rbR", "rbSR", "rbRS" + }; + /* corresponding expected hints */ + BOOL expected_hints[][2] = { + /* expect_sequential, expect_random */ + {FALSE, FALSE}, + {TRUE, FALSE}, + {FALSE, TRUE}, + {TRUE, FALSE}, + {FALSE, TRUE}, + }; + + /* create a test file */ + tempf = _tempnam(".","wne"); + fp = fopen(tempf, "wb"); + ok(fp != NULL, "unable to create test file\n"); + fwrite("abc\n", 1, 4, fp); + fclose(fp); + + /* test fopen with each mode */ + for (i = 0; i < sizeof(fopen_modes)/sizeof(char*); ++i) + { + BOOL expect_sequential, has_sequential; + const char *mode = fopen_modes[i]; + expect_sequential = expected_hints[i][0]; + + fp = fopen(tempf, mode); + ok(fp != NULL, "unable to fopen test file with mode "%s"\n", mode); + + has_sequential = has_sequential_hint(_fileno(fp)); + todo_wine_if(expect_sequential) ok(has_sequential == expect_sequential, + "unexpected sequential hint %d for fopen mode "%s"\n", + has_sequential, mode); + + /* TODO: Somehow check whether the random access hint has been applied. + * Sadly NtQueryInformationFile does not expose this information. */ + + fclose(fp); + } + + unlink(tempf); + free(tempf); +} + +static void test_open_hints(void) +{ + char *tempf; + int fd; + int i; + + /* fopen modes to test */ + int open_flags[] = { + _O_RDONLY | _O_BINARY, + _O_RDONLY | _O_BINARY | _O_SEQUENTIAL, + _O_RDONLY | _O_BINARY | _O_RANDOM, + _O_RDONLY | _O_BINARY | _O_RANDOM | _O_SEQUENTIAL, + }; + /* corresponding expected hints */ + BOOL expected_hints[][2] = { + /* expect_sequential, expect_random */ + {FALSE, FALSE}, + {TRUE, FALSE}, + {FALSE, TRUE}, + {TRUE, TRUE}, + }; + + /* create a test file */ + tempf = _tempnam(".","wne"); + fd = _open(tempf, _O_CREAT | _O_WRONLY | _O_BINARY); + ok(fd != -1, "unable to create test file\n"); + _write(fd, "abc\n", 4); + _close(fd); + + /* test _open with each mode */ + for (i = 0; i < sizeof(open_flags)/sizeof(int); ++i) + { + BOOL expect_sequential, has_sequential; + int flags = open_flags[i]; + expect_sequential = expected_hints[i][0]; + + fd = open(tempf, flags); + ok(fd != -1, "unable to _open test file with flags %x\n", flags); + + has_sequential = has_sequential_hint(fd); + todo_wine_if(expect_sequential) ok(has_sequential == expect_sequential, + "unexpected sequential hint %d for _open flags %x\n", + has_sequential, flags); + + /* TODO: Somehow check whether the random access hint has been applied. + * Sadly NtQueryInformationFile does not expose this information. */ + + close(fd); + } + + unlink(tempf); + free(tempf); +} + START_TEST(file) { int arg_c; @@ -2803,6 +2925,8 @@ START_TEST(file) test_close(); test__creat(); test_lseek(); + test_fopen_hints(); + test_open_hints();
/* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report * file contains lines in the correct order