// FuzzyMatcher (src/util/fuzzy.h): exactness, ordering, typos, determinism, ceilings. #include #include #include #include "fuzzy.h" using detz::FuzzyMatcher; static int failures = 0; #define CHECK(c) do { if (!(c)) { std::printf("FAIL %s:%d %s\n", __FILE__, __LINE__, #c); ++failures; } } while (0) static std::string top(const std::string& q, const std::vector& c) { long i = FuzzyMatcher::Best(q, c); return i < 0 ? "" : c[static_cast(i)]; } int main() { const std::vector c = {"claude-opus-4-5", "claude-sonnet-4-5", "claude-haiku-4-5", "gpt-4o", "gpt-4o-mini", "gemini-2.5-pro", "llama3:8b", "opencode", "zen-free", "devplace-free"}; CHECK(FuzzyMatcher::Score("GPT-4O", "gpt-4o") == 1.0); CHECK(FuzzyMatcher::Score("gpt", "gpt-4o") < 1.0); CHECK(FuzzyMatcher::Score("", "x") == 0.0 && FuzzyMatcher::Score("x", "") == 0.0); CHECK(FuzzyMatcher::Score("zzqq", "claude") == 0.0); CHECK(top("opus", c) == "claude-opus-4-5"); CHECK(top("son", c) == "claude-sonnet-4-5"); CHECK(top("sonet", c) == "claude-sonnet-4-5"); // dropped letter CHECK(top("snonet", c) == "claude-sonnet-4-5"); // transposition CHECK(top("opuss", c) == "claude-opus-4-5"); // extra letter CHECK(top("4omini", c) == "gpt-4o-mini"); CHECK(top("g4m", c) == "gpt-4o-mini"); // acronym of word starts CHECK(top("OC", c) == "opencode"); CHECK(top("free", c) == "zen-free"); // shorter id wins the tie CHECK(FuzzyMatcher::Score("pro", "gemini-2.5-pro") > FuzzyMatcher::Score("pro", "opencode")); // boundary beats scattered CHECK(FuzzyMatcher::Subsequence("fb", "FooBar") > FuzzyMatcher::Subsequence("fb", "fxxxxbxx")); // camelCase CHECK(FuzzyMatcher::Typo("ab", "ba") == 0.5); // one swap of two CHECK(FuzzyMatcher::Trigram("word", "word") == 1.0); CHECK(FuzzyMatcher::Trigram("word", "words") > 0.57 && FuzzyMatcher::Trigram("word", "words") < 0.58); // pg_trgm 4/7 // Determinism: equal candidates keep list order. std::vector twin = {"model-a", "model-a"}; auto r = FuzzyMatcher::Rank("model-a", twin); CHECK(r.size() == 2 && r[0].index == 0 && r[1].index == 1); // Floor and ceilings never crash. CHECK(FuzzyMatcher::Best("zzqq", c, 0.3) == -1); CHECK(FuzzyMatcher::Score(std::string(10000, 'a'), std::string(10000, 'a')) == 1.0); CHECK(FuzzyMatcher::Score(std::string(500, 'a'), std::string(5000, 'b')) == 0.0); std::printf(failures ? "FAILED %d\n" : "fuzzy_test OK\n", failures); return failures ? 1 : 0; }