mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 10:51:22 +00:00
Merge branch 'feat/printer-agent-infra' into feat/printer-agent-impl
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <slic3r/Utils/IPrinterAgent.hpp>
|
||||
#include <slic3r/Utils/OrcaCloudServiceAgent.hpp>
|
||||
#include <slic3r/Utils/OrcaPrinterAgent.hpp>
|
||||
|
||||
@@ -85,7 +86,10 @@ TEST_CASE("OrcaPrinterAgent::make_lan_client_id is stable and prefixed", "[OrcaP
|
||||
|
||||
TEST_CASE("connect_printer wires up a LAN Config", "[OrcaPrinterAgent][.integration]") {
|
||||
Probe agent("/tmp");
|
||||
const int rc = agent.connect_printer("dev-1", "10.255.255.1", "orcasonar", "code", false);
|
||||
Slic3r::PrinterConnectionParams params{
|
||||
"dev-1", "10.255.255.1", "orcasonar", "code", "", false, ""
|
||||
};
|
||||
const int rc = agent.connect_printer(params);
|
||||
CHECK(rc == BAMBU_NETWORK_SUCCESS);
|
||||
CHECK(agent.lan_connection_target() == "ws://10.255.255.1:8280/mqtt");
|
||||
CHECK(agent.get_user_selected_machine().empty()); // LAN path must not touch the cloud selection
|
||||
@@ -174,7 +178,7 @@ TEST_CASE("send_message_to_printer publishes on the LAN connection", "[OrcaPrint
|
||||
orca_mqtt_test::MockBroker broker;
|
||||
OrcaPrinterAgent agent("/tmp");
|
||||
const auto ep = broker.host_port();
|
||||
agent.connect_printer("dev-1", ep.first + ":" + ep.second, "orcasonar", "code", false);
|
||||
agent.connect_printer(Slic3r::PrinterConnectionParams{"dev-1", ep.first + ":" + ep.second, "orcasonar", "code", "", false, ""});
|
||||
|
||||
for (int i = 0; i < 150 && broker.connect_count() == 0; ++i)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
@@ -197,7 +201,7 @@ TEST_CASE("send_message_to_printer publishes on the LAN connection", "[OrcaPrint
|
||||
TEST_CASE("destroying an agent mid-connect does not hang or crash", "[OrcaPrinterAgent]") {
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
auto agent = std::make_unique<OrcaPrinterAgent>("/tmp");
|
||||
agent->connect_printer("dev-1", "127.0.0.1:1", "orcasonar", "code", false); // nothing listening: instant ECONNREFUSED
|
||||
agent->connect_printer(Slic3r::PrinterConnectionParams{"dev-1", "127.0.0.1:1", "orcasonar", "code", "", false, ""}); // nothing listening: instant ECONNREFUSED
|
||||
agent.reset(); // ~OrcaPrinterAgent must stop the conn, join the thread, and not hang/crash
|
||||
}
|
||||
SUCCEED();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <catch2/catch_all.hpp>
|
||||
|
||||
#include <libslic3r/LifecycleEvents.hpp>
|
||||
#include <libslic3r/Utils.hpp>
|
||||
#include <slic3r/Utils/NetworkAgentFactory.hpp>
|
||||
#include <slic3r/plugin/PluginDescriptor.hpp>
|
||||
@@ -13,8 +14,11 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace Slic3r;
|
||||
@@ -205,6 +209,72 @@ PluginDescriptor descriptor_of(PluginManager& manager, const std::string& plugin
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("Lifecycle hook shutdown drains concurrent dispatch", "[PluginLifecycle][LifecycleEvents]")
|
||||
{
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
bool callback_entered = false;
|
||||
bool release_callback = false;
|
||||
bool shutdown_started = false;
|
||||
bool shutdown_finished = false;
|
||||
|
||||
set_lifecycle_hook_fn([&](LifecycleEvent, const LifecycleEventContext&) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
callback_entered = true;
|
||||
cv.notify_all();
|
||||
cv.wait(lock, [&] { return release_callback; });
|
||||
});
|
||||
|
||||
std::thread dispatch_thread([] {
|
||||
LifecycleEventContext ctx;
|
||||
fire_lifecycle_event(LifecycleEvent::ProjectOpened, ctx);
|
||||
});
|
||||
|
||||
bool callback_was_entered = false;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
callback_was_entered = cv.wait_for(lock, std::chrono::seconds(5), [&] { return callback_entered; });
|
||||
}
|
||||
if (!callback_was_entered) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
release_callback = true;
|
||||
cv.notify_all();
|
||||
}
|
||||
dispatch_thread.join();
|
||||
set_lifecycle_hook_fn(nullptr);
|
||||
FAIL("Lifecycle callback did not start");
|
||||
}
|
||||
|
||||
std::thread shutdown_thread([&] {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
shutdown_started = true;
|
||||
cv.notify_all();
|
||||
}
|
||||
set_lifecycle_hook_fn(nullptr);
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
shutdown_finished = true;
|
||||
cv.notify_all();
|
||||
});
|
||||
|
||||
bool shutdown_was_started = false;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
shutdown_was_started = cv.wait_for(lock, std::chrono::seconds(5), [&] { return shutdown_started; });
|
||||
if (shutdown_was_started)
|
||||
CHECK_FALSE(cv.wait_for(lock, std::chrono::milliseconds(100), [&] { return shutdown_finished; }));
|
||||
release_callback = true;
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
dispatch_thread.join();
|
||||
shutdown_thread.join();
|
||||
if (!shutdown_was_started)
|
||||
FAIL("Lifecycle hook shutdown did not start");
|
||||
CHECK(shutdown_finished);
|
||||
}
|
||||
|
||||
TEST_CASE("A discovered script plugin loads and materializes its capability", "[PluginLifecycle][Python]")
|
||||
{
|
||||
ScopedPluginManager plugin_system;
|
||||
|
||||
Reference in New Issue
Block a user