[PATCH v2 6/6] robocopy/tests: Add basic conformance tests
Florian Eder
others.meder at gmail.com
Wed Sep 15 16:57:00 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