scalebox-sdk 0.1.11__py3-none-any.whl → 0.1.13__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scalebox/__init__.py +1 -1
- scalebox/code_interpreter/code_interpreter_async.py +12 -12
- scalebox/code_interpreter/code_interpreter_sync.py +11 -11
- scalebox/generated/api_pb2_connect.py +3 -3
- scalebox/sandbox_sync/main.py +1 -1
- scalebox/test/aclient.py +72 -72
- scalebox/test/code_interpreter_centext.py +21 -21
- scalebox/test/code_interpreter_centext_sync.py +21 -21
- scalebox/test/code_interpreter_test.py +34 -34
- scalebox/test/code_interpreter_test_sync.py +34 -34
- scalebox/test/run_all_validation_tests.py +334 -334
- scalebox/test/test_basic.py +78 -78
- scalebox/test/test_code_interpreter_async_comprehensive.py +2653 -2653
- scalebox/test/test_code_interpreter_e2basync_comprehensive.py +2655 -2655
- scalebox/test/test_code_interpreter_e2bsync_comprehensive.py +3416 -3416
- scalebox/test/test_code_interpreter_execcode.py +3352 -0
- scalebox/test/test_code_interpreter_sync_comprehensive.py +3416 -3412
- scalebox/test/test_csx_desktop_examples.py +130 -0
- scalebox/test/test_e2b_first.py +11 -11
- scalebox/test/test_sandbox_async_comprehensive.py +736 -738
- scalebox/test/test_sandbox_stress_and_edge_cases.py +778 -778
- scalebox/test/test_sandbox_sync_comprehensive.py +779 -770
- scalebox/test/test_sandbox_usage_examples.py +987 -987
- scalebox/test/testacreate.py +24 -24
- scalebox/test/testagetinfo.py +18 -18
- scalebox/test/testcodeinterpreter_async.py +508 -508
- scalebox/test/testcodeinterpreter_sync.py +239 -239
- scalebox/test/testcomputeuse.py +245 -243
- scalebox/test/testnovnc.py +12 -12
- scalebox/test/testsandbox_async.py +202 -118
- scalebox/test/testsandbox_sync.py +71 -38
- scalebox/version.py +2 -2
- {scalebox_sdk-0.1.11.dist-info → scalebox_sdk-0.1.13.dist-info}/METADATA +1 -1
- {scalebox_sdk-0.1.11.dist-info → scalebox_sdk-0.1.13.dist-info}/RECORD +38 -36
- {scalebox_sdk-0.1.11.dist-info → scalebox_sdk-0.1.13.dist-info}/WHEEL +0 -0
- {scalebox_sdk-0.1.11.dist-info → scalebox_sdk-0.1.13.dist-info}/entry_points.txt +0 -0
- {scalebox_sdk-0.1.11.dist-info → scalebox_sdk-0.1.13.dist-info}/licenses/LICENSE +0 -0
- {scalebox_sdk-0.1.11.dist-info → scalebox_sdk-0.1.13.dist-info}/top_level.txt +0 -0
|
@@ -1,2655 +1,2655 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Comprehensive validation test for code_interpreter async module.
|
|
4
|
-
|
|
5
|
-
This test suite demonstrates and validates all key functionality of the AsyncCodeInterpreter:
|
|
6
|
-
- Basic async code execution (Python, shell commands)
|
|
7
|
-
- Async callback handling (stdout, stderr, result, error)
|
|
8
|
-
- Context management (create, persist, destroy)
|
|
9
|
-
- Error handling and edge cases
|
|
10
|
-
- Performance testing with concurrency
|
|
11
|
-
- Different data types and formats
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
import asyncio
|
|
15
|
-
import datetime
|
|
16
|
-
import json
|
|
17
|
-
import logging
|
|
18
|
-
import os
|
|
19
|
-
import time
|
|
20
|
-
from typing import Any, Dict, List, Optional
|
|
21
|
-
|
|
22
|
-
from e2b_code_interpreter import Sandbox
|
|
23
|
-
|
|
24
|
-
from scalebox.code_interpreter import (
|
|
25
|
-
AsyncSandbox,
|
|
26
|
-
Context,
|
|
27
|
-
Execution,
|
|
28
|
-
ExecutionError,
|
|
29
|
-
Logs,
|
|
30
|
-
OutputMessage,
|
|
31
|
-
Result,
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
# 配置日志
|
|
35
|
-
logging.basicConfig(
|
|
36
|
-
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
|
|
37
|
-
)
|
|
38
|
-
logger = logging.getLogger(__name__)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class AsyncCodeInterpreterValidator:
|
|
42
|
-
"""Comprehensive AsyncCodeInterpreter validation test suite."""
|
|
43
|
-
|
|
44
|
-
def __init__(self):
|
|
45
|
-
self.sandbox: Optional[AsyncSandbox] = None
|
|
46
|
-
self.test_results = []
|
|
47
|
-
self.failed_tests = []
|
|
48
|
-
self.contexts: Dict[str, Context] = {}
|
|
49
|
-
|
|
50
|
-
async def log_test_result(
|
|
51
|
-
self, test_name: str, success: bool, message: str = "", duration: float = 0
|
|
52
|
-
):
|
|
53
|
-
"""记录测试结果"""
|
|
54
|
-
status = "✅ PASS" if success else "❌ FAIL"
|
|
55
|
-
result = {
|
|
56
|
-
"test": test_name,
|
|
57
|
-
"success": success,
|
|
58
|
-
"message": message,
|
|
59
|
-
"duration": duration,
|
|
60
|
-
}
|
|
61
|
-
self.test_results.append(result)
|
|
62
|
-
|
|
63
|
-
if not success:
|
|
64
|
-
self.failed_tests.append(test_name)
|
|
65
|
-
|
|
66
|
-
logger.info(f"{status} {test_name} ({duration:.3f}s) {message}")
|
|
67
|
-
|
|
68
|
-
async def run_test(self, test_func, test_name: str):
|
|
69
|
-
"""运行单个测试并记录结果"""
|
|
70
|
-
start_time = time.time()
|
|
71
|
-
try:
|
|
72
|
-
await test_func()
|
|
73
|
-
duration = time.time() - start_time
|
|
74
|
-
await self.log_test_result(test_name, True, duration=duration)
|
|
75
|
-
except Exception as e:
|
|
76
|
-
duration = time.time() - start_time
|
|
77
|
-
await self.log_test_result(test_name, False, str(e), duration=duration)
|
|
78
|
-
|
|
79
|
-
# ======================== 基础异步代码解释器操作测试 ========================
|
|
80
|
-
|
|
81
|
-
async def test_async_code_interpreter_creation(self):
|
|
82
|
-
"""测试异步代码解释器创建"""
|
|
83
|
-
self.sandbox = await AsyncSandbox.create(
|
|
84
|
-
template="code-interpreter",
|
|
85
|
-
timeout=3600,
|
|
86
|
-
debug=True,
|
|
87
|
-
metadata={"test": "async_code_interpreter_validation"},
|
|
88
|
-
envs={"CI_TEST": "async_test"},
|
|
89
|
-
)
|
|
90
|
-
# time.sleep(5)
|
|
91
|
-
assert self.sandbox is not None
|
|
92
|
-
assert self.sandbox.sandbox_id is not None
|
|
93
|
-
logger.info(
|
|
94
|
-
f"Created AsyncCodeInterpreter sandbox with ID: {self.sandbox.sandbox_id}"
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
async def test_basic_async_python_execution(self):
|
|
98
|
-
"""测试基础异步Python代码执行"""
|
|
99
|
-
assert self.sandbox is not None
|
|
100
|
-
|
|
101
|
-
code = """
|
|
102
|
-
import asyncio
|
|
103
|
-
import time
|
|
104
|
-
|
|
105
|
-
print("开始异步Python执行...")
|
|
106
|
-
|
|
107
|
-
async def async_calculation():
|
|
108
|
-
print("异步计算开始")
|
|
109
|
-
await asyncio.sleep(0.1) # 模拟异步操作
|
|
110
|
-
result = sum(range(100))
|
|
111
|
-
print(f"异步计算完成: {result}")
|
|
112
|
-
return result
|
|
113
|
-
|
|
114
|
-
async def main_async():
|
|
115
|
-
task1 = asyncio.create_task(async_calculation())
|
|
116
|
-
task2 = asyncio.create_task(async_calculation())
|
|
117
|
-
|
|
118
|
-
results = await asyncio.gather(task1, task2)
|
|
119
|
-
print(f"两个异步任务结果: {results}")
|
|
120
|
-
return {"results": results, "sum": sum(results)}
|
|
121
|
-
|
|
122
|
-
# 运行异步函数
|
|
123
|
-
result = await main_async()
|
|
124
|
-
print(f"最终结果: {result}")
|
|
125
|
-
"""
|
|
126
|
-
|
|
127
|
-
execution = await self.sandbox.run_code(code, language="python")
|
|
128
|
-
assert isinstance(execution, Execution)
|
|
129
|
-
assert execution.error is None
|
|
130
|
-
assert len(execution.logs.stdout) > 0
|
|
131
|
-
assert any("异步Python执行" in line for line in execution.logs.stdout)
|
|
132
|
-
logger.info("Async Python execution completed successfully")
|
|
133
|
-
|
|
134
|
-
async def test_concurrent_code_execution(self):
|
|
135
|
-
"""测试并发代码执行"""
|
|
136
|
-
assert self.sandbox is not None
|
|
137
|
-
|
|
138
|
-
codes = [
|
|
139
|
-
"""
|
|
140
|
-
import asyncio
|
|
141
|
-
print(f"任务 1 开始")
|
|
142
|
-
await asyncio.sleep(0.1)
|
|
143
|
-
result = {"task": 1, "value": 10}
|
|
144
|
-
print(f"任务 1 完成: {result}")
|
|
145
|
-
result
|
|
146
|
-
""",
|
|
147
|
-
"""
|
|
148
|
-
import asyncio
|
|
149
|
-
print(f"任务 2 开始")
|
|
150
|
-
await asyncio.sleep(0.1)
|
|
151
|
-
result = {"task": 2, "value": 20}
|
|
152
|
-
print(f"任务 2 完成: {result}")
|
|
153
|
-
result
|
|
154
|
-
""",
|
|
155
|
-
"""
|
|
156
|
-
import asyncio
|
|
157
|
-
print(f"任务 3 开始")
|
|
158
|
-
await asyncio.sleep(0.1)
|
|
159
|
-
result = {"task": 3, "value": 30}
|
|
160
|
-
print(f"任务 3 完成: {result}")
|
|
161
|
-
result
|
|
162
|
-
""",
|
|
163
|
-
]
|
|
164
|
-
|
|
165
|
-
# 并发执行多个代码片段
|
|
166
|
-
start_time = time.time()
|
|
167
|
-
tasks = [self.sandbox.run_code(code, language="python") for code in codes]
|
|
168
|
-
results = await asyncio.gather(*tasks)
|
|
169
|
-
duration = time.time() - start_time
|
|
170
|
-
|
|
171
|
-
# 验证结果
|
|
172
|
-
assert len(results) == 3
|
|
173
|
-
for execution in results:
|
|
174
|
-
assert execution.error is None
|
|
175
|
-
assert len(execution.logs.stdout) > 0
|
|
176
|
-
|
|
177
|
-
logger.info(f"Concurrent execution completed in {duration:.3f}s")
|
|
178
|
-
assert duration < 2.0 # 并发执行应该比串行快
|
|
179
|
-
|
|
180
|
-
async def test_async_data_science_workflow(self):
|
|
181
|
-
"""测试异步数据科学工作流"""
|
|
182
|
-
assert self.sandbox is not None
|
|
183
|
-
|
|
184
|
-
code = """
|
|
185
|
-
import asyncio
|
|
186
|
-
import pandas as pd
|
|
187
|
-
import numpy as np
|
|
188
|
-
import json
|
|
189
|
-
from concurrent.futures import ThreadPoolExecutor
|
|
190
|
-
import time
|
|
191
|
-
|
|
192
|
-
async def generate_data_async(size, data_type):
|
|
193
|
-
'''异步生成数据'''
|
|
194
|
-
print(f"开始生成 {data_type} 数据,大小: {size}")
|
|
195
|
-
|
|
196
|
-
# 在线程池中执行CPU密集型操作
|
|
197
|
-
loop = asyncio.get_event_loop()
|
|
198
|
-
with ThreadPoolExecutor() as executor:
|
|
199
|
-
if data_type == "random":
|
|
200
|
-
data = await loop.run_in_executor(executor, np.random.randn, size)
|
|
201
|
-
elif data_type == "sequence":
|
|
202
|
-
data = await loop.run_in_executor(executor, lambda: np.arange(size))
|
|
203
|
-
else:
|
|
204
|
-
data = await loop.run_in_executor(executor, np.ones, size)
|
|
205
|
-
|
|
206
|
-
print(f"{data_type} 数据生成完成")
|
|
207
|
-
return data
|
|
208
|
-
|
|
209
|
-
async def process_data_async(data, name):
|
|
210
|
-
'''异步处理数据'''
|
|
211
|
-
print(f"开始处理数据: {name}")
|
|
212
|
-
|
|
213
|
-
# 模拟异步处理
|
|
214
|
-
await asyncio.sleep(0.1)
|
|
215
|
-
|
|
216
|
-
stats = {
|
|
217
|
-
"name": name,
|
|
218
|
-
"mean": float(np.mean(data)),
|
|
219
|
-
"std": float(np.std(data)),
|
|
220
|
-
"min": float(np.min(data)),
|
|
221
|
-
"max": float(np.max(data)),
|
|
222
|
-
"size": len(data)
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
print(f"数据处理完成: {name}")
|
|
226
|
-
return stats
|
|
227
|
-
|
|
228
|
-
print("开始异步数据科学工作流...")
|
|
229
|
-
|
|
230
|
-
# 并发生成多个数据集
|
|
231
|
-
data_tasks = [
|
|
232
|
-
generate_data_async(1000, "random"),
|
|
233
|
-
generate_data_async(1000, "sequence"),
|
|
234
|
-
generate_data_async(1000, "ones")
|
|
235
|
-
]
|
|
236
|
-
|
|
237
|
-
datasets = await asyncio.gather(*data_tasks)
|
|
238
|
-
|
|
239
|
-
# 并发处理数据
|
|
240
|
-
process_tasks = [
|
|
241
|
-
process_data_async(datasets[0], "随机数据"),
|
|
242
|
-
process_data_async(datasets[1], "序列数据"),
|
|
243
|
-
process_data_async(datasets[2], "常数数据")
|
|
244
|
-
]
|
|
245
|
-
|
|
246
|
-
stats_results = await asyncio.gather(*process_tasks)
|
|
247
|
-
|
|
248
|
-
print("\\n数据统计结果:")
|
|
249
|
-
for stats in stats_results:
|
|
250
|
-
print(f"{stats['name']}: 均值={stats['mean']:.3f}, 标准差={stats['std']:.3f}")
|
|
251
|
-
|
|
252
|
-
# 创建综合报告
|
|
253
|
-
report = {
|
|
254
|
-
"total_datasets": len(datasets),
|
|
255
|
-
"total_datapoints": sum(len(d) for d in datasets),
|
|
256
|
-
"statistics": stats_results,
|
|
257
|
-
"processing_time": "异步并发处理"
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
print(f"\\n工作流完成,处理了 {report['total_datapoints']} 个数据点")
|
|
261
|
-
report
|
|
262
|
-
"""
|
|
263
|
-
|
|
264
|
-
execution = await self.sandbox.run_code(code, language="python")
|
|
265
|
-
assert execution.error is None
|
|
266
|
-
assert any("数据科学工作流" in line for line in execution.logs.stdout)
|
|
267
|
-
|
|
268
|
-
# ======================== 异步回调函数测试 ========================
|
|
269
|
-
|
|
270
|
-
async def test_async_callback_handling(self):
|
|
271
|
-
"""测试异步回调函数处理"""
|
|
272
|
-
assert self.sandbox is not None
|
|
273
|
-
|
|
274
|
-
stdout_messages = []
|
|
275
|
-
stderr_messages = []
|
|
276
|
-
results = []
|
|
277
|
-
errors = []
|
|
278
|
-
|
|
279
|
-
async def async_stdout_callback(msg: OutputMessage):
|
|
280
|
-
await asyncio.sleep(0.001) # 模拟异步处理
|
|
281
|
-
stdout_messages.append(msg.content)
|
|
282
|
-
logger.info(f"ASYNC STDOUT: {msg.content}")
|
|
283
|
-
|
|
284
|
-
async def async_stderr_callback(msg: OutputMessage):
|
|
285
|
-
await asyncio.sleep(0.001)
|
|
286
|
-
stderr_messages.append(msg.content)
|
|
287
|
-
logger.info(f"ASYNC STDERR: {msg.content}")
|
|
288
|
-
|
|
289
|
-
async def async_result_callback(result: Result):
|
|
290
|
-
await asyncio.sleep(0.001)
|
|
291
|
-
results.append(result)
|
|
292
|
-
logger.info(f"ASYNC RESULT: {result}")
|
|
293
|
-
|
|
294
|
-
async def async_error_callback(error: ExecutionError):
|
|
295
|
-
await asyncio.sleep(0.001)
|
|
296
|
-
errors.append(error)
|
|
297
|
-
logger.info(f"ASYNC ERROR: {error.name} - {error.value}")
|
|
298
|
-
|
|
299
|
-
code = """
|
|
300
|
-
import asyncio
|
|
301
|
-
import sys
|
|
302
|
-
|
|
303
|
-
print("异步回调测试开始")
|
|
304
|
-
|
|
305
|
-
async def async_output_generator():
|
|
306
|
-
for i in range(3):
|
|
307
|
-
print(f"异步输出 {i+1}")
|
|
308
|
-
await asyncio.sleep(0.05)
|
|
309
|
-
|
|
310
|
-
print("这是标准错误信息", file=sys.stderr)
|
|
311
|
-
|
|
312
|
-
result = {"status": "completed", "items": 3, "type": "async"}
|
|
313
|
-
print(f"生成结果: {result}")
|
|
314
|
-
return result
|
|
315
|
-
|
|
316
|
-
result = await async_output_generator()
|
|
317
|
-
print("异步回调测试完成")
|
|
318
|
-
result
|
|
319
|
-
"""
|
|
320
|
-
|
|
321
|
-
execution = await self.sandbox.run_code(
|
|
322
|
-
code,
|
|
323
|
-
language="python",
|
|
324
|
-
on_stdout=async_stdout_callback,
|
|
325
|
-
on_stderr=async_stderr_callback,
|
|
326
|
-
on_result=async_result_callback,
|
|
327
|
-
on_error=async_error_callback,
|
|
328
|
-
)
|
|
329
|
-
|
|
330
|
-
assert execution.error is None
|
|
331
|
-
logger.info(f"Async callback test completed")
|
|
332
|
-
|
|
333
|
-
# ======================== 异步上下文管理测试 ========================
|
|
334
|
-
|
|
335
|
-
async def test_async_context_creation(self):
|
|
336
|
-
"""测试异步上下文创建"""
|
|
337
|
-
assert self.sandbox is not None
|
|
338
|
-
|
|
339
|
-
# 创建Python上下文
|
|
340
|
-
python_context = await self.sandbox.create_code_context(
|
|
341
|
-
language="python", cwd="/tmp"
|
|
342
|
-
)
|
|
343
|
-
assert isinstance(python_context, Context)
|
|
344
|
-
assert python_context.id is not None
|
|
345
|
-
self.contexts["async_python"] = python_context
|
|
346
|
-
logger.info(f"Created async Python context: {python_context.id}")
|
|
347
|
-
|
|
348
|
-
# 测试完成后立即清理context
|
|
349
|
-
try:
|
|
350
|
-
await self.sandbox.destroy_context(python_context)
|
|
351
|
-
logger.info(f"Successfully destroyed async context: {python_context.id}")
|
|
352
|
-
# 从contexts字典中移除
|
|
353
|
-
if "async_python" in self.contexts:
|
|
354
|
-
del self.contexts["async_python"]
|
|
355
|
-
except Exception as e:
|
|
356
|
-
logger.warning(f"Failed to destroy async context {python_context.id}: {e}")
|
|
357
|
-
|
|
358
|
-
async def test_async_context_state_management(self):
|
|
359
|
-
"""测试异步上下文状态管理"""
|
|
360
|
-
assert self.sandbox is not None
|
|
361
|
-
|
|
362
|
-
# 创建新的上下文用于状态管理测试
|
|
363
|
-
context = await self.sandbox.create_code_context(language="python", cwd="/tmp")
|
|
364
|
-
self.contexts["async_state_test"] = context
|
|
365
|
-
|
|
366
|
-
# 在上下文中设置异步状态
|
|
367
|
-
setup_code = """
|
|
368
|
-
import asyncio
|
|
369
|
-
|
|
370
|
-
# 异步状态变量
|
|
371
|
-
async_state = {
|
|
372
|
-
"connections": [],
|
|
373
|
-
"tasks": [],
|
|
374
|
-
"data_cache": {}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
async def add_connection(conn_id):
|
|
378
|
-
print(f"添加连接: {conn_id}")
|
|
379
|
-
async_state["connections"].append(conn_id)
|
|
380
|
-
await asyncio.sleep(0.01) # 模拟异步操作
|
|
381
|
-
return len(async_state["connections"])
|
|
382
|
-
|
|
383
|
-
# 初始化一些连接
|
|
384
|
-
connection_count = 0
|
|
385
|
-
for i in range(3):
|
|
386
|
-
count = await add_connection(f"conn_{i}")
|
|
387
|
-
connection_count = count
|
|
388
|
-
|
|
389
|
-
print(f"初始化完成,连接数: {connection_count}")
|
|
390
|
-
async_state
|
|
391
|
-
"""
|
|
392
|
-
|
|
393
|
-
execution1 = await self.sandbox.run_code(setup_code, context=context)
|
|
394
|
-
assert execution1.error is None
|
|
395
|
-
|
|
396
|
-
# 在同一上下文中使用已设置的状态
|
|
397
|
-
use_code = """
|
|
398
|
-
print(f"当前连接数: {len(async_state['connections'])}")
|
|
399
|
-
print(f"连接列表: {async_state['connections']}")
|
|
400
|
-
|
|
401
|
-
async def process_connections():
|
|
402
|
-
results = []
|
|
403
|
-
for conn in async_state["connections"]:
|
|
404
|
-
print(f"处理连接: {conn}")
|
|
405
|
-
await asyncio.sleep(0.01)
|
|
406
|
-
results.append(f"processed_{conn}")
|
|
407
|
-
return results
|
|
408
|
-
|
|
409
|
-
processed = await process_connections()
|
|
410
|
-
async_state["processed"] = processed
|
|
411
|
-
|
|
412
|
-
print(f"处理完成: {len(processed)} 个连接")
|
|
413
|
-
{"total_connections": len(async_state["connections"]), "processed": len(processed)}
|
|
414
|
-
"""
|
|
415
|
-
|
|
416
|
-
execution2 = await self.sandbox.run_code(use_code, context=context)
|
|
417
|
-
assert execution2.error is None
|
|
418
|
-
assert any("处理完成" in line for line in execution2.logs.stdout)
|
|
419
|
-
|
|
420
|
-
# 测试完成后立即清理context
|
|
421
|
-
try:
|
|
422
|
-
await self.sandbox.destroy_context(context)
|
|
423
|
-
logger.info(f"Successfully destroyed async state context: {context.id}")
|
|
424
|
-
# 从contexts字典中移除
|
|
425
|
-
if "async_state_test" in self.contexts:
|
|
426
|
-
del self.contexts["async_state_test"]
|
|
427
|
-
except Exception as e:
|
|
428
|
-
logger.warning(f"Failed to destroy async state context {context.id}: {e}")
|
|
429
|
-
|
|
430
|
-
# ======================== 异步性能测试 ========================
|
|
431
|
-
|
|
432
|
-
async def test_async_performance_concurrent_tasks(self):
|
|
433
|
-
"""测试异步性能 - 并发任务"""
|
|
434
|
-
assert self.sandbox is not None
|
|
435
|
-
|
|
436
|
-
code = """
|
|
437
|
-
import asyncio
|
|
438
|
-
import time
|
|
439
|
-
import random
|
|
440
|
-
|
|
441
|
-
async def cpu_bound_task(task_id, iterations):
|
|
442
|
-
'''CPU密集型异步任务'''
|
|
443
|
-
print(f"CPU任务 {task_id} 开始,迭代次数: {iterations}")
|
|
444
|
-
|
|
445
|
-
result = 0
|
|
446
|
-
for i in range(iterations):
|
|
447
|
-
result += i ** 2
|
|
448
|
-
# 定期让出控制权
|
|
449
|
-
if i % 1000 == 0:
|
|
450
|
-
await asyncio.sleep(0)
|
|
451
|
-
|
|
452
|
-
print(f"CPU任务 {task_id} 完成,结果: {result}")
|
|
453
|
-
return {"task_id": task_id, "result": result, "iterations": iterations}
|
|
454
|
-
|
|
455
|
-
async def io_bound_task(task_id, delay_time):
|
|
456
|
-
'''IO密集型异步任务'''
|
|
457
|
-
print(f"IO任务 {task_id} 开始,延迟: {delay_time}s")
|
|
458
|
-
|
|
459
|
-
start = time.time()
|
|
460
|
-
await asyncio.sleep(delay_time)
|
|
461
|
-
duration = time.time() - start
|
|
462
|
-
|
|
463
|
-
print(f"IO任务 {task_id} 完成,实际耗时: {duration:.3f}s")
|
|
464
|
-
return {"task_id": task_id, "delay": delay_time, "actual_duration": duration}
|
|
465
|
-
|
|
466
|
-
print("异步性能测试开始...")
|
|
467
|
-
overall_start = time.time()
|
|
468
|
-
|
|
469
|
-
# 创建混合任务:CPU密集型和IO密集型
|
|
470
|
-
cpu_tasks = [cpu_bound_task(i, 5000) for i in range(3)]
|
|
471
|
-
io_tasks = [io_bound_task(i+10, 0.1 + i*0.05) for i in range(4)]
|
|
472
|
-
|
|
473
|
-
# 并发执行所有任务
|
|
474
|
-
all_tasks = cpu_tasks + io_tasks
|
|
475
|
-
results = await asyncio.gather(*all_tasks)
|
|
476
|
-
|
|
477
|
-
overall_duration = time.time() - overall_start
|
|
478
|
-
|
|
479
|
-
print(f"\\n性能测试完成:")
|
|
480
|
-
print(f"总任务数: {len(results)}")
|
|
481
|
-
print(f"CPU任务数: {len(cpu_tasks)}")
|
|
482
|
-
print(f"IO任务数: {len(io_tasks)}")
|
|
483
|
-
print(f"总执行时间: {overall_duration:.3f}s")
|
|
484
|
-
|
|
485
|
-
# 分析结果
|
|
486
|
-
cpu_results = [r for r in results if "iterations" in r]
|
|
487
|
-
io_results = [r for r in results if "delay" in r]
|
|
488
|
-
|
|
489
|
-
avg_cpu_result = sum(r["result"] for r in cpu_results) / len(cpu_results)
|
|
490
|
-
avg_io_duration = sum(r["actual_duration"] for r in io_results) / len(io_results)
|
|
491
|
-
|
|
492
|
-
print(f"平均CPU任务结果: {avg_cpu_result:.0f}")
|
|
493
|
-
print(f"平均IO任务耗时: {avg_io_duration:.3f}s")
|
|
494
|
-
|
|
495
|
-
{
|
|
496
|
-
"total_tasks": len(results),
|
|
497
|
-
"cpu_tasks": len(cpu_tasks),
|
|
498
|
-
"io_tasks": len(io_tasks),
|
|
499
|
-
"total_time": overall_duration,
|
|
500
|
-
"avg_cpu_result": avg_cpu_result,
|
|
501
|
-
"avg_io_duration": avg_io_duration,
|
|
502
|
-
"concurrency_efficiency": (sum(r["delay"] for r in io_results) / overall_duration) if overall_duration > 0 else 0
|
|
503
|
-
}
|
|
504
|
-
"""
|
|
505
|
-
|
|
506
|
-
start_test_time = time.time()
|
|
507
|
-
execution = await self.sandbox.run_code(code, language="python")
|
|
508
|
-
test_duration = time.time() - start_test_time
|
|
509
|
-
|
|
510
|
-
assert execution.error is None
|
|
511
|
-
assert any("性能测试开始" in line for line in execution.logs.stdout)
|
|
512
|
-
logger.info(f"Async performance test completed in {test_duration:.3f}s")
|
|
513
|
-
|
|
514
|
-
async def test_async_batch_processing(self):
|
|
515
|
-
"""测试异步批处理"""
|
|
516
|
-
assert self.sandbox is not None
|
|
517
|
-
|
|
518
|
-
code = """
|
|
519
|
-
import asyncio
|
|
520
|
-
import json
|
|
521
|
-
import time
|
|
522
|
-
|
|
523
|
-
async def process_batch(batch_id, items):
|
|
524
|
-
'''异步批处理函数'''
|
|
525
|
-
print(f"开始处理批次 {batch_id},包含 {len(items)} 个项目")
|
|
526
|
-
|
|
527
|
-
processed_items = []
|
|
528
|
-
start_time = time.time()
|
|
529
|
-
|
|
530
|
-
for i, item in enumerate(items):
|
|
531
|
-
# 模拟处理每个项目
|
|
532
|
-
processed = {
|
|
533
|
-
"original": item,
|
|
534
|
-
"processed_value": item * 2,
|
|
535
|
-
"batch_id": batch_id,
|
|
536
|
-
"item_index": i
|
|
537
|
-
}
|
|
538
|
-
processed_items.append(processed)
|
|
539
|
-
|
|
540
|
-
# 每处理几个项目就让出控制权
|
|
541
|
-
if i % 5 == 0:
|
|
542
|
-
await asyncio.sleep(0.01)
|
|
543
|
-
|
|
544
|
-
processing_time = time.time() - start_time
|
|
545
|
-
print(f"批次 {batch_id} 处理完成,耗时: {processing_time:.3f}s")
|
|
546
|
-
|
|
547
|
-
return {
|
|
548
|
-
"batch_id": batch_id,
|
|
549
|
-
"item_count": len(items),
|
|
550
|
-
"processed_items": processed_items,
|
|
551
|
-
"processing_time": processing_time
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
# 准备测试数据
|
|
555
|
-
print("准备批处理数据...")
|
|
556
|
-
all_data = list(range(100)) # 100个数据项
|
|
557
|
-
|
|
558
|
-
# 分成多个批次
|
|
559
|
-
batch_size = 15
|
|
560
|
-
batches = [all_data[i:i+batch_size] for i in range(0, len(all_data), batch_size)]
|
|
561
|
-
|
|
562
|
-
print(f"数据分为 {len(batches)} 个批次,每批最多 {batch_size} 项")
|
|
563
|
-
|
|
564
|
-
# 并发处理所有批次
|
|
565
|
-
start_time = time.time()
|
|
566
|
-
batch_tasks = [process_batch(i, batch) for i, batch in enumerate(batches)]
|
|
567
|
-
results = await asyncio.gather(*batch_tasks)
|
|
568
|
-
total_time = time.time() - start_time
|
|
569
|
-
|
|
570
|
-
# 汇总结果
|
|
571
|
-
total_items = sum(r["item_count"] for r in results)
|
|
572
|
-
avg_batch_time = sum(r["processing_time"] for r in results) / len(results)
|
|
573
|
-
throughput = total_items / total_time
|
|
574
|
-
|
|
575
|
-
print(f"\\n批处理完成:")
|
|
576
|
-
print(f"总批次数: {len(results)}")
|
|
577
|
-
print(f"总项目数: {total_items}")
|
|
578
|
-
print(f"总耗时: {total_time:.3f}s")
|
|
579
|
-
print(f"平均批次耗时: {avg_batch_time:.3f}s")
|
|
580
|
-
print(f"处理吞吐量: {throughput:.1f} items/s")
|
|
581
|
-
|
|
582
|
-
{
|
|
583
|
-
"total_batches": len(results),
|
|
584
|
-
"total_items": total_items,
|
|
585
|
-
"total_time": total_time,
|
|
586
|
-
"avg_batch_time": avg_batch_time,
|
|
587
|
-
"throughput": throughput,
|
|
588
|
-
"efficiency": avg_batch_time / total_time * len(results) # 并发效率指标
|
|
589
|
-
}
|
|
590
|
-
"""
|
|
591
|
-
|
|
592
|
-
execution = await self.sandbox.run_code(code, language="python")
|
|
593
|
-
assert execution.error is None
|
|
594
|
-
assert any("批处理完成" in line for line in execution.logs.stdout)
|
|
595
|
-
|
|
596
|
-
# ======================== 异步错误处理测试 ========================
|
|
597
|
-
|
|
598
|
-
async def test_async_error_handling(self):
|
|
599
|
-
"""测试异步错误处理"""
|
|
600
|
-
assert self.sandbox is not None
|
|
601
|
-
|
|
602
|
-
error_captured = []
|
|
603
|
-
|
|
604
|
-
async def async_error_callback(error: ExecutionError):
|
|
605
|
-
error_captured.append(error)
|
|
606
|
-
logger.info(f"捕获异步错误: {error.name} - {error.value}")
|
|
607
|
-
|
|
608
|
-
# 测试异步错误
|
|
609
|
-
error_code = """
|
|
610
|
-
import asyncio
|
|
611
|
-
|
|
612
|
-
async def failing_task():
|
|
613
|
-
print("开始可能失败的异步任务")
|
|
614
|
-
await asyncio.sleep(0.1)
|
|
615
|
-
|
|
616
|
-
# 这里会产生一个错误
|
|
617
|
-
result = 10 / 0 # 除零错误
|
|
618
|
-
return result
|
|
619
|
-
|
|
620
|
-
async def error_handler_demo():
|
|
621
|
-
try:
|
|
622
|
-
result = await failing_task()
|
|
623
|
-
return result
|
|
624
|
-
except Exception as e:
|
|
625
|
-
print(f"在异步函数中捕获错误: {type(e).__name__}: {e}")
|
|
626
|
-
raise # 重新抛出错误
|
|
627
|
-
|
|
628
|
-
# 执行会产生错误的异步代码
|
|
629
|
-
await error_handler_demo()
|
|
630
|
-
"""
|
|
631
|
-
|
|
632
|
-
execution = await self.sandbox.run_code(
|
|
633
|
-
error_code, language="python", on_error=async_error_callback
|
|
634
|
-
)
|
|
635
|
-
assert execution.error is not None
|
|
636
|
-
assert "ZeroDivisionError" in execution.error.name
|
|
637
|
-
logger.info("Async error handling test passed")
|
|
638
|
-
|
|
639
|
-
# ======================== 异步结果格式测试 ========================
|
|
640
|
-
|
|
641
|
-
async def test_async_text_result(self):
|
|
642
|
-
"""测试异步文本格式结果"""
|
|
643
|
-
assert self.sandbox is not None
|
|
644
|
-
|
|
645
|
-
code = """
|
|
646
|
-
import asyncio
|
|
647
|
-
|
|
648
|
-
# 异步生成纯文本结果
|
|
649
|
-
async def generate_async_text():
|
|
650
|
-
await asyncio.sleep(0.1) # 模拟异步操作
|
|
651
|
-
|
|
652
|
-
text_content = '''
|
|
653
|
-
异步 CodeInterpreter 测试报告
|
|
654
|
-
===================================
|
|
655
|
-
|
|
656
|
-
执行类型: 异步执行
|
|
657
|
-
开始时间: 2024-09-17 10:30:00
|
|
658
|
-
执行状态: ✅ 异步成功
|
|
659
|
-
|
|
660
|
-
异步特性验证:
|
|
661
|
-
- 支持 async/await 语法
|
|
662
|
-
- 并发任务处理能力
|
|
663
|
-
- 异步回调机制
|
|
664
|
-
- 上下文状态管理
|
|
665
|
-
|
|
666
|
-
详细描述:
|
|
667
|
-
异步CodeInterpreter能够高效处理并发任务,
|
|
668
|
-
支持复杂的异步工作流程,提供出色的性能表现。
|
|
669
|
-
'''
|
|
670
|
-
return text_content
|
|
671
|
-
|
|
672
|
-
text_result = await generate_async_text()
|
|
673
|
-
print("生成异步文本格式结果")
|
|
674
|
-
text_result
|
|
675
|
-
"""
|
|
676
|
-
|
|
677
|
-
execution = await self.sandbox.run_code(code, language="python")
|
|
678
|
-
assert execution.error is None
|
|
679
|
-
assert len(execution.results) > 0
|
|
680
|
-
logger.info("异步文本格式结果测试完成")
|
|
681
|
-
|
|
682
|
-
async def test_async_mixed_format_result(self):
|
|
683
|
-
"""测试异步混合格式结果"""
|
|
684
|
-
assert self.sandbox is not None
|
|
685
|
-
|
|
686
|
-
code = """
|
|
687
|
-
import asyncio
|
|
688
|
-
import json
|
|
689
|
-
import base64
|
|
690
|
-
import matplotlib.pyplot as plt
|
|
691
|
-
import numpy as np
|
|
692
|
-
import io
|
|
693
|
-
|
|
694
|
-
async def generate_async_mixed_results():
|
|
695
|
-
print("开始异步生成混合格式结果...")
|
|
696
|
-
|
|
697
|
-
# 1. 异步文本摘要
|
|
698
|
-
await asyncio.sleep(0.05)
|
|
699
|
-
text_summary = '''
|
|
700
|
-
异步 CodeInterpreter 综合测试报告
|
|
701
|
-
=====================================
|
|
702
|
-
|
|
703
|
-
执行模式: 异步并发
|
|
704
|
-
完成时间: 2024-09-17 10:30:00
|
|
705
|
-
并发任务: 8个
|
|
706
|
-
整体状态: ✅ 异步成功
|
|
707
|
-
|
|
708
|
-
异步特性亮点:
|
|
709
|
-
- 高并发处理能力
|
|
710
|
-
- 异步资源管理
|
|
711
|
-
- 事件驱动架构
|
|
712
|
-
- 非阻塞I/O操作
|
|
713
|
-
'''
|
|
714
|
-
|
|
715
|
-
# 2. 异步HTML报告生成
|
|
716
|
-
await asyncio.sleep(0.05)
|
|
717
|
-
html_report = '''
|
|
718
|
-
<div class="async-result-report">
|
|
719
|
-
<h2>⚡ 异步 CodeInterpreter 测试完成</h2>
|
|
720
|
-
<div class="status-badge async-success">🚀 异步全部通过</div>
|
|
721
|
-
<div class="async-metrics">
|
|
722
|
-
<div class="metric">
|
|
723
|
-
<label>并发任务:</label>
|
|
724
|
-
<value>8个</value>
|
|
725
|
-
</div>
|
|
726
|
-
<div class="metric">
|
|
727
|
-
<label>平均延迟:</label>
|
|
728
|
-
<value>0.123s</value>
|
|
729
|
-
</div>
|
|
730
|
-
<div class="metric">
|
|
731
|
-
<label>吞吐量:</label>
|
|
732
|
-
<value>65 ops/s</value>
|
|
733
|
-
</div>
|
|
734
|
-
</div>
|
|
735
|
-
</div>
|
|
736
|
-
'''
|
|
737
|
-
|
|
738
|
-
# 3. 异步生成图表数据
|
|
739
|
-
await asyncio.sleep(0.05)
|
|
740
|
-
|
|
741
|
-
# 并发生成多个数据集
|
|
742
|
-
async def generate_chart_data(chart_type):
|
|
743
|
-
await asyncio.sleep(0.02)
|
|
744
|
-
if chart_type == "performance":
|
|
745
|
-
return {
|
|
746
|
-
"type": "line",
|
|
747
|
-
"title": "异步性能趋势",
|
|
748
|
-
"data": {
|
|
749
|
-
"labels": ["Task1", "Task2", "Task3", "Task4", "Task5"],
|
|
750
|
-
"values": [92, 95, 88, 97, 94]
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
elif chart_type == "concurrency":
|
|
754
|
-
return {
|
|
755
|
-
"type": "bar",
|
|
756
|
-
"title": "并发执行统计",
|
|
757
|
-
"data": {
|
|
758
|
-
"labels": ["1并发", "2并发", "4并发", "8并发"],
|
|
759
|
-
"values": [45, 78, 142, 256]
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
# 并发生成图表数据
|
|
764
|
-
chart_tasks = [
|
|
765
|
-
generate_chart_data("performance"),
|
|
766
|
-
generate_chart_data("concurrency")
|
|
767
|
-
]
|
|
768
|
-
chart_data_list = await asyncio.gather(*chart_tasks)
|
|
769
|
-
|
|
770
|
-
# 4. 异步JSON数据编译
|
|
771
|
-
await asyncio.sleep(0.05)
|
|
772
|
-
json_data = {
|
|
773
|
-
"async_execution": {
|
|
774
|
-
"mode": "concurrent",
|
|
775
|
-
"tasks_completed": 8,
|
|
776
|
-
"success_rate": 100.0,
|
|
777
|
-
"avg_response_time": 0.123
|
|
778
|
-
},
|
|
779
|
-
"performance_summary": {
|
|
780
|
-
"throughput": 65,
|
|
781
|
-
"peak_concurrency": 8,
|
|
782
|
-
"memory_efficient": True,
|
|
783
|
-
"cpu_utilization": "optimal"
|
|
784
|
-
},
|
|
785
|
-
"async_features": [
|
|
786
|
-
"异步任务调度",
|
|
787
|
-
"并发资源管理",
|
|
788
|
-
"事件循环优化",
|
|
789
|
-
"非阻塞I/O处理"
|
|
790
|
-
],
|
|
791
|
-
"charts": chart_data_list
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
# 5. 异步Markdown生成
|
|
795
|
-
await asyncio.sleep(0.05)
|
|
796
|
-
markdown_content = '''
|
|
797
|
-
## ⚡ 异步 CodeInterpreter 测试总结
|
|
798
|
-
|
|
799
|
-
### 🎯 异步执行成就
|
|
800
|
-
- **完美并发**: 8个任务同时执行
|
|
801
|
-
- **零阻塞**: 所有I/O操作非阻塞
|
|
802
|
-
- **高吞吐量**: 65 操作/秒
|
|
803
|
-
- **资源高效**: CPU和内存使用最优
|
|
804
|
-
|
|
805
|
-
### 📊 并发性能指标
|
|
806
|
-
| 并发级别 | 吞吐量 | 响应时间 | 资源使用 |
|
|
807
|
-
|---------|--------|----------|----------|
|
|
808
|
-
| 1 | 45 ops/s | 0.022s | 低 |
|
|
809
|
-
| 2 | 78 ops/s | 0.025s | 低 |
|
|
810
|
-
| 4 | 142 ops/s | 0.028s | 中 |
|
|
811
|
-
| 8 | 256 ops/s | 0.031s | 中 |
|
|
812
|
-
|
|
813
|
-
### 🚀 异步优势
|
|
814
|
-
1. **事件驱动**: 基于事件循环的高效调度
|
|
815
|
-
2. **资源节约**: 单线程处理多任务
|
|
816
|
-
3. **扩展性强**: 轻松应对高并发场景
|
|
817
|
-
'''
|
|
818
|
-
|
|
819
|
-
print("异步混合格式结果生成完成!")
|
|
820
|
-
|
|
821
|
-
return {
|
|
822
|
-
"formats": ["text", "html", "json", "markdown", "chart"],
|
|
823
|
-
"text": text_summary,
|
|
824
|
-
"html": html_report,
|
|
825
|
-
"json_data": json_data,
|
|
826
|
-
"markdown": markdown_content,
|
|
827
|
-
"charts": chart_data_list,
|
|
828
|
-
"async_summary": {
|
|
829
|
-
"total_formats": 5,
|
|
830
|
-
"concurrent_tasks": 8,
|
|
831
|
-
"execution_mode": "async",
|
|
832
|
-
"performance": "excellent"
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
# 执行异步混合格式生成
|
|
837
|
-
result = await generate_async_mixed_results()
|
|
838
|
-
result
|
|
839
|
-
"""
|
|
840
|
-
|
|
841
|
-
execution = await self.sandbox.run_code(code, language="python")
|
|
842
|
-
assert execution.error is None
|
|
843
|
-
assert any("异步混合格式结果生成完成" in line for line in execution.logs.stdout)
|
|
844
|
-
logger.info("异步混合格式结果测试完成")
|
|
845
|
-
|
|
846
|
-
async def test_async_realtime_data_result(self):
|
|
847
|
-
"""测试异步实时数据结果"""
|
|
848
|
-
assert self.sandbox is not None
|
|
849
|
-
|
|
850
|
-
code = """
|
|
851
|
-
import asyncio
|
|
852
|
-
import json
|
|
853
|
-
import time
|
|
854
|
-
from datetime import datetime
|
|
855
|
-
|
|
856
|
-
class AsyncDataStream:
|
|
857
|
-
def __init__(self):
|
|
858
|
-
self.data_points = []
|
|
859
|
-
self.subscribers = []
|
|
860
|
-
|
|
861
|
-
async def generate_data_point(self, index):
|
|
862
|
-
'''异步生成单个数据点'''
|
|
863
|
-
await asyncio.sleep(0.02) # 模拟数据采集延迟
|
|
864
|
-
|
|
865
|
-
data_point = {
|
|
866
|
-
"id": index,
|
|
867
|
-
"timestamp": datetime.now().isoformat(),
|
|
868
|
-
"value": 50 + 25 * (0.5 - __import__('random').random()),
|
|
869
|
-
"status": "active",
|
|
870
|
-
"metadata": {
|
|
871
|
-
"source": f"sensor_{index % 4}",
|
|
872
|
-
"quality": __import__('random').choice(["high", "medium", "high", "high"])
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
return data_point
|
|
876
|
-
|
|
877
|
-
async def collect_realtime_data(self, duration_seconds=1):
|
|
878
|
-
'''异步收集实时数据流'''
|
|
879
|
-
print(f"开始 {duration_seconds}s 实时数据收集...")
|
|
880
|
-
|
|
881
|
-
start_time = time.time()
|
|
882
|
-
data_tasks = []
|
|
883
|
-
|
|
884
|
-
# 创建数据收集任务
|
|
885
|
-
for i in range(20): # 收集20个数据点
|
|
886
|
-
task = asyncio.create_task(self.generate_data_point(i))
|
|
887
|
-
data_tasks.append(task)
|
|
888
|
-
await asyncio.sleep(0.05) # 每50ms启动一个任务
|
|
889
|
-
|
|
890
|
-
# 并发等待所有数据收集完成
|
|
891
|
-
collected_data = await asyncio.gather(*data_tasks)
|
|
892
|
-
collection_time = time.time() - start_time
|
|
893
|
-
|
|
894
|
-
print(f"数据收集完成,耗时: {collection_time:.3f}s")
|
|
895
|
-
|
|
896
|
-
return {
|
|
897
|
-
"data_points": collected_data,
|
|
898
|
-
"collection_time": collection_time,
|
|
899
|
-
"total_points": len(collected_data),
|
|
900
|
-
"throughput": len(collected_data) / collection_time
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
async def process_data_stream(self, raw_data):
|
|
904
|
-
'''异步处理数据流'''
|
|
905
|
-
print("开始异步数据流处理...")
|
|
906
|
-
|
|
907
|
-
# 并发处理不同的数据分析任务
|
|
908
|
-
async def calculate_statistics():
|
|
909
|
-
await asyncio.sleep(0.1)
|
|
910
|
-
values = [dp["value"] for dp in raw_data["data_points"]]
|
|
911
|
-
return {
|
|
912
|
-
"mean": sum(values) / len(values),
|
|
913
|
-
"min": min(values),
|
|
914
|
-
"max": max(values),
|
|
915
|
-
"count": len(values)
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
async def analyze_quality():
|
|
919
|
-
await asyncio.sleep(0.08)
|
|
920
|
-
quality_counts = {}
|
|
921
|
-
for dp in raw_data["data_points"]:
|
|
922
|
-
quality = dp["metadata"]["quality"]
|
|
923
|
-
quality_counts[quality] = quality_counts.get(quality, 0) + 1
|
|
924
|
-
return quality_counts
|
|
925
|
-
|
|
926
|
-
async def detect_anomalies():
|
|
927
|
-
await asyncio.sleep(0.06)
|
|
928
|
-
values = [dp["value"] for dp in raw_data["data_points"]]
|
|
929
|
-
mean_val = sum(values) / len(values)
|
|
930
|
-
threshold = 20 # 异常阈值
|
|
931
|
-
|
|
932
|
-
anomalies = []
|
|
933
|
-
for dp in raw_data["data_points"]:
|
|
934
|
-
if abs(dp["value"] - mean_val) > threshold:
|
|
935
|
-
anomalies.append({
|
|
936
|
-
"id": dp["id"],
|
|
937
|
-
"value": dp["value"],
|
|
938
|
-
"deviation": abs(dp["value"] - mean_val)
|
|
939
|
-
})
|
|
940
|
-
return anomalies
|
|
941
|
-
|
|
942
|
-
# 并发执行所有分析任务
|
|
943
|
-
stats, quality, anomalies = await asyncio.gather(
|
|
944
|
-
calculate_statistics(),
|
|
945
|
-
analyze_quality(),
|
|
946
|
-
detect_anomalies()
|
|
947
|
-
)
|
|
948
|
-
|
|
949
|
-
return {
|
|
950
|
-
"statistics": stats,
|
|
951
|
-
"quality_distribution": quality,
|
|
952
|
-
"anomalies": anomalies,
|
|
953
|
-
"processed_at": datetime.now().isoformat()
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
# 运行异步实时数据收集和处理
|
|
957
|
-
print("启动异步实时数据系统...")
|
|
958
|
-
stream = AsyncDataStream()
|
|
959
|
-
|
|
960
|
-
# 收集数据
|
|
961
|
-
raw_data = await stream.collect_realtime_data(1)
|
|
962
|
-
print(f"收集了 {raw_data['total_points']} 个数据点")
|
|
963
|
-
print(f"数据吞吐量: {raw_data['throughput']:.1f} points/s")
|
|
964
|
-
|
|
965
|
-
# 处理数据
|
|
966
|
-
processed_data = await stream.process_data_stream(raw_data)
|
|
967
|
-
print(f"\\n数据处理结果:")
|
|
968
|
-
print(f" 平均值: {processed_data['statistics']['mean']:.2f}")
|
|
969
|
-
print(f" 数据质量分布: {processed_data['quality_distribution']}")
|
|
970
|
-
print(f" 异常数据点: {len(processed_data['anomalies'])} 个")
|
|
971
|
-
|
|
972
|
-
# 生成实时数据结果
|
|
973
|
-
result = {
|
|
974
|
-
"realtime_data": {
|
|
975
|
-
"collection_summary": {
|
|
976
|
-
"total_points": raw_data['total_points'],
|
|
977
|
-
"collection_time": raw_data['collection_time'],
|
|
978
|
-
"throughput": raw_data['throughput']
|
|
979
|
-
},
|
|
980
|
-
"data_analysis": processed_data,
|
|
981
|
-
"raw_samples": raw_data['data_points'][:5], # 显示前5个样本
|
|
982
|
-
"system_performance": {
|
|
983
|
-
"concurrent_tasks": 20,
|
|
984
|
-
"processing_efficiency": "高效",
|
|
985
|
-
"memory_usage": "优化",
|
|
986
|
-
"async_benefits": [
|
|
987
|
-
"非阻塞数据收集",
|
|
988
|
-
"并发数据处理",
|
|
989
|
-
"实时流式计算",
|
|
990
|
-
"资源高效利用"
|
|
991
|
-
]
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
print(f"\\n异步实时数据系统测试完成!")
|
|
997
|
-
result
|
|
998
|
-
"""
|
|
999
|
-
|
|
1000
|
-
execution = await self.sandbox.run_code(code, language="python")
|
|
1001
|
-
assert execution.error is None
|
|
1002
|
-
assert any("异步实时数据系统测试完成" in line for line in execution.logs.stdout)
|
|
1003
|
-
logger.info("异步实时数据结果测试完成")
|
|
1004
|
-
|
|
1005
|
-
# ======================== 异步R语言测试 ========================
|
|
1006
|
-
|
|
1007
|
-
async def test_async_r_language_basic_execution(self):
|
|
1008
|
-
"""测试异步R语言基础执行"""
|
|
1009
|
-
assert self.sandbox is not None
|
|
1010
|
-
|
|
1011
|
-
code = """
|
|
1012
|
-
# 异步R语言基础执行测试
|
|
1013
|
-
print("Hello from Async R Language!")
|
|
1014
|
-
|
|
1015
|
-
# 基础数学运算
|
|
1016
|
-
x <- 15
|
|
1017
|
-
y <- 25
|
|
1018
|
-
sum_result <- x + y
|
|
1019
|
-
product_result <- x * y
|
|
1020
|
-
|
|
1021
|
-
print(paste("Sum:", sum_result))
|
|
1022
|
-
print(paste("Product:", product_result))
|
|
1023
|
-
|
|
1024
|
-
# 向量操作
|
|
1025
|
-
numbers <- c(2, 4, 6, 8, 10)
|
|
1026
|
-
mean_value <- mean(numbers)
|
|
1027
|
-
print(paste("Mean of numbers:", mean_value))
|
|
1028
|
-
|
|
1029
|
-
# 数据框创建
|
|
1030
|
-
df <- data.frame(
|
|
1031
|
-
name = c("David", "Emma", "Frank"),
|
|
1032
|
-
age = c(28, 32, 26),
|
|
1033
|
-
city = c("Paris", "Berlin", "Madrid")
|
|
1034
|
-
)
|
|
1035
|
-
|
|
1036
|
-
print("Data frame created:")
|
|
1037
|
-
print(df)
|
|
1038
|
-
|
|
1039
|
-
# 返回结果
|
|
1040
|
-
list(
|
|
1041
|
-
sum = sum_result,
|
|
1042
|
-
product = product_result,
|
|
1043
|
-
mean = mean_value,
|
|
1044
|
-
data_frame = df
|
|
1045
|
-
)
|
|
1046
|
-
"""
|
|
1047
|
-
|
|
1048
|
-
execution = await self.sandbox.run_code(code, language="r")
|
|
1049
|
-
assert execution.error is None
|
|
1050
|
-
assert any(
|
|
1051
|
-
"Hello from Async R Language!" in line for line in execution.logs.stdout
|
|
1052
|
-
)
|
|
1053
|
-
assert any("Sum:" in line for line in execution.logs.stdout)
|
|
1054
|
-
logger.info("Async R language basic execution test passed")
|
|
1055
|
-
|
|
1056
|
-
async def test_async_r_language_data_analysis(self):
|
|
1057
|
-
"""测试异步R语言数据分析"""
|
|
1058
|
-
assert self.sandbox is not None
|
|
1059
|
-
|
|
1060
|
-
code = """
|
|
1061
|
-
# 异步R语言数据分析测试
|
|
1062
|
-
library(dplyr)
|
|
1063
|
-
|
|
1064
|
-
# 创建示例数据集
|
|
1065
|
-
set.seed(456)
|
|
1066
|
-
data <- data.frame(
|
|
1067
|
-
id = 1:150,
|
|
1068
|
-
value = rnorm(150, mean = 60, sd = 20),
|
|
1069
|
-
category = sample(c("X", "Y", "Z"), 150, replace = TRUE),
|
|
1070
|
-
score = runif(150, 0, 100)
|
|
1071
|
-
)
|
|
1072
|
-
|
|
1073
|
-
print("Async dataset created with 150 rows")
|
|
1074
|
-
print(paste("Columns:", paste(names(data), collapse = ", ")))
|
|
1075
|
-
|
|
1076
|
-
# 基础统计
|
|
1077
|
-
summary_stats <- summary(data$value)
|
|
1078
|
-
print("Summary statistics for value column:")
|
|
1079
|
-
print(summary_stats)
|
|
1080
|
-
|
|
1081
|
-
# 按类别分组统计
|
|
1082
|
-
grouped_stats <- data %>%
|
|
1083
|
-
group_by(category) %>%
|
|
1084
|
-
summarise(
|
|
1085
|
-
count = n(),
|
|
1086
|
-
mean_value = mean(value),
|
|
1087
|
-
mean_score = mean(score),
|
|
1088
|
-
.groups = 'drop'
|
|
1089
|
-
)
|
|
1090
|
-
|
|
1091
|
-
print("Grouped statistics:")
|
|
1092
|
-
print(grouped_stats)
|
|
1093
|
-
|
|
1094
|
-
# 数据过滤
|
|
1095
|
-
high_scores <- data %>%
|
|
1096
|
-
filter(score > 85) %>%
|
|
1097
|
-
arrange(desc(score))
|
|
1098
|
-
|
|
1099
|
-
print(paste("High scores (>85):", nrow(high_scores), "rows"))
|
|
1100
|
-
|
|
1101
|
-
# 返回分析结果
|
|
1102
|
-
list(
|
|
1103
|
-
total_rows = nrow(data),
|
|
1104
|
-
summary = summary_stats,
|
|
1105
|
-
grouped = grouped_stats,
|
|
1106
|
-
high_scores_count = nrow(high_scores)
|
|
1107
|
-
)
|
|
1108
|
-
"""
|
|
1109
|
-
|
|
1110
|
-
execution = await self.sandbox.run_code(code, language="r")
|
|
1111
|
-
assert execution.error is None
|
|
1112
|
-
assert any(
|
|
1113
|
-
"Async dataset created with 150 rows" in line
|
|
1114
|
-
for line in execution.logs.stdout
|
|
1115
|
-
)
|
|
1116
|
-
assert any("Summary statistics" in line for line in execution.logs.stdout)
|
|
1117
|
-
logger.info("Async R language data analysis test passed")
|
|
1118
|
-
|
|
1119
|
-
async def test_async_r_language_visualization(self):
|
|
1120
|
-
"""测试异步R语言数据可视化"""
|
|
1121
|
-
assert self.sandbox is not None
|
|
1122
|
-
|
|
1123
|
-
code = """
|
|
1124
|
-
# 异步R语言数据可视化测试
|
|
1125
|
-
library(ggplot2)
|
|
1126
|
-
|
|
1127
|
-
# 创建示例数据
|
|
1128
|
-
set.seed(789)
|
|
1129
|
-
plot_data <- data.frame(
|
|
1130
|
-
x = 1:60,
|
|
1131
|
-
y = cumsum(rnorm(60)),
|
|
1132
|
-
group = rep(c("GroupA", "GroupB", "GroupC"), each = 20)
|
|
1133
|
-
)
|
|
1134
|
-
|
|
1135
|
-
print("Creating async visualizations...")
|
|
1136
|
-
|
|
1137
|
-
# 基础散点图
|
|
1138
|
-
p1 <- ggplot(plot_data, aes(x = x, y = y)) +
|
|
1139
|
-
geom_point() +
|
|
1140
|
-
geom_smooth(method = "lm") +
|
|
1141
|
-
labs(title = "Async Scatter Plot with Trend Line",
|
|
1142
|
-
x = "X Values", y = "Y Values") +
|
|
1143
|
-
theme_minimal()
|
|
1144
|
-
|
|
1145
|
-
print("Async scatter plot created")
|
|
1146
|
-
|
|
1147
|
-
# 分组箱线图
|
|
1148
|
-
p2 <- ggplot(plot_data, aes(x = group, y = y, fill = group)) +
|
|
1149
|
-
geom_boxplot() +
|
|
1150
|
-
labs(title = "Async Box Plot by Group",
|
|
1151
|
-
x = "Group", y = "Y Values") +
|
|
1152
|
-
theme_minimal()
|
|
1153
|
-
|
|
1154
|
-
print("Async box plot created")
|
|
1155
|
-
|
|
1156
|
-
# 直方图
|
|
1157
|
-
p3 <- ggplot(plot_data, aes(x = y)) +
|
|
1158
|
-
geom_histogram(bins = 25, fill = "lightcoral", alpha = 0.7) +
|
|
1159
|
-
labs(title = "Async Distribution of Y Values",
|
|
1160
|
-
x = "Y Values", y = "Frequency") +
|
|
1161
|
-
theme_minimal()
|
|
1162
|
-
|
|
1163
|
-
print("Async histogram created")
|
|
1164
|
-
|
|
1165
|
-
# 保存图表信息
|
|
1166
|
-
plot_info <- list(
|
|
1167
|
-
scatter_plot = "Created async scatter plot with trend line",
|
|
1168
|
-
box_plot = "Created async box plot by group",
|
|
1169
|
-
histogram = "Created async histogram of y values",
|
|
1170
|
-
total_plots = 3
|
|
1171
|
-
)
|
|
1172
|
-
|
|
1173
|
-
print("All async visualizations completed successfully")
|
|
1174
|
-
plot_info
|
|
1175
|
-
"""
|
|
1176
|
-
|
|
1177
|
-
execution = await self.sandbox.run_code(code, language="r")
|
|
1178
|
-
assert execution.error is None
|
|
1179
|
-
assert any(
|
|
1180
|
-
"Creating async visualizations..." in line for line in execution.logs.stdout
|
|
1181
|
-
)
|
|
1182
|
-
assert any(
|
|
1183
|
-
"All async visualizations completed successfully" in line
|
|
1184
|
-
for line in execution.logs.stdout
|
|
1185
|
-
)
|
|
1186
|
-
logger.info("Async R language visualization test passed")
|
|
1187
|
-
|
|
1188
|
-
async def test_async_r_language_statistics(self):
|
|
1189
|
-
"""测试异步R语言统计分析"""
|
|
1190
|
-
assert self.sandbox is not None
|
|
1191
|
-
|
|
1192
|
-
code = """
|
|
1193
|
-
# 异步R语言统计分析测试
|
|
1194
|
-
library(stats)
|
|
1195
|
-
|
|
1196
|
-
# 创建两个样本数据
|
|
1197
|
-
set.seed(101112)
|
|
1198
|
-
sample1 <- rnorm(120, mean = 15, sd = 3)
|
|
1199
|
-
sample2 <- rnorm(120, mean = 18, sd = 3.5)
|
|
1200
|
-
|
|
1201
|
-
print("Created two async sample datasets")
|
|
1202
|
-
|
|
1203
|
-
# 描述性统计
|
|
1204
|
-
desc_stats1 <- list(
|
|
1205
|
-
mean = mean(sample1),
|
|
1206
|
-
median = median(sample1),
|
|
1207
|
-
sd = sd(sample1),
|
|
1208
|
-
min = min(sample1),
|
|
1209
|
-
max = max(sample1)
|
|
1210
|
-
)
|
|
1211
|
-
|
|
1212
|
-
desc_stats2 <- list(
|
|
1213
|
-
mean = mean(sample2),
|
|
1214
|
-
median = median(sample2),
|
|
1215
|
-
sd = sd(sample2),
|
|
1216
|
-
min = min(sample2),
|
|
1217
|
-
max = max(sample2)
|
|
1218
|
-
)
|
|
1219
|
-
|
|
1220
|
-
print("Async descriptive statistics calculated")
|
|
1221
|
-
|
|
1222
|
-
# t检验
|
|
1223
|
-
t_test_result <- t.test(sample1, sample2)
|
|
1224
|
-
print("Async T-test performed")
|
|
1225
|
-
|
|
1226
|
-
# 相关性分析
|
|
1227
|
-
correlation <- cor(sample1, sample2)
|
|
1228
|
-
print(paste("Async correlation coefficient:", round(correlation, 4)))
|
|
1229
|
-
|
|
1230
|
-
# 线性回归
|
|
1231
|
-
lm_model <- lm(sample2 ~ sample1)
|
|
1232
|
-
summary_lm <- summary(lm_model)
|
|
1233
|
-
print("Async linear regression model fitted")
|
|
1234
|
-
|
|
1235
|
-
# 正态性检验
|
|
1236
|
-
shapiro_test1 <- shapiro.test(sample1[1:50]) # 限制样本大小
|
|
1237
|
-
shapiro_test2 <- shapiro.test(sample2[1:50])
|
|
1238
|
-
|
|
1239
|
-
print("Async normality tests performed")
|
|
1240
|
-
|
|
1241
|
-
# 返回统计结果
|
|
1242
|
-
list(
|
|
1243
|
-
sample1_stats = desc_stats1,
|
|
1244
|
-
sample2_stats = desc_stats2,
|
|
1245
|
-
t_test_p_value = t_test_result$p.value,
|
|
1246
|
-
correlation = correlation,
|
|
1247
|
-
r_squared = summary_lm$r.squared,
|
|
1248
|
-
normality_test1_p = shapiro_test1$p.value,
|
|
1249
|
-
normality_test2_p = shapiro_test2$p.value
|
|
1250
|
-
)
|
|
1251
|
-
"""
|
|
1252
|
-
|
|
1253
|
-
execution = await self.sandbox.run_code(code, language="r")
|
|
1254
|
-
assert execution.error is None
|
|
1255
|
-
assert any(
|
|
1256
|
-
"Created two async sample datasets" in line
|
|
1257
|
-
for line in execution.logs.stdout
|
|
1258
|
-
)
|
|
1259
|
-
assert any("Async T-test performed" in line for line in execution.logs.stdout)
|
|
1260
|
-
logger.info("Async R language statistics test passed")
|
|
1261
|
-
|
|
1262
|
-
async def test_async_r_language_context_management(self):
|
|
1263
|
-
"""测试异步R语言上下文管理"""
|
|
1264
|
-
assert self.sandbox is not None
|
|
1265
|
-
|
|
1266
|
-
# 创建R语言上下文
|
|
1267
|
-
r_context = await self.sandbox.create_code_context(language="r", cwd="/tmp")
|
|
1268
|
-
self.contexts["async_r_language"] = r_context
|
|
1269
|
-
|
|
1270
|
-
# 在上下文中定义变量和函数
|
|
1271
|
-
setup_code = """
|
|
1272
|
-
# 异步R语言上下文设置
|
|
1273
|
-
print("Setting up async R language context...")
|
|
1274
|
-
|
|
1275
|
-
# 定义全局变量
|
|
1276
|
-
global_var <- "Hello from Async R Context"
|
|
1277
|
-
counter <- 0
|
|
1278
|
-
data_cache <- list()
|
|
1279
|
-
|
|
1280
|
-
# 定义函数
|
|
1281
|
-
increment_counter <- function() {
|
|
1282
|
-
counter <<- counter + 1
|
|
1283
|
-
return(counter)
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1286
|
-
add_to_cache <- function(key, value) {
|
|
1287
|
-
data_cache[[key]] <<- value
|
|
1288
|
-
return(length(data_cache))
|
|
1289
|
-
}
|
|
1290
|
-
|
|
1291
|
-
# 初始化一些数据
|
|
1292
|
-
sample_data <- data.frame(
|
|
1293
|
-
x = 1:15,
|
|
1294
|
-
y = (1:15) ^ 2
|
|
1295
|
-
)
|
|
1296
|
-
|
|
1297
|
-
print(paste("Async context setup complete. Counter:", counter))
|
|
1298
|
-
print(paste("Cache size:", length(data_cache)))
|
|
1299
|
-
|
|
1300
|
-
# 返回设置信息
|
|
1301
|
-
list(
|
|
1302
|
-
global_var = global_var,
|
|
1303
|
-
counter = counter,
|
|
1304
|
-
cache_size = length(data_cache),
|
|
1305
|
-
data_rows = nrow(sample_data)
|
|
1306
|
-
)
|
|
1307
|
-
"""
|
|
1308
|
-
|
|
1309
|
-
execution1 = await self.sandbox.run_code(setup_code, context=r_context)
|
|
1310
|
-
assert execution1.error is None
|
|
1311
|
-
assert any(
|
|
1312
|
-
"Setting up async R language context..." in line
|
|
1313
|
-
for line in execution1.logs.stdout
|
|
1314
|
-
)
|
|
1315
|
-
|
|
1316
|
-
# 在同一上下文中使用之前定义的变量和函数
|
|
1317
|
-
use_code = """
|
|
1318
|
-
# 使用异步R语言上下文中的变量和函数
|
|
1319
|
-
print("Using async R language context...")
|
|
1320
|
-
|
|
1321
|
-
# 使用全局变量
|
|
1322
|
-
print(paste("Global variable:", global_var))
|
|
1323
|
-
|
|
1324
|
-
# 使用函数
|
|
1325
|
-
new_counter <- increment_counter()
|
|
1326
|
-
print(paste("Counter after increment:", new_counter))
|
|
1327
|
-
|
|
1328
|
-
# 添加到缓存
|
|
1329
|
-
cache_size <- add_to_cache("async_test_key", "async_test_value")
|
|
1330
|
-
print(paste("Cache size after addition:", cache_size))
|
|
1331
|
-
|
|
1332
|
-
# 使用数据
|
|
1333
|
-
data_summary <- summary(sample_data)
|
|
1334
|
-
print("Data summary:")
|
|
1335
|
-
print(data_summary)
|
|
1336
|
-
|
|
1337
|
-
# 修改数据
|
|
1338
|
-
sample_data$z <- sample_data$x + sample_data$y
|
|
1339
|
-
print(paste("Added new column. Total columns:", ncol(sample_data)))
|
|
1340
|
-
|
|
1341
|
-
# 返回使用结果
|
|
1342
|
-
list(
|
|
1343
|
-
final_counter = new_counter,
|
|
1344
|
-
final_cache_size = cache_size,
|
|
1345
|
-
data_columns = ncol(sample_data),
|
|
1346
|
-
context_active = TRUE
|
|
1347
|
-
)
|
|
1348
|
-
"""
|
|
1349
|
-
|
|
1350
|
-
execution2 = await self.sandbox.run_code(use_code, context=r_context)
|
|
1351
|
-
assert execution2.error is None
|
|
1352
|
-
assert any(
|
|
1353
|
-
"Using async R language context..." in line
|
|
1354
|
-
for line in execution2.logs.stdout
|
|
1355
|
-
)
|
|
1356
|
-
assert any(
|
|
1357
|
-
"Counter after increment:" in line for line in execution2.logs.stdout
|
|
1358
|
-
)
|
|
1359
|
-
logger.info("Async R language context management test passed")
|
|
1360
|
-
|
|
1361
|
-
# 测试完成后立即清理context
|
|
1362
|
-
try:
|
|
1363
|
-
await self.sandbox.destroy_context(r_context)
|
|
1364
|
-
logger.info(f"Successfully destroyed async R context: {r_context.id}")
|
|
1365
|
-
# 从contexts字典中移除
|
|
1366
|
-
if "async_r_language" in self.contexts:
|
|
1367
|
-
del self.contexts["async_r_language"]
|
|
1368
|
-
except Exception as e:
|
|
1369
|
-
logger.warning(f"Failed to destroy async R context {r_context.id}: {e}")
|
|
1370
|
-
|
|
1371
|
-
# ======================== 异步Node.js/JavaScript 测试 ========================
|
|
1372
|
-
|
|
1373
|
-
async def test_async_nodejs_basic_execution(self):
|
|
1374
|
-
"""测试异步Node.js基础执行"""
|
|
1375
|
-
assert self.sandbox is not None
|
|
1376
|
-
|
|
1377
|
-
code = """
|
|
1378
|
-
// Node.js 基础执行(异步)
|
|
1379
|
-
console.log("Hello from Async Node.js Kernel!");
|
|
1380
|
-
const a = 11, b = 13;
|
|
1381
|
-
console.log(`Sum: ${a + b}`);
|
|
1382
|
-
console.log(`Product: ${a * b}`);
|
|
1383
|
-
({ sum: a + b, product: a * b })
|
|
1384
|
-
"""
|
|
1385
|
-
|
|
1386
|
-
execution = await self.sandbox.run_code(code, language="javascript")
|
|
1387
|
-
assert execution.error is None
|
|
1388
|
-
assert any(
|
|
1389
|
-
"Hello from Async Node.js Kernel!" in line for line in execution.logs.stdout
|
|
1390
|
-
)
|
|
1391
|
-
assert any("Sum:" in line for line in execution.logs.stdout)
|
|
1392
|
-
logger.info("Async Node.js basic execution test passed")
|
|
1393
|
-
|
|
1394
|
-
async def test_async_nodejs_async_promises(self):
|
|
1395
|
-
"""测试异步Node.js Promise/async"""
|
|
1396
|
-
assert self.sandbox is not None
|
|
1397
|
-
|
|
1398
|
-
code = """
|
|
1399
|
-
function delay(ms){ return new Promise(r=>setTimeout(r, ms)); }
|
|
1400
|
-
async function run(){
|
|
1401
|
-
console.log("Async tasks start");
|
|
1402
|
-
const t0 = Date.now();
|
|
1403
|
-
await delay(40);
|
|
1404
|
-
const res = await Promise.all([
|
|
1405
|
-
(async()=>{ await delay(15); return 21; })(),
|
|
1406
|
-
(async()=>{ await delay(25); return 21; })()
|
|
1407
|
-
]);
|
|
1408
|
-
const sum = res.reduce((a,b)=>a+b,0);
|
|
1409
|
-
const dt = Date.now()-t0;
|
|
1410
|
-
console.log(`Async tasks done in ${dt} ms`);
|
|
1411
|
-
return { sum, dt };
|
|
1412
|
-
}
|
|
1413
|
-
run();
|
|
1414
|
-
"""
|
|
1415
|
-
|
|
1416
|
-
execution = await self.sandbox.run_code(code, language="javascript")
|
|
1417
|
-
assert execution.error is None
|
|
1418
|
-
assert any("Async tasks start" in line for line in execution.logs.stdout)
|
|
1419
|
-
assert any("Async tasks done" in line for line in execution.logs.stdout)
|
|
1420
|
-
logger.info("Async Node.js promises test passed")
|
|
1421
|
-
|
|
1422
|
-
async def test_async_nodejs_data_processing(self):
|
|
1423
|
-
"""测试异步Node.js数据处理"""
|
|
1424
|
-
assert self.sandbox is not None
|
|
1425
|
-
|
|
1426
|
-
code = """
|
|
1427
|
-
const rows = Array.from({length: 120}, (_, i) => ({ id: i+1, value: Math.round(Math.random()*100), group: ['X','Y','Z'][i%3] }));
|
|
1428
|
-
const stats = rows.reduce((acc, r)=>{ if(!acc[r.group]) acc[r.group]={count:0,sum:0}; acc[r.group].count++; acc[r.group].sum+=r.value; return acc; }, {});
|
|
1429
|
-
const out = Object.entries(stats).map(([g,s])=>({ group: g, count: s.count, mean: s.sum/s.count }));
|
|
1430
|
-
console.log("Async grouped stats ready");
|
|
1431
|
-
({ total: rows.length, groups: out })
|
|
1432
|
-
"""
|
|
1433
|
-
|
|
1434
|
-
execution = await self.sandbox.run_code(code, language="javascript")
|
|
1435
|
-
assert execution.error is None
|
|
1436
|
-
assert any(
|
|
1437
|
-
"Async grouped stats ready" in line for line in execution.logs.stdout
|
|
1438
|
-
)
|
|
1439
|
-
logger.info("Async Node.js data processing test passed")
|
|
1440
|
-
|
|
1441
|
-
async def test_async_nodejs_chart_data(self):
|
|
1442
|
-
"""测试异步Node.js图表数据生成"""
|
|
1443
|
-
assert self.sandbox is not None
|
|
1444
|
-
|
|
1445
|
-
code = """
|
|
1446
|
-
const labels = Array.from({length: 5}, (_, i)=>`T${i+1}`);
|
|
1447
|
-
const values = labels.map(()=> Math.round(Math.random()*50+50));
|
|
1448
|
-
const chart = { type: 'bar', data: { labels, datasets: [{ label: 'Load', data: values, backgroundColor: '#1c7ed6' }] } };
|
|
1449
|
-
console.log("Async chart data generated");
|
|
1450
|
-
({ chart })
|
|
1451
|
-
"""
|
|
1452
|
-
|
|
1453
|
-
execution = await self.sandbox.run_code(code, language="javascript")
|
|
1454
|
-
assert execution.error is None
|
|
1455
|
-
assert any(
|
|
1456
|
-
"Async chart data generated" in line for line in execution.logs.stdout
|
|
1457
|
-
)
|
|
1458
|
-
assert len(execution.results) > 0
|
|
1459
|
-
logger.info("Async Node.js chart data test passed")
|
|
1460
|
-
|
|
1461
|
-
async def test_async_nodejs_context_management(self):
|
|
1462
|
-
"""测试异步Node.js上下文管理"""
|
|
1463
|
-
assert self.sandbox is not None
|
|
1464
|
-
|
|
1465
|
-
# 创建Node.js上下文
|
|
1466
|
-
js_context = await self.sandbox.create_code_context(
|
|
1467
|
-
language="javascript", cwd="/tmp"
|
|
1468
|
-
)
|
|
1469
|
-
self.contexts["async_nodejs"] = js_context
|
|
1470
|
-
|
|
1471
|
-
setup = """
|
|
1472
|
-
console.log("Setup async Node.js context");
|
|
1473
|
-
globalThis.state = { counter: 0 };
|
|
1474
|
-
function inc(){ globalThis.state.counter += 1; return globalThis.state.counter; }
|
|
1475
|
-
({ counter: globalThis.state.counter })
|
|
1476
|
-
"""
|
|
1477
|
-
|
|
1478
|
-
e1 = await self.sandbox.run_code(setup, context=js_context)
|
|
1479
|
-
assert e1.error is None
|
|
1480
|
-
assert any("Setup async Node.js context" in line for line in e1.logs.stdout)
|
|
1481
|
-
|
|
1482
|
-
use = """
|
|
1483
|
-
console.log("Use async Node.js context");
|
|
1484
|
-
const c1 = inc();
|
|
1485
|
-
const c2 = inc();
|
|
1486
|
-
({ after: c2 })
|
|
1487
|
-
"""
|
|
1488
|
-
|
|
1489
|
-
e2 = await self.sandbox.run_code(use, context=js_context)
|
|
1490
|
-
assert e2.error is None
|
|
1491
|
-
assert any("Use async Node.js context" in line for line in e2.logs.stdout)
|
|
1492
|
-
|
|
1493
|
-
# 清理上下文
|
|
1494
|
-
try:
|
|
1495
|
-
await self.sandbox.destroy_context(js_context)
|
|
1496
|
-
if "async_nodejs" in self.contexts:
|
|
1497
|
-
del self.contexts["async_nodejs"]
|
|
1498
|
-
logger.info("Destroyed async Node.js context")
|
|
1499
|
-
except Exception as e:
|
|
1500
|
-
logger.warning(f"Failed to destroy async Node.js context: {e}")
|
|
1501
|
-
|
|
1502
|
-
# ======================== 异步Bash 测试 ========================
|
|
1503
|
-
|
|
1504
|
-
async def test_async_bash_basic_execution(self):
|
|
1505
|
-
"""测试异步Bash基础执行"""
|
|
1506
|
-
assert self.sandbox is not None
|
|
1507
|
-
|
|
1508
|
-
code = """
|
|
1509
|
-
echo "Hello from Async Bash Kernel!"
|
|
1510
|
-
NAME="scalebox"
|
|
1511
|
-
echo "Hello, ${NAME}!"
|
|
1512
|
-
whoami
|
|
1513
|
-
date
|
|
1514
|
-
"""
|
|
1515
|
-
|
|
1516
|
-
execution = await self.sandbox.run_code(code, language="bash")
|
|
1517
|
-
assert execution.error is None
|
|
1518
|
-
assert any(
|
|
1519
|
-
"Hello from Async Bash Kernel!" in line for line in execution.logs.stdout
|
|
1520
|
-
)
|
|
1521
|
-
assert any("Hello, scalebox!" in line for line in execution.logs.stdout)
|
|
1522
|
-
logger.info("Async Bash basic execution test passed")
|
|
1523
|
-
|
|
1524
|
-
async def test_async_bash_file_operations(self):
|
|
1525
|
-
"""测试异步Bash文件操作"""
|
|
1526
|
-
assert self.sandbox is not None
|
|
1527
|
-
|
|
1528
|
-
code = """
|
|
1529
|
-
set -e
|
|
1530
|
-
WORKDIR="/tmp/abash_demo"
|
|
1531
|
-
mkdir -p "$WORKDIR"
|
|
1532
|
-
cd "$WORKDIR"
|
|
1533
|
-
echo "first" > one.txt
|
|
1534
|
-
echo "second" > two.txt
|
|
1535
|
-
cat one.txt two.txt > both.txt
|
|
1536
|
-
ls -l
|
|
1537
|
-
wc -l both.txt
|
|
1538
|
-
echo "ABASH_DONE"
|
|
1539
|
-
"""
|
|
1540
|
-
|
|
1541
|
-
execution = await self.sandbox.run_code(code, language="bash")
|
|
1542
|
-
assert execution.error is None
|
|
1543
|
-
assert any("ABASH_DONE" in line for line in execution.logs.stdout)
|
|
1544
|
-
logger.info("Async Bash file operations test passed")
|
|
1545
|
-
|
|
1546
|
-
async def test_async_bash_pipelines_and_grep(self):
|
|
1547
|
-
"""测试异步Bash管道与grep"""
|
|
1548
|
-
assert self.sandbox is not None
|
|
1549
|
-
|
|
1550
|
-
code = """
|
|
1551
|
-
printf "%s\n" a b a c a | grep -n "a" | awk -F: '{print "row", $1, ":", $2}'
|
|
1552
|
-
echo "ABASH_PIPE_OK"
|
|
1553
|
-
"""
|
|
1554
|
-
|
|
1555
|
-
execution = await self.sandbox.run_code(code, language="bash")
|
|
1556
|
-
assert execution.error is None
|
|
1557
|
-
assert any("ABASH_PIPE_OK" in line for line in execution.logs.stdout)
|
|
1558
|
-
logger.info("Async Bash pipelines/grep test passed")
|
|
1559
|
-
|
|
1560
|
-
async def test_async_bash_env_and_exit_codes(self):
|
|
1561
|
-
"""测试异步Bash环境变量与退出码"""
|
|
1562
|
-
assert self.sandbox is not None
|
|
1563
|
-
|
|
1564
|
-
code = """
|
|
1565
|
-
export MODE=async
|
|
1566
|
-
echo "MODE=$MODE"
|
|
1567
|
-
(exit 9)
|
|
1568
|
-
echo $?
|
|
1569
|
-
"""
|
|
1570
|
-
|
|
1571
|
-
execution = await self.sandbox.run_code(code, language="bash")
|
|
1572
|
-
assert execution.error is None
|
|
1573
|
-
assert any("MODE=async" in line for line in execution.logs.stdout)
|
|
1574
|
-
assert any(line.strip() == "9" for line in execution.logs.stdout)
|
|
1575
|
-
logger.info("Async Bash env and exit codes test passed")
|
|
1576
|
-
|
|
1577
|
-
async def test_async_bash_context_management(self):
|
|
1578
|
-
"""测试异步Bash上下文管理"""
|
|
1579
|
-
assert self.sandbox is not None
|
|
1580
|
-
|
|
1581
|
-
# 创建Bash上下文
|
|
1582
|
-
bash_ctx = await self.sandbox.create_code_context(language="bash", cwd="/tmp")
|
|
1583
|
-
self.contexts["async_bash"] = bash_ctx
|
|
1584
|
-
|
|
1585
|
-
setup = """
|
|
1586
|
-
echo "Setup async Bash context"
|
|
1587
|
-
COUNT=3
|
|
1588
|
-
echo $COUNT
|
|
1589
|
-
"""
|
|
1590
|
-
|
|
1591
|
-
e1 = await self.sandbox.run_code(setup, context=bash_ctx)
|
|
1592
|
-
assert e1.error is None
|
|
1593
|
-
assert any("Setup async Bash context" in line for line in e1.logs.stdout)
|
|
1594
|
-
|
|
1595
|
-
use = """
|
|
1596
|
-
echo "Use async Bash context"
|
|
1597
|
-
COUNT=$((COUNT+2))
|
|
1598
|
-
echo "COUNT_AFTER=$COUNT"
|
|
1599
|
-
"""
|
|
1600
|
-
|
|
1601
|
-
e2 = await self.sandbox.run_code(use, context=bash_ctx)
|
|
1602
|
-
assert e2.error is None
|
|
1603
|
-
assert any("Use async Bash context" in line for line in e2.logs.stdout)
|
|
1604
|
-
assert any("COUNT_AFTER=5" in line for line in e2.logs.stdout)
|
|
1605
|
-
|
|
1606
|
-
# 清理上下文
|
|
1607
|
-
try:
|
|
1608
|
-
await self.sandbox.destroy_context(bash_ctx)
|
|
1609
|
-
if "async_bash" in self.contexts:
|
|
1610
|
-
del self.contexts["async_bash"]
|
|
1611
|
-
logger.info("Destroyed async Bash context")
|
|
1612
|
-
except Exception as e:
|
|
1613
|
-
logger.warning(f"Failed to destroy async Bash context: {e}")
|
|
1614
|
-
|
|
1615
|
-
# ======================== 异步IJAVA 测试 ========================
|
|
1616
|
-
|
|
1617
|
-
async def test_async_ijava_basic_execution(self):
|
|
1618
|
-
"""测试异步IJAVA基础执行"""
|
|
1619
|
-
assert self.sandbox is not None
|
|
1620
|
-
|
|
1621
|
-
code = """
|
|
1622
|
-
// 异步IJAVA 基础执行测试
|
|
1623
|
-
System.out.println("Hello from Async IJAVA Kernel!");
|
|
1624
|
-
|
|
1625
|
-
// 基础变量和运算
|
|
1626
|
-
int x = 15;
|
|
1627
|
-
int y = 25;
|
|
1628
|
-
int sum = x + y;
|
|
1629
|
-
int product = x * y;
|
|
1630
|
-
|
|
1631
|
-
System.out.println("Sum: " + sum);
|
|
1632
|
-
System.out.println("Product: " + product);
|
|
1633
|
-
|
|
1634
|
-
// 字符串操作
|
|
1635
|
-
String name = "AsyncScaleBox";
|
|
1636
|
-
String greeting = "Hello, " + name + "!";
|
|
1637
|
-
System.out.println(greeting);
|
|
1638
|
-
|
|
1639
|
-
// 数组操作
|
|
1640
|
-
int[] numbers = {2, 4, 6, 8, 10};
|
|
1641
|
-
int total = 0;
|
|
1642
|
-
for (int num : numbers) {
|
|
1643
|
-
total += num;
|
|
1644
|
-
}
|
|
1645
|
-
System.out.println("Array sum: " + total);
|
|
1646
|
-
|
|
1647
|
-
// IJAVA 特色:直接输出变量值
|
|
1648
|
-
x;
|
|
1649
|
-
y;
|
|
1650
|
-
sum;
|
|
1651
|
-
product;
|
|
1652
|
-
total;
|
|
1653
|
-
"""
|
|
1654
|
-
|
|
1655
|
-
execution = await self.sandbox.run_code(code, language="java")
|
|
1656
|
-
assert execution.error is None
|
|
1657
|
-
assert any(
|
|
1658
|
-
"Hello from Async IJAVA Kernel!" in line for line in execution.logs.stdout
|
|
1659
|
-
)
|
|
1660
|
-
assert any("Sum: 40" in line for line in execution.logs.stdout)
|
|
1661
|
-
assert any("Array sum: 30" in line for line in execution.logs.stdout)
|
|
1662
|
-
logger.info("Async IJAVA basic execution test passed")
|
|
1663
|
-
|
|
1664
|
-
async def test_async_ijava_oop_features(self):
|
|
1665
|
-
"""测试异步IJAVA面向对象特性"""
|
|
1666
|
-
assert self.sandbox is not None
|
|
1667
|
-
|
|
1668
|
-
code = """
|
|
1669
|
-
// 异步IJAVA 面向对象特性测试
|
|
1670
|
-
System.out.println("Testing Async IJAVA OOP features...");
|
|
1671
|
-
|
|
1672
|
-
// 定义类
|
|
1673
|
-
class AsyncPerson {
|
|
1674
|
-
private String name;
|
|
1675
|
-
private int age;
|
|
1676
|
-
|
|
1677
|
-
public AsyncPerson(String name, int age) {
|
|
1678
|
-
this.name = name;
|
|
1679
|
-
this.age = age;
|
|
1680
|
-
}
|
|
1681
|
-
|
|
1682
|
-
public String getName() { return name; }
|
|
1683
|
-
public int getAge() { return age; }
|
|
1684
|
-
|
|
1685
|
-
public void introduce() {
|
|
1686
|
-
System.out.println("Hi, I'm " + name + " and I'm " + age + " years old.");
|
|
1687
|
-
}
|
|
1688
|
-
}
|
|
1689
|
-
|
|
1690
|
-
class AsyncStudent extends AsyncPerson {
|
|
1691
|
-
private String major;
|
|
1692
|
-
|
|
1693
|
-
public AsyncStudent(String name, int age, String major) {
|
|
1694
|
-
super(name, age);
|
|
1695
|
-
this.major = major;
|
|
1696
|
-
}
|
|
1697
|
-
|
|
1698
|
-
@Override
|
|
1699
|
-
public void introduce() {
|
|
1700
|
-
super.introduce();
|
|
1701
|
-
System.out.println("I'm studying " + major + ".");
|
|
1702
|
-
}
|
|
1703
|
-
}
|
|
1704
|
-
|
|
1705
|
-
// 创建对象并测试
|
|
1706
|
-
AsyncPerson person = new AsyncPerson("Eve", 28);
|
|
1707
|
-
person.introduce();
|
|
1708
|
-
|
|
1709
|
-
AsyncStudent student = new AsyncStudent("Frank", 24, "Data Science");
|
|
1710
|
-
student.introduce();
|
|
1711
|
-
|
|
1712
|
-
// IJAVA 特色:直接输出对象信息
|
|
1713
|
-
person.getName();
|
|
1714
|
-
student.getAge();
|
|
1715
|
-
person;
|
|
1716
|
-
student;
|
|
1717
|
-
|
|
1718
|
-
System.out.println("Async IJAVA OOP test completed successfully!");
|
|
1719
|
-
"""
|
|
1720
|
-
|
|
1721
|
-
execution = await self.sandbox.run_code(code, language="java")
|
|
1722
|
-
assert execution.error is None
|
|
1723
|
-
assert any(
|
|
1724
|
-
"Testing Async IJAVA OOP features..." in line
|
|
1725
|
-
for line in execution.logs.stdout
|
|
1726
|
-
)
|
|
1727
|
-
assert any("Hi, I'm Eve" in line for line in execution.logs.stdout)
|
|
1728
|
-
assert any(
|
|
1729
|
-
"I'm studying Data Science" in line for line in execution.logs.stdout
|
|
1730
|
-
)
|
|
1731
|
-
logger.info("Async IJAVA OOP features test passed")
|
|
1732
|
-
|
|
1733
|
-
async def test_async_ijava_collections(self):
|
|
1734
|
-
"""测试异步IJAVA集合框架"""
|
|
1735
|
-
assert self.sandbox is not None
|
|
1736
|
-
|
|
1737
|
-
code = """
|
|
1738
|
-
import java.util.*;
|
|
1739
|
-
|
|
1740
|
-
System.out.println("Testing Async IJAVA Collections...");
|
|
1741
|
-
|
|
1742
|
-
// ArrayList
|
|
1743
|
-
List<String> colors = new ArrayList<>();
|
|
1744
|
-
colors.add("Red");
|
|
1745
|
-
colors.add("Green");
|
|
1746
|
-
colors.add("Blue");
|
|
1747
|
-
System.out.println("Colors: " + colors);
|
|
1748
|
-
|
|
1749
|
-
// HashMap
|
|
1750
|
-
Map<String, Integer> ages = new HashMap<>();
|
|
1751
|
-
ages.put("Alice", 25);
|
|
1752
|
-
ages.put("Bob", 30);
|
|
1753
|
-
ages.put("Charlie", 35);
|
|
1754
|
-
System.out.println("Ages: " + ages);
|
|
1755
|
-
|
|
1756
|
-
// HashSet
|
|
1757
|
-
Set<String> uniqueWords = new HashSet<>();
|
|
1758
|
-
uniqueWords.add("hello");
|
|
1759
|
-
uniqueWords.add("world");
|
|
1760
|
-
uniqueWords.add("hello"); // 重复元素
|
|
1761
|
-
System.out.println("Unique words: " + uniqueWords);
|
|
1762
|
-
|
|
1763
|
-
// 遍历集合
|
|
1764
|
-
System.out.println("Iterating through colors:");
|
|
1765
|
-
for (String color : colors) {
|
|
1766
|
-
System.out.println("- " + color);
|
|
1767
|
-
}
|
|
1768
|
-
|
|
1769
|
-
// IJAVA 特色:直接输出集合内容
|
|
1770
|
-
colors;
|
|
1771
|
-
ages;
|
|
1772
|
-
uniqueWords;
|
|
1773
|
-
|
|
1774
|
-
// 集合操作
|
|
1775
|
-
colors.size();
|
|
1776
|
-
ages.containsKey("Alice");
|
|
1777
|
-
uniqueWords.contains("hello");
|
|
1778
|
-
|
|
1779
|
-
System.out.println("Async IJAVA Collections test completed!");
|
|
1780
|
-
"""
|
|
1781
|
-
|
|
1782
|
-
execution = await self.sandbox.run_code(code, language="java")
|
|
1783
|
-
assert execution.error is None
|
|
1784
|
-
assert any(
|
|
1785
|
-
"Testing Async IJAVA Collections..." in line
|
|
1786
|
-
for line in execution.logs.stdout
|
|
1787
|
-
)
|
|
1788
|
-
assert any(
|
|
1789
|
-
"Colors: [Red, Green, Blue]" in line for line in execution.logs.stdout
|
|
1790
|
-
)
|
|
1791
|
-
assert any(
|
|
1792
|
-
"Unique words: [hello, world]" in line for line in execution.logs.stdout
|
|
1793
|
-
)
|
|
1794
|
-
logger.info("Async IJAVA collections test passed")
|
|
1795
|
-
|
|
1796
|
-
async def test_async_ijava_file_io(self):
|
|
1797
|
-
"""测试异步IJAVA文件I/O"""
|
|
1798
|
-
assert self.sandbox is not None
|
|
1799
|
-
|
|
1800
|
-
code = """
|
|
1801
|
-
import java.io.*;
|
|
1802
|
-
import java.nio.file.*;
|
|
1803
|
-
|
|
1804
|
-
System.out.println("Testing Async IJAVA File I/O...");
|
|
1805
|
-
|
|
1806
|
-
try {
|
|
1807
|
-
// 创建临时目录
|
|
1808
|
-
Path tempDir = Files.createTempDirectory("async_ijava_demo");
|
|
1809
|
-
System.out.println("Created temp directory: " + tempDir);
|
|
1810
|
-
|
|
1811
|
-
// 写入文件
|
|
1812
|
-
Path filePath = tempDir.resolve("async_test.txt");
|
|
1813
|
-
String content = "Hello from Async IJAVA File I/O!\nThis is an async test file.\n";
|
|
1814
|
-
Files.write(filePath, content.getBytes());
|
|
1815
|
-
System.out.println("File written successfully");
|
|
1816
|
-
|
|
1817
|
-
// 读取文件
|
|
1818
|
-
String readContent = new String(Files.readAllBytes(filePath));
|
|
1819
|
-
System.out.println("File content:");
|
|
1820
|
-
System.out.println(readContent);
|
|
1821
|
-
|
|
1822
|
-
// 文件信息
|
|
1823
|
-
long size = Files.size(filePath);
|
|
1824
|
-
System.out.println("File size: " + size + " bytes");
|
|
1825
|
-
|
|
1826
|
-
// IJAVA 特色:直接输出文件信息
|
|
1827
|
-
filePath;
|
|
1828
|
-
size;
|
|
1829
|
-
Files.exists(filePath);
|
|
1830
|
-
|
|
1831
|
-
// 清理
|
|
1832
|
-
Files.delete(filePath);
|
|
1833
|
-
Files.delete(tempDir);
|
|
1834
|
-
System.out.println("Async IJAVA File I/O test completed successfully!");
|
|
1835
|
-
|
|
1836
|
-
} catch (IOException e) {
|
|
1837
|
-
System.err.println("Error: " + e.getMessage());
|
|
1838
|
-
}
|
|
1839
|
-
"""
|
|
1840
|
-
|
|
1841
|
-
execution = await self.sandbox.run_code(code, language="java")
|
|
1842
|
-
assert execution.error is None
|
|
1843
|
-
assert any(
|
|
1844
|
-
"Testing Async IJAVA File I/O..." in line for line in execution.logs.stdout
|
|
1845
|
-
)
|
|
1846
|
-
assert any(
|
|
1847
|
-
"File written successfully" in line for line in execution.logs.stdout
|
|
1848
|
-
)
|
|
1849
|
-
assert any(
|
|
1850
|
-
"Hello from Async IJAVA File I/O!" in line for line in execution.logs.stdout
|
|
1851
|
-
)
|
|
1852
|
-
logger.info("Async IJAVA file I/O test passed")
|
|
1853
|
-
|
|
1854
|
-
async def test_async_ijava_context_management(self):
|
|
1855
|
-
"""测试异步IJAVA上下文管理"""
|
|
1856
|
-
assert self.sandbox is not None
|
|
1857
|
-
|
|
1858
|
-
# 创建IJAVA上下文
|
|
1859
|
-
ijava_context = await self.sandbox.create_code_context(
|
|
1860
|
-
language="java", cwd="/tmp"
|
|
1861
|
-
)
|
|
1862
|
-
self.contexts["async_ijava"] = ijava_context
|
|
1863
|
-
|
|
1864
|
-
# 在上下文中定义类和变量
|
|
1865
|
-
setup_code = """
|
|
1866
|
-
System.out.println("Setting up async IJAVA context...");
|
|
1867
|
-
|
|
1868
|
-
// 定义全局变量
|
|
1869
|
-
int counter = 0;
|
|
1870
|
-
String message = "Hello from Async IJAVA Context!";
|
|
1871
|
-
|
|
1872
|
-
System.out.println("Initial counter: " + counter);
|
|
1873
|
-
System.out.println("Message: " + message);
|
|
1874
|
-
|
|
1875
|
-
// 定义方法
|
|
1876
|
-
void incrementCounter() {
|
|
1877
|
-
counter++;
|
|
1878
|
-
}
|
|
1879
|
-
|
|
1880
|
-
int getCounter() {
|
|
1881
|
-
return counter;
|
|
1882
|
-
}
|
|
1883
|
-
|
|
1884
|
-
// 定义类
|
|
1885
|
-
class AsyncContextDemo {
|
|
1886
|
-
private static int staticCounter = 0;
|
|
1887
|
-
|
|
1888
|
-
public static void incrementStaticCounter() {
|
|
1889
|
-
staticCounter++;
|
|
1890
|
-
}
|
|
1891
|
-
|
|
1892
|
-
public static int getStaticCounter() {
|
|
1893
|
-
return staticCounter;
|
|
1894
|
-
}
|
|
1895
|
-
}
|
|
1896
|
-
|
|
1897
|
-
// 测试方法
|
|
1898
|
-
incrementCounter();
|
|
1899
|
-
System.out.println("Counter after increment: " + counter);
|
|
1900
|
-
|
|
1901
|
-
// IJAVA 特色:直接输出变量值
|
|
1902
|
-
counter;
|
|
1903
|
-
message;
|
|
1904
|
-
getCounter();
|
|
1905
|
-
"""
|
|
1906
|
-
|
|
1907
|
-
execution1 = await self.sandbox.run_code(setup_code, context=ijava_context)
|
|
1908
|
-
assert execution1.error is None
|
|
1909
|
-
assert any(
|
|
1910
|
-
"Setting up async IJAVA context..." in line
|
|
1911
|
-
for line in execution1.logs.stdout
|
|
1912
|
-
)
|
|
1913
|
-
assert any("Initial counter: 0" in line for line in execution1.logs.stdout)
|
|
1914
|
-
|
|
1915
|
-
# 在同一上下文中使用之前定义的变量和方法
|
|
1916
|
-
use_code = """
|
|
1917
|
-
System.out.println("Using async IJAVA context...");
|
|
1918
|
-
|
|
1919
|
-
// 使用之前定义的变量和方法
|
|
1920
|
-
incrementCounter();
|
|
1921
|
-
int currentCounter = getCounter();
|
|
1922
|
-
System.out.println("Current counter: " + currentCounter);
|
|
1923
|
-
|
|
1924
|
-
// 使用之前定义的类
|
|
1925
|
-
AsyncContextDemo.incrementStaticCounter();
|
|
1926
|
-
int staticCounter = AsyncContextDemo.getStaticCounter();
|
|
1927
|
-
System.out.println("Static counter: " + staticCounter);
|
|
1928
|
-
|
|
1929
|
-
// 创建新变量
|
|
1930
|
-
String newMessage = "Modified async context data";
|
|
1931
|
-
System.out.println("New message: " + newMessage);
|
|
1932
|
-
|
|
1933
|
-
// IJAVA 特色:直接输出所有变量
|
|
1934
|
-
counter;
|
|
1935
|
-
currentCounter;
|
|
1936
|
-
staticCounter;
|
|
1937
|
-
newMessage;
|
|
1938
|
-
AsyncContextDemo.getStaticCounter();
|
|
1939
|
-
|
|
1940
|
-
System.out.println("Async IJAVA context usage completed!");
|
|
1941
|
-
"""
|
|
1942
|
-
|
|
1943
|
-
execution2 = await self.sandbox.run_code(use_code, context=ijava_context)
|
|
1944
|
-
assert execution2.error is None
|
|
1945
|
-
assert any(
|
|
1946
|
-
"Using async IJAVA context..." in line for line in execution2.logs.stdout
|
|
1947
|
-
)
|
|
1948
|
-
assert any("Current counter: 2" in line for line in execution2.logs.stdout)
|
|
1949
|
-
assert any("Static counter: 1" in line for line in execution2.logs.stdout)
|
|
1950
|
-
logger.info("Async IJAVA context management test passed")
|
|
1951
|
-
|
|
1952
|
-
# 测试完成后立即清理context
|
|
1953
|
-
try:
|
|
1954
|
-
await self.sandbox.destroy_context(ijava_context)
|
|
1955
|
-
logger.info(
|
|
1956
|
-
f"Successfully destroyed async IJAVA context: {ijava_context.id}"
|
|
1957
|
-
)
|
|
1958
|
-
# 从contexts字典中移除
|
|
1959
|
-
if "async_ijava" in self.contexts:
|
|
1960
|
-
del self.contexts["async_ijava"]
|
|
1961
|
-
except Exception as e:
|
|
1962
|
-
logger.warning(
|
|
1963
|
-
f"Failed to destroy async IJAVA context {ijava_context.id}: {e}"
|
|
1964
|
-
)
|
|
1965
|
-
|
|
1966
|
-
# ======================== 异步Deno 测试 ========================
|
|
1967
|
-
|
|
1968
|
-
async def test_async_deno_basic_execution(self):
|
|
1969
|
-
"""测试异步Deno基础执行"""
|
|
1970
|
-
assert self.sandbox is not None
|
|
1971
|
-
|
|
1972
|
-
code = """
|
|
1973
|
-
// 异步Deno 基础执行测试
|
|
1974
|
-
console.log("Hello from Async Deno Kernel!");
|
|
1975
|
-
|
|
1976
|
-
// 基础变量和运算
|
|
1977
|
-
const x: number = 14;
|
|
1978
|
-
const y: number = 16;
|
|
1979
|
-
const sum: number = x + y;
|
|
1980
|
-
const product: number = x * y;
|
|
1981
|
-
|
|
1982
|
-
console.log(`Sum: ${sum}`);
|
|
1983
|
-
console.log(`Product: ${product}`);
|
|
1984
|
-
|
|
1985
|
-
// 字符串操作
|
|
1986
|
-
const name: string = "AsyncDenoScaleBox";
|
|
1987
|
-
const greeting: string = `Hello, ${name}!`;
|
|
1988
|
-
console.log(greeting);
|
|
1989
|
-
|
|
1990
|
-
// 数组操作
|
|
1991
|
-
const numbers: number[] = [2, 4, 6, 8, 10];
|
|
1992
|
-
const total: number = numbers.reduce((acc, num) => acc + num, 0);
|
|
1993
|
-
console.log(`Array sum: ${total}`);
|
|
1994
|
-
|
|
1995
|
-
// 对象操作
|
|
1996
|
-
const person = {
|
|
1997
|
-
name: "Bob",
|
|
1998
|
-
age: 30,
|
|
1999
|
-
city: "London"
|
|
2000
|
-
};
|
|
2001
|
-
console.log(`Person: ${person.name}, ${person.age} years old`);
|
|
2002
|
-
"""
|
|
2003
|
-
|
|
2004
|
-
execution = await self.sandbox.run_code(code, language="typescript")
|
|
2005
|
-
assert execution.error is None
|
|
2006
|
-
assert any(
|
|
2007
|
-
"Hello from Async Deno Kernel!" in line for line in execution.logs.stdout
|
|
2008
|
-
)
|
|
2009
|
-
assert any("Sum: 30" in line for line in execution.logs.stdout)
|
|
2010
|
-
assert any("Array sum: 30" in line for line in execution.logs.stdout)
|
|
2011
|
-
logger.info("Async Deno basic execution test passed")
|
|
2012
|
-
|
|
2013
|
-
async def test_async_deno_typescript_features(self):
|
|
2014
|
-
"""测试异步Deno TypeScript特性"""
|
|
2015
|
-
assert self.sandbox is not None
|
|
2016
|
-
|
|
2017
|
-
code = """
|
|
2018
|
-
// 异步Deno TypeScript 特性测试
|
|
2019
|
-
interface AsyncUser {
|
|
2020
|
-
id: number;
|
|
2021
|
-
name: string;
|
|
2022
|
-
email: string;
|
|
2023
|
-
isActive: boolean;
|
|
2024
|
-
}
|
|
2025
|
-
|
|
2026
|
-
class AsyncUserManager {
|
|
2027
|
-
private users: AsyncUser[] = [];
|
|
2028
|
-
|
|
2029
|
-
constructor() {
|
|
2030
|
-
console.log("AsyncUserManager initialized");
|
|
2031
|
-
}
|
|
2032
|
-
|
|
2033
|
-
addUser(user: AsyncUser): void {
|
|
2034
|
-
this.users.push(user);
|
|
2035
|
-
console.log(`Added user: ${user.name}`);
|
|
2036
|
-
}
|
|
2037
|
-
|
|
2038
|
-
getUsers(): AsyncUser[] {
|
|
2039
|
-
return this.users;
|
|
2040
|
-
}
|
|
2041
|
-
|
|
2042
|
-
findUserById(id: number): AsyncUser | undefined {
|
|
2043
|
-
return this.users.find(user => user.id === id);
|
|
2044
|
-
}
|
|
2045
|
-
}
|
|
2046
|
-
|
|
2047
|
-
// 使用泛型
|
|
2048
|
-
function processAsyncItems<T>(items: T[], processor: (item: T) => void): void {
|
|
2049
|
-
items.forEach(processor);
|
|
2050
|
-
}
|
|
2051
|
-
|
|
2052
|
-
// 枚举
|
|
2053
|
-
enum AsyncStatus {
|
|
2054
|
-
PENDING = "pending",
|
|
2055
|
-
APPROVED = "approved",
|
|
2056
|
-
REJECTED = "rejected"
|
|
2057
|
-
}
|
|
2058
|
-
|
|
2059
|
-
console.log("Testing Async Deno TypeScript features...");
|
|
2060
|
-
|
|
2061
|
-
const asyncUserManager = new AsyncUserManager();
|
|
2062
|
-
asyncUserManager.addUser({
|
|
2063
|
-
id: 1,
|
|
2064
|
-
name: "Async John",
|
|
2065
|
-
email: "async.john@example.com",
|
|
2066
|
-
isActive: true
|
|
2067
|
-
});
|
|
2068
|
-
|
|
2069
|
-
asyncUserManager.addUser({
|
|
2070
|
-
id: 2,
|
|
2071
|
-
name: "Async Jane",
|
|
2072
|
-
email: "async.jane@example.com",
|
|
2073
|
-
isActive: false
|
|
2074
|
-
});
|
|
2075
|
-
|
|
2076
|
-
const users = asyncUserManager.getUsers();
|
|
2077
|
-
console.log(`Total users: ${users.length}`);
|
|
2078
|
-
|
|
2079
|
-
const foundUser = asyncUserManager.findUserById(1);
|
|
2080
|
-
console.log(`Found user: ${foundUser?.name}`);
|
|
2081
|
-
|
|
2082
|
-
// 使用泛型函数
|
|
2083
|
-
const numbers = [10, 20, 30, 40, 50];
|
|
2084
|
-
processAsyncItems(numbers, (num) => console.log(`Processing: ${num}`));
|
|
2085
|
-
|
|
2086
|
-
console.log(`Status: ${AsyncStatus.APPROVED}`);
|
|
2087
|
-
console.log("Async TypeScript features test completed!");
|
|
2088
|
-
"""
|
|
2089
|
-
|
|
2090
|
-
execution = await self.sandbox.run_code(code, language="typescript")
|
|
2091
|
-
assert execution.error is None
|
|
2092
|
-
assert any(
|
|
2093
|
-
"Testing Async Deno TypeScript features..." in line
|
|
2094
|
-
for line in execution.logs.stdout
|
|
2095
|
-
)
|
|
2096
|
-
assert any("Added user: Async John" in line for line in execution.logs.stdout)
|
|
2097
|
-
assert any("Total users: 2" in line for line in execution.logs.stdout)
|
|
2098
|
-
logger.info("Async Deno TypeScript features test passed")
|
|
2099
|
-
|
|
2100
|
-
async def test_async_deno_async_await(self):
|
|
2101
|
-
"""测试异步Deno异步/await"""
|
|
2102
|
-
assert self.sandbox is not None
|
|
2103
|
-
|
|
2104
|
-
code = """
|
|
2105
|
-
// 异步Deno 异步/await 测试
|
|
2106
|
-
async function asyncDelay(ms: number): Promise<void> {
|
|
2107
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
2108
|
-
}
|
|
2109
|
-
|
|
2110
|
-
async function asyncFetchData(id: number): Promise<{ id: number; data: string }> {
|
|
2111
|
-
await asyncDelay(30);
|
|
2112
|
-
return { id, data: `Async Data for ID ${id}` };
|
|
2113
|
-
}
|
|
2114
|
-
|
|
2115
|
-
async function asyncProcessBatch(ids: number[]): Promise<string[]> {
|
|
2116
|
-
console.log("Starting async batch processing...");
|
|
2117
|
-
const start = Date.now();
|
|
2118
|
-
|
|
2119
|
-
const results = await Promise.all(
|
|
2120
|
-
ids.map(async (id) => {
|
|
2121
|
-
const result = await asyncFetchData(id);
|
|
2122
|
-
console.log(`Async Processed: ${result.data}`);
|
|
2123
|
-
return result.data;
|
|
2124
|
-
})
|
|
2125
|
-
);
|
|
2126
|
-
|
|
2127
|
-
const duration = Date.now() - start;
|
|
2128
|
-
console.log(`Async batch processing completed in ${duration}ms`);
|
|
2129
|
-
return results;
|
|
2130
|
-
}
|
|
2131
|
-
|
|
2132
|
-
async function asyncMain(): Promise<void> {
|
|
2133
|
-
console.log("Testing Async Deno async/await...");
|
|
2134
|
-
|
|
2135
|
-
const ids = [1, 2, 3];
|
|
2136
|
-
const results = await asyncProcessBatch(ids);
|
|
2137
|
-
|
|
2138
|
-
console.log(`Total async results: ${results.length}`);
|
|
2139
|
-
console.log("Async async/await test completed!");
|
|
2140
|
-
}
|
|
2141
|
-
|
|
2142
|
-
asyncMain();
|
|
2143
|
-
"""
|
|
2144
|
-
|
|
2145
|
-
execution = await self.sandbox.run_code(code, language="typescript")
|
|
2146
|
-
assert execution.error is None
|
|
2147
|
-
assert any(
|
|
2148
|
-
"Testing Async Deno async/await..." in line
|
|
2149
|
-
for line in execution.logs.stdout
|
|
2150
|
-
)
|
|
2151
|
-
assert any(
|
|
2152
|
-
"Starting async batch processing..." in line
|
|
2153
|
-
for line in execution.logs.stdout
|
|
2154
|
-
)
|
|
2155
|
-
assert any(
|
|
2156
|
-
"Async batch processing completed" in line for line in execution.logs.stdout
|
|
2157
|
-
)
|
|
2158
|
-
logger.info("Async Deno async/await test passed")
|
|
2159
|
-
|
|
2160
|
-
async def test_async_deno_file_operations(self):
|
|
2161
|
-
"""测试异步Deno文件操作"""
|
|
2162
|
-
assert self.sandbox is not None
|
|
2163
|
-
|
|
2164
|
-
code = """
|
|
2165
|
-
// 异步Deno 文件操作测试
|
|
2166
|
-
import { ensureDir, writeTextFile, readTextFile, remove } from "https://deno.land/std@0.208.0/fs/mod.ts";
|
|
2167
|
-
|
|
2168
|
-
async function asyncFileOperations(): Promise<void> {
|
|
2169
|
-
console.log("Testing Async Deno file operations...");
|
|
2170
|
-
|
|
2171
|
-
try {
|
|
2172
|
-
// 创建临时目录
|
|
2173
|
-
const tempDir = "/tmp/async_deno_demo";
|
|
2174
|
-
await ensureDir(tempDir);
|
|
2175
|
-
console.log(`Created directory: ${tempDir}`);
|
|
2176
|
-
|
|
2177
|
-
// 写入文件
|
|
2178
|
-
const filePath = `${tempDir}/async_test.txt`;
|
|
2179
|
-
const content = "Hello from Async Deno File Operations!\nThis is an async test file.\n";
|
|
2180
|
-
await writeTextFile(filePath, content);
|
|
2181
|
-
console.log("Async file written successfully");
|
|
2182
|
-
|
|
2183
|
-
// 读取文件
|
|
2184
|
-
const readContent = await readTextFile(filePath);
|
|
2185
|
-
console.log("Async file content:");
|
|
2186
|
-
console.log(readContent);
|
|
2187
|
-
|
|
2188
|
-
// 文件信息
|
|
2189
|
-
const fileInfo = await Deno.stat(filePath);
|
|
2190
|
-
console.log(`Async file size: ${fileInfo.size} bytes`);
|
|
2191
|
-
console.log(`Async created: ${fileInfo.birthtime}`);
|
|
2192
|
-
|
|
2193
|
-
// 清理
|
|
2194
|
-
await remove(filePath);
|
|
2195
|
-
await remove(tempDir);
|
|
2196
|
-
console.log("Async file operations test completed successfully!");
|
|
2197
|
-
|
|
2198
|
-
} catch (error) {
|
|
2199
|
-
console.error(`Async Error: ${error.message}`);
|
|
2200
|
-
}
|
|
2201
|
-
}
|
|
2202
|
-
|
|
2203
|
-
asyncFileOperations();
|
|
2204
|
-
"""
|
|
2205
|
-
|
|
2206
|
-
execution = await self.sandbox.run_code(code, language="typescript")
|
|
2207
|
-
assert execution.error is None
|
|
2208
|
-
assert any(
|
|
2209
|
-
"Testing Async Deno file operations..." in line
|
|
2210
|
-
for line in execution.logs.stdout
|
|
2211
|
-
)
|
|
2212
|
-
assert any(
|
|
2213
|
-
"Async file written successfully" in line for line in execution.logs.stdout
|
|
2214
|
-
)
|
|
2215
|
-
assert any(
|
|
2216
|
-
"Hello from Async Deno File Operations!" in line
|
|
2217
|
-
for line in execution.logs.stdout
|
|
2218
|
-
)
|
|
2219
|
-
logger.info("Async Deno file operations test passed")
|
|
2220
|
-
|
|
2221
|
-
async def test_async_deno_context_management(self):
|
|
2222
|
-
"""测试异步Deno上下文管理"""
|
|
2223
|
-
assert self.sandbox is not None
|
|
2224
|
-
|
|
2225
|
-
# 创建Deno上下文
|
|
2226
|
-
deno_context = await self.sandbox.create_code_context(
|
|
2227
|
-
language="typescript", cwd="/tmp"
|
|
2228
|
-
)
|
|
2229
|
-
self.contexts["async_deno"] = deno_context
|
|
2230
|
-
|
|
2231
|
-
# 在上下文中定义变量和函数
|
|
2232
|
-
setup_code = """
|
|
2233
|
-
// 异步Deno 上下文设置
|
|
2234
|
-
console.log("Setting up async Deno context...");
|
|
2235
|
-
|
|
2236
|
-
// 定义全局变量
|
|
2237
|
-
let asyncCounter: number = 0;
|
|
2238
|
-
const asyncCache: Map<string, any> = new Map();
|
|
2239
|
-
|
|
2240
|
-
// 定义函数
|
|
2241
|
-
function asyncIncrementCounter(): number {
|
|
2242
|
-
asyncCounter++;
|
|
2243
|
-
return asyncCounter;
|
|
2244
|
-
}
|
|
2245
|
-
|
|
2246
|
-
function asyncAddToCache(key: string, value: any): number {
|
|
2247
|
-
asyncCache.set(key, value);
|
|
2248
|
-
return asyncCache.size;
|
|
2249
|
-
}
|
|
2250
|
-
|
|
2251
|
-
// 定义接口
|
|
2252
|
-
interface AsyncContextData {
|
|
2253
|
-
id: number;
|
|
2254
|
-
value: string;
|
|
2255
|
-
}
|
|
2256
|
-
|
|
2257
|
-
const asyncContextData: AsyncContextData = {
|
|
2258
|
-
id: 1,
|
|
2259
|
-
value: "Hello from Async Deno Context!"
|
|
2260
|
-
};
|
|
2261
|
-
|
|
2262
|
-
console.log(`Initial async counter: ${asyncCounter}`);
|
|
2263
|
-
console.log(`Async cache size: ${asyncCache.size}`);
|
|
2264
|
-
console.log(`Async context data: ${asyncContextData.value}`);
|
|
2265
|
-
"""
|
|
2266
|
-
|
|
2267
|
-
execution1 = await self.sandbox.run_code(setup_code, context=deno_context)
|
|
2268
|
-
assert execution1.error is None
|
|
2269
|
-
assert any(
|
|
2270
|
-
"Setting up async Deno context..." in line
|
|
2271
|
-
for line in execution1.logs.stdout
|
|
2272
|
-
)
|
|
2273
|
-
assert any(
|
|
2274
|
-
"Initial async counter: 0" in line for line in execution1.logs.stdout
|
|
2275
|
-
)
|
|
2276
|
-
|
|
2277
|
-
# 在同一上下文中使用之前定义的变量和函数
|
|
2278
|
-
use_code = """
|
|
2279
|
-
// 使用异步Deno 上下文中的变量和函数
|
|
2280
|
-
console.log("Using async Deno context...");
|
|
2281
|
-
|
|
2282
|
-
// 使用全局变量
|
|
2283
|
-
console.log(`Current async counter: ${asyncCounter}`);
|
|
2284
|
-
console.log(`Current async cache size: ${asyncCache.size}`);
|
|
2285
|
-
|
|
2286
|
-
// 使用函数
|
|
2287
|
-
const newAsyncCounter = asyncIncrementCounter();
|
|
2288
|
-
console.log(`Async counter after increment: ${newAsyncCounter}`);
|
|
2289
|
-
|
|
2290
|
-
const newAsyncCacheSize = asyncAddToCache("async_test_key", "async_test_value");
|
|
2291
|
-
console.log(`Async cache size after addition: ${newAsyncCacheSize}`);
|
|
2292
|
-
|
|
2293
|
-
// 使用上下文数据
|
|
2294
|
-
console.log(`Async context data ID: ${asyncContextData.id}`);
|
|
2295
|
-
console.log(`Async context data value: ${asyncContextData.value}`);
|
|
2296
|
-
|
|
2297
|
-
// 修改上下文数据
|
|
2298
|
-
asyncContextData.value = "Modified async context data";
|
|
2299
|
-
console.log(`Modified async context data: ${asyncContextData.value}`);
|
|
2300
|
-
|
|
2301
|
-
console.log("Async context usage completed!");
|
|
2302
|
-
"""
|
|
2303
|
-
|
|
2304
|
-
execution2 = await self.sandbox.run_code(use_code, context=deno_context)
|
|
2305
|
-
assert execution2.error is None
|
|
2306
|
-
assert any(
|
|
2307
|
-
"Using async Deno context..." in line for line in execution2.logs.stdout
|
|
2308
|
-
)
|
|
2309
|
-
assert any(
|
|
2310
|
-
"Async counter after increment: 1" in line
|
|
2311
|
-
for line in execution2.logs.stdout
|
|
2312
|
-
)
|
|
2313
|
-
assert any(
|
|
2314
|
-
"Async cache size after addition: 1" in line
|
|
2315
|
-
for line in execution2.logs.stdout
|
|
2316
|
-
)
|
|
2317
|
-
logger.info("Async Deno context management test passed")
|
|
2318
|
-
|
|
2319
|
-
# 测试完成后立即清理context
|
|
2320
|
-
try:
|
|
2321
|
-
await self.sandbox.destroy_context(deno_context)
|
|
2322
|
-
logger.info(f"Successfully destroyed async Deno context: {deno_context.id}")
|
|
2323
|
-
# 从contexts字典中移除
|
|
2324
|
-
if "async_deno" in self.contexts:
|
|
2325
|
-
del self.contexts["async_deno"]
|
|
2326
|
-
except Exception as e:
|
|
2327
|
-
logger.warning(
|
|
2328
|
-
f"Failed to destroy async Deno context {deno_context.id}: {e}"
|
|
2329
|
-
)
|
|
2330
|
-
|
|
2331
|
-
# ======================== 高级异步功能测试 ========================
|
|
2332
|
-
|
|
2333
|
-
async def test_async_websocket_simulation(self):
|
|
2334
|
-
"""测试异步WebSocket模拟"""
|
|
2335
|
-
assert self.sandbox is not None
|
|
2336
|
-
|
|
2337
|
-
code = """
|
|
2338
|
-
import asyncio
|
|
2339
|
-
import json
|
|
2340
|
-
import time
|
|
2341
|
-
from datetime import datetime
|
|
2342
|
-
|
|
2343
|
-
class MockWebSocketConnection:
|
|
2344
|
-
'''模拟WebSocket连接'''
|
|
2345
|
-
def __init__(self, connection_id):
|
|
2346
|
-
self.connection_id = connection_id
|
|
2347
|
-
self.connected = True
|
|
2348
|
-
self.message_queue = asyncio.Queue()
|
|
2349
|
-
|
|
2350
|
-
async def send_message(self, message):
|
|
2351
|
-
if self.connected:
|
|
2352
|
-
await self.message_queue.put({
|
|
2353
|
-
"type": "outgoing",
|
|
2354
|
-
"data": message,
|
|
2355
|
-
"timestamp": datetime.now().isoformat()
|
|
2356
|
-
})
|
|
2357
|
-
await asyncio.sleep(0.01) # 模拟网络延迟
|
|
2358
|
-
return True
|
|
2359
|
-
return False
|
|
2360
|
-
|
|
2361
|
-
async def receive_message(self):
|
|
2362
|
-
if self.connected:
|
|
2363
|
-
# 模拟接收消息
|
|
2364
|
-
await asyncio.sleep(0.05) # 模拟等待消息
|
|
2365
|
-
return {
|
|
2366
|
-
"type": "incoming",
|
|
2367
|
-
"data": f"Response from server to {self.connection_id}",
|
|
2368
|
-
"timestamp": datetime.now().isoformat()
|
|
2369
|
-
}
|
|
2370
|
-
return None
|
|
2371
|
-
|
|
2372
|
-
async def close(self):
|
|
2373
|
-
self.connected = False
|
|
2374
|
-
print(f"连接 {self.connection_id} 已关闭")
|
|
2375
|
-
|
|
2376
|
-
async def websocket_client(client_id, message_count):
|
|
2377
|
-
'''模拟WebSocket客户端'''
|
|
2378
|
-
print(f"客户端 {client_id} 开始连接")
|
|
2379
|
-
|
|
2380
|
-
connection = MockWebSocketConnection(client_id)
|
|
2381
|
-
messages_sent = 0
|
|
2382
|
-
messages_received = 0
|
|
2383
|
-
|
|
2384
|
-
try:
|
|
2385
|
-
# 发送和接收消息
|
|
2386
|
-
for i in range(message_count):
|
|
2387
|
-
# 发送消息
|
|
2388
|
-
message = f"Message {i+1} from client {client_id}"
|
|
2389
|
-
success = await connection.send_message(message)
|
|
2390
|
-
if success:
|
|
2391
|
-
messages_sent += 1
|
|
2392
|
-
|
|
2393
|
-
# 接收回复
|
|
2394
|
-
response = await connection.receive_message()
|
|
2395
|
-
if response:
|
|
2396
|
-
messages_received += 1
|
|
2397
|
-
print(f"客户端 {client_id} 收到: {response['data'][:50]}...")
|
|
2398
|
-
|
|
2399
|
-
finally:
|
|
2400
|
-
await connection.close()
|
|
2401
|
-
|
|
2402
|
-
return {
|
|
2403
|
-
"client_id": client_id,
|
|
2404
|
-
"messages_sent": messages_sent,
|
|
2405
|
-
"messages_received": messages_received,
|
|
2406
|
-
"success_rate": messages_received / messages_sent if messages_sent > 0 else 0
|
|
2407
|
-
}
|
|
2408
|
-
|
|
2409
|
-
print("开始WebSocket模拟测试...")
|
|
2410
|
-
start_time = time.time()
|
|
2411
|
-
|
|
2412
|
-
# 创建多个并发客户端
|
|
2413
|
-
client_count = 5
|
|
2414
|
-
messages_per_client = 3
|
|
2415
|
-
|
|
2416
|
-
client_tasks = [
|
|
2417
|
-
websocket_client(f"client_{i}", messages_per_client)
|
|
2418
|
-
for i in range(client_count)
|
|
2419
|
-
]
|
|
2420
|
-
|
|
2421
|
-
# 并发运行所有客户端
|
|
2422
|
-
results = await asyncio.gather(*client_tasks)
|
|
2423
|
-
|
|
2424
|
-
end_time = time.time()
|
|
2425
|
-
total_duration = end_time - start_time
|
|
2426
|
-
|
|
2427
|
-
# 汇总统计
|
|
2428
|
-
total_sent = sum(r["messages_sent"] for r in results)
|
|
2429
|
-
total_received = sum(r["messages_received"] for r in results)
|
|
2430
|
-
overall_success_rate = total_received / total_sent if total_sent > 0 else 0
|
|
2431
|
-
|
|
2432
|
-
print(f"\\nWebSocket模拟完成:")
|
|
2433
|
-
print(f"客户端数量: {client_count}")
|
|
2434
|
-
print(f"每客户端消息: {messages_per_client}")
|
|
2435
|
-
print(f"总发送消息: {total_sent}")
|
|
2436
|
-
print(f"总接收消息: {total_received}")
|
|
2437
|
-
print(f"整体成功率: {overall_success_rate:.2%}")
|
|
2438
|
-
print(f"总耗时: {total_duration:.3f}s")
|
|
2439
|
-
print(f"消息吞吐量: {(total_sent + total_received) / total_duration:.1f} messages/s")
|
|
2440
|
-
|
|
2441
|
-
{
|
|
2442
|
-
"client_count": client_count,
|
|
2443
|
-
"total_sent": total_sent,
|
|
2444
|
-
"total_received": total_received,
|
|
2445
|
-
"success_rate": overall_success_rate,
|
|
2446
|
-
"duration": total_duration,
|
|
2447
|
-
"throughput": (total_sent + total_received) / total_duration,
|
|
2448
|
-
"client_results": results
|
|
2449
|
-
}
|
|
2450
|
-
"""
|
|
2451
|
-
|
|
2452
|
-
execution = await self.sandbox.run_code(code, language="python")
|
|
2453
|
-
assert execution.error is None
|
|
2454
|
-
assert any("WebSocket模拟" in line for line in execution.logs.stdout)
|
|
2455
|
-
|
|
2456
|
-
# ======================== 主测试执行器 ========================
|
|
2457
|
-
|
|
2458
|
-
async def run_all_tests(self):
|
|
2459
|
-
"""运行所有异步测试"""
|
|
2460
|
-
logger.info("开始AsyncCodeInterpreter综合验证测试...")
|
|
2461
|
-
|
|
2462
|
-
# 基础异步操作测试
|
|
2463
|
-
await self.run_test(
|
|
2464
|
-
self.test_async_code_interpreter_creation, "Async CodeInterpreter Creation"
|
|
2465
|
-
)
|
|
2466
|
-
await self.run_test(
|
|
2467
|
-
self.test_basic_async_python_execution, "Basic Async Python Execution"
|
|
2468
|
-
)
|
|
2469
|
-
await self.run_test(
|
|
2470
|
-
self.test_concurrent_code_execution, "Concurrent Code Execution"
|
|
2471
|
-
)
|
|
2472
|
-
await self.run_test(
|
|
2473
|
-
self.test_async_data_science_workflow, "Async Data Science Workflow"
|
|
2474
|
-
)
|
|
2475
|
-
|
|
2476
|
-
# 异步回调测试
|
|
2477
|
-
await self.run_test(
|
|
2478
|
-
self.test_async_callback_handling, "Async Callback Handling"
|
|
2479
|
-
)
|
|
2480
|
-
|
|
2481
|
-
# 异步上下文管理测试
|
|
2482
|
-
await self.run_test(self.test_async_context_creation, "Async Context Creation")
|
|
2483
|
-
await self.run_test(
|
|
2484
|
-
self.test_async_context_state_management, "Async Context State Management"
|
|
2485
|
-
)
|
|
2486
|
-
|
|
2487
|
-
# 异步性能测试
|
|
2488
|
-
await self.run_test(
|
|
2489
|
-
self.test_async_performance_concurrent_tasks,
|
|
2490
|
-
"Async Performance Concurrent Tasks",
|
|
2491
|
-
)
|
|
2492
|
-
await self.run_test(self.test_async_batch_processing, "Async Batch Processing")
|
|
2493
|
-
|
|
2494
|
-
# 异步错误处理测试
|
|
2495
|
-
await self.run_test(self.test_async_error_handling, "Async Error Handling")
|
|
2496
|
-
|
|
2497
|
-
# 异步结果格式测试
|
|
2498
|
-
await self.run_test(self.test_async_text_result, "Async Text Result Format")
|
|
2499
|
-
await self.run_test(
|
|
2500
|
-
self.test_async_mixed_format_result, "Async Mixed Format Result"
|
|
2501
|
-
)
|
|
2502
|
-
await self.run_test(
|
|
2503
|
-
self.test_async_realtime_data_result, "Async Realtime Data Result"
|
|
2504
|
-
)
|
|
2505
|
-
|
|
2506
|
-
# 异步R语言测试
|
|
2507
|
-
await self.run_test(
|
|
2508
|
-
self.test_async_r_language_basic_execution,
|
|
2509
|
-
"Async R Language Basic Execution",
|
|
2510
|
-
)
|
|
2511
|
-
await self.run_test(
|
|
2512
|
-
self.test_async_r_language_data_analysis, "Async R Language Data Analysis"
|
|
2513
|
-
)
|
|
2514
|
-
await self.run_test(
|
|
2515
|
-
self.test_async_r_language_visualization, "Async R Language Visualization"
|
|
2516
|
-
)
|
|
2517
|
-
await self.run_test(
|
|
2518
|
-
self.test_async_r_language_statistics, "Async R Language Statistics"
|
|
2519
|
-
)
|
|
2520
|
-
await self.run_test(
|
|
2521
|
-
self.test_async_r_language_context_management,
|
|
2522
|
-
"Async R Language Context Management",
|
|
2523
|
-
)
|
|
2524
|
-
|
|
2525
|
-
# 异步Node.js/JavaScript 测试
|
|
2526
|
-
await self.run_test(
|
|
2527
|
-
self.test_async_nodejs_basic_execution, "Async Node.js Basic Execution"
|
|
2528
|
-
)
|
|
2529
|
-
await self.run_test(
|
|
2530
|
-
self.test_async_nodejs_async_promises, "Async Node.js Async Promises"
|
|
2531
|
-
)
|
|
2532
|
-
await self.run_test(
|
|
2533
|
-
self.test_async_nodejs_data_processing, "Async Node.js Data Processing"
|
|
2534
|
-
)
|
|
2535
|
-
await self.run_test(
|
|
2536
|
-
self.test_async_nodejs_chart_data, "Async Node.js Chart Data Generation"
|
|
2537
|
-
)
|
|
2538
|
-
await self.run_test(
|
|
2539
|
-
self.test_async_nodejs_context_management,
|
|
2540
|
-
"Async Node.js Context Management",
|
|
2541
|
-
)
|
|
2542
|
-
|
|
2543
|
-
# 异步Bash 测试
|
|
2544
|
-
await self.run_test(
|
|
2545
|
-
self.test_async_bash_basic_execution, "Async Bash Basic Execution"
|
|
2546
|
-
)
|
|
2547
|
-
await self.run_test(
|
|
2548
|
-
self.test_async_bash_file_operations, "Async Bash File Operations"
|
|
2549
|
-
)
|
|
2550
|
-
await self.run_test(
|
|
2551
|
-
self.test_async_bash_pipelines_and_grep, "Async Bash Pipelines and Grep"
|
|
2552
|
-
)
|
|
2553
|
-
await self.run_test(
|
|
2554
|
-
self.test_async_bash_env_and_exit_codes, "Async Bash Env and Exit Codes"
|
|
2555
|
-
)
|
|
2556
|
-
await self.run_test(
|
|
2557
|
-
self.test_async_bash_context_management, "Async Bash Context Management"
|
|
2558
|
-
)
|
|
2559
|
-
|
|
2560
|
-
# 异步IJAVA 测试
|
|
2561
|
-
await self.run_test(
|
|
2562
|
-
self.test_async_ijava_basic_execution, "Async IJAVA Basic Execution"
|
|
2563
|
-
)
|
|
2564
|
-
await self.run_test(
|
|
2565
|
-
self.test_async_ijava_oop_features, "Async IJAVA OOP Features"
|
|
2566
|
-
)
|
|
2567
|
-
await self.run_test(
|
|
2568
|
-
self.test_async_ijava_collections, "Async IJAVA Collections"
|
|
2569
|
-
)
|
|
2570
|
-
await self.run_test(self.test_async_ijava_file_io, "Async IJAVA File I/O")
|
|
2571
|
-
await self.run_test(
|
|
2572
|
-
self.test_async_ijava_context_management, "Async IJAVA Context Management"
|
|
2573
|
-
)
|
|
2574
|
-
|
|
2575
|
-
# 异步Deno 测试
|
|
2576
|
-
await self.run_test(
|
|
2577
|
-
self.test_async_deno_basic_execution, "Async Deno Basic Execution"
|
|
2578
|
-
)
|
|
2579
|
-
await self.run_test(
|
|
2580
|
-
self.test_async_deno_typescript_features, "Async Deno TypeScript Features"
|
|
2581
|
-
)
|
|
2582
|
-
await self.run_test(self.test_async_deno_async_await, "Async Deno Async/Await")
|
|
2583
|
-
await self.run_test(
|
|
2584
|
-
self.test_async_deno_file_operations, "Async Deno File Operations"
|
|
2585
|
-
)
|
|
2586
|
-
await self.run_test(
|
|
2587
|
-
self.test_async_deno_context_management, "Async Deno Context Management"
|
|
2588
|
-
)
|
|
2589
|
-
|
|
2590
|
-
# 高级异步功能测试
|
|
2591
|
-
await self.run_test(
|
|
2592
|
-
self.test_async_websocket_simulation, "Async WebSocket Simulation"
|
|
2593
|
-
)
|
|
2594
|
-
|
|
2595
|
-
async def cleanup(self):
|
|
2596
|
-
"""清理资源"""
|
|
2597
|
-
# 清理剩余的上下文
|
|
2598
|
-
for name, context in self.contexts.items():
|
|
2599
|
-
try:
|
|
2600
|
-
await self.sandbox.destroy_context(context)
|
|
2601
|
-
logger.info(
|
|
2602
|
-
f"Successfully destroyed async context {name}: {context.id}"
|
|
2603
|
-
)
|
|
2604
|
-
except Exception as e:
|
|
2605
|
-
logger.warning(f"Error cleaning up async context {name}: {e}")
|
|
2606
|
-
|
|
2607
|
-
# 清空contexts字典
|
|
2608
|
-
self.contexts.clear()
|
|
2609
|
-
|
|
2610
|
-
# 清理异步沙箱
|
|
2611
|
-
if self.sandbox:
|
|
2612
|
-
try:
|
|
2613
|
-
# await self.sandbox.kill()
|
|
2614
|
-
logger.info("AsyncCodeInterpreter sandbox cleaned up successfully")
|
|
2615
|
-
except Exception as e:
|
|
2616
|
-
logger.error(f"Error cleaning up async sandbox: {e}")
|
|
2617
|
-
|
|
2618
|
-
def print_summary(self):
|
|
2619
|
-
"""打印测试摘要"""
|
|
2620
|
-
total_tests = len(self.test_results)
|
|
2621
|
-
passed_tests = sum(1 for r in self.test_results if r["success"])
|
|
2622
|
-
failed_tests = total_tests - passed_tests
|
|
2623
|
-
|
|
2624
|
-
total_duration = sum(r["duration"] for r in self.test_results)
|
|
2625
|
-
|
|
2626
|
-
print("\n" + "=" * 60)
|
|
2627
|
-
print("AsyncCodeInterpreter综合验证测试报告")
|
|
2628
|
-
print("=" * 60)
|
|
2629
|
-
print(f"总测试数: {total_tests}")
|
|
2630
|
-
print(f"通过数: {passed_tests}")
|
|
2631
|
-
print(f"失败数: {failed_tests}")
|
|
2632
|
-
print(f"总耗时: {total_duration:.3f}秒")
|
|
2633
|
-
print(f"成功率: {(passed_tests/total_tests*100):.1f}%")
|
|
2634
|
-
|
|
2635
|
-
if self.failed_tests:
|
|
2636
|
-
print(f"\n失败的测试:")
|
|
2637
|
-
for test in self.failed_tests:
|
|
2638
|
-
print(f" ❌ {test}")
|
|
2639
|
-
|
|
2640
|
-
print("=" * 60)
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
async def main():
|
|
2644
|
-
"""主函数"""
|
|
2645
|
-
validator = AsyncCodeInterpreterValidator()
|
|
2646
|
-
|
|
2647
|
-
try:
|
|
2648
|
-
await validator.run_all_tests()
|
|
2649
|
-
finally:
|
|
2650
|
-
await validator.cleanup()
|
|
2651
|
-
validator.print_summary()
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
if __name__ == "__main__":
|
|
2655
|
-
asyncio.run(main())
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Comprehensive validation test for code_interpreter async module.
|
|
4
|
+
|
|
5
|
+
This test suite demonstrates and validates all key functionality of the AsyncCodeInterpreter:
|
|
6
|
+
- Basic async code execution (Python, shell commands)
|
|
7
|
+
- Async callback handling (stdout, stderr, result, error)
|
|
8
|
+
- Context management (create, persist, destroy)
|
|
9
|
+
- Error handling and edge cases
|
|
10
|
+
- Performance testing with concurrency
|
|
11
|
+
- Different data types and formats
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import asyncio
|
|
15
|
+
import datetime
|
|
16
|
+
import json
|
|
17
|
+
import logging
|
|
18
|
+
import os
|
|
19
|
+
import time
|
|
20
|
+
from typing import Any, Dict, List, Optional
|
|
21
|
+
|
|
22
|
+
from e2b_code_interpreter import Sandbox
|
|
23
|
+
|
|
24
|
+
from scalebox.code_interpreter import (
|
|
25
|
+
AsyncSandbox,
|
|
26
|
+
Context,
|
|
27
|
+
Execution,
|
|
28
|
+
ExecutionError,
|
|
29
|
+
Logs,
|
|
30
|
+
OutputMessage,
|
|
31
|
+
Result,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# 配置日志
|
|
35
|
+
logging.basicConfig(
|
|
36
|
+
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
|
|
37
|
+
)
|
|
38
|
+
logger = logging.getLogger(__name__)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class AsyncCodeInterpreterValidator:
|
|
42
|
+
"""Comprehensive AsyncCodeInterpreter validation test suite."""
|
|
43
|
+
|
|
44
|
+
def __init__(self):
|
|
45
|
+
self.sandbox: Optional[AsyncSandbox] = None
|
|
46
|
+
self.test_results = []
|
|
47
|
+
self.failed_tests = []
|
|
48
|
+
self.contexts: Dict[str, Context] = {}
|
|
49
|
+
|
|
50
|
+
async def log_test_result(
|
|
51
|
+
self, test_name: str, success: bool, message: str = "", duration: float = 0
|
|
52
|
+
):
|
|
53
|
+
"""记录测试结果"""
|
|
54
|
+
status = "✅ PASS" if success else "❌ FAIL"
|
|
55
|
+
result = {
|
|
56
|
+
"test": test_name,
|
|
57
|
+
"success": success,
|
|
58
|
+
"message": message,
|
|
59
|
+
"duration": duration,
|
|
60
|
+
}
|
|
61
|
+
self.test_results.append(result)
|
|
62
|
+
|
|
63
|
+
if not success:
|
|
64
|
+
self.failed_tests.append(test_name)
|
|
65
|
+
|
|
66
|
+
logger.info(f"{status} {test_name} ({duration:.3f}s) {message}")
|
|
67
|
+
|
|
68
|
+
async def run_test(self, test_func, test_name: str):
|
|
69
|
+
"""运行单个测试并记录结果"""
|
|
70
|
+
start_time = time.time()
|
|
71
|
+
try:
|
|
72
|
+
await test_func()
|
|
73
|
+
duration = time.time() - start_time
|
|
74
|
+
await self.log_test_result(test_name, True, duration=duration)
|
|
75
|
+
except Exception as e:
|
|
76
|
+
duration = time.time() - start_time
|
|
77
|
+
await self.log_test_result(test_name, False, str(e), duration=duration)
|
|
78
|
+
|
|
79
|
+
# ======================== 基础异步代码解释器操作测试 ========================
|
|
80
|
+
|
|
81
|
+
async def test_async_code_interpreter_creation(self):
|
|
82
|
+
"""测试异步代码解释器创建"""
|
|
83
|
+
self.sandbox = await AsyncSandbox.create(
|
|
84
|
+
template="code-interpreter",
|
|
85
|
+
timeout=3600,
|
|
86
|
+
debug=True,
|
|
87
|
+
metadata={"test": "async_code_interpreter_validation"},
|
|
88
|
+
envs={"CI_TEST": "async_test"},
|
|
89
|
+
)
|
|
90
|
+
# time.sleep(5)
|
|
91
|
+
assert self.sandbox is not None
|
|
92
|
+
assert self.sandbox.sandbox_id is not None
|
|
93
|
+
logger.info(
|
|
94
|
+
f"Created AsyncCodeInterpreter sandbox with ID: {self.sandbox.sandbox_id}"
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
async def test_basic_async_python_execution(self):
|
|
98
|
+
"""测试基础异步Python代码执行"""
|
|
99
|
+
assert self.sandbox is not None
|
|
100
|
+
|
|
101
|
+
code = """
|
|
102
|
+
import asyncio
|
|
103
|
+
import time
|
|
104
|
+
|
|
105
|
+
print("开始异步Python执行...")
|
|
106
|
+
|
|
107
|
+
async def async_calculation():
|
|
108
|
+
print("异步计算开始")
|
|
109
|
+
await asyncio.sleep(0.1) # 模拟异步操作
|
|
110
|
+
result = sum(range(100))
|
|
111
|
+
print(f"异步计算完成: {result}")
|
|
112
|
+
return result
|
|
113
|
+
|
|
114
|
+
async def main_async():
|
|
115
|
+
task1 = asyncio.create_task(async_calculation())
|
|
116
|
+
task2 = asyncio.create_task(async_calculation())
|
|
117
|
+
|
|
118
|
+
results = await asyncio.gather(task1, task2)
|
|
119
|
+
print(f"两个异步任务结果: {results}")
|
|
120
|
+
return {"results": results, "sum": sum(results)}
|
|
121
|
+
|
|
122
|
+
# 运行异步函数
|
|
123
|
+
result = await main_async()
|
|
124
|
+
print(f"最终结果: {result}")
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
execution = await self.sandbox.run_code(code, language="python")
|
|
128
|
+
assert isinstance(execution, Execution)
|
|
129
|
+
assert execution.error is None
|
|
130
|
+
assert len(execution.logs.stdout) > 0
|
|
131
|
+
assert any("异步Python执行" in line for line in execution.logs.stdout)
|
|
132
|
+
logger.info("Async Python execution completed successfully")
|
|
133
|
+
|
|
134
|
+
async def test_concurrent_code_execution(self):
|
|
135
|
+
"""测试并发代码执行"""
|
|
136
|
+
assert self.sandbox is not None
|
|
137
|
+
|
|
138
|
+
codes = [
|
|
139
|
+
"""
|
|
140
|
+
import asyncio
|
|
141
|
+
print(f"任务 1 开始")
|
|
142
|
+
await asyncio.sleep(0.1)
|
|
143
|
+
result = {"task": 1, "value": 10}
|
|
144
|
+
print(f"任务 1 完成: {result}")
|
|
145
|
+
result
|
|
146
|
+
""",
|
|
147
|
+
"""
|
|
148
|
+
import asyncio
|
|
149
|
+
print(f"任务 2 开始")
|
|
150
|
+
await asyncio.sleep(0.1)
|
|
151
|
+
result = {"task": 2, "value": 20}
|
|
152
|
+
print(f"任务 2 完成: {result}")
|
|
153
|
+
result
|
|
154
|
+
""",
|
|
155
|
+
"""
|
|
156
|
+
import asyncio
|
|
157
|
+
print(f"任务 3 开始")
|
|
158
|
+
await asyncio.sleep(0.1)
|
|
159
|
+
result = {"task": 3, "value": 30}
|
|
160
|
+
print(f"任务 3 完成: {result}")
|
|
161
|
+
result
|
|
162
|
+
""",
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
# 并发执行多个代码片段
|
|
166
|
+
start_time = time.time()
|
|
167
|
+
tasks = [self.sandbox.run_code(code, language="python") for code in codes]
|
|
168
|
+
results = await asyncio.gather(*tasks)
|
|
169
|
+
duration = time.time() - start_time
|
|
170
|
+
|
|
171
|
+
# 验证结果
|
|
172
|
+
assert len(results) == 3
|
|
173
|
+
for execution in results:
|
|
174
|
+
assert execution.error is None
|
|
175
|
+
assert len(execution.logs.stdout) > 0
|
|
176
|
+
|
|
177
|
+
logger.info(f"Concurrent execution completed in {duration:.3f}s")
|
|
178
|
+
assert duration < 2.0 # 并发执行应该比串行快
|
|
179
|
+
|
|
180
|
+
async def test_async_data_science_workflow(self):
|
|
181
|
+
"""测试异步数据科学工作流"""
|
|
182
|
+
assert self.sandbox is not None
|
|
183
|
+
|
|
184
|
+
code = """
|
|
185
|
+
import asyncio
|
|
186
|
+
import pandas as pd
|
|
187
|
+
import numpy as np
|
|
188
|
+
import json
|
|
189
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
190
|
+
import time
|
|
191
|
+
|
|
192
|
+
async def generate_data_async(size, data_type):
|
|
193
|
+
'''异步生成数据'''
|
|
194
|
+
print(f"开始生成 {data_type} 数据,大小: {size}")
|
|
195
|
+
|
|
196
|
+
# 在线程池中执行CPU密集型操作
|
|
197
|
+
loop = asyncio.get_event_loop()
|
|
198
|
+
with ThreadPoolExecutor() as executor:
|
|
199
|
+
if data_type == "random":
|
|
200
|
+
data = await loop.run_in_executor(executor, np.random.randn, size)
|
|
201
|
+
elif data_type == "sequence":
|
|
202
|
+
data = await loop.run_in_executor(executor, lambda: np.arange(size))
|
|
203
|
+
else:
|
|
204
|
+
data = await loop.run_in_executor(executor, np.ones, size)
|
|
205
|
+
|
|
206
|
+
print(f"{data_type} 数据生成完成")
|
|
207
|
+
return data
|
|
208
|
+
|
|
209
|
+
async def process_data_async(data, name):
|
|
210
|
+
'''异步处理数据'''
|
|
211
|
+
print(f"开始处理数据: {name}")
|
|
212
|
+
|
|
213
|
+
# 模拟异步处理
|
|
214
|
+
await asyncio.sleep(0.1)
|
|
215
|
+
|
|
216
|
+
stats = {
|
|
217
|
+
"name": name,
|
|
218
|
+
"mean": float(np.mean(data)),
|
|
219
|
+
"std": float(np.std(data)),
|
|
220
|
+
"min": float(np.min(data)),
|
|
221
|
+
"max": float(np.max(data)),
|
|
222
|
+
"size": len(data)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
print(f"数据处理完成: {name}")
|
|
226
|
+
return stats
|
|
227
|
+
|
|
228
|
+
print("开始异步数据科学工作流...")
|
|
229
|
+
|
|
230
|
+
# 并发生成多个数据集
|
|
231
|
+
data_tasks = [
|
|
232
|
+
generate_data_async(1000, "random"),
|
|
233
|
+
generate_data_async(1000, "sequence"),
|
|
234
|
+
generate_data_async(1000, "ones")
|
|
235
|
+
]
|
|
236
|
+
|
|
237
|
+
datasets = await asyncio.gather(*data_tasks)
|
|
238
|
+
|
|
239
|
+
# 并发处理数据
|
|
240
|
+
process_tasks = [
|
|
241
|
+
process_data_async(datasets[0], "随机数据"),
|
|
242
|
+
process_data_async(datasets[1], "序列数据"),
|
|
243
|
+
process_data_async(datasets[2], "常数数据")
|
|
244
|
+
]
|
|
245
|
+
|
|
246
|
+
stats_results = await asyncio.gather(*process_tasks)
|
|
247
|
+
|
|
248
|
+
print("\\n数据统计结果:")
|
|
249
|
+
for stats in stats_results:
|
|
250
|
+
print(f"{stats['name']}: 均值={stats['mean']:.3f}, 标准差={stats['std']:.3f}")
|
|
251
|
+
|
|
252
|
+
# 创建综合报告
|
|
253
|
+
report = {
|
|
254
|
+
"total_datasets": len(datasets),
|
|
255
|
+
"total_datapoints": sum(len(d) for d in datasets),
|
|
256
|
+
"statistics": stats_results,
|
|
257
|
+
"processing_time": "异步并发处理"
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
print(f"\\n工作流完成,处理了 {report['total_datapoints']} 个数据点")
|
|
261
|
+
report
|
|
262
|
+
"""
|
|
263
|
+
|
|
264
|
+
execution = await self.sandbox.run_code(code, language="python")
|
|
265
|
+
assert execution.error is None
|
|
266
|
+
assert any("数据科学工作流" in line for line in execution.logs.stdout)
|
|
267
|
+
|
|
268
|
+
# ======================== 异步回调函数测试 ========================
|
|
269
|
+
|
|
270
|
+
async def test_async_callback_handling(self):
|
|
271
|
+
"""测试异步回调函数处理"""
|
|
272
|
+
assert self.sandbox is not None
|
|
273
|
+
|
|
274
|
+
stdout_messages = []
|
|
275
|
+
stderr_messages = []
|
|
276
|
+
results = []
|
|
277
|
+
errors = []
|
|
278
|
+
|
|
279
|
+
async def async_stdout_callback(msg: OutputMessage):
|
|
280
|
+
await asyncio.sleep(0.001) # 模拟异步处理
|
|
281
|
+
stdout_messages.append(msg.content)
|
|
282
|
+
logger.info(f"ASYNC STDOUT: {msg.content}")
|
|
283
|
+
|
|
284
|
+
async def async_stderr_callback(msg: OutputMessage):
|
|
285
|
+
await asyncio.sleep(0.001)
|
|
286
|
+
stderr_messages.append(msg.content)
|
|
287
|
+
logger.info(f"ASYNC STDERR: {msg.content}")
|
|
288
|
+
|
|
289
|
+
async def async_result_callback(result: Result):
|
|
290
|
+
await asyncio.sleep(0.001)
|
|
291
|
+
results.append(result)
|
|
292
|
+
logger.info(f"ASYNC RESULT: {result}")
|
|
293
|
+
|
|
294
|
+
async def async_error_callback(error: ExecutionError):
|
|
295
|
+
await asyncio.sleep(0.001)
|
|
296
|
+
errors.append(error)
|
|
297
|
+
logger.info(f"ASYNC ERROR: {error.name} - {error.value}")
|
|
298
|
+
|
|
299
|
+
code = """
|
|
300
|
+
import asyncio
|
|
301
|
+
import sys
|
|
302
|
+
|
|
303
|
+
print("异步回调测试开始")
|
|
304
|
+
|
|
305
|
+
async def async_output_generator():
|
|
306
|
+
for i in range(3):
|
|
307
|
+
print(f"异步输出 {i+1}")
|
|
308
|
+
await asyncio.sleep(0.05)
|
|
309
|
+
|
|
310
|
+
print("这是标准错误信息", file=sys.stderr)
|
|
311
|
+
|
|
312
|
+
result = {"status": "completed", "items": 3, "type": "async"}
|
|
313
|
+
print(f"生成结果: {result}")
|
|
314
|
+
return result
|
|
315
|
+
|
|
316
|
+
result = await async_output_generator()
|
|
317
|
+
print("异步回调测试完成")
|
|
318
|
+
result
|
|
319
|
+
"""
|
|
320
|
+
|
|
321
|
+
execution = await self.sandbox.run_code(
|
|
322
|
+
code,
|
|
323
|
+
language="python",
|
|
324
|
+
on_stdout=async_stdout_callback,
|
|
325
|
+
on_stderr=async_stderr_callback,
|
|
326
|
+
on_result=async_result_callback,
|
|
327
|
+
on_error=async_error_callback,
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
assert execution.error is None
|
|
331
|
+
logger.info(f"Async callback test completed")
|
|
332
|
+
|
|
333
|
+
# ======================== 异步上下文管理测试 ========================
|
|
334
|
+
|
|
335
|
+
async def test_async_context_creation(self):
|
|
336
|
+
"""测试异步上下文创建"""
|
|
337
|
+
assert self.sandbox is not None
|
|
338
|
+
|
|
339
|
+
# 创建Python上下文
|
|
340
|
+
python_context = await self.sandbox.create_code_context(
|
|
341
|
+
language="python", cwd="/tmp"
|
|
342
|
+
)
|
|
343
|
+
assert isinstance(python_context, Context)
|
|
344
|
+
assert python_context.id is not None
|
|
345
|
+
self.contexts["async_python"] = python_context
|
|
346
|
+
logger.info(f"Created async Python context: {python_context.id}")
|
|
347
|
+
|
|
348
|
+
# 测试完成后立即清理context
|
|
349
|
+
try:
|
|
350
|
+
await self.sandbox.destroy_context(python_context)
|
|
351
|
+
logger.info(f"Successfully destroyed async context: {python_context.id}")
|
|
352
|
+
# 从contexts字典中移除
|
|
353
|
+
if "async_python" in self.contexts:
|
|
354
|
+
del self.contexts["async_python"]
|
|
355
|
+
except Exception as e:
|
|
356
|
+
logger.warning(f"Failed to destroy async context {python_context.id}: {e}")
|
|
357
|
+
|
|
358
|
+
async def test_async_context_state_management(self):
|
|
359
|
+
"""测试异步上下文状态管理"""
|
|
360
|
+
assert self.sandbox is not None
|
|
361
|
+
|
|
362
|
+
# 创建新的上下文用于状态管理测试
|
|
363
|
+
context = await self.sandbox.create_code_context(language="python", cwd="/tmp")
|
|
364
|
+
self.contexts["async_state_test"] = context
|
|
365
|
+
|
|
366
|
+
# 在上下文中设置异步状态
|
|
367
|
+
setup_code = """
|
|
368
|
+
import asyncio
|
|
369
|
+
|
|
370
|
+
# 异步状态变量
|
|
371
|
+
async_state = {
|
|
372
|
+
"connections": [],
|
|
373
|
+
"tasks": [],
|
|
374
|
+
"data_cache": {}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
async def add_connection(conn_id):
|
|
378
|
+
print(f"添加连接: {conn_id}")
|
|
379
|
+
async_state["connections"].append(conn_id)
|
|
380
|
+
await asyncio.sleep(0.01) # 模拟异步操作
|
|
381
|
+
return len(async_state["connections"])
|
|
382
|
+
|
|
383
|
+
# 初始化一些连接
|
|
384
|
+
connection_count = 0
|
|
385
|
+
for i in range(3):
|
|
386
|
+
count = await add_connection(f"conn_{i}")
|
|
387
|
+
connection_count = count
|
|
388
|
+
|
|
389
|
+
print(f"初始化完成,连接数: {connection_count}")
|
|
390
|
+
async_state
|
|
391
|
+
"""
|
|
392
|
+
|
|
393
|
+
execution1 = await self.sandbox.run_code(setup_code, context=context)
|
|
394
|
+
assert execution1.error is None
|
|
395
|
+
|
|
396
|
+
# 在同一上下文中使用已设置的状态
|
|
397
|
+
use_code = """
|
|
398
|
+
print(f"当前连接数: {len(async_state['connections'])}")
|
|
399
|
+
print(f"连接列表: {async_state['connections']}")
|
|
400
|
+
|
|
401
|
+
async def process_connections():
|
|
402
|
+
results = []
|
|
403
|
+
for conn in async_state["connections"]:
|
|
404
|
+
print(f"处理连接: {conn}")
|
|
405
|
+
await asyncio.sleep(0.01)
|
|
406
|
+
results.append(f"processed_{conn}")
|
|
407
|
+
return results
|
|
408
|
+
|
|
409
|
+
processed = await process_connections()
|
|
410
|
+
async_state["processed"] = processed
|
|
411
|
+
|
|
412
|
+
print(f"处理完成: {len(processed)} 个连接")
|
|
413
|
+
{"total_connections": len(async_state["connections"]), "processed": len(processed)}
|
|
414
|
+
"""
|
|
415
|
+
|
|
416
|
+
execution2 = await self.sandbox.run_code(use_code, context=context)
|
|
417
|
+
assert execution2.error is None
|
|
418
|
+
assert any("处理完成" in line for line in execution2.logs.stdout)
|
|
419
|
+
|
|
420
|
+
# 测试完成后立即清理context
|
|
421
|
+
try:
|
|
422
|
+
await self.sandbox.destroy_context(context)
|
|
423
|
+
logger.info(f"Successfully destroyed async state context: {context.id}")
|
|
424
|
+
# 从contexts字典中移除
|
|
425
|
+
if "async_state_test" in self.contexts:
|
|
426
|
+
del self.contexts["async_state_test"]
|
|
427
|
+
except Exception as e:
|
|
428
|
+
logger.warning(f"Failed to destroy async state context {context.id}: {e}")
|
|
429
|
+
|
|
430
|
+
# ======================== 异步性能测试 ========================
|
|
431
|
+
|
|
432
|
+
async def test_async_performance_concurrent_tasks(self):
|
|
433
|
+
"""测试异步性能 - 并发任务"""
|
|
434
|
+
assert self.sandbox is not None
|
|
435
|
+
|
|
436
|
+
code = """
|
|
437
|
+
import asyncio
|
|
438
|
+
import time
|
|
439
|
+
import random
|
|
440
|
+
|
|
441
|
+
async def cpu_bound_task(task_id, iterations):
|
|
442
|
+
'''CPU密集型异步任务'''
|
|
443
|
+
print(f"CPU任务 {task_id} 开始,迭代次数: {iterations}")
|
|
444
|
+
|
|
445
|
+
result = 0
|
|
446
|
+
for i in range(iterations):
|
|
447
|
+
result += i ** 2
|
|
448
|
+
# 定期让出控制权
|
|
449
|
+
if i % 1000 == 0:
|
|
450
|
+
await asyncio.sleep(0)
|
|
451
|
+
|
|
452
|
+
print(f"CPU任务 {task_id} 完成,结果: {result}")
|
|
453
|
+
return {"task_id": task_id, "result": result, "iterations": iterations}
|
|
454
|
+
|
|
455
|
+
async def io_bound_task(task_id, delay_time):
|
|
456
|
+
'''IO密集型异步任务'''
|
|
457
|
+
print(f"IO任务 {task_id} 开始,延迟: {delay_time}s")
|
|
458
|
+
|
|
459
|
+
start = time.time()
|
|
460
|
+
await asyncio.sleep(delay_time)
|
|
461
|
+
duration = time.time() - start
|
|
462
|
+
|
|
463
|
+
print(f"IO任务 {task_id} 完成,实际耗时: {duration:.3f}s")
|
|
464
|
+
return {"task_id": task_id, "delay": delay_time, "actual_duration": duration}
|
|
465
|
+
|
|
466
|
+
print("异步性能测试开始...")
|
|
467
|
+
overall_start = time.time()
|
|
468
|
+
|
|
469
|
+
# 创建混合任务:CPU密集型和IO密集型
|
|
470
|
+
cpu_tasks = [cpu_bound_task(i, 5000) for i in range(3)]
|
|
471
|
+
io_tasks = [io_bound_task(i+10, 0.1 + i*0.05) for i in range(4)]
|
|
472
|
+
|
|
473
|
+
# 并发执行所有任务
|
|
474
|
+
all_tasks = cpu_tasks + io_tasks
|
|
475
|
+
results = await asyncio.gather(*all_tasks)
|
|
476
|
+
|
|
477
|
+
overall_duration = time.time() - overall_start
|
|
478
|
+
|
|
479
|
+
print(f"\\n性能测试完成:")
|
|
480
|
+
print(f"总任务数: {len(results)}")
|
|
481
|
+
print(f"CPU任务数: {len(cpu_tasks)}")
|
|
482
|
+
print(f"IO任务数: {len(io_tasks)}")
|
|
483
|
+
print(f"总执行时间: {overall_duration:.3f}s")
|
|
484
|
+
|
|
485
|
+
# 分析结果
|
|
486
|
+
cpu_results = [r for r in results if "iterations" in r]
|
|
487
|
+
io_results = [r for r in results if "delay" in r]
|
|
488
|
+
|
|
489
|
+
avg_cpu_result = sum(r["result"] for r in cpu_results) / len(cpu_results)
|
|
490
|
+
avg_io_duration = sum(r["actual_duration"] for r in io_results) / len(io_results)
|
|
491
|
+
|
|
492
|
+
print(f"平均CPU任务结果: {avg_cpu_result:.0f}")
|
|
493
|
+
print(f"平均IO任务耗时: {avg_io_duration:.3f}s")
|
|
494
|
+
|
|
495
|
+
{
|
|
496
|
+
"total_tasks": len(results),
|
|
497
|
+
"cpu_tasks": len(cpu_tasks),
|
|
498
|
+
"io_tasks": len(io_tasks),
|
|
499
|
+
"total_time": overall_duration,
|
|
500
|
+
"avg_cpu_result": avg_cpu_result,
|
|
501
|
+
"avg_io_duration": avg_io_duration,
|
|
502
|
+
"concurrency_efficiency": (sum(r["delay"] for r in io_results) / overall_duration) if overall_duration > 0 else 0
|
|
503
|
+
}
|
|
504
|
+
"""
|
|
505
|
+
|
|
506
|
+
start_test_time = time.time()
|
|
507
|
+
execution = await self.sandbox.run_code(code, language="python")
|
|
508
|
+
test_duration = time.time() - start_test_time
|
|
509
|
+
|
|
510
|
+
assert execution.error is None
|
|
511
|
+
assert any("性能测试开始" in line for line in execution.logs.stdout)
|
|
512
|
+
logger.info(f"Async performance test completed in {test_duration:.3f}s")
|
|
513
|
+
|
|
514
|
+
async def test_async_batch_processing(self):
|
|
515
|
+
"""测试异步批处理"""
|
|
516
|
+
assert self.sandbox is not None
|
|
517
|
+
|
|
518
|
+
code = """
|
|
519
|
+
import asyncio
|
|
520
|
+
import json
|
|
521
|
+
import time
|
|
522
|
+
|
|
523
|
+
async def process_batch(batch_id, items):
|
|
524
|
+
'''异步批处理函数'''
|
|
525
|
+
print(f"开始处理批次 {batch_id},包含 {len(items)} 个项目")
|
|
526
|
+
|
|
527
|
+
processed_items = []
|
|
528
|
+
start_time = time.time()
|
|
529
|
+
|
|
530
|
+
for i, item in enumerate(items):
|
|
531
|
+
# 模拟处理每个项目
|
|
532
|
+
processed = {
|
|
533
|
+
"original": item,
|
|
534
|
+
"processed_value": item * 2,
|
|
535
|
+
"batch_id": batch_id,
|
|
536
|
+
"item_index": i
|
|
537
|
+
}
|
|
538
|
+
processed_items.append(processed)
|
|
539
|
+
|
|
540
|
+
# 每处理几个项目就让出控制权
|
|
541
|
+
if i % 5 == 0:
|
|
542
|
+
await asyncio.sleep(0.01)
|
|
543
|
+
|
|
544
|
+
processing_time = time.time() - start_time
|
|
545
|
+
print(f"批次 {batch_id} 处理完成,耗时: {processing_time:.3f}s")
|
|
546
|
+
|
|
547
|
+
return {
|
|
548
|
+
"batch_id": batch_id,
|
|
549
|
+
"item_count": len(items),
|
|
550
|
+
"processed_items": processed_items,
|
|
551
|
+
"processing_time": processing_time
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
# 准备测试数据
|
|
555
|
+
print("准备批处理数据...")
|
|
556
|
+
all_data = list(range(100)) # 100个数据项
|
|
557
|
+
|
|
558
|
+
# 分成多个批次
|
|
559
|
+
batch_size = 15
|
|
560
|
+
batches = [all_data[i:i+batch_size] for i in range(0, len(all_data), batch_size)]
|
|
561
|
+
|
|
562
|
+
print(f"数据分为 {len(batches)} 个批次,每批最多 {batch_size} 项")
|
|
563
|
+
|
|
564
|
+
# 并发处理所有批次
|
|
565
|
+
start_time = time.time()
|
|
566
|
+
batch_tasks = [process_batch(i, batch) for i, batch in enumerate(batches)]
|
|
567
|
+
results = await asyncio.gather(*batch_tasks)
|
|
568
|
+
total_time = time.time() - start_time
|
|
569
|
+
|
|
570
|
+
# 汇总结果
|
|
571
|
+
total_items = sum(r["item_count"] for r in results)
|
|
572
|
+
avg_batch_time = sum(r["processing_time"] for r in results) / len(results)
|
|
573
|
+
throughput = total_items / total_time
|
|
574
|
+
|
|
575
|
+
print(f"\\n批处理完成:")
|
|
576
|
+
print(f"总批次数: {len(results)}")
|
|
577
|
+
print(f"总项目数: {total_items}")
|
|
578
|
+
print(f"总耗时: {total_time:.3f}s")
|
|
579
|
+
print(f"平均批次耗时: {avg_batch_time:.3f}s")
|
|
580
|
+
print(f"处理吞吐量: {throughput:.1f} items/s")
|
|
581
|
+
|
|
582
|
+
{
|
|
583
|
+
"total_batches": len(results),
|
|
584
|
+
"total_items": total_items,
|
|
585
|
+
"total_time": total_time,
|
|
586
|
+
"avg_batch_time": avg_batch_time,
|
|
587
|
+
"throughput": throughput,
|
|
588
|
+
"efficiency": avg_batch_time / total_time * len(results) # 并发效率指标
|
|
589
|
+
}
|
|
590
|
+
"""
|
|
591
|
+
|
|
592
|
+
execution = await self.sandbox.run_code(code, language="python")
|
|
593
|
+
assert execution.error is None
|
|
594
|
+
assert any("批处理完成" in line for line in execution.logs.stdout)
|
|
595
|
+
|
|
596
|
+
# ======================== 异步错误处理测试 ========================
|
|
597
|
+
|
|
598
|
+
async def test_async_error_handling(self):
|
|
599
|
+
"""测试异步错误处理"""
|
|
600
|
+
assert self.sandbox is not None
|
|
601
|
+
|
|
602
|
+
error_captured = []
|
|
603
|
+
|
|
604
|
+
async def async_error_callback(error: ExecutionError):
|
|
605
|
+
error_captured.append(error)
|
|
606
|
+
logger.info(f"捕获异步错误: {error.name} - {error.value}")
|
|
607
|
+
|
|
608
|
+
# 测试异步错误
|
|
609
|
+
error_code = """
|
|
610
|
+
import asyncio
|
|
611
|
+
|
|
612
|
+
async def failing_task():
|
|
613
|
+
print("开始可能失败的异步任务")
|
|
614
|
+
await asyncio.sleep(0.1)
|
|
615
|
+
|
|
616
|
+
# 这里会产生一个错误
|
|
617
|
+
result = 10 / 0 # 除零错误
|
|
618
|
+
return result
|
|
619
|
+
|
|
620
|
+
async def error_handler_demo():
|
|
621
|
+
try:
|
|
622
|
+
result = await failing_task()
|
|
623
|
+
return result
|
|
624
|
+
except Exception as e:
|
|
625
|
+
print(f"在异步函数中捕获错误: {type(e).__name__}: {e}")
|
|
626
|
+
raise # 重新抛出错误
|
|
627
|
+
|
|
628
|
+
# 执行会产生错误的异步代码
|
|
629
|
+
await error_handler_demo()
|
|
630
|
+
"""
|
|
631
|
+
|
|
632
|
+
execution = await self.sandbox.run_code(
|
|
633
|
+
error_code, language="python", on_error=async_error_callback
|
|
634
|
+
)
|
|
635
|
+
assert execution.error is not None
|
|
636
|
+
assert "ZeroDivisionError" in execution.error.name
|
|
637
|
+
logger.info("Async error handling test passed")
|
|
638
|
+
|
|
639
|
+
# ======================== 异步结果格式测试 ========================
|
|
640
|
+
|
|
641
|
+
async def test_async_text_result(self):
|
|
642
|
+
"""测试异步文本格式结果"""
|
|
643
|
+
assert self.sandbox is not None
|
|
644
|
+
|
|
645
|
+
code = """
|
|
646
|
+
import asyncio
|
|
647
|
+
|
|
648
|
+
# 异步生成纯文本结果
|
|
649
|
+
async def generate_async_text():
|
|
650
|
+
await asyncio.sleep(0.1) # 模拟异步操作
|
|
651
|
+
|
|
652
|
+
text_content = '''
|
|
653
|
+
异步 CodeInterpreter 测试报告
|
|
654
|
+
===================================
|
|
655
|
+
|
|
656
|
+
执行类型: 异步执行
|
|
657
|
+
开始时间: 2024-09-17 10:30:00
|
|
658
|
+
执行状态: ✅ 异步成功
|
|
659
|
+
|
|
660
|
+
异步特性验证:
|
|
661
|
+
- 支持 async/await 语法
|
|
662
|
+
- 并发任务处理能力
|
|
663
|
+
- 异步回调机制
|
|
664
|
+
- 上下文状态管理
|
|
665
|
+
|
|
666
|
+
详细描述:
|
|
667
|
+
异步CodeInterpreter能够高效处理并发任务,
|
|
668
|
+
支持复杂的异步工作流程,提供出色的性能表现。
|
|
669
|
+
'''
|
|
670
|
+
return text_content
|
|
671
|
+
|
|
672
|
+
text_result = await generate_async_text()
|
|
673
|
+
print("生成异步文本格式结果")
|
|
674
|
+
text_result
|
|
675
|
+
"""
|
|
676
|
+
|
|
677
|
+
execution = await self.sandbox.run_code(code, language="python")
|
|
678
|
+
assert execution.error is None
|
|
679
|
+
assert len(execution.results) > 0
|
|
680
|
+
logger.info("异步文本格式结果测试完成")
|
|
681
|
+
|
|
682
|
+
async def test_async_mixed_format_result(self):
|
|
683
|
+
"""测试异步混合格式结果"""
|
|
684
|
+
assert self.sandbox is not None
|
|
685
|
+
|
|
686
|
+
code = """
|
|
687
|
+
import asyncio
|
|
688
|
+
import json
|
|
689
|
+
import base64
|
|
690
|
+
import matplotlib.pyplot as plt
|
|
691
|
+
import numpy as np
|
|
692
|
+
import io
|
|
693
|
+
|
|
694
|
+
async def generate_async_mixed_results():
|
|
695
|
+
print("开始异步生成混合格式结果...")
|
|
696
|
+
|
|
697
|
+
# 1. 异步文本摘要
|
|
698
|
+
await asyncio.sleep(0.05)
|
|
699
|
+
text_summary = '''
|
|
700
|
+
异步 CodeInterpreter 综合测试报告
|
|
701
|
+
=====================================
|
|
702
|
+
|
|
703
|
+
执行模式: 异步并发
|
|
704
|
+
完成时间: 2024-09-17 10:30:00
|
|
705
|
+
并发任务: 8个
|
|
706
|
+
整体状态: ✅ 异步成功
|
|
707
|
+
|
|
708
|
+
异步特性亮点:
|
|
709
|
+
- 高并发处理能力
|
|
710
|
+
- 异步资源管理
|
|
711
|
+
- 事件驱动架构
|
|
712
|
+
- 非阻塞I/O操作
|
|
713
|
+
'''
|
|
714
|
+
|
|
715
|
+
# 2. 异步HTML报告生成
|
|
716
|
+
await asyncio.sleep(0.05)
|
|
717
|
+
html_report = '''
|
|
718
|
+
<div class="async-result-report">
|
|
719
|
+
<h2>⚡ 异步 CodeInterpreter 测试完成</h2>
|
|
720
|
+
<div class="status-badge async-success">🚀 异步全部通过</div>
|
|
721
|
+
<div class="async-metrics">
|
|
722
|
+
<div class="metric">
|
|
723
|
+
<label>并发任务:</label>
|
|
724
|
+
<value>8个</value>
|
|
725
|
+
</div>
|
|
726
|
+
<div class="metric">
|
|
727
|
+
<label>平均延迟:</label>
|
|
728
|
+
<value>0.123s</value>
|
|
729
|
+
</div>
|
|
730
|
+
<div class="metric">
|
|
731
|
+
<label>吞吐量:</label>
|
|
732
|
+
<value>65 ops/s</value>
|
|
733
|
+
</div>
|
|
734
|
+
</div>
|
|
735
|
+
</div>
|
|
736
|
+
'''
|
|
737
|
+
|
|
738
|
+
# 3. 异步生成图表数据
|
|
739
|
+
await asyncio.sleep(0.05)
|
|
740
|
+
|
|
741
|
+
# 并发生成多个数据集
|
|
742
|
+
async def generate_chart_data(chart_type):
|
|
743
|
+
await asyncio.sleep(0.02)
|
|
744
|
+
if chart_type == "performance":
|
|
745
|
+
return {
|
|
746
|
+
"type": "line",
|
|
747
|
+
"title": "异步性能趋势",
|
|
748
|
+
"data": {
|
|
749
|
+
"labels": ["Task1", "Task2", "Task3", "Task4", "Task5"],
|
|
750
|
+
"values": [92, 95, 88, 97, 94]
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
elif chart_type == "concurrency":
|
|
754
|
+
return {
|
|
755
|
+
"type": "bar",
|
|
756
|
+
"title": "并发执行统计",
|
|
757
|
+
"data": {
|
|
758
|
+
"labels": ["1并发", "2并发", "4并发", "8并发"],
|
|
759
|
+
"values": [45, 78, 142, 256]
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
# 并发生成图表数据
|
|
764
|
+
chart_tasks = [
|
|
765
|
+
generate_chart_data("performance"),
|
|
766
|
+
generate_chart_data("concurrency")
|
|
767
|
+
]
|
|
768
|
+
chart_data_list = await asyncio.gather(*chart_tasks)
|
|
769
|
+
|
|
770
|
+
# 4. 异步JSON数据编译
|
|
771
|
+
await asyncio.sleep(0.05)
|
|
772
|
+
json_data = {
|
|
773
|
+
"async_execution": {
|
|
774
|
+
"mode": "concurrent",
|
|
775
|
+
"tasks_completed": 8,
|
|
776
|
+
"success_rate": 100.0,
|
|
777
|
+
"avg_response_time": 0.123
|
|
778
|
+
},
|
|
779
|
+
"performance_summary": {
|
|
780
|
+
"throughput": 65,
|
|
781
|
+
"peak_concurrency": 8,
|
|
782
|
+
"memory_efficient": True,
|
|
783
|
+
"cpu_utilization": "optimal"
|
|
784
|
+
},
|
|
785
|
+
"async_features": [
|
|
786
|
+
"异步任务调度",
|
|
787
|
+
"并发资源管理",
|
|
788
|
+
"事件循环优化",
|
|
789
|
+
"非阻塞I/O处理"
|
|
790
|
+
],
|
|
791
|
+
"charts": chart_data_list
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
# 5. 异步Markdown生成
|
|
795
|
+
await asyncio.sleep(0.05)
|
|
796
|
+
markdown_content = '''
|
|
797
|
+
## ⚡ 异步 CodeInterpreter 测试总结
|
|
798
|
+
|
|
799
|
+
### 🎯 异步执行成就
|
|
800
|
+
- **完美并发**: 8个任务同时执行
|
|
801
|
+
- **零阻塞**: 所有I/O操作非阻塞
|
|
802
|
+
- **高吞吐量**: 65 操作/秒
|
|
803
|
+
- **资源高效**: CPU和内存使用最优
|
|
804
|
+
|
|
805
|
+
### 📊 并发性能指标
|
|
806
|
+
| 并发级别 | 吞吐量 | 响应时间 | 资源使用 |
|
|
807
|
+
|---------|--------|----------|----------|
|
|
808
|
+
| 1 | 45 ops/s | 0.022s | 低 |
|
|
809
|
+
| 2 | 78 ops/s | 0.025s | 低 |
|
|
810
|
+
| 4 | 142 ops/s | 0.028s | 中 |
|
|
811
|
+
| 8 | 256 ops/s | 0.031s | 中 |
|
|
812
|
+
|
|
813
|
+
### 🚀 异步优势
|
|
814
|
+
1. **事件驱动**: 基于事件循环的高效调度
|
|
815
|
+
2. **资源节约**: 单线程处理多任务
|
|
816
|
+
3. **扩展性强**: 轻松应对高并发场景
|
|
817
|
+
'''
|
|
818
|
+
|
|
819
|
+
print("异步混合格式结果生成完成!")
|
|
820
|
+
|
|
821
|
+
return {
|
|
822
|
+
"formats": ["text", "html", "json", "markdown", "chart"],
|
|
823
|
+
"text": text_summary,
|
|
824
|
+
"html": html_report,
|
|
825
|
+
"json_data": json_data,
|
|
826
|
+
"markdown": markdown_content,
|
|
827
|
+
"charts": chart_data_list,
|
|
828
|
+
"async_summary": {
|
|
829
|
+
"total_formats": 5,
|
|
830
|
+
"concurrent_tasks": 8,
|
|
831
|
+
"execution_mode": "async",
|
|
832
|
+
"performance": "excellent"
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
# 执行异步混合格式生成
|
|
837
|
+
result = await generate_async_mixed_results()
|
|
838
|
+
result
|
|
839
|
+
"""
|
|
840
|
+
|
|
841
|
+
execution = await self.sandbox.run_code(code, language="python")
|
|
842
|
+
assert execution.error is None
|
|
843
|
+
assert any("异步混合格式结果生成完成" in line for line in execution.logs.stdout)
|
|
844
|
+
logger.info("异步混合格式结果测试完成")
|
|
845
|
+
|
|
846
|
+
async def test_async_realtime_data_result(self):
|
|
847
|
+
"""测试异步实时数据结果"""
|
|
848
|
+
assert self.sandbox is not None
|
|
849
|
+
|
|
850
|
+
code = """
|
|
851
|
+
import asyncio
|
|
852
|
+
import json
|
|
853
|
+
import time
|
|
854
|
+
from datetime import datetime
|
|
855
|
+
|
|
856
|
+
class AsyncDataStream:
|
|
857
|
+
def __init__(self):
|
|
858
|
+
self.data_points = []
|
|
859
|
+
self.subscribers = []
|
|
860
|
+
|
|
861
|
+
async def generate_data_point(self, index):
|
|
862
|
+
'''异步生成单个数据点'''
|
|
863
|
+
await asyncio.sleep(0.02) # 模拟数据采集延迟
|
|
864
|
+
|
|
865
|
+
data_point = {
|
|
866
|
+
"id": index,
|
|
867
|
+
"timestamp": datetime.now().isoformat(),
|
|
868
|
+
"value": 50 + 25 * (0.5 - __import__('random').random()),
|
|
869
|
+
"status": "active",
|
|
870
|
+
"metadata": {
|
|
871
|
+
"source": f"sensor_{index % 4}",
|
|
872
|
+
"quality": __import__('random').choice(["high", "medium", "high", "high"])
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
return data_point
|
|
876
|
+
|
|
877
|
+
async def collect_realtime_data(self, duration_seconds=1):
|
|
878
|
+
'''异步收集实时数据流'''
|
|
879
|
+
print(f"开始 {duration_seconds}s 实时数据收集...")
|
|
880
|
+
|
|
881
|
+
start_time = time.time()
|
|
882
|
+
data_tasks = []
|
|
883
|
+
|
|
884
|
+
# 创建数据收集任务
|
|
885
|
+
for i in range(20): # 收集20个数据点
|
|
886
|
+
task = asyncio.create_task(self.generate_data_point(i))
|
|
887
|
+
data_tasks.append(task)
|
|
888
|
+
await asyncio.sleep(0.05) # 每50ms启动一个任务
|
|
889
|
+
|
|
890
|
+
# 并发等待所有数据收集完成
|
|
891
|
+
collected_data = await asyncio.gather(*data_tasks)
|
|
892
|
+
collection_time = time.time() - start_time
|
|
893
|
+
|
|
894
|
+
print(f"数据收集完成,耗时: {collection_time:.3f}s")
|
|
895
|
+
|
|
896
|
+
return {
|
|
897
|
+
"data_points": collected_data,
|
|
898
|
+
"collection_time": collection_time,
|
|
899
|
+
"total_points": len(collected_data),
|
|
900
|
+
"throughput": len(collected_data) / collection_time
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
async def process_data_stream(self, raw_data):
|
|
904
|
+
'''异步处理数据流'''
|
|
905
|
+
print("开始异步数据流处理...")
|
|
906
|
+
|
|
907
|
+
# 并发处理不同的数据分析任务
|
|
908
|
+
async def calculate_statistics():
|
|
909
|
+
await asyncio.sleep(0.1)
|
|
910
|
+
values = [dp["value"] for dp in raw_data["data_points"]]
|
|
911
|
+
return {
|
|
912
|
+
"mean": sum(values) / len(values),
|
|
913
|
+
"min": min(values),
|
|
914
|
+
"max": max(values),
|
|
915
|
+
"count": len(values)
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
async def analyze_quality():
|
|
919
|
+
await asyncio.sleep(0.08)
|
|
920
|
+
quality_counts = {}
|
|
921
|
+
for dp in raw_data["data_points"]:
|
|
922
|
+
quality = dp["metadata"]["quality"]
|
|
923
|
+
quality_counts[quality] = quality_counts.get(quality, 0) + 1
|
|
924
|
+
return quality_counts
|
|
925
|
+
|
|
926
|
+
async def detect_anomalies():
|
|
927
|
+
await asyncio.sleep(0.06)
|
|
928
|
+
values = [dp["value"] for dp in raw_data["data_points"]]
|
|
929
|
+
mean_val = sum(values) / len(values)
|
|
930
|
+
threshold = 20 # 异常阈值
|
|
931
|
+
|
|
932
|
+
anomalies = []
|
|
933
|
+
for dp in raw_data["data_points"]:
|
|
934
|
+
if abs(dp["value"] - mean_val) > threshold:
|
|
935
|
+
anomalies.append({
|
|
936
|
+
"id": dp["id"],
|
|
937
|
+
"value": dp["value"],
|
|
938
|
+
"deviation": abs(dp["value"] - mean_val)
|
|
939
|
+
})
|
|
940
|
+
return anomalies
|
|
941
|
+
|
|
942
|
+
# 并发执行所有分析任务
|
|
943
|
+
stats, quality, anomalies = await asyncio.gather(
|
|
944
|
+
calculate_statistics(),
|
|
945
|
+
analyze_quality(),
|
|
946
|
+
detect_anomalies()
|
|
947
|
+
)
|
|
948
|
+
|
|
949
|
+
return {
|
|
950
|
+
"statistics": stats,
|
|
951
|
+
"quality_distribution": quality,
|
|
952
|
+
"anomalies": anomalies,
|
|
953
|
+
"processed_at": datetime.now().isoformat()
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
# 运行异步实时数据收集和处理
|
|
957
|
+
print("启动异步实时数据系统...")
|
|
958
|
+
stream = AsyncDataStream()
|
|
959
|
+
|
|
960
|
+
# 收集数据
|
|
961
|
+
raw_data = await stream.collect_realtime_data(1)
|
|
962
|
+
print(f"收集了 {raw_data['total_points']} 个数据点")
|
|
963
|
+
print(f"数据吞吐量: {raw_data['throughput']:.1f} points/s")
|
|
964
|
+
|
|
965
|
+
# 处理数据
|
|
966
|
+
processed_data = await stream.process_data_stream(raw_data)
|
|
967
|
+
print(f"\\n数据处理结果:")
|
|
968
|
+
print(f" 平均值: {processed_data['statistics']['mean']:.2f}")
|
|
969
|
+
print(f" 数据质量分布: {processed_data['quality_distribution']}")
|
|
970
|
+
print(f" 异常数据点: {len(processed_data['anomalies'])} 个")
|
|
971
|
+
|
|
972
|
+
# 生成实时数据结果
|
|
973
|
+
result = {
|
|
974
|
+
"realtime_data": {
|
|
975
|
+
"collection_summary": {
|
|
976
|
+
"total_points": raw_data['total_points'],
|
|
977
|
+
"collection_time": raw_data['collection_time'],
|
|
978
|
+
"throughput": raw_data['throughput']
|
|
979
|
+
},
|
|
980
|
+
"data_analysis": processed_data,
|
|
981
|
+
"raw_samples": raw_data['data_points'][:5], # 显示前5个样本
|
|
982
|
+
"system_performance": {
|
|
983
|
+
"concurrent_tasks": 20,
|
|
984
|
+
"processing_efficiency": "高效",
|
|
985
|
+
"memory_usage": "优化",
|
|
986
|
+
"async_benefits": [
|
|
987
|
+
"非阻塞数据收集",
|
|
988
|
+
"并发数据处理",
|
|
989
|
+
"实时流式计算",
|
|
990
|
+
"资源高效利用"
|
|
991
|
+
]
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
print(f"\\n异步实时数据系统测试完成!")
|
|
997
|
+
result
|
|
998
|
+
"""
|
|
999
|
+
|
|
1000
|
+
execution = await self.sandbox.run_code(code, language="python")
|
|
1001
|
+
assert execution.error is None
|
|
1002
|
+
assert any("异步实时数据系统测试完成" in line for line in execution.logs.stdout)
|
|
1003
|
+
logger.info("异步实时数据结果测试完成")
|
|
1004
|
+
|
|
1005
|
+
# ======================== 异步R语言测试 ========================
|
|
1006
|
+
|
|
1007
|
+
async def test_async_r_language_basic_execution(self):
|
|
1008
|
+
"""测试异步R语言基础执行"""
|
|
1009
|
+
assert self.sandbox is not None
|
|
1010
|
+
|
|
1011
|
+
code = """
|
|
1012
|
+
# 异步R语言基础执行测试
|
|
1013
|
+
print("Hello from Async R Language!")
|
|
1014
|
+
|
|
1015
|
+
# 基础数学运算
|
|
1016
|
+
x <- 15
|
|
1017
|
+
y <- 25
|
|
1018
|
+
sum_result <- x + y
|
|
1019
|
+
product_result <- x * y
|
|
1020
|
+
|
|
1021
|
+
print(paste("Sum:", sum_result))
|
|
1022
|
+
print(paste("Product:", product_result))
|
|
1023
|
+
|
|
1024
|
+
# 向量操作
|
|
1025
|
+
numbers <- c(2, 4, 6, 8, 10)
|
|
1026
|
+
mean_value <- mean(numbers)
|
|
1027
|
+
print(paste("Mean of numbers:", mean_value))
|
|
1028
|
+
|
|
1029
|
+
# 数据框创建
|
|
1030
|
+
df <- data.frame(
|
|
1031
|
+
name = c("David", "Emma", "Frank"),
|
|
1032
|
+
age = c(28, 32, 26),
|
|
1033
|
+
city = c("Paris", "Berlin", "Madrid")
|
|
1034
|
+
)
|
|
1035
|
+
|
|
1036
|
+
print("Data frame created:")
|
|
1037
|
+
print(df)
|
|
1038
|
+
|
|
1039
|
+
# 返回结果
|
|
1040
|
+
list(
|
|
1041
|
+
sum = sum_result,
|
|
1042
|
+
product = product_result,
|
|
1043
|
+
mean = mean_value,
|
|
1044
|
+
data_frame = df
|
|
1045
|
+
)
|
|
1046
|
+
"""
|
|
1047
|
+
|
|
1048
|
+
execution = await self.sandbox.run_code(code, language="r")
|
|
1049
|
+
assert execution.error is None
|
|
1050
|
+
assert any(
|
|
1051
|
+
"Hello from Async R Language!" in line for line in execution.logs.stdout
|
|
1052
|
+
)
|
|
1053
|
+
assert any("Sum:" in line for line in execution.logs.stdout)
|
|
1054
|
+
logger.info("Async R language basic execution test passed")
|
|
1055
|
+
|
|
1056
|
+
async def test_async_r_language_data_analysis(self):
|
|
1057
|
+
"""测试异步R语言数据分析"""
|
|
1058
|
+
assert self.sandbox is not None
|
|
1059
|
+
|
|
1060
|
+
code = """
|
|
1061
|
+
# 异步R语言数据分析测试
|
|
1062
|
+
library(dplyr)
|
|
1063
|
+
|
|
1064
|
+
# 创建示例数据集
|
|
1065
|
+
set.seed(456)
|
|
1066
|
+
data <- data.frame(
|
|
1067
|
+
id = 1:150,
|
|
1068
|
+
value = rnorm(150, mean = 60, sd = 20),
|
|
1069
|
+
category = sample(c("X", "Y", "Z"), 150, replace = TRUE),
|
|
1070
|
+
score = runif(150, 0, 100)
|
|
1071
|
+
)
|
|
1072
|
+
|
|
1073
|
+
print("Async dataset created with 150 rows")
|
|
1074
|
+
print(paste("Columns:", paste(names(data), collapse = ", ")))
|
|
1075
|
+
|
|
1076
|
+
# 基础统计
|
|
1077
|
+
summary_stats <- summary(data$value)
|
|
1078
|
+
print("Summary statistics for value column:")
|
|
1079
|
+
print(summary_stats)
|
|
1080
|
+
|
|
1081
|
+
# 按类别分组统计
|
|
1082
|
+
grouped_stats <- data %>%
|
|
1083
|
+
group_by(category) %>%
|
|
1084
|
+
summarise(
|
|
1085
|
+
count = n(),
|
|
1086
|
+
mean_value = mean(value),
|
|
1087
|
+
mean_score = mean(score),
|
|
1088
|
+
.groups = 'drop'
|
|
1089
|
+
)
|
|
1090
|
+
|
|
1091
|
+
print("Grouped statistics:")
|
|
1092
|
+
print(grouped_stats)
|
|
1093
|
+
|
|
1094
|
+
# 数据过滤
|
|
1095
|
+
high_scores <- data %>%
|
|
1096
|
+
filter(score > 85) %>%
|
|
1097
|
+
arrange(desc(score))
|
|
1098
|
+
|
|
1099
|
+
print(paste("High scores (>85):", nrow(high_scores), "rows"))
|
|
1100
|
+
|
|
1101
|
+
# 返回分析结果
|
|
1102
|
+
list(
|
|
1103
|
+
total_rows = nrow(data),
|
|
1104
|
+
summary = summary_stats,
|
|
1105
|
+
grouped = grouped_stats,
|
|
1106
|
+
high_scores_count = nrow(high_scores)
|
|
1107
|
+
)
|
|
1108
|
+
"""
|
|
1109
|
+
|
|
1110
|
+
execution = await self.sandbox.run_code(code, language="r")
|
|
1111
|
+
assert execution.error is None
|
|
1112
|
+
assert any(
|
|
1113
|
+
"Async dataset created with 150 rows" in line
|
|
1114
|
+
for line in execution.logs.stdout
|
|
1115
|
+
)
|
|
1116
|
+
assert any("Summary statistics" in line for line in execution.logs.stdout)
|
|
1117
|
+
logger.info("Async R language data analysis test passed")
|
|
1118
|
+
|
|
1119
|
+
async def test_async_r_language_visualization(self):
|
|
1120
|
+
"""测试异步R语言数据可视化"""
|
|
1121
|
+
assert self.sandbox is not None
|
|
1122
|
+
|
|
1123
|
+
code = """
|
|
1124
|
+
# 异步R语言数据可视化测试
|
|
1125
|
+
library(ggplot2)
|
|
1126
|
+
|
|
1127
|
+
# 创建示例数据
|
|
1128
|
+
set.seed(789)
|
|
1129
|
+
plot_data <- data.frame(
|
|
1130
|
+
x = 1:60,
|
|
1131
|
+
y = cumsum(rnorm(60)),
|
|
1132
|
+
group = rep(c("GroupA", "GroupB", "GroupC"), each = 20)
|
|
1133
|
+
)
|
|
1134
|
+
|
|
1135
|
+
print("Creating async visualizations...")
|
|
1136
|
+
|
|
1137
|
+
# 基础散点图
|
|
1138
|
+
p1 <- ggplot(plot_data, aes(x = x, y = y)) +
|
|
1139
|
+
geom_point() +
|
|
1140
|
+
geom_smooth(method = "lm") +
|
|
1141
|
+
labs(title = "Async Scatter Plot with Trend Line",
|
|
1142
|
+
x = "X Values", y = "Y Values") +
|
|
1143
|
+
theme_minimal()
|
|
1144
|
+
|
|
1145
|
+
print("Async scatter plot created")
|
|
1146
|
+
|
|
1147
|
+
# 分组箱线图
|
|
1148
|
+
p2 <- ggplot(plot_data, aes(x = group, y = y, fill = group)) +
|
|
1149
|
+
geom_boxplot() +
|
|
1150
|
+
labs(title = "Async Box Plot by Group",
|
|
1151
|
+
x = "Group", y = "Y Values") +
|
|
1152
|
+
theme_minimal()
|
|
1153
|
+
|
|
1154
|
+
print("Async box plot created")
|
|
1155
|
+
|
|
1156
|
+
# 直方图
|
|
1157
|
+
p3 <- ggplot(plot_data, aes(x = y)) +
|
|
1158
|
+
geom_histogram(bins = 25, fill = "lightcoral", alpha = 0.7) +
|
|
1159
|
+
labs(title = "Async Distribution of Y Values",
|
|
1160
|
+
x = "Y Values", y = "Frequency") +
|
|
1161
|
+
theme_minimal()
|
|
1162
|
+
|
|
1163
|
+
print("Async histogram created")
|
|
1164
|
+
|
|
1165
|
+
# 保存图表信息
|
|
1166
|
+
plot_info <- list(
|
|
1167
|
+
scatter_plot = "Created async scatter plot with trend line",
|
|
1168
|
+
box_plot = "Created async box plot by group",
|
|
1169
|
+
histogram = "Created async histogram of y values",
|
|
1170
|
+
total_plots = 3
|
|
1171
|
+
)
|
|
1172
|
+
|
|
1173
|
+
print("All async visualizations completed successfully")
|
|
1174
|
+
plot_info
|
|
1175
|
+
"""
|
|
1176
|
+
|
|
1177
|
+
execution = await self.sandbox.run_code(code, language="r")
|
|
1178
|
+
assert execution.error is None
|
|
1179
|
+
assert any(
|
|
1180
|
+
"Creating async visualizations..." in line for line in execution.logs.stdout
|
|
1181
|
+
)
|
|
1182
|
+
assert any(
|
|
1183
|
+
"All async visualizations completed successfully" in line
|
|
1184
|
+
for line in execution.logs.stdout
|
|
1185
|
+
)
|
|
1186
|
+
logger.info("Async R language visualization test passed")
|
|
1187
|
+
|
|
1188
|
+
async def test_async_r_language_statistics(self):
|
|
1189
|
+
"""测试异步R语言统计分析"""
|
|
1190
|
+
assert self.sandbox is not None
|
|
1191
|
+
|
|
1192
|
+
code = """
|
|
1193
|
+
# 异步R语言统计分析测试
|
|
1194
|
+
library(stats)
|
|
1195
|
+
|
|
1196
|
+
# 创建两个样本数据
|
|
1197
|
+
set.seed(101112)
|
|
1198
|
+
sample1 <- rnorm(120, mean = 15, sd = 3)
|
|
1199
|
+
sample2 <- rnorm(120, mean = 18, sd = 3.5)
|
|
1200
|
+
|
|
1201
|
+
print("Created two async sample datasets")
|
|
1202
|
+
|
|
1203
|
+
# 描述性统计
|
|
1204
|
+
desc_stats1 <- list(
|
|
1205
|
+
mean = mean(sample1),
|
|
1206
|
+
median = median(sample1),
|
|
1207
|
+
sd = sd(sample1),
|
|
1208
|
+
min = min(sample1),
|
|
1209
|
+
max = max(sample1)
|
|
1210
|
+
)
|
|
1211
|
+
|
|
1212
|
+
desc_stats2 <- list(
|
|
1213
|
+
mean = mean(sample2),
|
|
1214
|
+
median = median(sample2),
|
|
1215
|
+
sd = sd(sample2),
|
|
1216
|
+
min = min(sample2),
|
|
1217
|
+
max = max(sample2)
|
|
1218
|
+
)
|
|
1219
|
+
|
|
1220
|
+
print("Async descriptive statistics calculated")
|
|
1221
|
+
|
|
1222
|
+
# t检验
|
|
1223
|
+
t_test_result <- t.test(sample1, sample2)
|
|
1224
|
+
print("Async T-test performed")
|
|
1225
|
+
|
|
1226
|
+
# 相关性分析
|
|
1227
|
+
correlation <- cor(sample1, sample2)
|
|
1228
|
+
print(paste("Async correlation coefficient:", round(correlation, 4)))
|
|
1229
|
+
|
|
1230
|
+
# 线性回归
|
|
1231
|
+
lm_model <- lm(sample2 ~ sample1)
|
|
1232
|
+
summary_lm <- summary(lm_model)
|
|
1233
|
+
print("Async linear regression model fitted")
|
|
1234
|
+
|
|
1235
|
+
# 正态性检验
|
|
1236
|
+
shapiro_test1 <- shapiro.test(sample1[1:50]) # 限制样本大小
|
|
1237
|
+
shapiro_test2 <- shapiro.test(sample2[1:50])
|
|
1238
|
+
|
|
1239
|
+
print("Async normality tests performed")
|
|
1240
|
+
|
|
1241
|
+
# 返回统计结果
|
|
1242
|
+
list(
|
|
1243
|
+
sample1_stats = desc_stats1,
|
|
1244
|
+
sample2_stats = desc_stats2,
|
|
1245
|
+
t_test_p_value = t_test_result$p.value,
|
|
1246
|
+
correlation = correlation,
|
|
1247
|
+
r_squared = summary_lm$r.squared,
|
|
1248
|
+
normality_test1_p = shapiro_test1$p.value,
|
|
1249
|
+
normality_test2_p = shapiro_test2$p.value
|
|
1250
|
+
)
|
|
1251
|
+
"""
|
|
1252
|
+
|
|
1253
|
+
execution = await self.sandbox.run_code(code, language="r")
|
|
1254
|
+
assert execution.error is None
|
|
1255
|
+
assert any(
|
|
1256
|
+
"Created two async sample datasets" in line
|
|
1257
|
+
for line in execution.logs.stdout
|
|
1258
|
+
)
|
|
1259
|
+
assert any("Async T-test performed" in line for line in execution.logs.stdout)
|
|
1260
|
+
logger.info("Async R language statistics test passed")
|
|
1261
|
+
|
|
1262
|
+
async def test_async_r_language_context_management(self):
|
|
1263
|
+
"""测试异步R语言上下文管理"""
|
|
1264
|
+
assert self.sandbox is not None
|
|
1265
|
+
|
|
1266
|
+
# 创建R语言上下文
|
|
1267
|
+
r_context = await self.sandbox.create_code_context(language="r", cwd="/tmp")
|
|
1268
|
+
self.contexts["async_r_language"] = r_context
|
|
1269
|
+
|
|
1270
|
+
# 在上下文中定义变量和函数
|
|
1271
|
+
setup_code = """
|
|
1272
|
+
# 异步R语言上下文设置
|
|
1273
|
+
print("Setting up async R language context...")
|
|
1274
|
+
|
|
1275
|
+
# 定义全局变量
|
|
1276
|
+
global_var <- "Hello from Async R Context"
|
|
1277
|
+
counter <- 0
|
|
1278
|
+
data_cache <- list()
|
|
1279
|
+
|
|
1280
|
+
# 定义函数
|
|
1281
|
+
increment_counter <- function() {
|
|
1282
|
+
counter <<- counter + 1
|
|
1283
|
+
return(counter)
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
add_to_cache <- function(key, value) {
|
|
1287
|
+
data_cache[[key]] <<- value
|
|
1288
|
+
return(length(data_cache))
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
# 初始化一些数据
|
|
1292
|
+
sample_data <- data.frame(
|
|
1293
|
+
x = 1:15,
|
|
1294
|
+
y = (1:15) ^ 2
|
|
1295
|
+
)
|
|
1296
|
+
|
|
1297
|
+
print(paste("Async context setup complete. Counter:", counter))
|
|
1298
|
+
print(paste("Cache size:", length(data_cache)))
|
|
1299
|
+
|
|
1300
|
+
# 返回设置信息
|
|
1301
|
+
list(
|
|
1302
|
+
global_var = global_var,
|
|
1303
|
+
counter = counter,
|
|
1304
|
+
cache_size = length(data_cache),
|
|
1305
|
+
data_rows = nrow(sample_data)
|
|
1306
|
+
)
|
|
1307
|
+
"""
|
|
1308
|
+
|
|
1309
|
+
execution1 = await self.sandbox.run_code(setup_code, context=r_context)
|
|
1310
|
+
assert execution1.error is None
|
|
1311
|
+
assert any(
|
|
1312
|
+
"Setting up async R language context..." in line
|
|
1313
|
+
for line in execution1.logs.stdout
|
|
1314
|
+
)
|
|
1315
|
+
|
|
1316
|
+
# 在同一上下文中使用之前定义的变量和函数
|
|
1317
|
+
use_code = """
|
|
1318
|
+
# 使用异步R语言上下文中的变量和函数
|
|
1319
|
+
print("Using async R language context...")
|
|
1320
|
+
|
|
1321
|
+
# 使用全局变量
|
|
1322
|
+
print(paste("Global variable:", global_var))
|
|
1323
|
+
|
|
1324
|
+
# 使用函数
|
|
1325
|
+
new_counter <- increment_counter()
|
|
1326
|
+
print(paste("Counter after increment:", new_counter))
|
|
1327
|
+
|
|
1328
|
+
# 添加到缓存
|
|
1329
|
+
cache_size <- add_to_cache("async_test_key", "async_test_value")
|
|
1330
|
+
print(paste("Cache size after addition:", cache_size))
|
|
1331
|
+
|
|
1332
|
+
# 使用数据
|
|
1333
|
+
data_summary <- summary(sample_data)
|
|
1334
|
+
print("Data summary:")
|
|
1335
|
+
print(data_summary)
|
|
1336
|
+
|
|
1337
|
+
# 修改数据
|
|
1338
|
+
sample_data$z <- sample_data$x + sample_data$y
|
|
1339
|
+
print(paste("Added new column. Total columns:", ncol(sample_data)))
|
|
1340
|
+
|
|
1341
|
+
# 返回使用结果
|
|
1342
|
+
list(
|
|
1343
|
+
final_counter = new_counter,
|
|
1344
|
+
final_cache_size = cache_size,
|
|
1345
|
+
data_columns = ncol(sample_data),
|
|
1346
|
+
context_active = TRUE
|
|
1347
|
+
)
|
|
1348
|
+
"""
|
|
1349
|
+
|
|
1350
|
+
execution2 = await self.sandbox.run_code(use_code, context=r_context)
|
|
1351
|
+
assert execution2.error is None
|
|
1352
|
+
assert any(
|
|
1353
|
+
"Using async R language context..." in line
|
|
1354
|
+
for line in execution2.logs.stdout
|
|
1355
|
+
)
|
|
1356
|
+
assert any(
|
|
1357
|
+
"Counter after increment:" in line for line in execution2.logs.stdout
|
|
1358
|
+
)
|
|
1359
|
+
logger.info("Async R language context management test passed")
|
|
1360
|
+
|
|
1361
|
+
# 测试完成后立即清理context
|
|
1362
|
+
try:
|
|
1363
|
+
await self.sandbox.destroy_context(r_context)
|
|
1364
|
+
logger.info(f"Successfully destroyed async R context: {r_context.id}")
|
|
1365
|
+
# 从contexts字典中移除
|
|
1366
|
+
if "async_r_language" in self.contexts:
|
|
1367
|
+
del self.contexts["async_r_language"]
|
|
1368
|
+
except Exception as e:
|
|
1369
|
+
logger.warning(f"Failed to destroy async R context {r_context.id}: {e}")
|
|
1370
|
+
|
|
1371
|
+
# ======================== 异步Node.js/JavaScript 测试 ========================
|
|
1372
|
+
|
|
1373
|
+
async def test_async_nodejs_basic_execution(self):
|
|
1374
|
+
"""测试异步Node.js基础执行"""
|
|
1375
|
+
assert self.sandbox is not None
|
|
1376
|
+
|
|
1377
|
+
code = """
|
|
1378
|
+
// Node.js 基础执行(异步)
|
|
1379
|
+
console.log("Hello from Async Node.js Kernel!");
|
|
1380
|
+
const a = 11, b = 13;
|
|
1381
|
+
console.log(`Sum: ${a + b}`);
|
|
1382
|
+
console.log(`Product: ${a * b}`);
|
|
1383
|
+
({ sum: a + b, product: a * b })
|
|
1384
|
+
"""
|
|
1385
|
+
|
|
1386
|
+
execution = await self.sandbox.run_code(code, language="javascript")
|
|
1387
|
+
assert execution.error is None
|
|
1388
|
+
assert any(
|
|
1389
|
+
"Hello from Async Node.js Kernel!" in line for line in execution.logs.stdout
|
|
1390
|
+
)
|
|
1391
|
+
assert any("Sum:" in line for line in execution.logs.stdout)
|
|
1392
|
+
logger.info("Async Node.js basic execution test passed")
|
|
1393
|
+
|
|
1394
|
+
async def test_async_nodejs_async_promises(self):
|
|
1395
|
+
"""测试异步Node.js Promise/async"""
|
|
1396
|
+
assert self.sandbox is not None
|
|
1397
|
+
|
|
1398
|
+
code = """
|
|
1399
|
+
function delay(ms){ return new Promise(r=>setTimeout(r, ms)); }
|
|
1400
|
+
async function run(){
|
|
1401
|
+
console.log("Async tasks start");
|
|
1402
|
+
const t0 = Date.now();
|
|
1403
|
+
await delay(40);
|
|
1404
|
+
const res = await Promise.all([
|
|
1405
|
+
(async()=>{ await delay(15); return 21; })(),
|
|
1406
|
+
(async()=>{ await delay(25); return 21; })()
|
|
1407
|
+
]);
|
|
1408
|
+
const sum = res.reduce((a,b)=>a+b,0);
|
|
1409
|
+
const dt = Date.now()-t0;
|
|
1410
|
+
console.log(`Async tasks done in ${dt} ms`);
|
|
1411
|
+
return { sum, dt };
|
|
1412
|
+
}
|
|
1413
|
+
run();
|
|
1414
|
+
"""
|
|
1415
|
+
|
|
1416
|
+
execution = await self.sandbox.run_code(code, language="javascript")
|
|
1417
|
+
assert execution.error is None
|
|
1418
|
+
assert any("Async tasks start" in line for line in execution.logs.stdout)
|
|
1419
|
+
assert any("Async tasks done" in line for line in execution.logs.stdout)
|
|
1420
|
+
logger.info("Async Node.js promises test passed")
|
|
1421
|
+
|
|
1422
|
+
async def test_async_nodejs_data_processing(self):
|
|
1423
|
+
"""测试异步Node.js数据处理"""
|
|
1424
|
+
assert self.sandbox is not None
|
|
1425
|
+
|
|
1426
|
+
code = """
|
|
1427
|
+
const rows = Array.from({length: 120}, (_, i) => ({ id: i+1, value: Math.round(Math.random()*100), group: ['X','Y','Z'][i%3] }));
|
|
1428
|
+
const stats = rows.reduce((acc, r)=>{ if(!acc[r.group]) acc[r.group]={count:0,sum:0}; acc[r.group].count++; acc[r.group].sum+=r.value; return acc; }, {});
|
|
1429
|
+
const out = Object.entries(stats).map(([g,s])=>({ group: g, count: s.count, mean: s.sum/s.count }));
|
|
1430
|
+
console.log("Async grouped stats ready");
|
|
1431
|
+
({ total: rows.length, groups: out })
|
|
1432
|
+
"""
|
|
1433
|
+
|
|
1434
|
+
execution = await self.sandbox.run_code(code, language="javascript")
|
|
1435
|
+
assert execution.error is None
|
|
1436
|
+
assert any(
|
|
1437
|
+
"Async grouped stats ready" in line for line in execution.logs.stdout
|
|
1438
|
+
)
|
|
1439
|
+
logger.info("Async Node.js data processing test passed")
|
|
1440
|
+
|
|
1441
|
+
async def test_async_nodejs_chart_data(self):
|
|
1442
|
+
"""测试异步Node.js图表数据生成"""
|
|
1443
|
+
assert self.sandbox is not None
|
|
1444
|
+
|
|
1445
|
+
code = """
|
|
1446
|
+
const labels = Array.from({length: 5}, (_, i)=>`T${i+1}`);
|
|
1447
|
+
const values = labels.map(()=> Math.round(Math.random()*50+50));
|
|
1448
|
+
const chart = { type: 'bar', data: { labels, datasets: [{ label: 'Load', data: values, backgroundColor: '#1c7ed6' }] } };
|
|
1449
|
+
console.log("Async chart data generated");
|
|
1450
|
+
({ chart })
|
|
1451
|
+
"""
|
|
1452
|
+
|
|
1453
|
+
execution = await self.sandbox.run_code(code, language="javascript")
|
|
1454
|
+
assert execution.error is None
|
|
1455
|
+
assert any(
|
|
1456
|
+
"Async chart data generated" in line for line in execution.logs.stdout
|
|
1457
|
+
)
|
|
1458
|
+
assert len(execution.results) > 0
|
|
1459
|
+
logger.info("Async Node.js chart data test passed")
|
|
1460
|
+
|
|
1461
|
+
async def test_async_nodejs_context_management(self):
|
|
1462
|
+
"""测试异步Node.js上下文管理"""
|
|
1463
|
+
assert self.sandbox is not None
|
|
1464
|
+
|
|
1465
|
+
# 创建Node.js上下文
|
|
1466
|
+
js_context = await self.sandbox.create_code_context(
|
|
1467
|
+
language="javascript", cwd="/tmp"
|
|
1468
|
+
)
|
|
1469
|
+
self.contexts["async_nodejs"] = js_context
|
|
1470
|
+
|
|
1471
|
+
setup = """
|
|
1472
|
+
console.log("Setup async Node.js context");
|
|
1473
|
+
globalThis.state = { counter: 0 };
|
|
1474
|
+
function inc(){ globalThis.state.counter += 1; return globalThis.state.counter; }
|
|
1475
|
+
({ counter: globalThis.state.counter })
|
|
1476
|
+
"""
|
|
1477
|
+
|
|
1478
|
+
e1 = await self.sandbox.run_code(setup, context=js_context)
|
|
1479
|
+
assert e1.error is None
|
|
1480
|
+
assert any("Setup async Node.js context" in line for line in e1.logs.stdout)
|
|
1481
|
+
|
|
1482
|
+
use = """
|
|
1483
|
+
console.log("Use async Node.js context");
|
|
1484
|
+
const c1 = inc();
|
|
1485
|
+
const c2 = inc();
|
|
1486
|
+
({ after: c2 })
|
|
1487
|
+
"""
|
|
1488
|
+
|
|
1489
|
+
e2 = await self.sandbox.run_code(use, context=js_context)
|
|
1490
|
+
assert e2.error is None
|
|
1491
|
+
assert any("Use async Node.js context" in line for line in e2.logs.stdout)
|
|
1492
|
+
|
|
1493
|
+
# 清理上下文
|
|
1494
|
+
try:
|
|
1495
|
+
await self.sandbox.destroy_context(js_context)
|
|
1496
|
+
if "async_nodejs" in self.contexts:
|
|
1497
|
+
del self.contexts["async_nodejs"]
|
|
1498
|
+
logger.info("Destroyed async Node.js context")
|
|
1499
|
+
except Exception as e:
|
|
1500
|
+
logger.warning(f"Failed to destroy async Node.js context: {e}")
|
|
1501
|
+
|
|
1502
|
+
# ======================== 异步Bash 测试 ========================
|
|
1503
|
+
|
|
1504
|
+
async def test_async_bash_basic_execution(self):
|
|
1505
|
+
"""测试异步Bash基础执行"""
|
|
1506
|
+
assert self.sandbox is not None
|
|
1507
|
+
|
|
1508
|
+
code = """
|
|
1509
|
+
echo "Hello from Async Bash Kernel!"
|
|
1510
|
+
NAME="scalebox"
|
|
1511
|
+
echo "Hello, ${NAME}!"
|
|
1512
|
+
whoami
|
|
1513
|
+
date
|
|
1514
|
+
"""
|
|
1515
|
+
|
|
1516
|
+
execution = await self.sandbox.run_code(code, language="bash")
|
|
1517
|
+
assert execution.error is None
|
|
1518
|
+
assert any(
|
|
1519
|
+
"Hello from Async Bash Kernel!" in line for line in execution.logs.stdout
|
|
1520
|
+
)
|
|
1521
|
+
assert any("Hello, scalebox!" in line for line in execution.logs.stdout)
|
|
1522
|
+
logger.info("Async Bash basic execution test passed")
|
|
1523
|
+
|
|
1524
|
+
async def test_async_bash_file_operations(self):
|
|
1525
|
+
"""测试异步Bash文件操作"""
|
|
1526
|
+
assert self.sandbox is not None
|
|
1527
|
+
|
|
1528
|
+
code = """
|
|
1529
|
+
set -e
|
|
1530
|
+
WORKDIR="/tmp/abash_demo"
|
|
1531
|
+
mkdir -p "$WORKDIR"
|
|
1532
|
+
cd "$WORKDIR"
|
|
1533
|
+
echo "first" > one.txt
|
|
1534
|
+
echo "second" > two.txt
|
|
1535
|
+
cat one.txt two.txt > both.txt
|
|
1536
|
+
ls -l
|
|
1537
|
+
wc -l both.txt
|
|
1538
|
+
echo "ABASH_DONE"
|
|
1539
|
+
"""
|
|
1540
|
+
|
|
1541
|
+
execution = await self.sandbox.run_code(code, language="bash")
|
|
1542
|
+
assert execution.error is None
|
|
1543
|
+
assert any("ABASH_DONE" in line for line in execution.logs.stdout)
|
|
1544
|
+
logger.info("Async Bash file operations test passed")
|
|
1545
|
+
|
|
1546
|
+
async def test_async_bash_pipelines_and_grep(self):
|
|
1547
|
+
"""测试异步Bash管道与grep"""
|
|
1548
|
+
assert self.sandbox is not None
|
|
1549
|
+
|
|
1550
|
+
code = """
|
|
1551
|
+
printf "%s\n" a b a c a | grep -n "a" | awk -F: '{print "row", $1, ":", $2}'
|
|
1552
|
+
echo "ABASH_PIPE_OK"
|
|
1553
|
+
"""
|
|
1554
|
+
|
|
1555
|
+
execution = await self.sandbox.run_code(code, language="bash")
|
|
1556
|
+
assert execution.error is None
|
|
1557
|
+
assert any("ABASH_PIPE_OK" in line for line in execution.logs.stdout)
|
|
1558
|
+
logger.info("Async Bash pipelines/grep test passed")
|
|
1559
|
+
|
|
1560
|
+
async def test_async_bash_env_and_exit_codes(self):
|
|
1561
|
+
"""测试异步Bash环境变量与退出码"""
|
|
1562
|
+
assert self.sandbox is not None
|
|
1563
|
+
|
|
1564
|
+
code = """
|
|
1565
|
+
export MODE=async
|
|
1566
|
+
echo "MODE=$MODE"
|
|
1567
|
+
(exit 9)
|
|
1568
|
+
echo $?
|
|
1569
|
+
"""
|
|
1570
|
+
|
|
1571
|
+
execution = await self.sandbox.run_code(code, language="bash")
|
|
1572
|
+
assert execution.error is None
|
|
1573
|
+
assert any("MODE=async" in line for line in execution.logs.stdout)
|
|
1574
|
+
assert any(line.strip() == "9" for line in execution.logs.stdout)
|
|
1575
|
+
logger.info("Async Bash env and exit codes test passed")
|
|
1576
|
+
|
|
1577
|
+
async def test_async_bash_context_management(self):
|
|
1578
|
+
"""测试异步Bash上下文管理"""
|
|
1579
|
+
assert self.sandbox is not None
|
|
1580
|
+
|
|
1581
|
+
# 创建Bash上下文
|
|
1582
|
+
bash_ctx = await self.sandbox.create_code_context(language="bash", cwd="/tmp")
|
|
1583
|
+
self.contexts["async_bash"] = bash_ctx
|
|
1584
|
+
|
|
1585
|
+
setup = """
|
|
1586
|
+
echo "Setup async Bash context"
|
|
1587
|
+
COUNT=3
|
|
1588
|
+
echo $COUNT
|
|
1589
|
+
"""
|
|
1590
|
+
|
|
1591
|
+
e1 = await self.sandbox.run_code(setup, context=bash_ctx)
|
|
1592
|
+
assert e1.error is None
|
|
1593
|
+
assert any("Setup async Bash context" in line for line in e1.logs.stdout)
|
|
1594
|
+
|
|
1595
|
+
use = """
|
|
1596
|
+
echo "Use async Bash context"
|
|
1597
|
+
COUNT=$((COUNT+2))
|
|
1598
|
+
echo "COUNT_AFTER=$COUNT"
|
|
1599
|
+
"""
|
|
1600
|
+
|
|
1601
|
+
e2 = await self.sandbox.run_code(use, context=bash_ctx)
|
|
1602
|
+
assert e2.error is None
|
|
1603
|
+
assert any("Use async Bash context" in line for line in e2.logs.stdout)
|
|
1604
|
+
assert any("COUNT_AFTER=5" in line for line in e2.logs.stdout)
|
|
1605
|
+
|
|
1606
|
+
# 清理上下文
|
|
1607
|
+
try:
|
|
1608
|
+
await self.sandbox.destroy_context(bash_ctx)
|
|
1609
|
+
if "async_bash" in self.contexts:
|
|
1610
|
+
del self.contexts["async_bash"]
|
|
1611
|
+
logger.info("Destroyed async Bash context")
|
|
1612
|
+
except Exception as e:
|
|
1613
|
+
logger.warning(f"Failed to destroy async Bash context: {e}")
|
|
1614
|
+
|
|
1615
|
+
# ======================== 异步IJAVA 测试 ========================
|
|
1616
|
+
|
|
1617
|
+
async def test_async_ijava_basic_execution(self):
|
|
1618
|
+
"""测试异步IJAVA基础执行"""
|
|
1619
|
+
assert self.sandbox is not None
|
|
1620
|
+
|
|
1621
|
+
code = """
|
|
1622
|
+
// 异步IJAVA 基础执行测试
|
|
1623
|
+
System.out.println("Hello from Async IJAVA Kernel!");
|
|
1624
|
+
|
|
1625
|
+
// 基础变量和运算
|
|
1626
|
+
int x = 15;
|
|
1627
|
+
int y = 25;
|
|
1628
|
+
int sum = x + y;
|
|
1629
|
+
int product = x * y;
|
|
1630
|
+
|
|
1631
|
+
System.out.println("Sum: " + sum);
|
|
1632
|
+
System.out.println("Product: " + product);
|
|
1633
|
+
|
|
1634
|
+
// 字符串操作
|
|
1635
|
+
String name = "AsyncScaleBox";
|
|
1636
|
+
String greeting = "Hello, " + name + "!";
|
|
1637
|
+
System.out.println(greeting);
|
|
1638
|
+
|
|
1639
|
+
// 数组操作
|
|
1640
|
+
int[] numbers = {2, 4, 6, 8, 10};
|
|
1641
|
+
int total = 0;
|
|
1642
|
+
for (int num : numbers) {
|
|
1643
|
+
total += num;
|
|
1644
|
+
}
|
|
1645
|
+
System.out.println("Array sum: " + total);
|
|
1646
|
+
|
|
1647
|
+
// IJAVA 特色:直接输出变量值
|
|
1648
|
+
x;
|
|
1649
|
+
y;
|
|
1650
|
+
sum;
|
|
1651
|
+
product;
|
|
1652
|
+
total;
|
|
1653
|
+
"""
|
|
1654
|
+
|
|
1655
|
+
execution = await self.sandbox.run_code(code, language="java")
|
|
1656
|
+
assert execution.error is None
|
|
1657
|
+
assert any(
|
|
1658
|
+
"Hello from Async IJAVA Kernel!" in line for line in execution.logs.stdout
|
|
1659
|
+
)
|
|
1660
|
+
assert any("Sum: 40" in line for line in execution.logs.stdout)
|
|
1661
|
+
assert any("Array sum: 30" in line for line in execution.logs.stdout)
|
|
1662
|
+
logger.info("Async IJAVA basic execution test passed")
|
|
1663
|
+
|
|
1664
|
+
async def test_async_ijava_oop_features(self):
|
|
1665
|
+
"""测试异步IJAVA面向对象特性"""
|
|
1666
|
+
assert self.sandbox is not None
|
|
1667
|
+
|
|
1668
|
+
code = """
|
|
1669
|
+
// 异步IJAVA 面向对象特性测试
|
|
1670
|
+
System.out.println("Testing Async IJAVA OOP features...");
|
|
1671
|
+
|
|
1672
|
+
// 定义类
|
|
1673
|
+
class AsyncPerson {
|
|
1674
|
+
private String name;
|
|
1675
|
+
private int age;
|
|
1676
|
+
|
|
1677
|
+
public AsyncPerson(String name, int age) {
|
|
1678
|
+
this.name = name;
|
|
1679
|
+
this.age = age;
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
public String getName() { return name; }
|
|
1683
|
+
public int getAge() { return age; }
|
|
1684
|
+
|
|
1685
|
+
public void introduce() {
|
|
1686
|
+
System.out.println("Hi, I'm " + name + " and I'm " + age + " years old.");
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
class AsyncStudent extends AsyncPerson {
|
|
1691
|
+
private String major;
|
|
1692
|
+
|
|
1693
|
+
public AsyncStudent(String name, int age, String major) {
|
|
1694
|
+
super(name, age);
|
|
1695
|
+
this.major = major;
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
@Override
|
|
1699
|
+
public void introduce() {
|
|
1700
|
+
super.introduce();
|
|
1701
|
+
System.out.println("I'm studying " + major + ".");
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
// 创建对象并测试
|
|
1706
|
+
AsyncPerson person = new AsyncPerson("Eve", 28);
|
|
1707
|
+
person.introduce();
|
|
1708
|
+
|
|
1709
|
+
AsyncStudent student = new AsyncStudent("Frank", 24, "Data Science");
|
|
1710
|
+
student.introduce();
|
|
1711
|
+
|
|
1712
|
+
// IJAVA 特色:直接输出对象信息
|
|
1713
|
+
person.getName();
|
|
1714
|
+
student.getAge();
|
|
1715
|
+
person;
|
|
1716
|
+
student;
|
|
1717
|
+
|
|
1718
|
+
System.out.println("Async IJAVA OOP test completed successfully!");
|
|
1719
|
+
"""
|
|
1720
|
+
|
|
1721
|
+
execution = await self.sandbox.run_code(code, language="java")
|
|
1722
|
+
assert execution.error is None
|
|
1723
|
+
assert any(
|
|
1724
|
+
"Testing Async IJAVA OOP features..." in line
|
|
1725
|
+
for line in execution.logs.stdout
|
|
1726
|
+
)
|
|
1727
|
+
assert any("Hi, I'm Eve" in line for line in execution.logs.stdout)
|
|
1728
|
+
assert any(
|
|
1729
|
+
"I'm studying Data Science" in line for line in execution.logs.stdout
|
|
1730
|
+
)
|
|
1731
|
+
logger.info("Async IJAVA OOP features test passed")
|
|
1732
|
+
|
|
1733
|
+
async def test_async_ijava_collections(self):
|
|
1734
|
+
"""测试异步IJAVA集合框架"""
|
|
1735
|
+
assert self.sandbox is not None
|
|
1736
|
+
|
|
1737
|
+
code = """
|
|
1738
|
+
import java.util.*;
|
|
1739
|
+
|
|
1740
|
+
System.out.println("Testing Async IJAVA Collections...");
|
|
1741
|
+
|
|
1742
|
+
// ArrayList
|
|
1743
|
+
List<String> colors = new ArrayList<>();
|
|
1744
|
+
colors.add("Red");
|
|
1745
|
+
colors.add("Green");
|
|
1746
|
+
colors.add("Blue");
|
|
1747
|
+
System.out.println("Colors: " + colors);
|
|
1748
|
+
|
|
1749
|
+
// HashMap
|
|
1750
|
+
Map<String, Integer> ages = new HashMap<>();
|
|
1751
|
+
ages.put("Alice", 25);
|
|
1752
|
+
ages.put("Bob", 30);
|
|
1753
|
+
ages.put("Charlie", 35);
|
|
1754
|
+
System.out.println("Ages: " + ages);
|
|
1755
|
+
|
|
1756
|
+
// HashSet
|
|
1757
|
+
Set<String> uniqueWords = new HashSet<>();
|
|
1758
|
+
uniqueWords.add("hello");
|
|
1759
|
+
uniqueWords.add("world");
|
|
1760
|
+
uniqueWords.add("hello"); // 重复元素
|
|
1761
|
+
System.out.println("Unique words: " + uniqueWords);
|
|
1762
|
+
|
|
1763
|
+
// 遍历集合
|
|
1764
|
+
System.out.println("Iterating through colors:");
|
|
1765
|
+
for (String color : colors) {
|
|
1766
|
+
System.out.println("- " + color);
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
// IJAVA 特色:直接输出集合内容
|
|
1770
|
+
colors;
|
|
1771
|
+
ages;
|
|
1772
|
+
uniqueWords;
|
|
1773
|
+
|
|
1774
|
+
// 集合操作
|
|
1775
|
+
colors.size();
|
|
1776
|
+
ages.containsKey("Alice");
|
|
1777
|
+
uniqueWords.contains("hello");
|
|
1778
|
+
|
|
1779
|
+
System.out.println("Async IJAVA Collections test completed!");
|
|
1780
|
+
"""
|
|
1781
|
+
|
|
1782
|
+
execution = await self.sandbox.run_code(code, language="java")
|
|
1783
|
+
assert execution.error is None
|
|
1784
|
+
assert any(
|
|
1785
|
+
"Testing Async IJAVA Collections..." in line
|
|
1786
|
+
for line in execution.logs.stdout
|
|
1787
|
+
)
|
|
1788
|
+
assert any(
|
|
1789
|
+
"Colors: [Red, Green, Blue]" in line for line in execution.logs.stdout
|
|
1790
|
+
)
|
|
1791
|
+
assert any(
|
|
1792
|
+
"Unique words: [hello, world]" in line for line in execution.logs.stdout
|
|
1793
|
+
)
|
|
1794
|
+
logger.info("Async IJAVA collections test passed")
|
|
1795
|
+
|
|
1796
|
+
async def test_async_ijava_file_io(self):
|
|
1797
|
+
"""测试异步IJAVA文件I/O"""
|
|
1798
|
+
assert self.sandbox is not None
|
|
1799
|
+
|
|
1800
|
+
code = """
|
|
1801
|
+
import java.io.*;
|
|
1802
|
+
import java.nio.file.*;
|
|
1803
|
+
|
|
1804
|
+
System.out.println("Testing Async IJAVA File I/O...");
|
|
1805
|
+
|
|
1806
|
+
try {
|
|
1807
|
+
// 创建临时目录
|
|
1808
|
+
Path tempDir = Files.createTempDirectory("async_ijava_demo");
|
|
1809
|
+
System.out.println("Created temp directory: " + tempDir);
|
|
1810
|
+
|
|
1811
|
+
// 写入文件
|
|
1812
|
+
Path filePath = tempDir.resolve("async_test.txt");
|
|
1813
|
+
String content = "Hello from Async IJAVA File I/O!\nThis is an async test file.\n";
|
|
1814
|
+
Files.write(filePath, content.getBytes());
|
|
1815
|
+
System.out.println("File written successfully");
|
|
1816
|
+
|
|
1817
|
+
// 读取文件
|
|
1818
|
+
String readContent = new String(Files.readAllBytes(filePath));
|
|
1819
|
+
System.out.println("File content:");
|
|
1820
|
+
System.out.println(readContent);
|
|
1821
|
+
|
|
1822
|
+
// 文件信息
|
|
1823
|
+
long size = Files.size(filePath);
|
|
1824
|
+
System.out.println("File size: " + size + " bytes");
|
|
1825
|
+
|
|
1826
|
+
// IJAVA 特色:直接输出文件信息
|
|
1827
|
+
filePath;
|
|
1828
|
+
size;
|
|
1829
|
+
Files.exists(filePath);
|
|
1830
|
+
|
|
1831
|
+
// 清理
|
|
1832
|
+
Files.delete(filePath);
|
|
1833
|
+
Files.delete(tempDir);
|
|
1834
|
+
System.out.println("Async IJAVA File I/O test completed successfully!");
|
|
1835
|
+
|
|
1836
|
+
} catch (IOException e) {
|
|
1837
|
+
System.err.println("Error: " + e.getMessage());
|
|
1838
|
+
}
|
|
1839
|
+
"""
|
|
1840
|
+
|
|
1841
|
+
execution = await self.sandbox.run_code(code, language="java")
|
|
1842
|
+
assert execution.error is None
|
|
1843
|
+
assert any(
|
|
1844
|
+
"Testing Async IJAVA File I/O..." in line for line in execution.logs.stdout
|
|
1845
|
+
)
|
|
1846
|
+
assert any(
|
|
1847
|
+
"File written successfully" in line for line in execution.logs.stdout
|
|
1848
|
+
)
|
|
1849
|
+
assert any(
|
|
1850
|
+
"Hello from Async IJAVA File I/O!" in line for line in execution.logs.stdout
|
|
1851
|
+
)
|
|
1852
|
+
logger.info("Async IJAVA file I/O test passed")
|
|
1853
|
+
|
|
1854
|
+
async def test_async_ijava_context_management(self):
|
|
1855
|
+
"""测试异步IJAVA上下文管理"""
|
|
1856
|
+
assert self.sandbox is not None
|
|
1857
|
+
|
|
1858
|
+
# 创建IJAVA上下文
|
|
1859
|
+
ijava_context = await self.sandbox.create_code_context(
|
|
1860
|
+
language="java", cwd="/tmp"
|
|
1861
|
+
)
|
|
1862
|
+
self.contexts["async_ijava"] = ijava_context
|
|
1863
|
+
|
|
1864
|
+
# 在上下文中定义类和变量
|
|
1865
|
+
setup_code = """
|
|
1866
|
+
System.out.println("Setting up async IJAVA context...");
|
|
1867
|
+
|
|
1868
|
+
// 定义全局变量
|
|
1869
|
+
int counter = 0;
|
|
1870
|
+
String message = "Hello from Async IJAVA Context!";
|
|
1871
|
+
|
|
1872
|
+
System.out.println("Initial counter: " + counter);
|
|
1873
|
+
System.out.println("Message: " + message);
|
|
1874
|
+
|
|
1875
|
+
// 定义方法
|
|
1876
|
+
void incrementCounter() {
|
|
1877
|
+
counter++;
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
int getCounter() {
|
|
1881
|
+
return counter;
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
// 定义类
|
|
1885
|
+
class AsyncContextDemo {
|
|
1886
|
+
private static int staticCounter = 0;
|
|
1887
|
+
|
|
1888
|
+
public static void incrementStaticCounter() {
|
|
1889
|
+
staticCounter++;
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
public static int getStaticCounter() {
|
|
1893
|
+
return staticCounter;
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
// 测试方法
|
|
1898
|
+
incrementCounter();
|
|
1899
|
+
System.out.println("Counter after increment: " + counter);
|
|
1900
|
+
|
|
1901
|
+
// IJAVA 特色:直接输出变量值
|
|
1902
|
+
counter;
|
|
1903
|
+
message;
|
|
1904
|
+
getCounter();
|
|
1905
|
+
"""
|
|
1906
|
+
|
|
1907
|
+
execution1 = await self.sandbox.run_code(setup_code, context=ijava_context)
|
|
1908
|
+
assert execution1.error is None
|
|
1909
|
+
assert any(
|
|
1910
|
+
"Setting up async IJAVA context..." in line
|
|
1911
|
+
for line in execution1.logs.stdout
|
|
1912
|
+
)
|
|
1913
|
+
assert any("Initial counter: 0" in line for line in execution1.logs.stdout)
|
|
1914
|
+
|
|
1915
|
+
# 在同一上下文中使用之前定义的变量和方法
|
|
1916
|
+
use_code = """
|
|
1917
|
+
System.out.println("Using async IJAVA context...");
|
|
1918
|
+
|
|
1919
|
+
// 使用之前定义的变量和方法
|
|
1920
|
+
incrementCounter();
|
|
1921
|
+
int currentCounter = getCounter();
|
|
1922
|
+
System.out.println("Current counter: " + currentCounter);
|
|
1923
|
+
|
|
1924
|
+
// 使用之前定义的类
|
|
1925
|
+
AsyncContextDemo.incrementStaticCounter();
|
|
1926
|
+
int staticCounter = AsyncContextDemo.getStaticCounter();
|
|
1927
|
+
System.out.println("Static counter: " + staticCounter);
|
|
1928
|
+
|
|
1929
|
+
// 创建新变量
|
|
1930
|
+
String newMessage = "Modified async context data";
|
|
1931
|
+
System.out.println("New message: " + newMessage);
|
|
1932
|
+
|
|
1933
|
+
// IJAVA 特色:直接输出所有变量
|
|
1934
|
+
counter;
|
|
1935
|
+
currentCounter;
|
|
1936
|
+
staticCounter;
|
|
1937
|
+
newMessage;
|
|
1938
|
+
AsyncContextDemo.getStaticCounter();
|
|
1939
|
+
|
|
1940
|
+
System.out.println("Async IJAVA context usage completed!");
|
|
1941
|
+
"""
|
|
1942
|
+
|
|
1943
|
+
execution2 = await self.sandbox.run_code(use_code, context=ijava_context)
|
|
1944
|
+
assert execution2.error is None
|
|
1945
|
+
assert any(
|
|
1946
|
+
"Using async IJAVA context..." in line for line in execution2.logs.stdout
|
|
1947
|
+
)
|
|
1948
|
+
assert any("Current counter: 2" in line for line in execution2.logs.stdout)
|
|
1949
|
+
assert any("Static counter: 1" in line for line in execution2.logs.stdout)
|
|
1950
|
+
logger.info("Async IJAVA context management test passed")
|
|
1951
|
+
|
|
1952
|
+
# 测试完成后立即清理context
|
|
1953
|
+
try:
|
|
1954
|
+
await self.sandbox.destroy_context(ijava_context)
|
|
1955
|
+
logger.info(
|
|
1956
|
+
f"Successfully destroyed async IJAVA context: {ijava_context.id}"
|
|
1957
|
+
)
|
|
1958
|
+
# 从contexts字典中移除
|
|
1959
|
+
if "async_ijava" in self.contexts:
|
|
1960
|
+
del self.contexts["async_ijava"]
|
|
1961
|
+
except Exception as e:
|
|
1962
|
+
logger.warning(
|
|
1963
|
+
f"Failed to destroy async IJAVA context {ijava_context.id}: {e}"
|
|
1964
|
+
)
|
|
1965
|
+
|
|
1966
|
+
# ======================== 异步Deno 测试 ========================
|
|
1967
|
+
|
|
1968
|
+
async def test_async_deno_basic_execution(self):
|
|
1969
|
+
"""测试异步Deno基础执行"""
|
|
1970
|
+
assert self.sandbox is not None
|
|
1971
|
+
|
|
1972
|
+
code = """
|
|
1973
|
+
// 异步Deno 基础执行测试
|
|
1974
|
+
console.log("Hello from Async Deno Kernel!");
|
|
1975
|
+
|
|
1976
|
+
// 基础变量和运算
|
|
1977
|
+
const x: number = 14;
|
|
1978
|
+
const y: number = 16;
|
|
1979
|
+
const sum: number = x + y;
|
|
1980
|
+
const product: number = x * y;
|
|
1981
|
+
|
|
1982
|
+
console.log(`Sum: ${sum}`);
|
|
1983
|
+
console.log(`Product: ${product}`);
|
|
1984
|
+
|
|
1985
|
+
// 字符串操作
|
|
1986
|
+
const name: string = "AsyncDenoScaleBox";
|
|
1987
|
+
const greeting: string = `Hello, ${name}!`;
|
|
1988
|
+
console.log(greeting);
|
|
1989
|
+
|
|
1990
|
+
// 数组操作
|
|
1991
|
+
const numbers: number[] = [2, 4, 6, 8, 10];
|
|
1992
|
+
const total: number = numbers.reduce((acc, num) => acc + num, 0);
|
|
1993
|
+
console.log(`Array sum: ${total}`);
|
|
1994
|
+
|
|
1995
|
+
// 对象操作
|
|
1996
|
+
const person = {
|
|
1997
|
+
name: "Bob",
|
|
1998
|
+
age: 30,
|
|
1999
|
+
city: "London"
|
|
2000
|
+
};
|
|
2001
|
+
console.log(`Person: ${person.name}, ${person.age} years old`);
|
|
2002
|
+
"""
|
|
2003
|
+
|
|
2004
|
+
execution = await self.sandbox.run_code(code, language="typescript")
|
|
2005
|
+
assert execution.error is None
|
|
2006
|
+
assert any(
|
|
2007
|
+
"Hello from Async Deno Kernel!" in line for line in execution.logs.stdout
|
|
2008
|
+
)
|
|
2009
|
+
assert any("Sum: 30" in line for line in execution.logs.stdout)
|
|
2010
|
+
assert any("Array sum: 30" in line for line in execution.logs.stdout)
|
|
2011
|
+
logger.info("Async Deno basic execution test passed")
|
|
2012
|
+
|
|
2013
|
+
async def test_async_deno_typescript_features(self):
|
|
2014
|
+
"""测试异步Deno TypeScript特性"""
|
|
2015
|
+
assert self.sandbox is not None
|
|
2016
|
+
|
|
2017
|
+
code = """
|
|
2018
|
+
// 异步Deno TypeScript 特性测试
|
|
2019
|
+
interface AsyncUser {
|
|
2020
|
+
id: number;
|
|
2021
|
+
name: string;
|
|
2022
|
+
email: string;
|
|
2023
|
+
isActive: boolean;
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
class AsyncUserManager {
|
|
2027
|
+
private users: AsyncUser[] = [];
|
|
2028
|
+
|
|
2029
|
+
constructor() {
|
|
2030
|
+
console.log("AsyncUserManager initialized");
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
addUser(user: AsyncUser): void {
|
|
2034
|
+
this.users.push(user);
|
|
2035
|
+
console.log(`Added user: ${user.name}`);
|
|
2036
|
+
}
|
|
2037
|
+
|
|
2038
|
+
getUsers(): AsyncUser[] {
|
|
2039
|
+
return this.users;
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2042
|
+
findUserById(id: number): AsyncUser | undefined {
|
|
2043
|
+
return this.users.find(user => user.id === id);
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
// 使用泛型
|
|
2048
|
+
function processAsyncItems<T>(items: T[], processor: (item: T) => void): void {
|
|
2049
|
+
items.forEach(processor);
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
// 枚举
|
|
2053
|
+
enum AsyncStatus {
|
|
2054
|
+
PENDING = "pending",
|
|
2055
|
+
APPROVED = "approved",
|
|
2056
|
+
REJECTED = "rejected"
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
console.log("Testing Async Deno TypeScript features...");
|
|
2060
|
+
|
|
2061
|
+
const asyncUserManager = new AsyncUserManager();
|
|
2062
|
+
asyncUserManager.addUser({
|
|
2063
|
+
id: 1,
|
|
2064
|
+
name: "Async John",
|
|
2065
|
+
email: "async.john@example.com",
|
|
2066
|
+
isActive: true
|
|
2067
|
+
});
|
|
2068
|
+
|
|
2069
|
+
asyncUserManager.addUser({
|
|
2070
|
+
id: 2,
|
|
2071
|
+
name: "Async Jane",
|
|
2072
|
+
email: "async.jane@example.com",
|
|
2073
|
+
isActive: false
|
|
2074
|
+
});
|
|
2075
|
+
|
|
2076
|
+
const users = asyncUserManager.getUsers();
|
|
2077
|
+
console.log(`Total users: ${users.length}`);
|
|
2078
|
+
|
|
2079
|
+
const foundUser = asyncUserManager.findUserById(1);
|
|
2080
|
+
console.log(`Found user: ${foundUser?.name}`);
|
|
2081
|
+
|
|
2082
|
+
// 使用泛型函数
|
|
2083
|
+
const numbers = [10, 20, 30, 40, 50];
|
|
2084
|
+
processAsyncItems(numbers, (num) => console.log(`Processing: ${num}`));
|
|
2085
|
+
|
|
2086
|
+
console.log(`Status: ${AsyncStatus.APPROVED}`);
|
|
2087
|
+
console.log("Async TypeScript features test completed!");
|
|
2088
|
+
"""
|
|
2089
|
+
|
|
2090
|
+
execution = await self.sandbox.run_code(code, language="typescript")
|
|
2091
|
+
assert execution.error is None
|
|
2092
|
+
assert any(
|
|
2093
|
+
"Testing Async Deno TypeScript features..." in line
|
|
2094
|
+
for line in execution.logs.stdout
|
|
2095
|
+
)
|
|
2096
|
+
assert any("Added user: Async John" in line for line in execution.logs.stdout)
|
|
2097
|
+
assert any("Total users: 2" in line for line in execution.logs.stdout)
|
|
2098
|
+
logger.info("Async Deno TypeScript features test passed")
|
|
2099
|
+
|
|
2100
|
+
async def test_async_deno_async_await(self):
|
|
2101
|
+
"""测试异步Deno异步/await"""
|
|
2102
|
+
assert self.sandbox is not None
|
|
2103
|
+
|
|
2104
|
+
code = """
|
|
2105
|
+
// 异步Deno 异步/await 测试
|
|
2106
|
+
async function asyncDelay(ms: number): Promise<void> {
|
|
2107
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
async function asyncFetchData(id: number): Promise<{ id: number; data: string }> {
|
|
2111
|
+
await asyncDelay(30);
|
|
2112
|
+
return { id, data: `Async Data for ID ${id}` };
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
async function asyncProcessBatch(ids: number[]): Promise<string[]> {
|
|
2116
|
+
console.log("Starting async batch processing...");
|
|
2117
|
+
const start = Date.now();
|
|
2118
|
+
|
|
2119
|
+
const results = await Promise.all(
|
|
2120
|
+
ids.map(async (id) => {
|
|
2121
|
+
const result = await asyncFetchData(id);
|
|
2122
|
+
console.log(`Async Processed: ${result.data}`);
|
|
2123
|
+
return result.data;
|
|
2124
|
+
})
|
|
2125
|
+
);
|
|
2126
|
+
|
|
2127
|
+
const duration = Date.now() - start;
|
|
2128
|
+
console.log(`Async batch processing completed in ${duration}ms`);
|
|
2129
|
+
return results;
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
async function asyncMain(): Promise<void> {
|
|
2133
|
+
console.log("Testing Async Deno async/await...");
|
|
2134
|
+
|
|
2135
|
+
const ids = [1, 2, 3];
|
|
2136
|
+
const results = await asyncProcessBatch(ids);
|
|
2137
|
+
|
|
2138
|
+
console.log(`Total async results: ${results.length}`);
|
|
2139
|
+
console.log("Async async/await test completed!");
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
asyncMain();
|
|
2143
|
+
"""
|
|
2144
|
+
|
|
2145
|
+
execution = await self.sandbox.run_code(code, language="typescript")
|
|
2146
|
+
assert execution.error is None
|
|
2147
|
+
assert any(
|
|
2148
|
+
"Testing Async Deno async/await..." in line
|
|
2149
|
+
for line in execution.logs.stdout
|
|
2150
|
+
)
|
|
2151
|
+
assert any(
|
|
2152
|
+
"Starting async batch processing..." in line
|
|
2153
|
+
for line in execution.logs.stdout
|
|
2154
|
+
)
|
|
2155
|
+
assert any(
|
|
2156
|
+
"Async batch processing completed" in line for line in execution.logs.stdout
|
|
2157
|
+
)
|
|
2158
|
+
logger.info("Async Deno async/await test passed")
|
|
2159
|
+
|
|
2160
|
+
async def test_async_deno_file_operations(self):
|
|
2161
|
+
"""测试异步Deno文件操作"""
|
|
2162
|
+
assert self.sandbox is not None
|
|
2163
|
+
|
|
2164
|
+
code = """
|
|
2165
|
+
// 异步Deno 文件操作测试
|
|
2166
|
+
import { ensureDir, writeTextFile, readTextFile, remove } from "https://deno.land/std@0.208.0/fs/mod.ts";
|
|
2167
|
+
|
|
2168
|
+
async function asyncFileOperations(): Promise<void> {
|
|
2169
|
+
console.log("Testing Async Deno file operations...");
|
|
2170
|
+
|
|
2171
|
+
try {
|
|
2172
|
+
// 创建临时目录
|
|
2173
|
+
const tempDir = "/tmp/async_deno_demo";
|
|
2174
|
+
await ensureDir(tempDir);
|
|
2175
|
+
console.log(`Created directory: ${tempDir}`);
|
|
2176
|
+
|
|
2177
|
+
// 写入文件
|
|
2178
|
+
const filePath = `${tempDir}/async_test.txt`;
|
|
2179
|
+
const content = "Hello from Async Deno File Operations!\nThis is an async test file.\n";
|
|
2180
|
+
await writeTextFile(filePath, content);
|
|
2181
|
+
console.log("Async file written successfully");
|
|
2182
|
+
|
|
2183
|
+
// 读取文件
|
|
2184
|
+
const readContent = await readTextFile(filePath);
|
|
2185
|
+
console.log("Async file content:");
|
|
2186
|
+
console.log(readContent);
|
|
2187
|
+
|
|
2188
|
+
// 文件信息
|
|
2189
|
+
const fileInfo = await Deno.stat(filePath);
|
|
2190
|
+
console.log(`Async file size: ${fileInfo.size} bytes`);
|
|
2191
|
+
console.log(`Async created: ${fileInfo.birthtime}`);
|
|
2192
|
+
|
|
2193
|
+
// 清理
|
|
2194
|
+
await remove(filePath);
|
|
2195
|
+
await remove(tempDir);
|
|
2196
|
+
console.log("Async file operations test completed successfully!");
|
|
2197
|
+
|
|
2198
|
+
} catch (error) {
|
|
2199
|
+
console.error(`Async Error: ${error.message}`);
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2203
|
+
asyncFileOperations();
|
|
2204
|
+
"""
|
|
2205
|
+
|
|
2206
|
+
execution = await self.sandbox.run_code(code, language="typescript")
|
|
2207
|
+
assert execution.error is None
|
|
2208
|
+
assert any(
|
|
2209
|
+
"Testing Async Deno file operations..." in line
|
|
2210
|
+
for line in execution.logs.stdout
|
|
2211
|
+
)
|
|
2212
|
+
assert any(
|
|
2213
|
+
"Async file written successfully" in line for line in execution.logs.stdout
|
|
2214
|
+
)
|
|
2215
|
+
assert any(
|
|
2216
|
+
"Hello from Async Deno File Operations!" in line
|
|
2217
|
+
for line in execution.logs.stdout
|
|
2218
|
+
)
|
|
2219
|
+
logger.info("Async Deno file operations test passed")
|
|
2220
|
+
|
|
2221
|
+
async def test_async_deno_context_management(self):
|
|
2222
|
+
"""测试异步Deno上下文管理"""
|
|
2223
|
+
assert self.sandbox is not None
|
|
2224
|
+
|
|
2225
|
+
# 创建Deno上下文
|
|
2226
|
+
deno_context = await self.sandbox.create_code_context(
|
|
2227
|
+
language="typescript", cwd="/tmp"
|
|
2228
|
+
)
|
|
2229
|
+
self.contexts["async_deno"] = deno_context
|
|
2230
|
+
|
|
2231
|
+
# 在上下文中定义变量和函数
|
|
2232
|
+
setup_code = """
|
|
2233
|
+
// 异步Deno 上下文设置
|
|
2234
|
+
console.log("Setting up async Deno context...");
|
|
2235
|
+
|
|
2236
|
+
// 定义全局变量
|
|
2237
|
+
let asyncCounter: number = 0;
|
|
2238
|
+
const asyncCache: Map<string, any> = new Map();
|
|
2239
|
+
|
|
2240
|
+
// 定义函数
|
|
2241
|
+
function asyncIncrementCounter(): number {
|
|
2242
|
+
asyncCounter++;
|
|
2243
|
+
return asyncCounter;
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
function asyncAddToCache(key: string, value: any): number {
|
|
2247
|
+
asyncCache.set(key, value);
|
|
2248
|
+
return asyncCache.size;
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
// 定义接口
|
|
2252
|
+
interface AsyncContextData {
|
|
2253
|
+
id: number;
|
|
2254
|
+
value: string;
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
const asyncContextData: AsyncContextData = {
|
|
2258
|
+
id: 1,
|
|
2259
|
+
value: "Hello from Async Deno Context!"
|
|
2260
|
+
};
|
|
2261
|
+
|
|
2262
|
+
console.log(`Initial async counter: ${asyncCounter}`);
|
|
2263
|
+
console.log(`Async cache size: ${asyncCache.size}`);
|
|
2264
|
+
console.log(`Async context data: ${asyncContextData.value}`);
|
|
2265
|
+
"""
|
|
2266
|
+
|
|
2267
|
+
execution1 = await self.sandbox.run_code(setup_code, context=deno_context)
|
|
2268
|
+
assert execution1.error is None
|
|
2269
|
+
assert any(
|
|
2270
|
+
"Setting up async Deno context..." in line
|
|
2271
|
+
for line in execution1.logs.stdout
|
|
2272
|
+
)
|
|
2273
|
+
assert any(
|
|
2274
|
+
"Initial async counter: 0" in line for line in execution1.logs.stdout
|
|
2275
|
+
)
|
|
2276
|
+
|
|
2277
|
+
# 在同一上下文中使用之前定义的变量和函数
|
|
2278
|
+
use_code = """
|
|
2279
|
+
// 使用异步Deno 上下文中的变量和函数
|
|
2280
|
+
console.log("Using async Deno context...");
|
|
2281
|
+
|
|
2282
|
+
// 使用全局变量
|
|
2283
|
+
console.log(`Current async counter: ${asyncCounter}`);
|
|
2284
|
+
console.log(`Current async cache size: ${asyncCache.size}`);
|
|
2285
|
+
|
|
2286
|
+
// 使用函数
|
|
2287
|
+
const newAsyncCounter = asyncIncrementCounter();
|
|
2288
|
+
console.log(`Async counter after increment: ${newAsyncCounter}`);
|
|
2289
|
+
|
|
2290
|
+
const newAsyncCacheSize = asyncAddToCache("async_test_key", "async_test_value");
|
|
2291
|
+
console.log(`Async cache size after addition: ${newAsyncCacheSize}`);
|
|
2292
|
+
|
|
2293
|
+
// 使用上下文数据
|
|
2294
|
+
console.log(`Async context data ID: ${asyncContextData.id}`);
|
|
2295
|
+
console.log(`Async context data value: ${asyncContextData.value}`);
|
|
2296
|
+
|
|
2297
|
+
// 修改上下文数据
|
|
2298
|
+
asyncContextData.value = "Modified async context data";
|
|
2299
|
+
console.log(`Modified async context data: ${asyncContextData.value}`);
|
|
2300
|
+
|
|
2301
|
+
console.log("Async context usage completed!");
|
|
2302
|
+
"""
|
|
2303
|
+
|
|
2304
|
+
execution2 = await self.sandbox.run_code(use_code, context=deno_context)
|
|
2305
|
+
assert execution2.error is None
|
|
2306
|
+
assert any(
|
|
2307
|
+
"Using async Deno context..." in line for line in execution2.logs.stdout
|
|
2308
|
+
)
|
|
2309
|
+
assert any(
|
|
2310
|
+
"Async counter after increment: 1" in line
|
|
2311
|
+
for line in execution2.logs.stdout
|
|
2312
|
+
)
|
|
2313
|
+
assert any(
|
|
2314
|
+
"Async cache size after addition: 1" in line
|
|
2315
|
+
for line in execution2.logs.stdout
|
|
2316
|
+
)
|
|
2317
|
+
logger.info("Async Deno context management test passed")
|
|
2318
|
+
|
|
2319
|
+
# 测试完成后立即清理context
|
|
2320
|
+
try:
|
|
2321
|
+
await self.sandbox.destroy_context(deno_context)
|
|
2322
|
+
logger.info(f"Successfully destroyed async Deno context: {deno_context.id}")
|
|
2323
|
+
# 从contexts字典中移除
|
|
2324
|
+
if "async_deno" in self.contexts:
|
|
2325
|
+
del self.contexts["async_deno"]
|
|
2326
|
+
except Exception as e:
|
|
2327
|
+
logger.warning(
|
|
2328
|
+
f"Failed to destroy async Deno context {deno_context.id}: {e}"
|
|
2329
|
+
)
|
|
2330
|
+
|
|
2331
|
+
# ======================== 高级异步功能测试 ========================
|
|
2332
|
+
|
|
2333
|
+
async def test_async_websocket_simulation(self):
|
|
2334
|
+
"""测试异步WebSocket模拟"""
|
|
2335
|
+
assert self.sandbox is not None
|
|
2336
|
+
|
|
2337
|
+
code = """
|
|
2338
|
+
import asyncio
|
|
2339
|
+
import json
|
|
2340
|
+
import time
|
|
2341
|
+
from datetime import datetime
|
|
2342
|
+
|
|
2343
|
+
class MockWebSocketConnection:
|
|
2344
|
+
'''模拟WebSocket连接'''
|
|
2345
|
+
def __init__(self, connection_id):
|
|
2346
|
+
self.connection_id = connection_id
|
|
2347
|
+
self.connected = True
|
|
2348
|
+
self.message_queue = asyncio.Queue()
|
|
2349
|
+
|
|
2350
|
+
async def send_message(self, message):
|
|
2351
|
+
if self.connected:
|
|
2352
|
+
await self.message_queue.put({
|
|
2353
|
+
"type": "outgoing",
|
|
2354
|
+
"data": message,
|
|
2355
|
+
"timestamp": datetime.now().isoformat()
|
|
2356
|
+
})
|
|
2357
|
+
await asyncio.sleep(0.01) # 模拟网络延迟
|
|
2358
|
+
return True
|
|
2359
|
+
return False
|
|
2360
|
+
|
|
2361
|
+
async def receive_message(self):
|
|
2362
|
+
if self.connected:
|
|
2363
|
+
# 模拟接收消息
|
|
2364
|
+
await asyncio.sleep(0.05) # 模拟等待消息
|
|
2365
|
+
return {
|
|
2366
|
+
"type": "incoming",
|
|
2367
|
+
"data": f"Response from server to {self.connection_id}",
|
|
2368
|
+
"timestamp": datetime.now().isoformat()
|
|
2369
|
+
}
|
|
2370
|
+
return None
|
|
2371
|
+
|
|
2372
|
+
async def close(self):
|
|
2373
|
+
self.connected = False
|
|
2374
|
+
print(f"连接 {self.connection_id} 已关闭")
|
|
2375
|
+
|
|
2376
|
+
async def websocket_client(client_id, message_count):
|
|
2377
|
+
'''模拟WebSocket客户端'''
|
|
2378
|
+
print(f"客户端 {client_id} 开始连接")
|
|
2379
|
+
|
|
2380
|
+
connection = MockWebSocketConnection(client_id)
|
|
2381
|
+
messages_sent = 0
|
|
2382
|
+
messages_received = 0
|
|
2383
|
+
|
|
2384
|
+
try:
|
|
2385
|
+
# 发送和接收消息
|
|
2386
|
+
for i in range(message_count):
|
|
2387
|
+
# 发送消息
|
|
2388
|
+
message = f"Message {i+1} from client {client_id}"
|
|
2389
|
+
success = await connection.send_message(message)
|
|
2390
|
+
if success:
|
|
2391
|
+
messages_sent += 1
|
|
2392
|
+
|
|
2393
|
+
# 接收回复
|
|
2394
|
+
response = await connection.receive_message()
|
|
2395
|
+
if response:
|
|
2396
|
+
messages_received += 1
|
|
2397
|
+
print(f"客户端 {client_id} 收到: {response['data'][:50]}...")
|
|
2398
|
+
|
|
2399
|
+
finally:
|
|
2400
|
+
await connection.close()
|
|
2401
|
+
|
|
2402
|
+
return {
|
|
2403
|
+
"client_id": client_id,
|
|
2404
|
+
"messages_sent": messages_sent,
|
|
2405
|
+
"messages_received": messages_received,
|
|
2406
|
+
"success_rate": messages_received / messages_sent if messages_sent > 0 else 0
|
|
2407
|
+
}
|
|
2408
|
+
|
|
2409
|
+
print("开始WebSocket模拟测试...")
|
|
2410
|
+
start_time = time.time()
|
|
2411
|
+
|
|
2412
|
+
# 创建多个并发客户端
|
|
2413
|
+
client_count = 5
|
|
2414
|
+
messages_per_client = 3
|
|
2415
|
+
|
|
2416
|
+
client_tasks = [
|
|
2417
|
+
websocket_client(f"client_{i}", messages_per_client)
|
|
2418
|
+
for i in range(client_count)
|
|
2419
|
+
]
|
|
2420
|
+
|
|
2421
|
+
# 并发运行所有客户端
|
|
2422
|
+
results = await asyncio.gather(*client_tasks)
|
|
2423
|
+
|
|
2424
|
+
end_time = time.time()
|
|
2425
|
+
total_duration = end_time - start_time
|
|
2426
|
+
|
|
2427
|
+
# 汇总统计
|
|
2428
|
+
total_sent = sum(r["messages_sent"] for r in results)
|
|
2429
|
+
total_received = sum(r["messages_received"] for r in results)
|
|
2430
|
+
overall_success_rate = total_received / total_sent if total_sent > 0 else 0
|
|
2431
|
+
|
|
2432
|
+
print(f"\\nWebSocket模拟完成:")
|
|
2433
|
+
print(f"客户端数量: {client_count}")
|
|
2434
|
+
print(f"每客户端消息: {messages_per_client}")
|
|
2435
|
+
print(f"总发送消息: {total_sent}")
|
|
2436
|
+
print(f"总接收消息: {total_received}")
|
|
2437
|
+
print(f"整体成功率: {overall_success_rate:.2%}")
|
|
2438
|
+
print(f"总耗时: {total_duration:.3f}s")
|
|
2439
|
+
print(f"消息吞吐量: {(total_sent + total_received) / total_duration:.1f} messages/s")
|
|
2440
|
+
|
|
2441
|
+
{
|
|
2442
|
+
"client_count": client_count,
|
|
2443
|
+
"total_sent": total_sent,
|
|
2444
|
+
"total_received": total_received,
|
|
2445
|
+
"success_rate": overall_success_rate,
|
|
2446
|
+
"duration": total_duration,
|
|
2447
|
+
"throughput": (total_sent + total_received) / total_duration,
|
|
2448
|
+
"client_results": results
|
|
2449
|
+
}
|
|
2450
|
+
"""
|
|
2451
|
+
|
|
2452
|
+
execution = await self.sandbox.run_code(code, language="python")
|
|
2453
|
+
assert execution.error is None
|
|
2454
|
+
assert any("WebSocket模拟" in line for line in execution.logs.stdout)
|
|
2455
|
+
|
|
2456
|
+
# ======================== 主测试执行器 ========================
|
|
2457
|
+
|
|
2458
|
+
async def run_all_tests(self):
|
|
2459
|
+
"""运行所有异步测试"""
|
|
2460
|
+
logger.info("开始AsyncCodeInterpreter综合验证测试...")
|
|
2461
|
+
|
|
2462
|
+
# 基础异步操作测试
|
|
2463
|
+
await self.run_test(
|
|
2464
|
+
self.test_async_code_interpreter_creation, "Async CodeInterpreter Creation"
|
|
2465
|
+
)
|
|
2466
|
+
await self.run_test(
|
|
2467
|
+
self.test_basic_async_python_execution, "Basic Async Python Execution"
|
|
2468
|
+
)
|
|
2469
|
+
await self.run_test(
|
|
2470
|
+
self.test_concurrent_code_execution, "Concurrent Code Execution"
|
|
2471
|
+
)
|
|
2472
|
+
await self.run_test(
|
|
2473
|
+
self.test_async_data_science_workflow, "Async Data Science Workflow"
|
|
2474
|
+
)
|
|
2475
|
+
|
|
2476
|
+
# 异步回调测试
|
|
2477
|
+
await self.run_test(
|
|
2478
|
+
self.test_async_callback_handling, "Async Callback Handling"
|
|
2479
|
+
)
|
|
2480
|
+
|
|
2481
|
+
# 异步上下文管理测试
|
|
2482
|
+
await self.run_test(self.test_async_context_creation, "Async Context Creation")
|
|
2483
|
+
await self.run_test(
|
|
2484
|
+
self.test_async_context_state_management, "Async Context State Management"
|
|
2485
|
+
)
|
|
2486
|
+
|
|
2487
|
+
# 异步性能测试
|
|
2488
|
+
await self.run_test(
|
|
2489
|
+
self.test_async_performance_concurrent_tasks,
|
|
2490
|
+
"Async Performance Concurrent Tasks",
|
|
2491
|
+
)
|
|
2492
|
+
await self.run_test(self.test_async_batch_processing, "Async Batch Processing")
|
|
2493
|
+
|
|
2494
|
+
# 异步错误处理测试
|
|
2495
|
+
await self.run_test(self.test_async_error_handling, "Async Error Handling")
|
|
2496
|
+
|
|
2497
|
+
# 异步结果格式测试
|
|
2498
|
+
await self.run_test(self.test_async_text_result, "Async Text Result Format")
|
|
2499
|
+
await self.run_test(
|
|
2500
|
+
self.test_async_mixed_format_result, "Async Mixed Format Result"
|
|
2501
|
+
)
|
|
2502
|
+
await self.run_test(
|
|
2503
|
+
self.test_async_realtime_data_result, "Async Realtime Data Result"
|
|
2504
|
+
)
|
|
2505
|
+
|
|
2506
|
+
# 异步R语言测试
|
|
2507
|
+
await self.run_test(
|
|
2508
|
+
self.test_async_r_language_basic_execution,
|
|
2509
|
+
"Async R Language Basic Execution",
|
|
2510
|
+
)
|
|
2511
|
+
await self.run_test(
|
|
2512
|
+
self.test_async_r_language_data_analysis, "Async R Language Data Analysis"
|
|
2513
|
+
)
|
|
2514
|
+
await self.run_test(
|
|
2515
|
+
self.test_async_r_language_visualization, "Async R Language Visualization"
|
|
2516
|
+
)
|
|
2517
|
+
await self.run_test(
|
|
2518
|
+
self.test_async_r_language_statistics, "Async R Language Statistics"
|
|
2519
|
+
)
|
|
2520
|
+
await self.run_test(
|
|
2521
|
+
self.test_async_r_language_context_management,
|
|
2522
|
+
"Async R Language Context Management",
|
|
2523
|
+
)
|
|
2524
|
+
|
|
2525
|
+
# 异步Node.js/JavaScript 测试
|
|
2526
|
+
await self.run_test(
|
|
2527
|
+
self.test_async_nodejs_basic_execution, "Async Node.js Basic Execution"
|
|
2528
|
+
)
|
|
2529
|
+
await self.run_test(
|
|
2530
|
+
self.test_async_nodejs_async_promises, "Async Node.js Async Promises"
|
|
2531
|
+
)
|
|
2532
|
+
await self.run_test(
|
|
2533
|
+
self.test_async_nodejs_data_processing, "Async Node.js Data Processing"
|
|
2534
|
+
)
|
|
2535
|
+
await self.run_test(
|
|
2536
|
+
self.test_async_nodejs_chart_data, "Async Node.js Chart Data Generation"
|
|
2537
|
+
)
|
|
2538
|
+
await self.run_test(
|
|
2539
|
+
self.test_async_nodejs_context_management,
|
|
2540
|
+
"Async Node.js Context Management",
|
|
2541
|
+
)
|
|
2542
|
+
|
|
2543
|
+
# 异步Bash 测试
|
|
2544
|
+
await self.run_test(
|
|
2545
|
+
self.test_async_bash_basic_execution, "Async Bash Basic Execution"
|
|
2546
|
+
)
|
|
2547
|
+
await self.run_test(
|
|
2548
|
+
self.test_async_bash_file_operations, "Async Bash File Operations"
|
|
2549
|
+
)
|
|
2550
|
+
await self.run_test(
|
|
2551
|
+
self.test_async_bash_pipelines_and_grep, "Async Bash Pipelines and Grep"
|
|
2552
|
+
)
|
|
2553
|
+
await self.run_test(
|
|
2554
|
+
self.test_async_bash_env_and_exit_codes, "Async Bash Env and Exit Codes"
|
|
2555
|
+
)
|
|
2556
|
+
await self.run_test(
|
|
2557
|
+
self.test_async_bash_context_management, "Async Bash Context Management"
|
|
2558
|
+
)
|
|
2559
|
+
|
|
2560
|
+
# 异步IJAVA 测试
|
|
2561
|
+
await self.run_test(
|
|
2562
|
+
self.test_async_ijava_basic_execution, "Async IJAVA Basic Execution"
|
|
2563
|
+
)
|
|
2564
|
+
await self.run_test(
|
|
2565
|
+
self.test_async_ijava_oop_features, "Async IJAVA OOP Features"
|
|
2566
|
+
)
|
|
2567
|
+
await self.run_test(
|
|
2568
|
+
self.test_async_ijava_collections, "Async IJAVA Collections"
|
|
2569
|
+
)
|
|
2570
|
+
await self.run_test(self.test_async_ijava_file_io, "Async IJAVA File I/O")
|
|
2571
|
+
await self.run_test(
|
|
2572
|
+
self.test_async_ijava_context_management, "Async IJAVA Context Management"
|
|
2573
|
+
)
|
|
2574
|
+
|
|
2575
|
+
# 异步Deno 测试
|
|
2576
|
+
await self.run_test(
|
|
2577
|
+
self.test_async_deno_basic_execution, "Async Deno Basic Execution"
|
|
2578
|
+
)
|
|
2579
|
+
await self.run_test(
|
|
2580
|
+
self.test_async_deno_typescript_features, "Async Deno TypeScript Features"
|
|
2581
|
+
)
|
|
2582
|
+
await self.run_test(self.test_async_deno_async_await, "Async Deno Async/Await")
|
|
2583
|
+
await self.run_test(
|
|
2584
|
+
self.test_async_deno_file_operations, "Async Deno File Operations"
|
|
2585
|
+
)
|
|
2586
|
+
await self.run_test(
|
|
2587
|
+
self.test_async_deno_context_management, "Async Deno Context Management"
|
|
2588
|
+
)
|
|
2589
|
+
|
|
2590
|
+
# 高级异步功能测试
|
|
2591
|
+
await self.run_test(
|
|
2592
|
+
self.test_async_websocket_simulation, "Async WebSocket Simulation"
|
|
2593
|
+
)
|
|
2594
|
+
|
|
2595
|
+
async def cleanup(self):
|
|
2596
|
+
"""清理资源"""
|
|
2597
|
+
# 清理剩余的上下文
|
|
2598
|
+
for name, context in self.contexts.items():
|
|
2599
|
+
try:
|
|
2600
|
+
await self.sandbox.destroy_context(context)
|
|
2601
|
+
logger.info(
|
|
2602
|
+
f"Successfully destroyed async context {name}: {context.id}"
|
|
2603
|
+
)
|
|
2604
|
+
except Exception as e:
|
|
2605
|
+
logger.warning(f"Error cleaning up async context {name}: {e}")
|
|
2606
|
+
|
|
2607
|
+
# 清空contexts字典
|
|
2608
|
+
self.contexts.clear()
|
|
2609
|
+
|
|
2610
|
+
# 清理异步沙箱
|
|
2611
|
+
if self.sandbox:
|
|
2612
|
+
try:
|
|
2613
|
+
# await self.sandbox.kill()
|
|
2614
|
+
logger.info("AsyncCodeInterpreter sandbox cleaned up successfully")
|
|
2615
|
+
except Exception as e:
|
|
2616
|
+
logger.error(f"Error cleaning up async sandbox: {e}")
|
|
2617
|
+
|
|
2618
|
+
def print_summary(self):
|
|
2619
|
+
"""打印测试摘要"""
|
|
2620
|
+
total_tests = len(self.test_results)
|
|
2621
|
+
passed_tests = sum(1 for r in self.test_results if r["success"])
|
|
2622
|
+
failed_tests = total_tests - passed_tests
|
|
2623
|
+
|
|
2624
|
+
total_duration = sum(r["duration"] for r in self.test_results)
|
|
2625
|
+
|
|
2626
|
+
print("\n" + "=" * 60)
|
|
2627
|
+
print("AsyncCodeInterpreter综合验证测试报告")
|
|
2628
|
+
print("=" * 60)
|
|
2629
|
+
print(f"总测试数: {total_tests}")
|
|
2630
|
+
print(f"通过数: {passed_tests}")
|
|
2631
|
+
print(f"失败数: {failed_tests}")
|
|
2632
|
+
print(f"总耗时: {total_duration:.3f}秒")
|
|
2633
|
+
print(f"成功率: {(passed_tests/total_tests*100):.1f}%")
|
|
2634
|
+
|
|
2635
|
+
if self.failed_tests:
|
|
2636
|
+
print(f"\n失败的测试:")
|
|
2637
|
+
for test in self.failed_tests:
|
|
2638
|
+
print(f" ❌ {test}")
|
|
2639
|
+
|
|
2640
|
+
print("=" * 60)
|
|
2641
|
+
|
|
2642
|
+
|
|
2643
|
+
async def main():
|
|
2644
|
+
"""主函数"""
|
|
2645
|
+
validator = AsyncCodeInterpreterValidator()
|
|
2646
|
+
|
|
2647
|
+
try:
|
|
2648
|
+
await validator.run_all_tests()
|
|
2649
|
+
finally:
|
|
2650
|
+
await validator.cleanup()
|
|
2651
|
+
validator.print_summary()
|
|
2652
|
+
|
|
2653
|
+
|
|
2654
|
+
if __name__ == "__main__":
|
|
2655
|
+
asyncio.run(main())
|