Align rule table display widths
This commit is contained in:
@@ -77,6 +77,8 @@ sudo ./iptables-forward.sh
|
|||||||
- `✓`:该条规则对应的 PREROUTING / POSTROUTING / 双向 FORWARD 运行态规则都存在
|
- `✓`:该条规则对应的 PREROUTING / POSTROUTING / 双向 FORWARD 运行态规则都存在
|
||||||
- `!`:至少缺少一条运行态规则,或仅剩数据库记录
|
- `!`:至少缺少一条运行态规则,或仅剩数据库记录
|
||||||
|
|
||||||
|
列表表头与内容会按显示宽度对齐,中文与 ASCII 混排时也尽量保持列起始位置一致。
|
||||||
|
|
||||||
### 批处理模式
|
### 批处理模式
|
||||||
|
|
||||||
用于自动化测试或脚本调用:
|
用于自动化测试或脚本调用:
|
||||||
|
|||||||
@@ -57,18 +57,16 @@ log_ok() { _log_with_color "${CLR_GREEN}" OK "$@"; }
|
|||||||
|
|
||||||
display_width() {
|
display_width() {
|
||||||
local input=${1-}
|
local input=${1-}
|
||||||
awk -v str="${input}" 'BEGIN {
|
local char code width=0
|
||||||
n = split(str, chars, "")
|
while IFS= read -r -n1 char; do
|
||||||
width = 0
|
code=$(printf '%d' "'${char}")
|
||||||
for (i = 1; i <= n; i++) {
|
if (( code >= 32 && code <= 126 )); then
|
||||||
if (chars[i] ~ /[ -~]/) {
|
((width += 1))
|
||||||
width += 1
|
else
|
||||||
} else {
|
((width += 2))
|
||||||
width += 2
|
fi
|
||||||
}
|
done < <(printf '%s' "${input}")
|
||||||
}
|
printf '%s\n' "${width}"
|
||||||
print width
|
|
||||||
}'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
repeat_char() {
|
repeat_char() {
|
||||||
|
|||||||
@@ -146,6 +146,12 @@ rule_health_mark() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render_rules_row() {
|
||||||
|
printf '%s %s %s %s %s %s %s %s\n' \
|
||||||
|
"$(pad_right "${1-}" 3)" "$(pad_right "${2-}" 10)" "$(pad_right "${3-}" 10)" "$(pad_right "${4-}" 32)" \
|
||||||
|
"$(pad_right "${5-}" 10)" "$(pad_right "${6-}" 12)" "$(pad_right "${7-}" 4)" "${8-}"
|
||||||
|
}
|
||||||
|
|
||||||
render_rules_plain() {
|
render_rules_plain() {
|
||||||
local -a lines=("$@")
|
local -a lines=("$@")
|
||||||
local line idx uuid proto lport tip tport ipver desc health
|
local line idx uuid proto lport tip tport ipver desc health
|
||||||
@@ -154,7 +160,7 @@ render_rules_plain() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf '%-3s %-10s %-10s %-32s %-10s %-12s %-4s %s\n' '#' '协议' '本地端口' '目标地址' '目标端口' 'IP版本' '状态' '描述'
|
render_rules_row '#' '协议' '本地端口' '目标地址' '目标端口' 'IP版本' '状态' '描述'
|
||||||
for ((idx = 0; idx < ${#lines[@]}; idx++)); do
|
for ((idx = 0; idx < ${#lines[@]}; idx++)); do
|
||||||
line=${lines[idx]}
|
line=${lines[idx]}
|
||||||
uuid=$(rule_field "${line}" uuid)
|
uuid=$(rule_field "${line}" uuid)
|
||||||
@@ -165,8 +171,7 @@ render_rules_plain() {
|
|||||||
ipver=$(rule_ipver_label "$(rule_field "${line}" ipver)")
|
ipver=$(rule_ipver_label "$(rule_field "${line}" ipver)")
|
||||||
desc=$(rule_field "${line}" desc || true)
|
desc=$(rule_field "${line}" desc || true)
|
||||||
health=$(rule_health_mark "${line}")
|
health=$(rule_health_mark "${line}")
|
||||||
printf '%-3s %-10s %-10s %-32s %-10s %-12s %-4s %s\n' \
|
render_rules_row "$((idx + 1))" "${proto}" "${lport}" "${tip}" "${tport}" "${ipver}" "${health}" "${desc}"
|
||||||
"$((idx + 1))" "${proto}" "${lport}" "${tip}" "${tport}" "${ipver}" "${health}" "${desc}"
|
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -364,7 +364,7 @@ persist_reload() { netfilter-persistent reload >/dev/null; }
|
|||||||
- `cmd_add` (tcp/ipv4) 后:
|
- `cmd_add` (tcp/ipv4) 后:
|
||||||
- mock 日志包含 4 条命令 (PREROUTING/POSTROUTING/FORWARD 请求/回程) 且参数正确
|
- mock 日志包含 4 条命令 (PREROUTING/POSTROUTING/FORWARD 请求/回程) 且参数正确
|
||||||
- storage 中新增 1 条,UUID 与 mock 注释一致
|
- storage 中新增 1 条,UUID 与 mock 注释一致
|
||||||
- `cmd_add` (both/both) 后:mock 日志包含 12 条命令
|
- `cmd_add` (both/both) 后:mock 日志包含 16 条命令
|
||||||
- `cmd_delete` 后:mock 日志包含对应 `-D` 命令,storage 中记录被移除
|
- `cmd_delete` 后:mock 日志包含对应 `-D` 命令,storage 中记录被移除
|
||||||
- `cmd_add` 中途失败 (mock 注入错误):确认回滚,storage 不写入,已执行的 iptables `-A` 对应 `-D` 被调用
|
- `cmd_add` 中途失败 (mock 注入错误):确认回滚,storage 不写入,已执行的 iptables `-A` 对应 `-D` 被调用
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ assert_eq 'second' "$(cat "${prompt_tmp}")" 'prompt_input should consume subsequ
|
|||||||
assert_eq '' "${IPF_TEST_INPUTS}" 'prompt_input should drain queued test inputs in the current shell'
|
assert_eq '' "${IPF_TEST_INPUTS}" 'prompt_input should drain queued test inputs in the current shell'
|
||||||
unset IPF_TEST_INPUTS
|
unset IPF_TEST_INPUTS
|
||||||
|
|
||||||
|
assert_eq '4' "$(display_width '协议')" 'display_width should count CJK characters as double width'
|
||||||
|
assert_eq '8' "$(display_width 'IPv4规则')" 'display_width should handle ASCII and CJK mixed text'
|
||||||
|
|
||||||
assert_status 0 "$(status_of validate_ipv4 '0.0.0.0')" 'validate_ipv4 should accept 0.0.0.0'
|
assert_status 0 "$(status_of validate_ipv4 '0.0.0.0')" 'validate_ipv4 should accept 0.0.0.0'
|
||||||
assert_status 0 "$(status_of validate_ipv4 '192.168.1.1')" 'validate_ipv4 should accept private address'
|
assert_status 0 "$(status_of validate_ipv4 '192.168.1.1')" 'validate_ipv4 should accept private address'
|
||||||
assert_status 0 "$(status_of validate_ipv4 '255.255.255.255')" 'validate_ipv4 should accept broadcast'
|
assert_status 0 "$(status_of validate_ipv4 '255.255.255.255')" 'validate_ipv4 should accept broadcast'
|
||||||
|
|||||||
@@ -89,6 +89,11 @@ del_count=$(grep -Ec ' -D ' "${IPTABLES_MOCK_LOG}")
|
|||||||
assert_eq '16' "${del_count}" 'deleting both/both rule should emit sixteen delete commands'
|
assert_eq '16' "${del_count}" 'deleting both/both rule should emit sixteen delete commands'
|
||||||
assert_eq '0' "$(storage_count)" 'cmd_delete_uuid should remove rule from storage'
|
assert_eq '0' "$(storage_count)" 'cmd_delete_uuid should remove rule from storage'
|
||||||
|
|
||||||
|
reset_mock_state
|
||||||
|
cmd_add_batch tcp 9080 127.0.0.1 98 4 'desc-mark' >/dev/null
|
||||||
|
mapfile -t list_lines < <(cmd_list 0)
|
||||||
|
assert_eq "$(display_width "${list_lines[0]%%描述*}")" "$(display_width "${list_lines[1]%%desc-mark*}")" 'cmd_list should align description column by display width'
|
||||||
|
|
||||||
reset_mock_state
|
reset_mock_state
|
||||||
export IPTABLES_MOCK_FAIL_ON_N=2
|
export IPTABLES_MOCK_FAIL_ON_N=2
|
||||||
assert_eq '1' "$(status_of cmd_add_batch tcp 9000 127.0.0.1 90 4 'rollback')" 'cmd_add_batch should fail when iptables mock injects an error'
|
assert_eq '1' "$(status_of cmd_add_batch tcp 9000 127.0.0.1 90 4 'rollback')" 'cmd_add_batch should fail when iptables mock injects an error'
|
||||||
|
|||||||
Reference in New Issue
Block a user