- 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 与旧扁平模块
91 lines
3.6 KiB
Bash
91 lines
3.6 KiB
Bash
# ============================================================================
|
||
# 字符串工具模块测试(src/lib/strings.sh)
|
||
# ============================================================================
|
||
|
||
# 每个测试前重置依赖的全局状态
|
||
setup() {
|
||
COLOR_OUTPUT=false
|
||
TMDB_LANG="zh-CN"
|
||
SPECIAL_MAP=()
|
||
}
|
||
|
||
# sanitize:删除非法字符
|
||
test_sanitize_removes_illegal_chars() {
|
||
assert_eq "abcdefghij" "$(sanitize 'a/b\c:d*e?f"g<h>i|j')" "sanitize 应删除 \\ / : * ? \" < > |"
|
||
}
|
||
|
||
# sanitize:保留中文与空格
|
||
test_sanitize_keeps_cjk_and_spaces() {
|
||
assert_eq "某科学的超电磁炮T" "$(sanitize '某科学的超电磁炮T')"
|
||
assert_eq "刀剑神域 爱丽丝篇" "$(sanitize '刀剑神域 爱丽丝篇')"
|
||
}
|
||
|
||
# sanitize:空输入
|
||
test_sanitize_empty_input() {
|
||
assert_eq "" "$(sanitize "")"
|
||
assert_eq "" "$(sanitize "///")"
|
||
}
|
||
|
||
# clean_name:去方括号标记与首尾空白
|
||
test_clean_name_strips_brackets_and_spaces() {
|
||
assert_eq "Show Title" "$(clean_name '[VCB-Studio] Show Title [1080p]')"
|
||
assert_eq "Title" "$(clean_name ' [A] Title [B] ')"
|
||
}
|
||
|
||
# strip_season_suffix:多种季后缀
|
||
test_strip_season_suffix_variants() {
|
||
assert_eq "Show" "$(strip_season_suffix 'Show S01')"
|
||
assert_eq "Show" "$(strip_season_suffix 'Show 2nd Season')"
|
||
assert_eq "Show" "$(strip_season_suffix 'Show S12')"
|
||
# 行为契约:仅剥离 Season 前带数字的形式;"Show Season 2" 由 parse_media_filename 处理
|
||
assert_eq "Show Season 2" "$(strip_season_suffix 'Show Season 2')"
|
||
assert_eq "无需处理" "$(strip_season_suffix '无需处理')"
|
||
}
|
||
|
||
# norm_str:全角转半角 + 去空格/连字符 + 小写
|
||
test_norm_str_fullwidth_to_halfwidth() {
|
||
assert_eq "aliceization" "$(norm_str 'Aliceization')"
|
||
assert_eq "swordartonline" "$(norm_str 'Sword Art Online')"
|
||
assert_eq "iiiiiivv" "$(norm_str 'ⅡⅢⅣⅤ')"
|
||
assert_eq "menu01" "$(norm_str 'Menu 01')"
|
||
}
|
||
|
||
# safe_printf_int:补零与非数字默认值
|
||
test_safe_printf_int_padding() {
|
||
assert_eq "01" "$(safe_printf_int 1)"
|
||
assert_eq "23" "$(safe_printf_int 23)"
|
||
assert_eq "00" "$(safe_printf_int "")"
|
||
assert_eq "99" "$(safe_printf_int "abc" "99")"
|
||
assert_eq "07" "$(safe_printf_int "007")"
|
||
}
|
||
|
||
# normalize_abs:相对/绝对路径归一化
|
||
test_normalize_abs_paths() {
|
||
local d
|
||
d="$(mktemp -d)"
|
||
assert_eq "$d" "$(normalize_abs "$d")" "绝对路径原样返回"
|
||
assert_eq "$d/sub" "$(normalize_abs "$d/sub")" "不存在的子目录也应归一化"
|
||
assert_eq "" "$(normalize_abs "")" "空串原样返回"
|
||
rm -rf "$d"
|
||
}
|
||
|
||
# is_companion:伴随文件判断
|
||
test_is_companion_detection() {
|
||
assert_success is_companion "/path/Show.S01E01.mkv.ass" "/path/Show.S01E01.mkv"
|
||
assert_success is_companion "/path/Show.S01E01.zh-CN.ass" "/path/Show.S01E01"
|
||
assert_success is_companion "/path/Show.S01E01.flac" "/path/Show.S01E01"
|
||
assert_failure is_companion "/path/Other.mkv" "/path/Show.S01E01"
|
||
# 行为契约:视频自身去扩展名后等于 vbase → 也判为伴随(link_companions 调用前先跳过自身)
|
||
assert_success is_companion "/path/Show.S01E01.mkv" "/path/Show.S01E01"
|
||
}
|
||
|
||
# translate_fragment:查表、核心词回退、归一化
|
||
test_translate_fragment_lookup() {
|
||
SPECIAL_MAP["menu"]='["Menu", "菜单"]'
|
||
SPECIAL_MAP["cm01"]='["CM", "广告"]'
|
||
assert_eq "Menu" "$(translate_fragment "Menu01")" "去数字后查核心词"
|
||
assert_eq "CM" "$(translate_fragment "CM01")" "精确键优先"
|
||
assert_eq "Menu" "$(translate_fragment "Menu01")" "全角归一化"
|
||
assert_eq "PV-01" "$(translate_fragment "PV-01")" "无映射时原样返回"
|
||
}
|