import os
import tempfile
import threading
import unittest
from unittest.mock import Mock, patch
from olc.bean.olc_control_request import OlcControlRequest
from olc.config.properties_loader import OlcConfigManager
from olc.control.context.context import OlcContext
from olc.rule.olc_rule_convert import OlcRuleConvert
from olc.task_schedule.task_schedule import OlcScheduleManager
class TestOLC(unittest.TestCase):
"""OLC入口类测试"""
def setUp(self):
OlcConfigManager._instance = None
OlcScheduleManager._instance = None
OlcRuleConvert._instance = None
self._reset_olc_class()
def tearDown(self):
self._reset_olc_class()
OlcConfigManager._instance = None
OlcScheduleManager._instance = None
OlcRuleConvert._instance = None
def _reset_olc_class(self):
from olc.olc import OLC
OLC._instance = None
OLC._initialized = False
def _create_temp_config(self, switch: bool = True):
temp_dir = tempfile.mkdtemp()
config_file = os.path.join(temp_dir, 'test-config.properties')
with open(config_file, 'w') as f:
f.write(f'olc.sdk.switch={str(switch).lower()}\n')
return temp_dir, config_file
@patch('olc.olc.OlcConfigManager.get_instance')
@patch('olc.olc.OlcScheduleManager.get_instance')
@patch('olc.olc.OlcRuleConvert.get_instance')
def test_singleton_pattern(self, mock_rule, mock_schedule, mock_config):
"""测试OLC单例模式"""
mock_sdk_config = Mock()
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule.return_value = Mock()
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
from olc.olc import OLC
instance1 = OLC.get_instance()
instance2 = OLC.get_instance()
self.assertIs(instance1, instance2)
@patch('olc.olc.OlcConfigManager.get_instance')
@patch('olc.olc.OlcScheduleManager.get_instance')
@patch('olc.olc.OlcRuleConvert.get_instance')
def test_process_with_switch_enabled(self, mock_rule, mock_schedule, mock_config):
"""测试开关开启时的process方法"""
mock_sdk_config = Mock()
mock_sdk_config.switch = True
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule.return_value = Mock()
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
from olc.olc import OLC
olc = OLC.get_instance()
request = OlcControlRequest(tags={"user": "test"}, token_number=10)
context = olc.process(request)
self.assertIsInstance(context, OlcContext)
self.assertEqual(context.request, request)
@patch('olc.olc.OlcConfigManager.get_instance')
@patch('olc.olc.OlcScheduleManager.get_instance')
@patch('olc.olc.OlcRuleConvert.get_instance')
def test_process_with_switch_disabled(self, mock_rule, mock_schedule, mock_config):
"""测试开关关闭时的process方法"""
mock_sdk_config = Mock()
mock_sdk_config.switch = False
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule.return_value = Mock()
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
from olc.olc import OLC
olc = OLC.get_instance()
request = OlcControlRequest(tags={"user": "test"}, token_number=10)
context = olc.process(request)
self.assertIsInstance(context, OlcContext)
self.assertEqual(context.request, request)
@patch('olc.olc.OlcConfigManager.get_instance')
@patch('olc.olc.OlcScheduleManager.get_instance')
@patch('olc.olc.OlcRuleConvert.get_instance')
def test_process_with_groups(self, mock_rule, mock_schedule, mock_config):
"""测试带groups参数的process方法"""
mock_sdk_config = Mock()
mock_sdk_config.switch = True
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule.return_value = Mock()
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
from olc.olc import OLC
olc = OLC.get_instance()
request = OlcControlRequest(tags={"user": "test"}, token_number=10)
context = olc.process(request)
self.assertIsInstance(context, OlcContext)
@patch('olc.olc.OlcConfigManager.get_instance')
@patch('olc.olc.OlcScheduleManager.get_instance')
@patch('olc.olc.OlcRuleConvert.get_instance')
def test_clean_with_switch_enabled(self, mock_rule, mock_schedule, mock_config):
"""测试开关开启时的clean方法"""
mock_sdk_config = Mock()
mock_sdk_config.switch = True
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule.return_value = Mock()
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
from olc.olc import OLC
olc = OLC.get_instance()
request = OlcControlRequest()
context = OlcContext(request)
olc.clean(context)
@patch('olc.olc.OlcConfigManager.get_instance')
@patch('olc.olc.OlcScheduleManager.get_instance')
@patch('olc.olc.OlcRuleConvert.get_instance')
def test_clean_with_switch_disabled(self, mock_rule, mock_schedule, mock_config):
"""测试开关关闭时的clean方法"""
mock_sdk_config = Mock()
mock_sdk_config.switch = False
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule.return_value = Mock()
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
from olc.olc import OLC
olc = OLC.get_instance()
request = OlcControlRequest()
context = OlcContext(request)
olc.clean(context)
@patch('olc.olc.OlcConfigManager.get_instance')
@patch('olc.olc.OlcScheduleManager.get_instance')
@patch('olc.olc.OlcRuleConvert.get_instance')
def test_clean_with_none_context(self, mock_rule, mock_schedule, mock_config):
"""测试clean方法传入None参数"""
mock_sdk_config = Mock()
mock_sdk_config.switch = True
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule.return_value = Mock()
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
from olc.olc import OLC
olc = OLC.get_instance()
olc.clean(None)
@patch('olc.olc.OlcConfigManager.get_instance')
@patch('olc.olc.OlcScheduleManager.get_instance')
@patch('olc.olc.OlcRuleConvert.get_instance')
def test_process_exception_handling(self, mock_rule, mock_schedule, mock_config):
"""测试process方法异常处理"""
mock_sdk_config = Mock()
mock_sdk_config.switch = True
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule.return_value = Mock()
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
from olc.olc import OLC
from olc.control.handler_chain.box_handler_chain_builder import OlcHandlerChain
original_chain = OlcHandlerChain.chain
try:
mock_chain = Mock()
mock_chain.in_coming.side_effect = Exception("Chain error")
OlcHandlerChain.chain = mock_chain
olc = OLC.get_instance()
request = OlcControlRequest()
context = olc.process(request)
self.assertIsInstance(context, OlcContext)
finally:
OlcHandlerChain.chain = original_chain
@patch('olc.olc.OlcConfigManager.get_instance')
@patch('olc.olc.OlcScheduleManager.get_instance')
@patch('olc.olc.OlcRuleConvert.get_instance')
def test_clean_exception_handling(self, mock_rule, mock_schedule, mock_config):
"""测试clean方法异常处理"""
mock_sdk_config = Mock()
mock_sdk_config.switch = True
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule.return_value = Mock()
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
from olc.olc import OLC
from olc.control.handler_chain.box_handler_chain_builder import OlcHandlerChain
original_chain = OlcHandlerChain.chain
try:
mock_chain = Mock()
mock_chain.out_coming.side_effect = Exception("Chain error")
OlcHandlerChain.chain = mock_chain
olc = OLC.get_instance()
request = OlcControlRequest()
context = OlcContext(request)
olc.clean(context)
finally:
OlcHandlerChain.chain = original_chain
@patch('olc.olc.OlcConfigManager.get_instance')
@patch('olc.olc.OlcScheduleManager.get_instance')
@patch('olc.olc.OlcRuleConvert.get_instance')
def test_graceful_shutdown(self, mock_rule, mock_schedule, mock_config):
"""测试优雅关闭"""
mock_sdk_config = Mock()
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule_instance = Mock()
mock_schedule.return_value = mock_schedule_instance
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
from olc.olc import OLC
olc = OLC.get_instance()
olc._graceful_shutdown()
mock_schedule_instance.close.assert_called_once()
@patch('olc.olc.OlcConfigManager.get_instance')
@patch('olc.olc.OlcScheduleManager.get_instance')
@patch('olc.olc.OlcRuleConvert.get_instance')
def test_graceful_shutdown_with_exception(self, mock_rule, mock_schedule, mock_config):
"""测试优雅关闭异常处理"""
mock_sdk_config = Mock()
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule_instance = Mock()
mock_schedule_instance.close.side_effect = Exception("Close error")
mock_schedule.return_value = mock_schedule_instance
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
from olc.olc import OLC
olc = OLC.get_instance()
olc._graceful_shutdown()
mock_schedule_instance.close.assert_called_once()
@patch('olc.olc.OlcConfigManager.get_instance')
@patch('olc.olc.OlcScheduleManager.get_instance')
@patch('olc.olc.OlcRuleConvert.get_instance')
def test_signal_handler(self, mock_rule, mock_schedule, mock_config):
"""测试信号处理器"""
mock_sdk_config = Mock()
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule_instance = Mock()
mock_schedule.return_value = mock_schedule_instance
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
from olc.olc import OLC
olc = OLC.get_instance()
olc._signal_handler(2, None)
mock_schedule_instance.close.assert_called_once()
def test_thread_safety(self):
"""测试多线程安全性"""
from olc.olc import OLC
with patch('olc.olc.OlcConfigManager.get_instance') as mock_config, \
patch('olc.olc.OlcScheduleManager.get_instance') as mock_schedule, \
patch('olc.olc.OlcRuleConvert.get_instance') as mock_rule:
mock_sdk_config = Mock()
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule.return_value = Mock()
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
instances = []
errors = []
lock = threading.Lock()
def get_olc_instance():
try:
instance = OLC.get_instance()
with lock:
instances.append(instance)
except Exception as e:
with lock:
errors.append(e)
threads = [threading.Thread(target=get_olc_instance) for _ in range(10)]
for t in threads:
t.start()
for t in threads:
t.join()
self.assertEqual(len(errors), 0, f"Errors occurred: {errors}")
self.assertEqual(len(set(id(i) for i in instances)), 1, "Multiple instances created")
@patch('olc.olc.OlcConfigManager.get_instance')
@patch('olc.olc.OlcScheduleManager.get_instance')
@patch('olc.olc.OlcRuleConvert.get_instance')
def test_process_with_empty_tags(self, mock_rule, mock_schedule, mock_config):
"""测试空tags请求"""
mock_sdk_config = Mock()
mock_sdk_config.switch = True
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule.return_value = Mock()
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
from olc.olc import OLC
olc = OLC.get_instance()
request = OlcControlRequest(tags={}, token_number=0)
context = olc.process(request)
self.assertIsInstance(context, OlcContext)
self.assertEqual(context.request.tags, {})
@patch('olc.olc.OlcConfigManager.get_instance')
@patch('olc.olc.OlcScheduleManager.get_instance')
@patch('olc.olc.OlcRuleConvert.get_instance')
def test_process_with_large_token_number(self, mock_rule, mock_schedule, mock_config):
"""测试大token_number边界条件"""
mock_sdk_config = Mock()
mock_sdk_config.switch = True
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule.return_value = Mock()
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
from olc.olc import OLC
olc = OLC.get_instance()
request = OlcControlRequest(tags={"user": "test"}, token_number=1000000)
context = olc.process(request)
self.assertIsInstance(context, OlcContext)
self.assertEqual(context.request.token_number, 1000000)
@patch('olc.olc.OlcConfigManager.get_instance')
@patch('olc.olc.OlcScheduleManager.get_instance')
@patch('olc.olc.OlcRuleConvert.get_instance')
def test_process_with_negative_token_number(self, mock_rule, mock_schedule, mock_config):
"""测试负数token_number边界条件"""
mock_sdk_config = Mock()
mock_sdk_config.switch = True
mock_sdk_config.collector_active = ""
mock_config_instance = Mock()
mock_config_instance.get_sdk_config.return_value = mock_sdk_config
mock_config.return_value = mock_config_instance
mock_schedule.return_value = Mock()
mock_rule_instance = Mock()
mock_rule.return_value = mock_rule_instance
from olc.olc import OLC
olc = OLC.get_instance()
request = OlcControlRequest(tags={"user": "test"}, token_number=-100)
context = olc.process(request)
self.assertIsInstance(context, OlcContext)
self.assertEqual(context.request.token_number, -100)
if __name__ == '__main__':
unittest.main(verbosity=2)