Skip to content

Commit ffca4a8

Browse files
committed
🧪 Add tests for vectordb core
1 parent c24c41f commit ffca4a8

File tree

1 file changed

+227
-1
lines changed

1 file changed

+227
-1
lines changed

‎test/sdk/vector_database/test_elasticsearch_core_coverage.py‎

Lines changed: 227 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
import os
1010
import sys
1111
from typing import List, Dict, Any
12+
from datetime import datetime, timedelta
1213

1314
# Add the project root to the path
1415
current_dir = os.path.dirname(os.path.abspath(__file__))
1516
project_root = os.path.abspath(os.path.join(current_dir, "../../.."))
1617
sys.path.insert(0, project_root)
1718

1819
# Import the class under test
19-
from sdk.nexent.vector_database.elasticsearch_core import ElasticSearchCore
20+
from sdk.nexent.vector_database.elasticsearch_core import ElasticSearchCore, BulkOperation
2021
from elasticsearch import exceptions
2122

2223

@@ -257,6 +258,231 @@ def test_delete_documents_exception(self, vdb_core):
257258
assert result == 0
258259
vdb_core.client.delete_by_query.assert_called_once()
259260

261+
def test_create_index_request_error_existing(self, vdb_core):
262+
"""Ensure RequestError with resource already exists still succeeds."""
263+
vdb_core.client = MagicMock()
264+
vdb_core.client.indices.exists.return_value = False
265+
meta = MagicMock(status=400)
266+
vdb_core.client.indices.create.side_effect = exceptions.RequestError(
267+
"resource_already_exists_exception", meta, {"error": {"reason": "exists"}}
268+
)
269+
vdb_core._ensure_index_ready = MagicMock(return_value=True)
270+
271+
assert vdb_core.create_index("test_index") is True
272+
vdb_core._ensure_index_ready.assert_called_once_with("test_index")
273+
274+
def test_create_index_request_error_failure(self, vdb_core):
275+
"""Ensure create_index returns False for non recoverable RequestError."""
276+
vdb_core.client = MagicMock()
277+
vdb_core.client.indices.exists.return_value = False
278+
meta = MagicMock(status=400)
279+
vdb_core.client.indices.create.side_effect = exceptions.RequestError(
280+
"validation_exception", meta, {"error": {"reason": "bad"}}
281+
)
282+
283+
assert vdb_core.create_index("test_index") is False
284+
285+
def test_create_index_general_exception(self, vdb_core):
286+
"""Ensure unexpected exception from create_index returns False."""
287+
vdb_core.client = MagicMock()
288+
vdb_core.client.indices.exists.return_value = False
289+
vdb_core.client.indices.create.side_effect = Exception("boom")
290+
291+
assert vdb_core.create_index("test_index") is False
292+
293+
def test_force_refresh_with_retry_zero_attempts(self, vdb_core):
294+
"""Ensure guard clause without attempts returns False."""
295+
vdb_core.client = MagicMock()
296+
result = vdb_core._force_refresh_with_retry("idx", max_retries=0)
297+
assert result is False
298+
299+
def test_bulk_operation_context_preexisting_operation(self, vdb_core):
300+
"""Ensure context skips apply/restore when operations remain."""
301+
existing = BulkOperation(
302+
index_name="test_index",
303+
operation_id="existing",
304+
start_time=datetime.utcnow(),
305+
expected_duration=timedelta(seconds=30),
306+
)
307+
vdb_core._bulk_operations = {"test_index": [existing]}
308+
309+
with patch.object(vdb_core, "_apply_bulk_settings") as mock_apply, \
310+
patch.object(vdb_core, "_restore_normal_settings") as mock_restore:
311+
312+
with vdb_core.bulk_operation_context("test_index") as op_id:
313+
assert op_id != existing.operation_id
314+
315+
mock_apply.assert_not_called()
316+
mock_restore.assert_not_called()
317+
assert vdb_core._bulk_operations["test_index"] == [existing]
318+
319+
def test_get_user_indices_exception(self, vdb_core):
320+
"""Ensure get_user_indices returns empty list on failure."""
321+
vdb_core.client = MagicMock()
322+
vdb_core.client.indices.get_alias.side_effect = Exception("failure")
323+
324+
assert vdb_core.get_user_indices() == []
325+
326+
def test_check_index_exists(self, vdb_core):
327+
"""Ensure check_index_exists delegates to client."""
328+
vdb_core.client = MagicMock()
329+
vdb_core.client.indices.exists.return_value = True
330+
331+
assert vdb_core.check_index_exists("idx") is True
332+
vdb_core.client.indices.exists.assert_called_once_with(index="idx")
333+
334+
def test_small_batch_insert_sets_embedding_model_name(self, vdb_core):
335+
"""_small_batch_insert should attach embedding model name."""
336+
vdb_core.client = MagicMock()
337+
vdb_core.client.bulk.return_value = {"errors": False, "items": []}
338+
vdb_core._preprocess_documents = MagicMock(return_value=[{"content": "body"}])
339+
vdb_core._handle_bulk_errors = MagicMock()
340+
341+
mock_embedding_model = MagicMock()
342+
mock_embedding_model.get_embeddings.return_value = [[0.1, 0.2]]
343+
mock_embedding_model.embedding_model_name = "demo-model"
344+
345+
vdb_core._small_batch_insert("idx", [{"content": "body"}], "content", mock_embedding_model)
346+
operations = vdb_core.client.bulk.call_args.kwargs["operations"]
347+
inserted_doc = operations[1]
348+
assert inserted_doc["embedding_model_name"] == "demo-model"
349+
350+
def test_large_batch_insert_sets_default_embedding_model_name(self, vdb_core):
351+
"""_large_batch_insert should fall back to 'unknown' when attr missing."""
352+
vdb_core.client = MagicMock()
353+
vdb_core.client.bulk.return_value = {"errors": False, "items": []}
354+
vdb_core._preprocess_documents = MagicMock(return_value=[{"content": "body"}])
355+
vdb_core._handle_bulk_errors = MagicMock()
356+
357+
class SimpleEmbedding:
358+
def get_embeddings(self, texts):
359+
return [[0.1 for _ in texts]]
360+
361+
embedding_model = SimpleEmbedding()
362+
363+
vdb_core._large_batch_insert("idx", [{"content": "body"}], 10, "content", embedding_model)
364+
operations = vdb_core.client.bulk.call_args.kwargs["operations"]
365+
inserted_doc = operations[1]
366+
assert inserted_doc["embedding_model_name"] == "unknown"
367+
368+
def test_large_batch_insert_bulk_exception(self, vdb_core):
369+
"""Ensure bulk exceptions are handled and indexing continues."""
370+
vdb_core.client = MagicMock()
371+
vdb_core.client.bulk.side_effect = Exception("bulk error")
372+
vdb_core._preprocess_documents = MagicMock(return_value=[{"content": "body"}])
373+
374+
mock_embedding_model = MagicMock()
375+
mock_embedding_model.get_embeddings.return_value = [[0.1]]
376+
377+
result = vdb_core._large_batch_insert("idx", [{"content": "body"}], 1, "content", mock_embedding_model)
378+
assert result == 0
379+
380+
def test_large_batch_insert_preprocess_exception(self, vdb_core):
381+
"""Ensure outer exception handler returns zero on preprocess failure."""
382+
vdb_core._preprocess_documents = MagicMock(side_effect=Exception("fail"))
383+
384+
mock_embedding_model = MagicMock()
385+
result = vdb_core._large_batch_insert("idx", [{"content": "body"}], 10, "content", mock_embedding_model)
386+
assert result == 0
387+
388+
def test_count_documents_success(self, vdb_core):
389+
"""Ensure count_documents returns ES count."""
390+
vdb_core.client = MagicMock()
391+
vdb_core.client.count.return_value = {"count": 42}
392+
393+
assert vdb_core.count_documents("idx") == 42
394+
395+
def test_count_documents_exception(self, vdb_core):
396+
"""Ensure count_documents returns zero on error."""
397+
vdb_core.client = MagicMock()
398+
vdb_core.client.count.side_effect = Exception("fail")
399+
400+
assert vdb_core.count_documents("idx") == 0
401+
402+
def test_search_and_multi_search_passthrough(self, vdb_core):
403+
"""Ensure search helpers delegate to the client."""
404+
vdb_core.client = MagicMock()
405+
vdb_core.client.search.return_value = {"hits": {}}
406+
vdb_core.client.msearch.return_value = {"responses": []}
407+
408+
assert vdb_core.search("idx", {"query": {"match_all": {}}}) == {"hits": {}}
409+
assert vdb_core.multi_search([{"query": {"match_all": {}}}], "idx") == {"responses": []}
410+
411+
def test_exec_query_formats_results(self, vdb_core):
412+
"""Ensure exec_query strips metadata and exposes scores."""
413+
vdb_core.client = MagicMock()
414+
vdb_core.client.search.return_value = {
415+
"hits": {
416+
"hits": [
417+
{
418+
"_score": 1.23,
419+
"_index": "idx",
420+
"_source": {"id": "doc1", "content": "body"},
421+
}
422+
]
423+
}
424+
}
425+
426+
results = vdb_core.exec_query("idx", {"query": {}})
427+
assert results == [
428+
{"score": 1.23, "document": {"id": "doc1", "content": "body"}, "index": "idx"}
429+
]
430+
431+
def test_hybrid_search_missing_fields_logged_for_accurate(self, vdb_core):
432+
"""Ensure hybrid_search tolerates missing accurate fields."""
433+
mock_embedding_model = MagicMock()
434+
with patch.object(vdb_core, "accurate_search", return_value=[{"score": 1.0}]), \
435+
patch.object(vdb_core, "semantic_search", return_value=[]):
436+
assert vdb_core.hybrid_search(["idx"], "query", mock_embedding_model) == []
437+
438+
def test_hybrid_search_missing_fields_logged_for_semantic(self, vdb_core):
439+
"""Ensure hybrid_search tolerates missing semantic fields."""
440+
mock_embedding_model = MagicMock()
441+
with patch.object(vdb_core, "accurate_search", return_value=[]), \
442+
patch.object(vdb_core, "semantic_search", return_value=[{"score": 0.5}]):
443+
assert vdb_core.hybrid_search(["idx"], "query", mock_embedding_model) == []
444+
445+
def test_hybrid_search_faulty_combined_results(self, vdb_core):
446+
"""Inject faulty combined result to hit KeyError handling in final loop."""
447+
mock_embedding_model = MagicMock()
448+
accurate_payload = [
449+
{"score": 1.0, "document": {"id": "doc1"}, "index": "idx"}
450+
]
451+
452+
with patch.object(vdb_core, "accurate_search", return_value=accurate_payload), \
453+
patch.object(vdb_core, "semantic_search", return_value=[]):
454+
455+
injected = {"done": False}
456+
457+
def tracer(frame, event, arg):
458+
if (
459+
frame.f_code.co_name == "hybrid_search"
460+
and event == "line"
461+
and frame.f_lineno == 788
462+
and not injected["done"]
463+
):
464+
frame.f_locals["combined_results"]["faulty"] = {
465+
"accurate_score": 0,
466+
"semantic_score": 0,
467+
}
468+
injected["done"] = True
469+
return tracer
470+
471+
sys.settrace(tracer)
472+
try:
473+
results = vdb_core.hybrid_search(["idx"], "query", mock_embedding_model)
474+
finally:
475+
sys.settrace(None)
476+
477+
assert len(results) == 1
478+
479+
def test_get_documents_detail_exception(self, vdb_core):
480+
"""Ensure get_documents_detail returns empty list on failure."""
481+
vdb_core.client = MagicMock()
482+
vdb_core.client.search.side_effect = Exception("fail")
483+
484+
assert vdb_core.get_documents_detail("idx") == []
485+
260486
def test_get_indices_detail_success(self, vdb_core):
261487
"""Test get_indices_detail successful case"""
262488
vdb_core.client = MagicMock()

0 commit comments

Comments
 (0)