[PATCH v3 6/6] robocopy/tests: Add basic conformance tests

Florian Eder others.meder at gmail.com
Fri Sep 17 02:34:17 CDT 2021


Basic conformance tests create a test source directory with
files and execute robocopy on it, checking whether the resulting
destination directory, the remaining source directory and the exit code
is as expected

Signed-off-by: Florian Eder <others.meder at gmail.com>
---
 programs/robocopy/tests/robocopy.c | 189 ++++++++++++++++++++++++++++-
 1 file changed, 187 insertions(+), 2 deletions(-)

diff --git a/programs/robocopy/tests/robocopy.c b/programs/robocopy/tests/robocopy.c
index 02798663ba5..60ce0aeecca 100644
--- a/programs/robocopy/tests/robocopy.c
+++ b/programs/robocopy/tests/robocopy.c
@@ -48,9 +48,153 @@ static DWORD execute_robocopy(const WCHAR *cmd_line)
     return exit_code;
 }
 
+static void create_test_file(const WCHAR *relative_path, size_t size, LONGLONG fixed_filetime, long filetime_offset)
+{
+    HANDLE handle;
+    WCHAR path[1024];
+    wcscpy(path, L"\\\\?\\");
+    GetTempPathW(ARRAY_SIZE(path) - 4, &(path[4]));
+    wcscat(path, relative_path);
+    handle = CreateFileW(path, FILE_GENERIC_WRITE | FILE_GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
+    ok(handle != INVALID_HANDLE_VALUE, "creation of %S failed (0x%08x)\n", path, GetLastError());
+    if (size != 0)
+    {
+        BYTE *data;
+        DWORD bytes_written;
+        data = calloc(size, sizeof(BYTE));
+        ok(WriteFile(handle, data, size, &bytes_written, NULL), "writing to %S failed (%d)\n", path, GetLastError());
+    }
+    if (fixed_filetime != 0)
+    {
+        FILETIME time;
+        LARGE_INTEGER time_as_integer;
+        time_as_integer.QuadPart = fixed_filetime;
+        time.dwHighDateTime = time_as_integer.HighPart;
+        time.dwLowDateTime = time_as_integer.LowPart;
+        ok(SetFileTime(handle, &time, &time, &time), "filetime manipulation of %S failed (%d)\n", path, GetLastError());
+    }
+    if (filetime_offset != 0)
+    {
+        FILETIME time, modified_time, access_time;
+        LARGE_INTEGER time_as_integer;
+        GetFileTime(handle, &time, &modified_time, &access_time);
+        /* FILETIME is no union with LONGLONG / LONG64, casting could be unsafe */
+        time_as_integer.HighPart = time.dwHighDateTime;
+        time_as_integer.LowPart = time.dwLowDateTime;
+        /* 1000 * 1000 * 60 * 60 * 24 = 86400000000ns per day */
+        time_as_integer.QuadPart += 864000000000LL * filetime_offset;
+        time.dwHighDateTime = time_as_integer.HighPart;
+        time.dwLowDateTime = time_as_integer.LowPart;
+        ok(SetFileTime(handle, &time, &time, &time), "filetime manipulation of %S failed (%d)\n", path, GetLastError());
+    }
+    CloseHandle(handle);
+}
+
+static void create_test_folder(const WCHAR *relative_path)
+{
+    WCHAR path[1024];
+    wcscpy(path, L"\\\\?\\");
+    GetTempPathW(ARRAY_SIZE(path) - 4, &(path[4]));
+    wcscat(path, relative_path);
+    CreateDirectoryW(path, NULL);
+}
+
+static void create_test_source_folder(void)
+{
+    create_test_folder(L"robocopy_source");
+    create_test_folder(L"robocopy_source\\folderA");
+    create_test_folder(L"robocopy_source\\folderB");
+    create_test_folder(L"robocopy_source\\folderC");
+    create_test_folder(L"robocopy_source\\folderA\\folderD");
+    create_test_folder(L"robocopy_source\\folderA\\folderE");
+    create_test_file(L"robocopy_source\\fileA.a", 4000, 0, -10);
+    create_test_file(L"robocopy_source\\fileB.b", 8000, 0, -2);
+    create_test_file(L"robocopy_source\\folderA\\fileC.c", 60, 0, -2);
+    create_test_file(L"robocopy_source\\folderA\\fileD.d", 80, 0, 0);
+    create_test_file(L"robocopy_source\\folderA\\folderD\\fileE.e", 10000, 0, -10);
+    create_test_file(L"robocopy_source\\folderB\\fileF.f", 10000, 132223104000000000, 0);
+    create_test_file(L"robocopy_source\\folderB\\fileG.g", 200, 132223104000000000, 0);
+}
+
+static void check_file_and_delete(const WCHAR *relative_path, BOOL should_exist)
+{
+    WCHAR path[1024];
+    wcscpy(path, L"\\\\?\\");
+    GetTempPathW(ARRAY_SIZE(path) - 4, &(path[4]));
+    wcscat(path, relative_path);
+    if (!DeleteFileW(path))
+    {
+        if (GetLastError() == ERROR_FILE_NOT_FOUND)
+            ok(!should_exist, "file \"%S\" does not exist, but should exist\n", relative_path);
+        else if (GetLastError() == ERROR_PATH_NOT_FOUND)
+            ok(!should_exist, "file \"%S\" and the parent directory do not exist, but should exist\n", relative_path);
+        else
+            ok(FALSE, "file \"%S\" DeleteFileW returned error %d\n", relative_path, GetLastError());
+    }
+    else
+    {
+        ok(should_exist, "file \"%S\" should not exist, but does exist\n", relative_path);
+    }
+}
+
+static void check_folder_and_delete(const WCHAR *relative_path, BOOL should_exist)
+{
+    WCHAR path[1024];
+    wcscpy(path, L"\\\\?\\");
+    GetTempPathW(ARRAY_SIZE(path) - 4, &(path[4]));
+    wcscat(path, relative_path);
+    if (!RemoveDirectoryW(path))
+    {
+        if (GetLastError() == ERROR_FILE_NOT_FOUND)
+            ok(!should_exist, "directory \"%S\" does not exist, but should exist\n", relative_path);
+        else if (GetLastError() == ERROR_PATH_NOT_FOUND)
+            ok(!should_exist, "directory \"%S\" and the parent directory do not exist, but should exist\n", relative_path);
+        else if (GetLastError() == ERROR_DIR_NOT_EMPTY)
+            ok(FALSE, "directory \"%S\" is unexpectedly not empty\n", relative_path);
+        else
+            ok(FALSE, "directory \"%S\" DeleteFileW returned error %d\n", relative_path, GetLastError());
+    }
+    else
+    {
+        ok(should_exist, "directory \"%S\" should not exist, but does exist\n", relative_path);
+    }
+}
+
+static void check_basic_copy_test(void)
+{
+    check_file_and_delete(L"robocopy_source\\fileA.a", TRUE);
+    check_file_and_delete(L"robocopy_source\\fileB.b", TRUE);
+    check_file_and_delete(L"robocopy_source\\folderA\\fileC.c", TRUE);
+    check_file_and_delete(L"robocopy_source\\folderA\\fileD.d", TRUE);
+    check_file_and_delete(L"robocopy_source\\folderA\\folderD\\fileE.e", TRUE);
+    check_file_and_delete(L"robocopy_source\\folderB\\fileF.f", TRUE);
+    check_file_and_delete(L"robocopy_source\\folderB\\fileG.g", TRUE);
+    check_folder_and_delete(L"robocopy_source\\folderA\\folderD", TRUE);
+    check_folder_and_delete(L"robocopy_source\\folderA\\folderE", TRUE);
+    check_folder_and_delete(L"robocopy_source\\folderA", TRUE);
+    check_folder_and_delete(L"robocopy_source\\folderB", TRUE);
+    check_folder_and_delete(L"robocopy_source\\folderC", TRUE);
+    check_folder_and_delete(L"robocopy_source", TRUE);
+
+    check_file_and_delete(L"robocopy_destination\\fileA.a", TRUE);
+    check_file_and_delete(L"robocopy_destination\\fileB.b", TRUE);
+    todo_wine check_file_and_delete(L"robocopy_destination\\folderA\\fileC.c", FALSE);
+    todo_wine check_file_and_delete(L"robocopy_destination\\folderA\\fileD.d", FALSE);
+    todo_wine check_file_and_delete(L"robocopy_destination\\folderA\\folderD\\fileE.e", FALSE);
+    todo_wine check_file_and_delete(L"robocopy_destination\\folderB\\fileF.f", FALSE);
+    todo_wine check_file_and_delete(L"robocopy_destination\\folderB\\fileG.g", FALSE);
+    todo_wine check_folder_and_delete(L"robocopy_destination\\folderA\\folderD", FALSE);
+    check_folder_and_delete(L"robocopy_destination\\folderA\\folderE", FALSE);
+    todo_wine check_folder_and_delete(L"robocopy_destination\\folderA", FALSE);
+    todo_wine check_folder_and_delete(L"robocopy_destination\\folderB", FALSE);
+    check_folder_and_delete(L"robocopy_destination\\folderC", FALSE);
+    check_folder_and_delete(L"robocopy_destination", TRUE);
+}
+
 START_TEST(robocopy)
 {
-    WCHAR previous_cwd_path[4096], temp_path[4096];
+    WCHAR temp_command_line[2048], previous_cwd_path[4096], temp_path[4096];
+    DWORD exit_code;
 
     ok(GetFullPathNameW(L".", ARRAY_SIZE(previous_cwd_path), previous_cwd_path, NULL) != 0, "couldn't get CWD path");
     ok(GetTempPathW(ARRAY_SIZE(temp_path), temp_path) != 0, "couldn't get temp folder path");
@@ -60,7 +204,48 @@ START_TEST(robocopy)
 
     ok(SetCurrentDirectoryW(temp_path), "couldn't set CWD to temp folder \"%S\"", temp_path);
 
-    /* TODO: conformance tests here */
+    winetest_push_context("basic copy test 1");
+    create_test_source_folder();
+    exit_code = execute_robocopy(L"robocopy.exe robocopy_source robocopy_destination /r:1 /w:0");
+    ok(exit_code == 1, "unexpected exit code %d\n", exit_code);
+    check_basic_copy_test();
+    winetest_pop_context();
+
+    winetest_push_context("basic copy test 2");
+    create_test_source_folder();
+    exit_code = execute_robocopy(L"robocopy.exe ./robocopy_source third_folder/../robocopy_destination /r:1 /w:0");
+    ok(exit_code == 1, "unexpected exit code %d\n", exit_code);
+    check_basic_copy_test();
+    winetest_pop_context();
+
+    winetest_push_context("basic copy test 3");
+    create_test_source_folder();
+    create_test_folder(L"robocopy_destination");
+    create_test_file(L"robocopy_destination\\fileA.a", 9000, 0, -10);
+    exit_code = execute_robocopy(L"robocopy.exe ./robocopy_source robocopy_source/../robocopy_destination /r:1 /w:0");
+    ok(exit_code == 1, "unexpected exit code %d\n", exit_code);
+    check_basic_copy_test();
+    winetest_pop_context();
+
+    winetest_push_context("basic copy test 4");
+    create_test_source_folder();
+    swprintf(temp_command_line, ARRAY_SIZE(temp_command_line),
+                L"robocopy.exe %s\\robocopy_source %s\\robocopy_destination /r:1 /w:0",
+                temp_path, temp_path);
+    exit_code = execute_robocopy(temp_command_line);
+    ok(exit_code == 1, "unexpected exit code %d\n", exit_code);
+    check_basic_copy_test();
+    winetest_pop_context();
+
+    winetest_push_context("basic copy test 5");
+    create_test_source_folder();
+    swprintf(temp_command_line, ARRAY_SIZE(temp_command_line),
+                L"robocopy.exe %s\\third_folder\\..\\robocopy_source %s\\third_folder\\..\\robocopy_destination /r:1 /w:0",
+                temp_path, temp_path);
+    exit_code = execute_robocopy(temp_command_line);
+    ok(exit_code == 1, "unexpected exit code %d\n", exit_code);
+    check_basic_copy_test();
+    winetest_pop_context();
 
     ok(SetCurrentDirectoryW(previous_cwd_path), "couldn't set CWD to previous CWD folder \"%S\"", previous_cwd_path);
 }
-- 
2.32.0




More information about the wine-devel mailing list