# ============================================================================ # 识别登记与并发池模块测试(src/lib/registry.sh) # ============================================================================ setup() { MEDIA_DESTINATION_MAP=() MEDIA_OUTCOME_MAP=() PENDING_AI_SEARCH=() PENDING_AI_SPECIAL=() PENDING_AI_ARTIST=() PENDING_AI_MATCH=() PENDING_SEARCH_COUNT=0 PENDING_SPECIAL_COUNT=0 PENDING_ARTIST_COUNT=0 PENDING_MATCH_COUNT=0 LINK_SUCCESS_COUNT=0 LINK_FAIL_COUNT=0 } # register_identified:登记目的与结局账本 test_register_identified() { register_identified "/m/a.mkv" "Movie/A (2020)" "A (2020).mkv" assert_eq "Movie/A (2020)|A (2020).mkv" "${MEDIA_DESTINATION_MAP[/m/a.mkv]}" assert_eq "identified" "${MEDIA_OUTCOME_MAP[/m/a.mkv]}" } # register_skip:跳过不进入目的映射 test_register_skip() { register_skip "/m/a.mkv" "skip_unidentified" assert_eq "skip_unidentified" "${MEDIA_OUTCOME_MAP[/m/a.mkv]}" assert_empty "${MEDIA_DESTINATION_MAP[/m/a.mkv]:-}" } # register_request_failed:请求失败结局 test_register_request_failed() { register_request_failed "/m/a.mkv" assert_eq "request_failed" "${MEDIA_OUTCOME_MAP[/m/a.mkv]}" } # register_pending:待 AI 搜索并计入计数 test_register_pending() { register_pending "/m/a.mkv" "unknown dir" assert_eq "unknown dir" "${PENDING_AI_SEARCH[/m/a.mkv]}" assert_eq "1" "$PENDING_SEARCH_COUNT" } # emit:DEST 协议行写入 POOL_EMIT_FILE(识别池 worker 模式;父进程 merge 后登记) test_emit_dest_protocol() { local f f="$(mktemp)" POOL_EMIT_FILE="$f" emit "/m/a.mkv" DEST "Movie/A (2020)|A (2020).mkv" assert_eq $'/m/a.mkv DEST Movie/A (2020)|A (2020).mkv' "$(cat "$f")" assert_empty "${MEDIA_OUTCOME_MAP[/m/a.mkv]:-}" "emit 本身不登记,merge 才登记" rm -f "$f" unset POOL_EMIT_FILE } # emit:SPECIAL_PENDING 直接登记待学习特典 test_emit_special_pending() { emit "/m/a.mkv" SPECIAL_PENDING "123|Menu01|Show|01:Menu; 02:CM" assert_eq "Show|01:Menu; 02:CM" "${PENDING_AI_SPECIAL[123|Menu01]}" assert_eq "1" "$PENDING_SPECIAL_COUNT" } # emit:MATCH 直接登记待甄别 test_emit_match_protocol() { emit "/m/a.mkv" MATCH "tv 1 /search/tv key123" assert_eq "1" "$PENDING_MATCH_COUNT" assert_not_empty "${PENDING_AI_MATCH[/m/a.mkv]:-}" } # merge_emit_lines:合并子进程协议行(临时文件) test_merge_emit_lines() { local f f="$(mktemp)" printf '/m/a.mkv\tDEST\tMovie/A|A.mkv\n' >"$f" printf '/m/b.mkv\tSKIP\tskip_type\n' >>"$f" merge_emit_lines "$f" rm -f "$f" assert_eq "identified" "${MEDIA_OUTCOME_MAP[/m/a.mkv]}" assert_eq "skip_type" "${MEDIA_OUTCOME_MAP[/m/b.mkv]}" } # dir_chain:相对源根的目录链(最多 3 层) test_dir_chain() { SOURCE_DIR="/media/src" assert_eq "Show/Season 1" "$(dir_chain "/media/src/Show/Season 1/a.mkv")" # 契约:最多 3 层,保留最靠近文件的 3 层(含文件所在目录) assert_eq "B/C/D" "$(dir_chain "/media/src/A/B/C/D/a.mkv")" assert_eq "src" "$(dir_chain "/media/src/a.mkv")" }