File size: 2,733 Bytes
a57b9dc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# tests/test_state.py

import unittest
from unittest.mock import MagicMock, patch

from src.core.state import AppState, get_state


class TestAppState(unittest.TestCase):
	"""Test suite for the AppState singleton and its initialization logic."""

	def tearDown(self):
		"""Resets the singleton after each test to ensure test isolation."""
		if hasattr(AppState, '_instance'):
			AppState._instance = None

	def test_singleton_instance_is_consistent(self):
		"""Tests that multiple calls to AppState() and get_state() return the same object instance."""
		instance1 = AppState()
		instance2 = AppState()
		instance3 = get_state()

		self.assertIs(instance1, instance2)
		self.assertIs(instance2, instance3)

	def test_init_logic_is_idempotent(self):
		"""Tests that the internal logic of __init__ does not re-run on subsequent calls."""
		state1 = AppState()
		self.assertTrue(state1._initialized)

		# Use a non-bool "marker" to verify the initialization logic is skipped on the next call.
		# The `# type: ignore` is needed because Pylance correctly infers _initialized as bool.
		state1._initialized = "marker"  # type: ignore

		state2 = AppState()

		self.assertIs(state1, state2)
		self.assertEqual(state2._initialized, "marker", "Initialization logic ran again when it should have been skipped.")

	@patch('src.core.state.MemoryManager')
	@patch('src.core.state.APIKeyRotator')
	@patch('src.core.state.EmbeddingClient')
	def test_initialize_creates_and_injects_dependencies(self, MockEmbeddingClient, MockAPIKeyRotator, MockMemoryManager):
		"""Tests that initialize() correctly instantiates and wires up all service dependencies."""
		mock_embedder_instance = MagicMock()
		mock_gemini_rotator_instance = MagicMock()
		mock_nvidia_rotator_instance = MagicMock()

		MockEmbeddingClient.return_value = mock_embedder_instance
		MockAPIKeyRotator.side_effect = [mock_gemini_rotator_instance, mock_nvidia_rotator_instance]

		state = get_state()
		state.initialize()

		MockEmbeddingClient.assert_called_once_with(model_name="all-MiniLM-L6-v2", dimension=384)
		MockAPIKeyRotator.assert_any_call("GEMINI_API_", max_slots=5)
		MockAPIKeyRotator.assert_any_call("NVIDIA_API_", max_slots=5)
		MockMemoryManager.assert_called_once_with(
			embedder=mock_embedder_instance,
			max_sessions_per_user=20
		)

		self.assertIs(state.embedding_client, mock_embedder_instance)
		self.assertIs(state.gemini_rotator, mock_gemini_rotator_instance)
		self.assertIs(state.nvidia_rotator, mock_nvidia_rotator_instance)

	def test_get_state_returns_appstate_instance(self):
		"""Tests that get_state() returns an object of type AppState."""
		state = get_state()
		self.assertIsInstance(state, AppState)

if __name__ == '__main__':
	unittest.main()