#include #include #include #include #include "../../common/test_helpers_catch2.h" using Catch::Matchers::ContainsSubstring; namespace yams::vector { TEST_CASE("EmbeddingService returns NotFound when no models are available", "[vector][embedding][service][synthetic]") { const auto tempDir = yams::test::make_temp_dir("embed_service_no_models_"); EmbeddingService svc(nullptr, nullptr, tempDir); auto result = svc.generateEmbeddingsForDocuments({"doc-a"}); REQUIRE_FALSE(result); CHECK(result.error().code == ErrorCode::NotFound); CHECK(result.error().message == "No embedding models available"); } TEST_CASE("EmbeddingService fails fast on model/db dimension mismatch", "[vector][embedding][service][synthetic]") { const auto tempDir = yams::test::make_temp_dir("embed_service_dim_mismatch_"); // Make one discoverable model with MiniLM heuristic (384 dim). yams::test::write_file(tempDir / "models" / "all-MiniLM-L6-v2" / "model.onnx", "stub"); // Force DB target dimension to conflict with runtime provider dimension. // Synthetic tests may use either mock or daemon-backed providers; choose a sentinel value // that does not match common embedding dimensions. yams::test::write_file(tempDir / "vectors_sentinel.json", R"({"embedding_dim":1536})"); yams::test::ScopedEnvVar inDaemon{"YAMS_IN_DAEMON", std::string{"1"}}; yams::test::ScopedEnvVar mockProvider{"YAMS_USE_MOCK_PROVIDER", std::string{"1"}}; EmbeddingService svc(nullptr, nullptr, tempDir); auto result = svc.generateEmbeddingsForDocuments({}); REQUIRE_FALSE(result); CHECK(result.error().code == ErrorCode::InvalidState); CHECK_THAT(result.error().message, ContainsSubstring("Embedding dimension mismatch")); CHECK_THAT(result.error().message, ContainsSubstring("DB expects 1536")); } TEST_CASE("Adaptive split recovers when only singleton batches succeed", "[vector][embedding][service][synthetic]") { int calls = 0; auto generator = [&](const std::vector& batch) { ++calls; if (batch.size() > 1) { return std::vector>{}; } return std::vector>{{static_cast(batch[0].size())}}; }; const std::vector texts{"a", "bb", "ccc", "dddd"}; auto out = testing::generateEmbeddingsAdaptiveSplit(texts, generator); REQUIRE(out.size() == texts.size()); CHECK(out[0][0] == 1.0f); CHECK(out[3][0] == 4.0f); CHECK(calls > 1); } TEST_CASE("Adaptive split returns empty when all retries fail", "[vector][embedding][service][synthetic]") { auto alwaysFail = [](const std::vector&) { return std::vector>{}; }; auto out = testing::generateEmbeddingsAdaptiveSplit({"x", "y", "z"}, alwaysFail); CHECK(out.empty()); } } // namespace yams::vector