#include "fiko/zeka/kural.hpp" #include "fiko_test.hpp" using namespace fiko; using namespace fiko::zeka; namespace { const char* derinCepJson = R"({"kurallar":[{ "ad":"derin_cep_riski", "kosul":{"pipeline":[{"kaynak":"Cep"},{"suz":{"derinlik":{">":20}}}]}, "eylemler":[ {"ozYaz":{"anahtar":"risk","deger":75}}, {"ozYaz":{"anahtar":"uretim_tipi","deger":"derin_cep_frezeleme"}}, {"etiketle":{"etiket":"derin cep"}}, {"dugumEkle":{"tip":"Uyari","mesaj":"Derin cep: ozel takim gerekir"}} ]}]})"; } FIKO_TEST(kural_json_derin_cep) { Pipeline::onbellekTemizle(); GrafDeposu g; u64 c1 = g.dugumEkle("Cep"); g.ozAyarla(c1, "derinlik", 30.0); u64 c2 = g.dugumEkle("Cep"); g.ozAyarla(c2, "derinlik", 5.0); KuralMotoru km; std::string hata; FIKO_KONTROL(km.jsonYukle(derinCepJson, &hata)); FIKO_KONTROL(hata.empty()); FIKO_KONTROL(km.listele() == std::vector{"derin_cep_riski"}); auto sonuc = km.calistir(g); FIKO_KONTROL(sonuc.size() == 1); FIKO_KONTROL(sonuc[0].kural == "derin_cep_riski"); FIKO_KONTROL(sonuc[0].eslesen == 1); FIKO_KONTROL(sonuc[0].uygulanan == 4); FIKO_KONTROL(sonuc[0].hata.empty()); FIKO_KONTROL(g.ozSayi(c1, "risk") == 75); FIKO_KONTROL(g.oz(c2, "risk") == nullptr); const Deger* ut = g.oz(c1, "uretim_tipi"); FIKO_KONTROL(ut && std::get(*ut) == "derin_cep_frezeleme"); const Deger* et = g.oz(c1, "kullanici_etiket"); FIKO_KONTROL(et && std::get(*et) == "derin cep"); auto uyarilar = g.tipteki("Uyari"); FIKO_KONTROL(uyarilar.size() == 1); FIKO_KONTROL(g.komsular(uyarilar[0], "bagli", +1) == std::vector{c1}); const Deger* msj = g.oz(uyarilar[0], "mesaj"); FIKO_KONTROL(msj && std::get(*msj) == "Derin cep: ozel takim gerekir"); // İkinci koşum: ozYaz/etiketle ÜZERİNE yazar (aynı sonuç — idempotent), // dugumEkle her koşumda YENİ düğüm ekler (belgelenen davranış) auto sonuc2 = km.calistir(g); FIKO_KONTROL(sonuc2[0].eslesen == 1 && sonuc2[0].uygulanan == 4); FIKO_KONTROL(g.ozSayi(c1, "risk") == 75); FIKO_KONTROL(g.tipteki("Uyari").size() == 2); } FIKO_TEST(kural_eylem_registry_plugin) { Pipeline::onbellekTemizle(); eylemKaydet("test_carp", [](GrafDeposu& g, u64 d, const std::unordered_map& p) { f64 carpan = 0; auto it = p.find("carpan"); if (it == p.end() || !degerSayi(it->second, carpan)) return false; g.ozAyarla(d, "deger", g.ozSayi(d, "deger") * carpan); return true; }); FIKO_KONTROL(eylemVar("test_carp")); FIKO_KONTROL(!eylemVar("olmayan_eylem")); GrafDeposu g; u64 a = g.dugumEkle("Parca"); g.ozAyarla(a, "deger", 10.0); KuralMotoru km; std::string hata; Pipeline p; // koşul fluent Pipeline olarak p.kaynak("Parca").suzVar("deger"); FIKO_KONTROL(km.kuralEkle("katla", std::move(p), {{"test_carp", {{"carpan", (i64)3}}}}, &hata)); auto sonuc = km.calistir(g); FIKO_KONTROL(sonuc.size() == 1 && sonuc[0].eslesen == 1 && sonuc[0].uygulanan == 1); FIKO_KONTROL(g.ozSayi(a, "deger") == 30.0); } FIKO_TEST(kural_deterministik_sira) { Pipeline::onbellekTemizle(); GrafDeposu g; u64 a = g.dugumEkle("Parca"); KuralMotoru km; std::string hata; Pipeline p1; p1.kaynak("Parca"); FIKO_KONTROL(km.kuralEkle( "birinci", std::move(p1), {{"ozYaz", {{"anahtar", std::string("asama")}, {"deger", (i64)1}}}}, &hata)); Pipeline p2; p2.kaynak("Parca").suz("asama", "==", (i64)1); FIKO_KONTROL(km.kuralEkle( "ikinci", std::move(p2), {{"ozYaz", {{"anahtar", std::string("asama")}, {"deger", (i64)2}}}}, &hata)); auto sonuc = km.calistir(g); FIKO_KONTROL(sonuc.size() == 2); FIKO_KONTROL(sonuc[0].kural == "birinci" && sonuc[1].kural == "ikinci"); FIKO_KONTROL(sonuc[1].eslesen == 1); FIKO_KONTROL(g.ozSayi(a, "asama") == 2); // ikinci kural birincinin yazdığını gördü } FIKO_TEST(kural_json_hata_ve_yonetim) { KuralMotoru km; std::string hata; FIKO_KONTROL(!km.jsonYukle("{bozuk", &hata)); FIKO_KONTROL(!hata.empty()); hata.clear(); FIKO_KONTROL(!km.jsonYukle( R"({"kurallar":[{"kosul":{"pipeline":[{"kaynak":"X"}]},"eylemler":[]}]})", &hata)); FIKO_KONTROL(hata.find("ad") != std::string::npos); hata.clear(); FIKO_KONTROL(!km.jsonYukle( R"({"kurallar":[{"ad":"a","kosul":{"pipeline":[{"kaynak":"X"}]},)" R"("eylemler":[{"olmayanEylem":{}}]}]})", &hata)); FIKO_KONTROL(hata.find("olmayanEylem") != std::string::npos); hata.clear(); // Çekirdek eylem zorunlu parametre denetimi (anahtar eksik) FIKO_KONTROL(!km.jsonYukle( R"({"kurallar":[{"ad":"b","kosul":{"pipeline":[{"kaynak":"X"}]},)" R"("eylemler":[{"ozYaz":{"deger":5}}]}]})", &hata)); FIKO_KONTROL(!hata.empty()); hata.clear(); // Bozuk koşul pipeline'ı da Türkçe hatayla reddedilir FIKO_KONTROL(!km.jsonYukle( R"({"kurallar":[{"ad":"c","kosul":{"pipeline":[{"yokStage":{}}]},"eylemler":[]}]})", &hata)); FIKO_KONTROL(hata.find("yokStage") != std::string::npos); FIKO_KONTROL(km.listele().empty()); // atomik: hatalı setlerden hiçbir kural kalmadı FIKO_KONTROL(km.jsonYukle(derinCepJson, &hata)); FIKO_KONTROL(km.listele().size() == 1); FIKO_KONTROL(!km.jsonYukle(derinCepJson, &hata)); // aynı ad — reddedilir FIKO_KONTROL(km.listele().size() == 1); // atomiklik korunur FIKO_KONTROL(!km.kaldir("yok")); FIKO_KONTROL(km.kaldir("derin_cep_riski")); FIKO_KONTROL(km.listele().empty()); }