# ============================================================================ # AI 批处理模块测试(src/lib/ai.sh) # ============================================================================ setup() { AI_BATCH_SIZE=50 AI_BATCH_KEYS_SEARCH=() AI_BATCH_KEYS_SPECIAL=() AI_BATCH_KEYS_ARTIST=() AI_BATCH_KEYS_MATCH=() PENDING_AI_SEARCH=() PENDING_AI_SPECIAL=() PENDING_AI_ARTIST=() PENDING_AI_MATCH=() } # ai_extract_json:直接 JSON test_ai_extract_direct_json() { assert_eq '{"a": 1}' "$(ai_extract_json '{"a": 1}')" } # ai_extract_json:```json 围栏 test_ai_extract_fenced_json() { local input=$'```json\n{"a": 1}\n```' assert_eq '{"a": 1}' "$(ai_extract_json "$input")" } # ai_extract_json:异行 标签 test_ai_extract_thinking_block() { local input=$'分析中\n{"a": 1}' assert_eq '{"a": 1}' "$(ai_extract_json "$input")" } # ai_extract_json:同行 标签(awk 行级处理无法吞掉,需 sed 预处理) test_ai_extract_thinking_inline() { assert_eq '{"a": 1}' "$(ai_extract_json '分析中{"a": 1}')" } # ai_extract_json:「思考:」前缀 test_ai_extract_thinking_prefix() { assert_eq '{"a": 1}' "$(ai_extract_json '思考:这是答案。{"a": 1}')" } # ai_extract_json:非 JSON 返回空 test_ai_extract_invalid_returns_empty() { assert_eq "" "$(ai_extract_json 'not json at all')" assert_eq "" "$(ai_extract_json '')" } # build_ai_input_json:三类条目构造正确的 JSON 结构 test_ai_input_json_structure() { PENDING_AI_SEARCH["/m/电影 (2020).mkv"]="movie dir" PENDING_AI_SPECIAL["123|Menu01"]="Show|01:Menu; 02:CM" PENDING_AI_ARTIST["/m/song.flac"]="A; B|Album|" # 值格式:artists|album|rel_dir local json rc=0 build_ai_input_json json echo "$json" | jq -e ' (.search_entries | length) == 1 and (.special_entries | length) == 1 and (.artist_entries | length) == 1 and (.match_entries | length) == 0 ' >/dev/null || rc=$? assert_eq '0' "$rc" "JSON 结构校验" assert_eq "/m/电影 (2020).mkv" "$(echo "$json" | jq -r '.search_entries[0].file')" assert_eq "123" "$(echo "$json" | jq -r '.special_entries[0].show_id')" assert_eq "A; B" "$(echo "$json" | jq -r '.artist_entries[0].artists')" # 副作用:keys 数组在调用方可见(修复子 shell 丢失 bug 后) assert_eq '1' "${#AI_BATCH_KEYS_SEARCH[@]}" assert_eq '1' "${#AI_BATCH_KEYS_SPECIAL[@]}" assert_eq '1' "${#AI_BATCH_KEYS_ARTIST[@]}" } # build_ai_input_json:批大小上限 test_ai_input_json_batch_limit() { AI_BATCH_SIZE=2 PENDING_AI_SEARCH["/a1.mkv"]="movie " PENDING_AI_SEARCH["/a2.mkv"]="movie " PENDING_AI_SEARCH["/a3.mkv"]="movie " local json build_ai_input_json json assert_eq '2' "$(echo "$json" | jq '.search_entries | length')" assert_eq '2' "${#AI_BATCH_KEYS_SEARCH[@]}" }