#include "../../../sources/ui/nokde/kautosavefile.h" #include #include #include #include #include #include #include #ifdef Q_OS_UNIX #include #include #include #include #endif TEST_CASE("Qt-only KAutoSaveFile recovers stale files", "[nokde][autosave]") { #ifndef Q_OS_UNIX SUCCEED("crash-style stale lock test is Unix-only"); #else QTemporaryDir data_home; REQUIRE(data_home.isValid()); qputenv("XDG_DATA_HOME", QFile::encodeName(data_home.path())); QCoreApplication::setOrganizationName(QStringLiteral("QElectroTech")); QCoreApplication::setApplicationName(QStringLiteral("KAutoSaveFileTest")); const auto managed_path = data_home.filePath(QStringLiteral("project.qet")); QFile managed_file(managed_path); REQUIRE(managed_file.open(QIODevice::WriteOnly | QIODevice::Text)); REQUIRE(managed_file.write("\n") > 0); managed_file.close(); int ready_pipe[2] = {-1, -1}; REQUIRE(pipe(ready_pipe) == 0); const QByteArray payload("\n"); const auto child_pid = fork(); REQUIRE(child_pid >= 0); if (child_pid == 0) { close(ready_pipe[0]); KAutoSaveFile backup(QUrl::fromLocalFile(managed_path)); if (!backup.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) { _exit(2); } if (backup.write(payload) != payload.size()) { _exit(3); } if (!backup.flush()) { _exit(4); } const char ready = '1'; if (write(ready_pipe[1], &ready, 1) != 1) { _exit(5); } close(ready_pipe[1]); for (;;) { pause(); } } close(ready_pipe[1]); char ready = 0; REQUIRE(read(ready_pipe[0], &ready, 1) == 1); close(ready_pipe[0]); REQUIRE(ready == '1'); auto active_files = KAutoSaveFile::allStaleFiles(); CHECK(active_files.isEmpty()); for (auto *file : active_files) { delete file; } REQUIRE(kill(child_pid, SIGKILL) == 0); int status = 0; REQUIRE(waitpid(child_pid, &status, 0) == child_pid); REQUIRE(WIFSIGNALED(status)); REQUIRE(WTERMSIG(status) == SIGKILL); auto stale_files = KAutoSaveFile::allStaleFiles(); REQUIRE(stale_files.size() == 1); std::unique_ptr stale_file(stale_files.takeFirst()); CHECK(stale_file->managedFile().path() == QFileInfo(managed_path).absoluteFilePath()); REQUIRE(stale_file->open(QIODevice::ReadOnly | QIODevice::Text)); CHECK(stale_file->readAll() == payload); const auto autosave_file_name = stale_file->fileName(); const auto metadata_file_name = autosave_file_name + QStringLiteral(".path"); const auto lock_file_name = autosave_file_name + QStringLiteral(".lock"); stale_file.reset(); CHECK_FALSE(QFile::exists(autosave_file_name)); CHECK_FALSE(QFile::exists(metadata_file_name)); CHECK_FALSE(QFile::exists(lock_file_name)); #endif }