/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* * Copyright the Collabora Online contributors. * * SPDX-License-Identifier: MPL-2.0 * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "KitPidHelpers.hpp" #include #include #include #include #include #include #include #include #include std::string getPidList(const std::set& pids); std::set helpers::getKitPids() { return COOLWSD::getKitPids(); } std::set helpers::getSpareKitPids() { return COOLWSD::getSpareKitPids(); } std::set helpers::getDocKitPids() { return COOLWSD::getDocKitPids(); } pid_t helpers::getForKitPid() { std::string testname = "getForKitPid"; pid_t pid = COOLWSD::ForKitProcId; LOK_ASSERT_MESSAGE("Expected forkit process id to be >= 0", pid > 0); return pid; } std::string getPidList(const std::set& pids) { std::ostringstream oss; oss << "["; for (pid_t i : pids) { oss << i << ", "; } oss << "]"; return oss.str(); } void helpers::logKitProcesses(const std::string& testname) { std::set docKitPids = getDocKitPids(); std::set spareKitPids = getSpareKitPids(); TST_LOG("Current kit processes: " << "Doc Kits: " << getPidList(docKitPids) << " Spare Kits: " << getPidList(spareKitPids)); } void helpers::waitForKitPidsReady( const std::string& testname, const std::chrono::milliseconds timeoutMs /* = KIT_PID_TIMEOUT_MS */, const std::chrono::milliseconds retryMs /* = KIT_PID_RETRY_MS */) { // It is generally not a great idea to look for exactly processes const int targetDocKits = 0; const int targetSpareKits = 1; TST_LOG("Waiting for kit processes to close, with one spare kit"); std::set docKitPids; std::set spareKitPids; bool pass = false; int tries = timeoutMs / retryMs; while (tries >= 0 && !pass) { docKitPids = helpers::getDocKitPids(); spareKitPids = helpers::getSpareKitPids(); pass = (docKitPids.size() == static_cast(targetDocKits) && spareKitPids.size() == static_cast(targetSpareKits)); tries--; TST_LOG("Current kit processes: " << "Doc Kits: " << getPidList(docKitPids) << " Spare Kits: " << getPidList(spareKitPids)); if (!pass) std::this_thread::sleep_for(retryMs); } if (pass) { TST_LOG("Finished waiting for kit processes to close"); } else { std::ostringstream oss; oss << "Current kit processes:" << " Doc Kits: " << getPidList(docKitPids) << " Spare Kits: " << getPidList(spareKitPids); LOK_ASSERT_FAIL("Timed out waiting for kit processes to close: " + oss.str()); } } void helpers::killPid(const std::string& testname, const pid_t pid) { TST_LOG("Killing " << pid); if (kill(pid, SIGKILL) == -1) TST_LOG("kill(" << pid << ", SIGKILL) failed: " << Util::symbolicErrno(errno) << ": " << std::strerror(errno)); } void helpers::killAllKitProcesses( const std::string& testname, const std::chrono::milliseconds timeoutMs /* = COMMAND_TIMEOUT_MS * 8 */, const std::chrono::milliseconds retryMs /* = 10ms */) { auto before = getKitPids(); for (pid_t pid : before) killPid(testname, pid); TST_LOG("Waiting for these kit processes to close: " << getPidList(before)); bool pass = false; int tries = (timeoutMs / retryMs); std::set inters; while (tries >= 0 && !pass) { std::this_thread::sleep_for(retryMs); auto current = getKitPids(); inters.clear(); std::set_intersection( current.begin(), current.end(), before.begin(), before.end(), std::inserter(inters, inters.begin())); pass = inters.empty(); tries--; TST_LOG("Current kit processes: " << getPidList(current)); } TST_LOG("Finished waiting for all previous kit processes to close" << " before: " << getPidList(before) << " current: " << getPidList(getKitPids()) << " intersection: " << getPidList(inters)); LOK_ASSERT_MESSAGE_SILENT("Timed out waiting for these kit processes to close", pass); }