#include "fiko/mcp/zeka_araclari.hpp" #include "fiko_test.hpp" using namespace fiko::mcp; namespace { // Sahte makro kanalı: üretilen Lua kodunu yakalar, fikocad'a gitmez. struct KanalKaydi { std::string kod; long long pid = -1; int cagri = 0; }; McpSunucu zekaSunucu(KanalKaydi& k) { McpSunucu s("fikocad-mcp", "1.0"); zekaAraclariKaydet(s, [&k](const Json& a) { ++k.cagri; k.kod = a["kod"].metinAl(); k.pid = a["pid"].tamAl(-1); return AracSonuc::ok("kanal-tamam"); }); return s; } Json aracCagir(McpSunucu& s, const std::string& ad, const std::string& argsJson) { return Json::coz(s.istekIsle( R"({"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":")" + ad + R"(","arguments":)" + argsJson + "}}")); } } // namespace FIKO_TEST(zeka_lua_metin_kacir) { FIKO_KONTROL(luaMetinKacir("ab") == "\"ab\""); FIKO_KONTROL(luaMetinKacir("a\"b") == "\"a\\\"b\""); FIKO_KONTROL(luaMetinKacir("a\\b") == "\"a\\\\b\""); FIKO_KONTROL(luaMetinKacir("a\nb") == "\"a\\nb\""); // Kontrol karakteri 3 haneli ondalık — ardından rakam gelse bile güvenli. FIKO_KONTROL(luaMetinKacir(std::string(1, '\x01') + "2") == "\"\\0012\""); // Lua uzun-köşeli enjeksiyonu kapanır (]==] metin içinde zararsız kalır). FIKO_KONTROL(luaMetinKacir("]==]") == "\"]==]\""); } FIKO_TEST(zeka_araclari_listede) { KanalKaydi k; McpSunucu s = zekaSunucu(k); const Json y = Json::coz(s.istekIsle(R"({"jsonrpc":"2.0","id":2,"method":"tools/list"})")); const auto& t = y["result"]["tools"].diziAl(); FIKO_KONTROL(t.size() == 2); FIKO_KONTROL(t[0]["name"].metinAl() == "zeka_pipeline"); FIKO_KONTROL(t[1]["name"].metinAl() == "zeka_ozet"); FIKO_KONTROL(t[0]["inputSchema"]["required"].diziAl().size() == 1); } FIKO_TEST(zeka_pipeline_lua_uretir) { KanalKaydi k; McpSunucu s = zekaSunucu(k); const Json y = aracCagir(s, "zeka_pipeline", R"({"pipeline":"{\"asamalar\":[]}","govde":5,"pid":42})"); FIKO_KONTROL(!y["result"]["isError"].mantikAl(true)); FIKO_KONTROL(k.cagri == 1); FIKO_KONTROL(k.pid == 42); // Plan Lua dizesi olarak kaçışlı gömülür + gövde argümanı geçer. FIKO_KONTROL(k.kod.find("fiko.zeka.pipeline(\"{\\\"asamalar\\\":[]}\", 5)") != std::string::npos); FIKO_KONTROL(k.kod.find("error(h") != std::string::npos); // hata yolu makro hatasına döner } FIKO_TEST(zeka_pipeline_govdesiz) { KanalKaydi k; McpSunucu s = zekaSunucu(k); aracCagir(s, "zeka_pipeline", R"({"pipeline":"{}"})"); FIKO_KONTROL(k.kod.find("fiko.zeka.pipeline(\"{}\")") != std::string::npos); } FIKO_TEST(zeka_pipeline_bos_plan_hata) { KanalKaydi k; McpSunucu s = zekaSunucu(k); const Json y = aracCagir(s, "zeka_pipeline", R"({"pipeline":""})"); FIKO_KONTROL(y["result"]["isError"].mantikAl(false)); FIKO_KONTROL(k.cagri == 0); // kanal hiç aranmadı } FIKO_TEST(zeka_ozet_lua_uretir) { KanalKaydi k; McpSunucu s = zekaSunucu(k); const Json y = aracCagir(s, "zeka_ozet", "{}"); FIKO_KONTROL(!y["result"]["isError"].mantikAl(true)); FIKO_KONTROL(k.kod.find("fiko.zeka.ozet()") != std::string::npos); aracCagir(s, "zeka_ozet", R"({"govde":7})"); FIKO_KONTROL(k.kod.find("fiko.zeka.ozet(7)") != std::string::npos); }