mirror of
https://github.com/nestriness/cdc-file-transfer.git
synced 2026-02-07 17:25:36 +02:00
Add actions for building and testing (#8)
* Add a Github action for building and testing On Windows, -- -//third_party/... doesn't seem to work, so add all test directories manually. Also run the tests_*. We run only fastbuild tests here, since the opt tests will be run in the release workflow. Also fix a number of compilation and test issues found along the way.
This commit is contained in:
@@ -29,6 +29,14 @@
|
||||
#include "common/util.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
#include <windows.h> // GetLongPathName
|
||||
#undef ReplaceFile
|
||||
#endif
|
||||
|
||||
namespace cdc_ft {
|
||||
namespace {
|
||||
|
||||
@@ -53,6 +61,22 @@ constexpr char kTestFileName[] = "test.txt";
|
||||
constexpr char kUnicodeTestFileName[] = u8"unicode test \U0001F964.txt";
|
||||
constexpr char kSubDirFileName[] = "subdir_file.txt";
|
||||
|
||||
// Converts e.g. C:\Progra~1 to C:\Program Files on Windows.
|
||||
std::string GetLongPath(std::string path) {
|
||||
#if PLATFORM_WINDOWS
|
||||
std::wstring wpath = Util::Utf8ToWideStr(path);
|
||||
std::wstring long_wpath(4096, 0);
|
||||
size_t buf_len =
|
||||
GetLongPathName(wpath.c_str(), const_cast<wchar_t*>(long_wpath.c_str()),
|
||||
long_wpath.size() * sizeof(wchar_t));
|
||||
EXPECT_GT(buf_len, 0);
|
||||
long_wpath.resize(buf_len);
|
||||
return Util::WideToUtf8Str(long_wpath);
|
||||
#else
|
||||
return path;
|
||||
#endif
|
||||
}
|
||||
|
||||
class PathTest : public ::testing::Test {
|
||||
public:
|
||||
PathTest() {
|
||||
@@ -159,7 +183,10 @@ class PathTest : public ::testing::Test {
|
||||
|
||||
std::vector<File> SearchFiles(const std::string& pattern, bool recursive);
|
||||
|
||||
std::string base_dir_ = path::Join(path::GetTempDir(), kBaseDirName);
|
||||
// Some tests get confused if the temp dir is a short filename
|
||||
// (e.g. RUNNER~1 instead of runneradmin - I'm looking at you, Github!).
|
||||
const std::string tmp_dir_ = GetLongPath(path::GetTempDir());
|
||||
std::string base_dir_ = path::Join(tmp_dir_, kBaseDirName);
|
||||
std::string search_dir_ = path::Join(base_dir_, kSearchDirName);
|
||||
std::string subdir_ = path::Join(search_dir_, kSubDirName);
|
||||
const std::string subdir_fulldirpath_ = subdir_;
|
||||
@@ -303,9 +330,11 @@ TEST_F(PathTest, GetFullPath) {
|
||||
path::Join(cwd, u8"\U0001F964", "foo"));
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
// These test cases assume that C: is the current drive.
|
||||
EXPECT_EQ(path::GetFullPath("C:"), cwd);
|
||||
EXPECT_EQ(path::GetFullPath("C:foo"), path::Join(cwd, "foo"));
|
||||
std::string current_drive = path::GetDrivePrefix(cwd);
|
||||
ASSERT_NE(current_drive, std::string());
|
||||
ASSERT_EQ(current_drive.size(), 2) << current_drive;
|
||||
EXPECT_EQ(path::GetFullPath(current_drive), cwd);
|
||||
EXPECT_EQ(path::GetFullPath(current_drive + "foo"), path::Join(cwd, "foo"));
|
||||
EXPECT_EQ(path::GetFullPath("V:foo"), "V:\\foo");
|
||||
EXPECT_EQ(path::GetFullPath("C:\\"), "C:\\");
|
||||
EXPECT_EQ(path::GetFullPath("C:\\foo"), "C:\\foo");
|
||||
@@ -322,9 +351,10 @@ TEST_F(PathTest, GetFullPath) {
|
||||
// other Windows APIs are trimming such spaces, most notably GetFullPathNameW.
|
||||
EXPECT_EQ(path::GetFullPath("trailing space "),
|
||||
path::Join(cwd, "trailing space "));
|
||||
EXPECT_EQ(path::GetFullPath("C:trailing space "),
|
||||
EXPECT_EQ(path::GetFullPath(current_drive + "trailing space "),
|
||||
path::Join(cwd, "trailing space "));
|
||||
EXPECT_EQ(path::GetFullPath("C:\\trailing space "), "C:\\trailing space ");
|
||||
EXPECT_EQ(path::GetFullPath(current_drive + "\\trailing space "),
|
||||
current_drive + "\\trailing space ");
|
||||
EXPECT_EQ(path::GetFullPath("V:trailing space "), "V:\\trailing space ");
|
||||
#else
|
||||
EXPECT_EQ(path::GetFullPath("/"), "/");
|
||||
@@ -753,6 +783,12 @@ std::vector<PathTest::File> PathTest::SearchFiles(const std::string& pattern,
|
||||
};
|
||||
|
||||
EXPECT_OK(path::SearchFiles(pattern, recursive, handler));
|
||||
|
||||
// Linux and Windows yield a slightly different order, so sort first.
|
||||
std::sort(files.begin(), files.end(), [](const File& a, const File& b) {
|
||||
return a.filename_ < b.filename_;
|
||||
});
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
@@ -771,9 +807,11 @@ TEST_F(PathTest, SearchFiles_NonRecursiveTrailingSeparator) {
|
||||
|
||||
EXPECT_EQ(files[1].dir_, search_dir_);
|
||||
EXPECT_EQ(files[1].Path(), test_filepath_);
|
||||
EXPECT_FALSE(files[1].is_directory_);
|
||||
|
||||
EXPECT_EQ(files[2].dir_, search_dir_);
|
||||
EXPECT_EQ(files[2].Path(), unicode_test_filepath_);
|
||||
EXPECT_FALSE(files[2].is_directory_);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -793,9 +831,11 @@ TEST_F(PathTest, SearchFiles_NonRecursiveNoTrailingSeparator) {
|
||||
|
||||
EXPECT_EQ(files[1].dir_, search_dir_);
|
||||
EXPECT_EQ(files[1].Path(), test_filepath_);
|
||||
EXPECT_FALSE(files[1].is_directory_);
|
||||
|
||||
EXPECT_EQ(files[2].dir_, search_dir_);
|
||||
EXPECT_EQ(files[2].Path(), unicode_test_filepath_);
|
||||
EXPECT_FALSE(files[2].is_directory_);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -814,9 +854,11 @@ TEST_F(PathTest, SearchFiles_RecursiveTrailingSeparator) {
|
||||
|
||||
EXPECT_EQ(files[2].dir_, search_dir_);
|
||||
EXPECT_EQ(files[2].Path(), test_filepath_);
|
||||
EXPECT_FALSE(files[2].is_directory_);
|
||||
|
||||
EXPECT_EQ(files[3].dir_, search_dir_);
|
||||
EXPECT_EQ(files[3].Path(), unicode_test_filepath_);
|
||||
EXPECT_FALSE(files[3].is_directory_);
|
||||
}
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
@@ -1215,7 +1257,7 @@ TEST_F(PathTest, Exists) {
|
||||
}
|
||||
|
||||
TEST_F(PathTest, CreateDir) {
|
||||
std::string dir = path::Join(path::GetTempDir(), "createdir_test");
|
||||
std::string dir = path::Join(tmp_dir_, "createdir_test");
|
||||
std::string unicode_dir = path::Join(dir, u8"\U0001F964\U0001F964\U0001F964");
|
||||
path::RemoveDirRec(dir).IgnoreError();
|
||||
EXPECT_NOT_OK(path::CreateDir(path::Join(dir, "subdir")));
|
||||
@@ -1232,7 +1274,7 @@ TEST_F(PathTest, CreateDir) {
|
||||
}
|
||||
|
||||
TEST_F(PathTest, CreateDirRec) {
|
||||
std::string dir = path::Join(path::GetTempDir(), "createdir_test", "subdir");
|
||||
std::string dir = path::Join(tmp_dir_, "createdir_test", "subdir");
|
||||
std::string unicode_dir = path::Join(dir, u8"\U0001F964\U0001F964\U0001F964");
|
||||
path::RemoveDirRec(dir).IgnoreError();
|
||||
EXPECT_OK(path::CreateDirRec(dir));
|
||||
|
||||
@@ -230,7 +230,7 @@ TEST_F(ProcessTest, RunUntil) {
|
||||
ProcessStartInfo start_info;
|
||||
start_info.command = "findstr stop";
|
||||
start_info.redirect_stdin = true;
|
||||
std::atomic_bool stop(false);
|
||||
std::atomic_bool stop{false};
|
||||
start_info.stdout_handler = [&std_out, &stop](const char* data, size_t) {
|
||||
// Check whether someone sent the "stop" command.
|
||||
// Note: This runs in a background thread.
|
||||
|
||||
@@ -49,7 +49,7 @@ void SetThreadName(const std::string& name) {
|
||||
}
|
||||
}
|
||||
|
||||
std::atomic_int g_pipe_serial_number(0);
|
||||
std::atomic_int g_pipe_serial_number{0};
|
||||
|
||||
// Creates a pipe suitable for overlapped IO. Regular anonymous pipes in Windows
|
||||
// don't support overlapped IO. This method creates a named pipe with a unique
|
||||
|
||||
@@ -79,9 +79,9 @@ TEST_F(SemaphoreTest, DoesNotBlockIfInitialCountIsOne) {
|
||||
|
||||
TEST_F(SemaphoreTest, SignalManyThreads) {
|
||||
Semaphore semaphore(0);
|
||||
std::atomic_int a(0);
|
||||
std::atomic_int b(0);
|
||||
std::atomic_int c(0);
|
||||
std::atomic_int a{0};
|
||||
std::atomic_int b{0};
|
||||
std::atomic_int c{0};
|
||||
|
||||
const int N = 16;
|
||||
std::vector<std::thread> threads;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
namespace cdc_ft {
|
||||
|
||||
Threadpool::Threadpool(size_t num_threads) : shutdown_(false) {
|
||||
Threadpool::Threadpool(size_t num_threads) : shutdown_{false} {
|
||||
workers_.reserve(num_threads);
|
||||
for (size_t n = 0; n < num_threads; ++n) {
|
||||
workers_.emplace_back([this]() { ThreadWorkerMain(); });
|
||||
|
||||
@@ -49,7 +49,7 @@ TEST_F(ThreadpoolTest, WaitShutdownWorkWithoutTasks) {
|
||||
}
|
||||
|
||||
TEST_F(ThreadpoolTest, SingleThreadedRunsToCompletion) {
|
||||
std::atomic_bool task_finished(false);
|
||||
std::atomic_bool task_finished{false};
|
||||
auto task_func = [&task_finished](Task::IsCancelledPredicate) {
|
||||
task_finished = true;
|
||||
};
|
||||
@@ -69,7 +69,7 @@ TEST_F(ThreadpoolTest, SingleThreadedRunsToCompletion) {
|
||||
TEST_F(ThreadpoolTest, MultiThreadedRunsToCompletion) {
|
||||
const int num_tasks = 19;
|
||||
const int num_threads = 7;
|
||||
std::atomic_int num_completed(0);
|
||||
std::atomic_int num_completed{0};
|
||||
|
||||
Threadpool pool(num_threads);
|
||||
std::unordered_set<Task*> tasks;
|
||||
@@ -95,7 +95,7 @@ TEST_F(ThreadpoolTest, MultiThreadedRunsToCompletion) {
|
||||
|
||||
TEST_F(ThreadpoolTest, TaskIsCancelledOnShutdown) {
|
||||
Semaphore task_started(0);
|
||||
std::atomic_bool task_finished(false);
|
||||
std::atomic_bool task_finished{false};
|
||||
auto task_func = [&task_started,
|
||||
&task_finished](Task::IsCancelledPredicate is_cancelled) {
|
||||
task_started.Signal();
|
||||
|
||||
Reference in New Issue
Block a user