This commit is contained in:
NgoQuocViet2001 2026-08-09 03:26:22 +00:00 committed by GitHub
commit 7aeebc45ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 145 additions and 8 deletions

View File

@ -273,7 +273,7 @@ def _check_simulation_prepared(simulation_id: str) -> tuple:
检查条件
1. state.json 存在且 status "ready"
2. 必要文件存在reddit_profiles.json, twitter_profiles.csv, simulation_config.json
2. simulation_config.json 和已启用平台对应的 Profile 文件存在
注意运行脚本(run_*.py)保留在 backend/scripts/ 目录不再复制到模拟目录
@ -295,10 +295,26 @@ def _check_simulation_prepared(simulation_id: str) -> tuple:
# 必要文件列表(不包括脚本,脚本位于 backend/scripts/
required_files = [
"state.json",
"simulation_config.json",
"reddit_profiles.json",
"twitter_profiles.csv"
"simulation_config.json"
]
# Profile文件仅在对应平台启用时生成。旧状态文件没有平台字段
# 此时继续按双平台处理以保持向后兼容。
state_file = os.path.join(simulation_dir, "state.json")
platform_state = {}
if os.path.exists(state_file):
try:
import json
with open(state_file, 'r', encoding='utf-8') as f:
platform_state = json.load(f)
except (OSError, json.JSONDecodeError):
# 保留后续原有的缺失文件和状态文件错误处理。
pass
if platform_state.get("enable_reddit", True):
required_files.append("reddit_profiles.json")
if platform_state.get("enable_twitter", True):
required_files.append("twitter_profiles.csv")
# 检查文件是否存在
existing_files = []
@ -318,7 +334,6 @@ def _check_simulation_prepared(simulation_id: str) -> tuple:
}
# 检查state.json中的状态
state_file = os.path.join(simulation_dir, "state.json")
try:
import json
with open(state_file, 'r', encoding='utf-8') as f:
@ -341,14 +356,19 @@ def _check_simulation_prepared(simulation_id: str) -> tuple:
prepared_statuses = ["ready", "preparing", "running", "completed", "stopped", "failed"]
if status in prepared_statuses and config_generated:
# 获取文件统计信息
profiles_file = os.path.join(simulation_dir, "reddit_profiles.json")
config_file = os.path.join(simulation_dir, "simulation_config.json")
profiles_count = 0
if os.path.exists(profiles_file):
profiles_count = state_data.get("profiles_count", 0)
if state_data.get("enable_reddit", True):
profiles_file = os.path.join(simulation_dir, "reddit_profiles.json")
with open(profiles_file, 'r', encoding='utf-8') as f:
profiles_data = json.load(f)
profiles_count = len(profiles_data) if isinstance(profiles_data, list) else 0
elif state_data.get("enable_twitter", True):
import csv
profiles_file = os.path.join(simulation_dir, "twitter_profiles.csv")
with open(profiles_file, 'r', encoding='utf-8', newline='') as f:
profiles_count = sum(1 for _ in csv.DictReader(f))
# 如果状态是preparing但文件已完成自动更新状态为ready
if status == "preparing":

View File

@ -0,0 +1,117 @@
import json
import pytest
from app.api.simulation import _check_simulation_prepared
from app.config import Config
def _write_prepared_simulation(
root,
*,
enable_twitter=None,
enable_reddit=None,
profile_files=(),
):
simulation_id = "sim_prepared"
simulation_dir = root / simulation_id
simulation_dir.mkdir(parents=True)
state = {
"status": "ready",
"config_generated": True,
"profiles_count": 1,
}
if enable_twitter is not None:
state["enable_twitter"] = enable_twitter
if enable_reddit is not None:
state["enable_reddit"] = enable_reddit
(simulation_dir / "state.json").write_text(
json.dumps(state),
encoding="utf-8",
)
(simulation_dir / "simulation_config.json").write_text(
"{}",
encoding="utf-8",
)
for filename in profile_files:
content = "[{}]" if filename.endswith(".json") else "user_id,user_name\n0,alice\n"
(simulation_dir / filename).write_text(content, encoding="utf-8")
return simulation_id
def test_twitter_only_simulation_does_not_require_reddit_profiles(tmp_path, monkeypatch):
simulation_id = _write_prepared_simulation(
tmp_path,
enable_twitter=True,
enable_reddit=False,
profile_files=("twitter_profiles.csv",),
)
monkeypatch.setattr(Config, "OASIS_SIMULATION_DATA_DIR", str(tmp_path))
is_prepared, info = _check_simulation_prepared(simulation_id)
assert is_prepared is True
assert info["profiles_count"] == 1
assert "twitter_profiles.csv" in info["existing_files"]
assert "reddit_profiles.json" not in info["existing_files"]
def test_reddit_only_simulation_does_not_require_twitter_profiles(tmp_path, monkeypatch):
simulation_id = _write_prepared_simulation(
tmp_path,
enable_twitter=False,
enable_reddit=True,
profile_files=("reddit_profiles.json",),
)
monkeypatch.setattr(Config, "OASIS_SIMULATION_DATA_DIR", str(tmp_path))
is_prepared, info = _check_simulation_prepared(simulation_id)
assert is_prepared is True
assert info["profiles_count"] == 1
assert "reddit_profiles.json" in info["existing_files"]
assert "twitter_profiles.csv" not in info["existing_files"]
@pytest.mark.parametrize(
("enable_twitter", "enable_reddit", "missing_profile"),
[
(True, False, "twitter_profiles.csv"),
(False, True, "reddit_profiles.json"),
],
)
def test_enabled_platform_profile_is_still_required(
tmp_path,
monkeypatch,
enable_twitter,
enable_reddit,
missing_profile,
):
simulation_id = _write_prepared_simulation(
tmp_path,
enable_twitter=enable_twitter,
enable_reddit=enable_reddit,
)
monkeypatch.setattr(Config, "OASIS_SIMULATION_DATA_DIR", str(tmp_path))
is_prepared, info = _check_simulation_prepared(simulation_id)
assert is_prepared is False
assert info["missing_files"] == [missing_profile]
def test_legacy_state_without_platform_flags_requires_both_profiles(tmp_path, monkeypatch):
simulation_id = _write_prepared_simulation(
tmp_path,
profile_files=("reddit_profiles.json",),
)
monkeypatch.setattr(Config, "OASIS_SIMULATION_DATA_DIR", str(tmp_path))
is_prepared, info = _check_simulation_prepared(simulation_id)
assert is_prepared is False
assert info["missing_files"] == ["twitter_profiles.csv"]