- CLI 定义迁移至 src/bashly.yml(bashly 1.4 生成参数解析),入口收敛为 src/root_command.sh - 源码按功能域重组:config/storage/integrate/media/pipeline,消除扁平散落 - 新增零依赖测试框架 tests/(123 用例)与 CI 流水线(lint + test + build + 产物一致性) - build.sh 支持版本单一来源注入与 --check 产物校验;新增 lint.sh(bash -n + shellcheck 零容忍) - 删除旧单文件 media_organizer.sh 与旧扁平模块
84 lines
2.8 KiB
Bash
84 lines
2.8 KiB
Bash
# ============================================================================
|
||
# 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:异行 <thinking> 标签
|
||
test_ai_extract_thinking_block() {
|
||
local input=$'<thinking>分析中</thinking>\n{"a": 1}'
|
||
assert_eq '{"a": 1}' "$(ai_extract_json "$input")"
|
||
}
|
||
|
||
# ai_extract_json:同行 <thinking> 标签(awk 行级处理无法吞掉,需 sed 预处理)
|
||
test_ai_extract_thinking_inline() {
|
||
assert_eq '{"a": 1}' "$(ai_extract_json '<thinking>分析中</thinking>{"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[@]}"
|
||
}
|