// SPDX-License-Identifier: LGPL-2.1-or-later #include #include #include #include #include using namespace KCSolve; // ── Minimal mock solver for registry tests ───────────────────────── namespace { class MockSolver : public IKCSolver { public: std::string name() const override { return "MockSolver"; } std::vector supported_joints() const override { return {BaseJointKind::Fixed, BaseJointKind::Revolute}; } SolveResult solve(const SolveContext& /*ctx*/) override { return SolveResult {SolveStatus::Success, {}, 0, {}, 0}; } }; } // namespace // ── Tests ────────────────────────────────────────────────────────── // // SolverRegistry is a singleton — tests use unique names to avoid // interference across test cases. TEST(SolverRegistryTest, GetUnknownReturnsNull) // NOLINT { auto solver = SolverRegistry::instance().get("nonexistent_solver_xyz"); EXPECT_EQ(solver, nullptr); } TEST(SolverRegistryTest, RegisterAndGet) // NOLINT { auto& reg = SolverRegistry::instance(); bool ok = reg.register_solver("test_reg_get", []() { return std::make_unique(); }); EXPECT_TRUE(ok); auto solver = reg.get("test_reg_get"); ASSERT_NE(solver, nullptr); EXPECT_EQ(solver->name(), "MockSolver"); } TEST(SolverRegistryTest, DuplicateRegistrationFails) // NOLINT { auto& reg = SolverRegistry::instance(); bool first = reg.register_solver("test_dup", []() { return std::make_unique(); }); EXPECT_TRUE(first); bool second = reg.register_solver("test_dup", []() { return std::make_unique(); }); EXPECT_FALSE(second); } TEST(SolverRegistryTest, AvailableListsSolvers) // NOLINT { auto& reg = SolverRegistry::instance(); reg.register_solver("test_avail_1", []() { return std::make_unique(); }); reg.register_solver("test_avail_2", []() { return std::make_unique(); }); auto names = reg.available(); EXPECT_NE(std::find(names.begin(), names.end(), "test_avail_1"), names.end()); EXPECT_NE(std::find(names.begin(), names.end(), "test_avail_2"), names.end()); } TEST(SolverRegistryTest, SetDefaultAndGet) // NOLINT { auto& reg = SolverRegistry::instance(); reg.register_solver("test_default", []() { return std::make_unique(); }); bool ok = reg.set_default("test_default"); EXPECT_TRUE(ok); // get() with no arg should return the default. auto solver = reg.get(); ASSERT_NE(solver, nullptr); EXPECT_EQ(solver->name(), "MockSolver"); } TEST(SolverRegistryTest, SetDefaultUnknownFails) // NOLINT { auto& reg = SolverRegistry::instance(); bool ok = reg.set_default("totally_unknown_solver"); EXPECT_FALSE(ok); } TEST(SolverRegistryTest, JointsForReturnsCapabilities) // NOLINT { auto& reg = SolverRegistry::instance(); reg.register_solver("test_joints", []() { return std::make_unique(); }); auto joints = reg.joints_for("test_joints"); EXPECT_EQ(joints.size(), 2u); EXPECT_NE(std::find(joints.begin(), joints.end(), BaseJointKind::Fixed), joints.end()); EXPECT_NE(std::find(joints.begin(), joints.end(), BaseJointKind::Revolute), joints.end()); } TEST(SolverRegistryTest, JointsForUnknownReturnsEmpty) // NOLINT { auto joints = SolverRegistry::instance().joints_for("totally_unknown_solver_2"); EXPECT_TRUE(joints.empty()); }