#include "fiko/zeka/graf.hpp" #include "fiko/zeka/pipeline.hpp" #include "fiko_test.hpp" using namespace fiko; using namespace fiko::zeka; // Delik(1) cap=8.5, Delik(2) cap=5, Delik(3) cap=12, Yuz(4), Yuz(5); // bagli: 1→4, 3→5 static GrafDeposu ornekGraf() { GrafDeposu g; u64 d1 = g.dugumEkle("Delik"); g.ozAyarla(d1, "cap", 8.5); u64 d2 = g.dugumEkle("Delik"); g.ozAyarla(d2, "cap", 5.0); u64 d3 = g.dugumEkle("Delik"); g.ozAyarla(d3, "cap", 12.0); u64 y1 = g.dugumEkle("Yuz"); u64 y2 = g.dugumEkle("Yuz"); g.iliskiEkle("bagli", d1, y1); g.iliskiEkle("bagli", d3, y2); return g; } FIKO_TEST(pipeline_fluent_uctan_uca) { auto g = ornekGraf(); Pipeline p; p.kaynak("Delik").suz("cap", ">=", 6.0).sirala("cap").limit(10); auto s = p.calistir(g); FIKO_KONTROL(s.basarili()); FIKO_KONTROL(s.kimlikler == (std::vector{1, 3})); // 8.5, 12 artan // Azalan sıralama Pipeline p2; p2.kaynak("Delik").sirala("cap", false).limit(1); auto s2 = p2.calistir(g); FIKO_KONTROL(s2.kimlikler == (std::vector{3})); // derle() sonrası plan immutable — fluent çağrı hata bırakır p.limit(1); FIKO_KONTROL(!p.hata().empty()); FIKO_KONTROL(!p.calistir(g).basarili()); } FIKO_TEST(pipeline_json_fluent_ayni) { auto g = ornekGraf(); Pipeline pf; pf.kaynak("Delik").suz("cap", ">=", 6.0).sirala("cap").limit(10); auto sf = pf.calistir(g); Pipeline pj = Pipeline::jsonDanKur( R"({"surum":1,"pipeline":[{"kaynak":"Delik"},{"suz":{"cap":{">=":6}}},)" R"({"sirala":{"anahtar":"cap","artan":true}},{"limit":10}]})"); FIKO_KONTROL(pj.hata().empty()); auto sj = pj.calistir(g); FIKO_KONTROL(sj.basarili()); FIKO_KONTROL(sj.kimlikler == sf.kimlikler); // üç temsil sözleşmesinin ikisi aynı sonuç // suz kısa formu (skaler = eşitlik) Pipeline pe = Pipeline::jsonDanKur(R"({"pipeline":[{"suz":{"cap":5}}]})"); auto se = pe.calistir(g); FIKO_KONTROL(se.basarili() && se.kimlikler == (std::vector{2})); } FIKO_TEST(pipeline_genislet) { auto g = ornekGraf(); Pipeline p; p.kaynak("Delik").suz("cap", ">=", 6.0).genislet("bagli", "Yuz"); auto s = p.calistir(g); FIKO_KONTROL(s.basarili()); FIKO_KONTROL(s.kimlikler == (std::vector{4, 5})); // Hedef tipi grafta hiç yoksa küme boşalır (Sorgu semantiğiyle tutarlı) Pipeline p2; p2.kaynak("Delik").genislet("bagli", "OlmayanTip"); FIKO_KONTROL(p2.calistir(g).kimlikler.empty()); // JSON'dan aynı gezinti Pipeline pj = Pipeline::jsonDanKur( R"({"pipeline":[{"kaynak":"Delik"},{"suz":{"cap":{">=":6}}},)" R"({"genislet":{"iliski":"bagli","hedef":"Yuz"}}]})"); FIKO_KONTROL(pj.calistir(g).kimlikler == s.kimlikler); } FIKO_TEST(pipeline_sec_ve_json_sonuc) { auto g = ornekGraf(); Pipeline p; p.kaynak("Delik").suz("cap", ">=", 6.0).sirala("cap").sec({"cap", "olmayan"}); auto s = p.calistir(g); FIKO_KONTROL(s.basarili()); FIKO_KONTROL(s.kimlikler == (std::vector{1, 3})); FIKO_KONTROL(s.satirlar.size() == 2); FIKO_KONTROL(s.satirlar[0][0].first == "cap"); FIKO_KONTROL(std::get(s.satirlar[0][0].second) == 8.5); FIKO_KONTROL(std::get(s.satirlar[1][0].second) == 12.0); // eksik anahtar monostate (JSON'da null) olarak taşınır FIKO_KONTROL(std::holds_alternative(s.satirlar[0][1].second)); std::string j = s.jsonYaz(); FIKO_KONTROL(j.find("\"kimlikler\":[1,3]") != std::string::npos); FIKO_KONTROL(j.find("\"cap\"") != std::string::npos); FIKO_KONTROL(j.find("null") != std::string::npos); } FIKO_TEST(pipeline_say_topla) { auto g = ornekGraf(); Pipeline ps; ps.kaynak("Delik").say(); auto rs = ps.calistir(g); FIKO_KONTROL(rs.skalerVar && std::get(rs.skaler) == 3); FIKO_KONTROL(rs.kimlikler.empty()); FIKO_KONTROL(rs.jsonYaz().find("\"skaler\":3") != std::string::npos); Pipeline pt; pt.kaynak("Delik").topla("cap", "sum"); FIKO_KONTROL(std::get(pt.calistir(g).skaler) == 25.5); Pipeline po; po.kaynak("Delik").topla("cap", "ort"); FIKO_KONTROL(std::get(po.calistir(g).skaler) == 8.5); Pipeline pmin; pmin.kaynak("Delik").topla("cap", "min"); FIKO_KONTROL(std::get(pmin.calistir(g).skaler) == 5.0); Pipeline pmax; pmax.kaynak("Delik").topla("cap", "max"); FIKO_KONTROL(std::get(pmax.calistir(g).skaler) == 12.0); // bilinmeyen işlem derlemede Türkçe hata Pipeline ph; ph.kaynak("Delik").topla("cap", "carp"); FIKO_KONTROL(!ph.calistir(g).basarili()); FIKO_KONTROL(ph.hata().find("carp") != std::string::npos); } FIKO_TEST(pipeline_bilinmeyen_stage) { auto g = ornekGraf(); Pipeline p = Pipeline::jsonDanKur(R"({"pipeline":[{"uydurma":{}}]})"); FIKO_KONTROL(!p.hata().empty()); FIKO_KONTROL(p.hata().find("uydurma") != std::string::npos); FIKO_KONTROL(p.hata().find("Bilinmeyen") != std::string::npos); FIKO_KONTROL(!p.calistir(g).basarili()); // desteklenmeyen sürüm FIKO_KONTROL(!Pipeline::jsonDanKur(R"({"surum":2,"pipeline":[]})").hata().empty()); // pipeline dizisi yok FIKO_KONTROL(!Pipeline::jsonDanKur(R"({"surum":1})").hata().empty()); // bozuk JSON açık hata (bozuk plan değil) FIKO_KONTROL(!Pipeline::jsonDanKur("{bozuk").hata().empty()); } FIKO_TEST(pipeline_onbellek) { Pipeline::onbellekTemizle(); GrafDeposu g; u64 d = g.dugumEkle("Delik"); g.ozAyarla(d, "cap", 8.0); Pipeline p; p.kaynak("Delik"); auto s1 = p.calistir(g); FIKO_KONTROL(s1.basarili() && !s1.onbellekten); auto s2 = p.calistir(g); FIKO_KONTROL(s2.onbellekten && s2.kimlikler == s1.kimlikler); // graf sürümü değişince önbellek düşer g.ozAyarla(d, "cap", 9.0); auto s3 = p.calistir(g); FIKO_KONTROL(!s3.onbellekten && s3.kimlikler == s1.kimlikler); // aynı plan imzalı BAŞKA pipeline nesnesi de isabet alır Pipeline p2; p2.kaynak("Delik"); FIKO_KONTROL(p2.calistir(g).onbellekten); } FIKO_TEST(pipeline_suz_birlesme) { auto g = ornekGraf(); Pipeline p; p.kaynak("Delik").suz("cap", ">=", 6.0).suz("cap", "<=", 9.0); FIKO_KONTROL(p.derle()); // ardışık suz'lar tek stage'e birleşti, davranış aynı size_t suzSayisi = 0; for (const auto& a : p.asamalar()) if (a.adMetin == "suz") ++suzSayisi; FIKO_KONTROL(suzSayisi == 1); auto s = p.calistir(g); FIKO_KONTROL(s.kimlikler == (std::vector{1})); // yalnız 8.5 // ardışık limit'ler min'e birleşir Pipeline pl; pl.kaynak("Delik").limit(2).limit(1); FIKO_KONTROL(pl.derle()); size_t limitSayisi = 0; for (const auto& a : pl.asamalar()) if (a.adMetin == "limit") ++limitSayisi; FIKO_KONTROL(limitSayisi == 1); FIKO_KONTROL(pl.calistir(g).kimlikler.size() == 1); } FIKO_TEST(pipeline_plugin_stage) { stageKaydet("ilk_n", [](const PipelineAsama& a, std::string& hata) -> AsamaYurutucu { f64 n = 0; auto it = a.param.find("n"); if (it == a.param.end() || !degerSayi(it->second, n)) { hata = "ilk_n: 'n' (sayı) gerekli"; return {}; } u64 adet = (u64)n; return [adet](AsamaBaglam& b) { asamaBaslat(b); if (b.sonuc.kimlikler.size() > adet) b.sonuc.kimlikler.resize(adet); b.sonuc.satirlar.clear(); }; }); auto g = ornekGraf(); Pipeline p; p.kaynak("Delik").asama("ilk_n", {{"n", (i64)2}}); auto s = p.calistir(g); FIKO_KONTROL(s.basarili() && s.kimlikler.size() == 2); // aynı plugin stage JSON'dan da kurulur (genel parametre çantası) Pipeline pj = Pipeline::jsonDanKur(R"({"pipeline":[{"kaynak":"Delik"},{"ilk_n":{"n":2}}]})"); FIKO_KONTROL(pj.hata().empty()); auto sj = pj.calistir(g); FIKO_KONTROL(sj.basarili() && sj.kimlikler == s.kimlikler); // parametre eksikse fabrika hatası Türkçe Pipeline ph; ph.kaynak("Delik").asama("ilk_n"); FIKO_KONTROL(!ph.calistir(g).basarili()); FIKO_KONTROL(ph.hata().find("ilk_n") != std::string::npos); } FIKO_TEST(pipeline_suz_cesitleri) { auto g = ornekGraf(); auto lg = g; // kopya: ek özellikler bu testte kalsın u64 d1 = 1; lg.ozAyarla(d1, "uretim_tipi", std::string("delme")); // ozVar + iliskili + aralik + esitDegil tek zincirde (hepsi tek suz'a birleşir) Pipeline p; p.kaynak("Delik") .suzVar("cap") .suzAralik("cap", 6.0, 13.0) .suz("cap", "!=", 12.0) .suzIliskili("bagli", "Yuz"); auto s = p.calistir(lg); FIKO_KONTROL(s.basarili() && s.kimlikler == (std::vector{1})); // JSON'da var/aralik/iliskili biçimleri Pipeline pj = Pipeline::jsonDanKur( R"({"pipeline":[{"kaynak":"Delik"},{"suz":{"cap":{"var":true,"aralik":[6,13],"!=":12}}},)" R"({"suz":{"iliskili":{"iliski":"bagli","hedef":"Yuz"}}}]})"); FIKO_KONTROL(pj.hata().empty()); FIKO_KONTROL(pj.calistir(lg).kimlikler == s.kimlikler); // bilinmeyen işleç Türkçe hata Pipeline ph; ph.suz("cap", "~~", 5.0); FIKO_KONTROL(!ph.hata().empty()); }