[PATCH v4 1/4] msvcrt/tests: Add test for fopen/_open access hints

Luke Deller luke at deller.id.au
Tue Aug 3 10:30:04 CDT 2021


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 at deller.id.au>
---
v4: Adjust the test for the contradictory "rbRS" fopen mode, to match
what Marvin <testbot at 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
-- 
2.25.1




More information about the wine-devel mailing list