Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improving Test Reliability in RemoteTemporaryDirectory and TestJobManager #452

Merged
merged 14 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libsyncengine/jobs/abstractjob.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class AbstractJob : public Poco::Runnable {
inline void setProgressPercentCallback(const std::function<void(UniqueId, int)> &newCallback) {
_progressPercentCallback = newCallback;
}

inline ExitInfo exitInfo() const { return ExitInfo(_exitCode, _exitCause); }
inline ExitCode exitCode() const { return _exitCode; }
inline ExitCause exitCause() const { return _exitCause; }

Expand Down
37 changes: 24 additions & 13 deletions test/libcommonserver/log/testlog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,28 +91,37 @@ void TestLog::testExpiredLogFiles(void) {
// This test checks that old archived log files are deleted after a certain time
clearLogDirectory();

// Generate a fake log file
// Generate a fake old log file
std::ofstream fakeLogFile(_logDir / APPLICATION_NAME "_fake.log.gz");
fakeLogFile << "Fake old log file" << std::endl;
fakeLogFile.close();
LOG_INFO(_logger, "Test log file expiration"); // Ensure the log file is created.

CPPUNIT_ASSERT_EQUAL(2, countFilesInDirectory(_logDir)); // The current log file and the fake archived log file.
// Ensure that a new log file is created
LOG_INFO(_logger, "Test log file expiration");

// Check that we got 2 log files (the current one and the fake old one)
CPPUNIT_ASSERT_EQUAL(2, countFilesInDirectory(_logDir));

// Set the expiration time to 2 seconds
auto *appender = static_cast<CustomRollingFileAppender *>(_logger.getAppender(Log::rfName).get());
appender->setExpire(2); // 2 seconds
Utility::msleep(1000);
appender->checkForExpiredFiles();

const auto now = std::chrono::system_clock::now();
KDC::testhelpers::setModificationDate(Log::instance()->getLogFilePath(), now);

CPPUNIT_ASSERT_EQUAL(2, countFilesInDirectory(_logDir)); // The fake log file should not be deleted yet (< 2 seconds).

Utility::msleep(1000);
appender->checkForExpiredFiles();
const auto start = std::chrono::system_clock::now();
auto now = std::chrono::system_clock::now();
while (now - start < std::chrono::seconds(3)) {
now = std::chrono::system_clock::now();
KDC::testhelpers::setModificationDate(Log::instance()->getLogFilePath(),
now); // Prevent the current log file from being deleted.
appender->checkForExpiredFiles();
if (now - start < std::chrono::milliseconds(1500)) { // The fake log file should not be deleted yet.
CPPUNIT_ASSERT_EQUAL(2, countFilesInDirectory(_logDir));
} else if (countFilesInDirectory(_logDir) == 1) { // The fake log file MIGHT be deleted now.
break;
}
Utility::msleep(500);
}

CPPUNIT_ASSERT_EQUAL(1, countFilesInDirectory(_logDir)); // The fake log file should be deleted now.
CPPUNIT_ASSERT_EQUAL(1, countFilesInDirectory(_logDir)); // The fake log file SHOULD be deleted now.
appender->setExpire(CommonUtility::logsPurgeRate * 24 * 3600);
}

Expand Down Expand Up @@ -145,6 +154,8 @@ void TestLog::clearLogDirectory(void) const {
continue;
}
IoHelper::deleteItem(entry.path(), ioError);
CPPUNIT_ASSERT_EQUAL(IoError::Success, ioError);

}
CPPUNIT_ASSERT_EQUAL(IoError::Success, ioError);
CPPUNIT_ASSERT(endOfDirectory);
Expand Down
40 changes: 25 additions & 15 deletions test/libsyncengine/jobs/testjobmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ namespace KDC {
static const SyncPath localTestDirPath(std::wstring(L"" TEST_DIR) + L"/test_ci");
static const SyncPath localTestDirPath_manyFiles(std::wstring(L"" TEST_DIR) + L"/test_ci/many_files_dir");
static const SyncPath localTestDirPath_pictures(std::wstring(L"" TEST_DIR) + L"/test_ci/test_pictures");
static const SyncPath localTestDirPath_bigFiles(std::wstring(L"" TEST_DIR) + L"/test_ci/big_file_dir");
static const int driveDbId = 1;
void KDC::TestJobManager::setUp() {
const testhelpers::TestVariables testVariables;
Expand Down Expand Up @@ -175,25 +174,40 @@ void TestJobManager::testWithCallbackBigFiles() {
}

void TestJobManager::testCancelJobs() {
// Create temp remote directory
const RemoteTemporaryDirectory remoteTmpDir(driveDbId, _testVariables.remoteDirId, "TestJobManager testCancelJobs");
const LocalTemporaryDirectory localTmpDir("testJobManager");
const int localFileCounter = 100;
for (int i = 0; i < localFileCounter; i++) {
testhelpers::generateOrEditTestFile(localTmpDir.path() / ("file_" + std::to_string(i) + ".txt"));
}

// Upload all files in testDir
ulong jobCounter = 0;
for (auto &dirEntry: std::filesystem::directory_iterator(localTestDirPath_manyFiles)) {
for (auto &dirEntry: std::filesystem::directory_iterator(localTmpDir.path())) {
auto job = std::make_shared<UploadJob>(driveDbId, dirEntry.path(), dirEntry.path().filename().native(), remoteTmpDir.id(),
0);
std::function<void(UniqueId)> callback = std::bind(&TestJobManager::callback, this, std::placeholders::_1);
JobManager::instance()->queueAsyncJob(job, Poco::Thread::PRIO_NORMAL, callback);
jobCounter++;
const std::scoped_lock lock(_mutex);
_ongoingJobs.try_emplace(static_cast<uint64_t>(job->jobId()), job);
}

Utility::msleep(1000); // Wait 1sec
while (_ongoingJobs.size() == localFileCounter) {
Utility::msleep(1); // Wait 1ms
}

cancelAllOngoingJobs();

Utility::msleep(10000); // Wait 10sec
int retry = 1000; // Wait max 10sec
while ((!JobManager::_managedJobs.empty() || !JobManager::_queuedJobs.empty() || !JobManager::_runningJobs.empty() ||
!JobManager::_pendingJobs.empty()) &&
(retry > 0)) {
retry--;
Utility::msleep(10);
}

CPPUNIT_ASSERT(JobManager::instance()->_managedJobs.empty());
CPPUNIT_ASSERT(JobManager::instance()->_queuedJobs.empty());
CPPUNIT_ASSERT(JobManager::instance()->_runningJobs.empty());
CPPUNIT_ASSERT(JobManager::instance()->_pendingJobs.empty());

GetFileListJob fileListJob(driveDbId, remoteTmpDir.id());
fileListJob.runSynchronously();
Expand All @@ -202,14 +216,10 @@ void TestJobManager::testCancelJobs() {
CPPUNIT_ASSERT(resObj);

Poco::JSON::Array::Ptr data = resObj->getArray(dataKey);
size_t total = data->size();
CPPUNIT_ASSERT(jobCounter != total);
CPPUNIT_ASSERT(total > 0);
const size_t uploadedFileCounter = data->size();
CPPUNIT_ASSERT(localFileCounter != uploadedFileCounter);
CPPUNIT_ASSERT(uploadedFileCounter > 0);
CPPUNIT_ASSERT(ongoingJobsCount() == 0);
CPPUNIT_ASSERT(JobManager::instance()->_managedJobs.empty());
CPPUNIT_ASSERT(JobManager::instance()->_queuedJobs.empty());
CPPUNIT_ASSERT(JobManager::instance()->_runningJobs.empty());
CPPUNIT_ASSERT(JobManager::instance()->_pendingJobs.empty());
}

std::queue<int64_t> finishedJobs;
Expand Down
51 changes: 33 additions & 18 deletions test/test_utility/remotetemporarydirectory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,43 @@
#include "../../src/libsyncengine/jobs/network/API_v2/deletejob.h"
#include "libsyncengine/jobs/network/networkjobsparams.h"
#include "libcommonserver/utility/utility.h"
#include "libcommon/utility/utility.h"

namespace KDC {
RemoteTemporaryDirectory::RemoteTemporaryDirectory(int driveDbId, const NodeId& parentId,
const std::string& testType /*= "undef"*/) : _driveDbId(driveDbId) {
// Generate directory name
const std::time_t now = std::time(nullptr);
const std::tm tm = *std::localtime(&now);
std::ostringstream woss;
woss << std::put_time(&tm, "%Y%m%d_%H%M");

_dirName = Str("kdrive_") + Str2SyncName(testType) + Str("_unit_tests_") + Str2SyncName(woss.str());

// Create remote test dir
CreateDirJob job(_driveDbId, parentId, _dirName);
CPPUNIT_ASSERT_EQUAL(ExitCode::Ok, job.runSynchronously());

// Extract file ID
CPPUNIT_ASSERT(job.jsonRes());
Poco::JSON::Object::Ptr dataObj = job.jsonRes()->getObject(dataKey);
CPPUNIT_ASSERT(dataObj);
_dirId = dataObj->get(idKey).toString();
const std::string& testType /*= "undef"*/) :
_driveDbId(driveDbId) {
int retry = 5;
do {
std::string suffix = CommonUtility::generateRandomStringAlphaNum(5);
// Generate directory name
const std::time_t now = std::time(nullptr);
const std::tm tm = *std::localtime(&now);
std::ostringstream woss;
woss << std::put_time(&tm, "%Y%m%d_%H%M");
_dirName = Str("kdrive_") + Str2SyncName(testType) + Str("_unit_tests_") + Str2SyncName(woss.str() + "___" + suffix);

// Create remote test dir
CreateDirJob job(_driveDbId, parentId, _dirName);
job.runSynchronously();
if (job.exitInfo() == ExitInfo(ExitCode::BackError, ExitCause::FileAlreadyExist) && retry > 0) {
retry--;
continue;
}

CPPUNIT_ASSERT_EQUAL(ExitInfo(ExitCode::Ok), job.exitInfo());
luc-guyot-infomaniak marked this conversation as resolved.
Show resolved Hide resolved

// Extract file ID
CPPUNIT_ASSERT(job.jsonRes());
Poco::JSON::Object::Ptr dataObj = job.jsonRes()->getObject(dataKey);
CPPUNIT_ASSERT(dataObj);
_dirId = dataObj->get(idKey).toString();
LOGW_INFO(Log::instance()->getLogger(), L"RemoteTemporaryDirectory created: " << Utility::formatSyncName(_dirName)
<< L" with ID: " << Utility::s2ws(_dirId));
break;
} while (true);
}

RemoteTemporaryDirectory::~RemoteTemporaryDirectory() {
if (_isDeleted) return;

Expand Down
Loading