mirror of
https://github.com/Shu-Ying/main_plugin_farm.git
synced 2026-10-30 22:30:01 +08:00
fixed # 修复astrbot日志未使用logging.basicConfig
This commit is contained in:
@@ -102,3 +102,45 @@ class BundleTests(unittest.TestCase):
|
||||
with patch.object(bundle, 'urlopen', return_value=response):
|
||||
with self.assertRaises(ValueError):
|
||||
bundle._copy_remote('https://farm.example/a', BytesIO(), 10)
|
||||
|
||||
def test_download_reports_throttled_progress_without_urls(self):
|
||||
class Response(BytesIO):
|
||||
headers = {'Content-Length': '262144'}
|
||||
def geturl(self):
|
||||
return 'https://farm.example/private/assets.zip'
|
||||
with patch.object(bundle, 'urlopen', return_value=Response(
|
||||
b'x' * 262144)), patch.object(
|
||||
bundle.time, 'monotonic',
|
||||
side_effect=[0, 0.2, 1.1, 1.2, 2.2]), \
|
||||
self.assertLogs(bundle.logger, level='INFO') as captured:
|
||||
bundle._copy_remote('https://farm.example/private/assets.zip',
|
||||
BytesIO(), 262144)
|
||||
messages = '\n'.join(captured.output)
|
||||
self.assertIn('下载开始', messages)
|
||||
self.assertIn('50.0%', messages)
|
||||
self.assertIn('100.0%', messages)
|
||||
self.assertIn('下载完成', messages)
|
||||
self.assertEqual(messages.count('下载进度'), 2)
|
||||
self.assertNotIn('farm.example', messages)
|
||||
self.assertNotIn('private', messages)
|
||||
|
||||
def test_unknown_length_and_failed_download_report_truthfully(self):
|
||||
class Response(BytesIO):
|
||||
headers = {}
|
||||
def geturl(self):
|
||||
return 'https://farm.example/a'
|
||||
with patch.object(bundle, 'urlopen', return_value=Response(b'abc')), \
|
||||
patch.object(bundle.time, 'monotonic', side_effect=[0, 1.1]), \
|
||||
self.assertLogs(bundle.logger, level='INFO') as captured:
|
||||
bundle._copy_remote('https://farm.example/a', BytesIO(), 10)
|
||||
self.assertIn('下载完成', '\n'.join(captured.output))
|
||||
self.assertIn('已下载', '\n'.join(captured.output))
|
||||
self.assertNotIn('%', '\n'.join(captured.output))
|
||||
with patch.object(bundle, 'urlopen', side_effect=OSError('secret')), \
|
||||
self.assertLogs(bundle.logger, level='INFO') as captured:
|
||||
with self.assertRaises(OSError):
|
||||
bundle._copy_remote('https://farm.example/a', BytesIO(), 10)
|
||||
messages = '\n'.join(captured.output)
|
||||
self.assertIn('下载失败', messages)
|
||||
self.assertNotIn('下载完成', messages)
|
||||
self.assertNotIn('secret', messages)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import asyncio
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from types import ModuleType
|
||||
import unittest
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
@@ -10,6 +12,11 @@ ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
class AvatarTests(unittest.IsolatedAsyncioTestCase):
|
||||
def setUp(self):
|
||||
api = ModuleType('astrbot.api')
|
||||
api.logger = Mock()
|
||||
host = patch.dict(sys.modules, {'astrbot.api': api})
|
||||
host.start()
|
||||
self.addCleanup(host.stop)
|
||||
spec = importlib.util.spec_from_file_location(
|
||||
'farm_astrbot_avatars',
|
||||
ROOT / 'integrations/astrbot/avatars.py',
|
||||
|
||||
@@ -7,7 +7,7 @@ import sys
|
||||
import tempfile
|
||||
from types import ModuleType, SimpleNamespace
|
||||
import unittest
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
@@ -62,19 +62,43 @@ class AstrBotPackageTests(unittest.IsolatedAsyncioTestCase):
|
||||
with patch('verify_astrbot.MAX_ARCHIVE_BYTES', 1):
|
||||
with self.assertRaisesRegex(ValueError, '16 MiB'):
|
||||
verify_package(first, marketplace=True)
|
||||
self.assertEqual(files['runtime.py'], (
|
||||
ROOT / 'integrations/shared/runtime.py'
|
||||
).read_bytes())
|
||||
source_tree = ast.parse((ROOT / 'integrations/shared/runtime.py')
|
||||
.read_bytes())
|
||||
built_tree = ast.parse(files['runtime.py'])
|
||||
source_runtime = next(node for node in source_tree.body
|
||||
if isinstance(node, ast.ClassDef))
|
||||
built_runtime = next(node for node in built_tree.body
|
||||
if isinstance(node, ast.ClassDef))
|
||||
self.assertEqual(ast.dump(source_runtime), ast.dump(built_runtime))
|
||||
self.assertFalse('_vendor/farm_core/__main__.py' in files)
|
||||
for name, content in files.items():
|
||||
self.assertNotIn('.git/', name)
|
||||
self.assertNotIn('farm.sqlite3', name)
|
||||
if name.endswith('.py'):
|
||||
tree = ast.parse(content)
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.Import):
|
||||
self.assertFalse(any(
|
||||
alias.name.split('.')[0] == 'logging'
|
||||
for alias in node.names
|
||||
), name)
|
||||
if isinstance(node, ast.ImportFrom):
|
||||
self.assertFalse((node.module or '').startswith(
|
||||
('nonebot', 'zhenxun'),
|
||||
('nonebot', 'zhenxun', 'logging'),
|
||||
))
|
||||
for snippet in (b'\nimport logging\n',
|
||||
b'\nlogger.setLevel(20)\n'):
|
||||
invalid = dict(files)
|
||||
invalid['main.py'] += snippet
|
||||
invalid_manifest = json.loads(invalid['FARM-MANIFEST.json'])
|
||||
invalid_manifest['files']['main.py'] = hashlib.sha256(
|
||||
invalid['main.py'],
|
||||
).hexdigest()
|
||||
invalid['FARM-MANIFEST.json'] = json.dumps(
|
||||
invalid_manifest,
|
||||
).encode()
|
||||
with self.assertRaisesRegex(ValueError, 'logging'):
|
||||
verify_files(invalid)
|
||||
files['main.py'] += b'\n# tampered\n'
|
||||
with self.assertRaisesRegex(ValueError, 'checksum'):
|
||||
verify_files(files)
|
||||
@@ -91,6 +115,7 @@ class AstrBotPackageTests(unittest.IsolatedAsyncioTestCase):
|
||||
package.__path__ = [str(self.root / 'host/repository')]
|
||||
api = ModuleType('astrbot.api')
|
||||
api.AstrBotConfig = dict
|
||||
api.logger = Mock()
|
||||
events = ModuleType('astrbot.api.event')
|
||||
commands = {}
|
||||
|
||||
@@ -152,6 +177,14 @@ class AstrBotPackageTests(unittest.IsolatedAsyncioTestCase):
|
||||
side_effect=OSError('offline fixture'),
|
||||
):
|
||||
await plugin.initialize()
|
||||
self.assertIs(main.logger, api.logger)
|
||||
self.assertIsNone(plugin.runtime.log_handler)
|
||||
self.assertIsNone(plugin.runtime.console_handler)
|
||||
self.assertFalse((plugin.runtime.data_dir /
|
||||
'farm-preview.log').exists())
|
||||
api.logger.info.assert_any_call(
|
||||
'农场启动:正在检查作物版本和本地缓存',
|
||||
)
|
||||
self.assertEqual(set(commands), set(main.COMMANDS))
|
||||
|
||||
class Event:
|
||||
|
||||
@@ -84,6 +84,45 @@ class ZhenxunRuntimeTests(unittest.IsolatedAsyncioTestCase):
|
||||
for action in ('seeds', 'crops'):
|
||||
self.assertIsInstance(await self.call(action, '1'), bytes)
|
||||
|
||||
async def test_start_progress_reaches_console_and_file(self):
|
||||
import logging
|
||||
from contextlib import redirect_stderr
|
||||
from io import StringIO
|
||||
|
||||
await self.runtime.close()
|
||||
output = StringIO()
|
||||
package_log = logging.getLogger(self.package)
|
||||
with patch.object(logging.getLogger(), 'handlers', []), \
|
||||
patch.object(package_log, 'handlers', []), \
|
||||
redirect_stderr(output):
|
||||
await self.runtime.start()
|
||||
await self.runtime.close()
|
||||
self.assertFalse(package_log.handlers)
|
||||
self.assertIn('正在检查作物版本', output.getvalue())
|
||||
self.assertIn('使用内置作物版本', output.getvalue())
|
||||
self.assertIn('字体', output.getvalue())
|
||||
self.assertIn('农场启动完成', output.getvalue())
|
||||
saved = (self.runtime.data_dir / 'farm-preview.log').read_text(
|
||||
encoding='utf-8',
|
||||
)
|
||||
self.assertIn('正在检查作物版本', saved)
|
||||
|
||||
async def test_start_reuses_existing_console_without_duplicate_output(self):
|
||||
import logging
|
||||
from io import StringIO
|
||||
|
||||
await self.runtime.close()
|
||||
output = StringIO()
|
||||
handler = logging.StreamHandler(output)
|
||||
handler.setLevel(logging.INFO)
|
||||
with patch.object(logging.getLogger(), 'handlers', [handler]):
|
||||
await self.runtime.start()
|
||||
await self.runtime.start()
|
||||
self.assertIsNone(self.runtime.console_handler)
|
||||
await self.runtime.close()
|
||||
self.assertEqual(output.getvalue().count('正在检查作物版本'), 1)
|
||||
self.assertEqual(output.getvalue().count('农场启动完成'), 1)
|
||||
|
||||
async def test_catalogue_is_loaded_once_before_store_initialization(self):
|
||||
import json
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
Reference in New Issue
Block a user