shell 测试在运行bat测试文件时出错

vecaoik1  于 2023-05-07  发布在  Shell
关注(0)|答案(1)|浏览(230)

考虑一下,我有一个shell脚本abc.sh


execute_curl() {
    curl_command="curl"
    for arg in "$@"; do
        curl_command=$(printf "%s %s" "$curl_command" "$arg")
    done
    eval "$curl_command"
}
URL='https://some.github.com/api/v3/repos/gimlet-dev-repos/repository-name/contents/file.name?ref=branch-name’

execute_curl -s -H “Authorization: token ${TOKEN}” -H "Accept: application/vnd.github.v3+json" -L ”${URL}"

和test.bats为同一

@test "test-run-command perform" {
    export PATH="${RESOURCES_DIR}/mocks/:${PATH}"
    TEMP_DIR=$(mktemp -d)
    debug "TEMP_DIR: ${TEMP_DIR}"
    run abc -t TOKEN -d 'some.github.com' -o 'myorg' -r 'myrepo' -g "${RESOURCES_DIR}/mock-global" -b branch -a "${TEMP_DIR}"
    assert_success
 }



在mocks目录中,我有curl文件来测试curl:
例如:


#!/bin/sh
string_matches_glob() {
    eval "
    case \$1 in
        $2) return 0 ;;
        *) return 1 ;;
    esac
    "
}
while getopts "H:L:o:w:" OPT; do
    case "${OPT}" in
    o) OUTPUT_FILE="${OPTARG}" ;;
    L) CURL_URL="${OPTARG}" ;;
    ?) ;;
    esac
done

if string_matches_glob "${CURL_URL}" ‘*/contents/file.name*’; then
    echo '
Content…
' >"${OUTPUT_FILE}"
    printf '%s' '200'
else
    exit 97
fi

问题是,如果我不使用execute_curl,而是直接使用带参数的curl命令,测试会通过,但当我使用execute_curl函数时,测试会失败,并显示97

以上curl文件的详细说明:

string_matches_glob计算第一个参数是否匹配第二个参数中指定的glob模式。然后,脚本使用getopts命令解析传递给脚本的命令行选项和参数。
有三个选项可以传递给脚本:
-o:指定脚本要写入的输出文件-L:指定要传递给string_matches_glob的URL
如果URL与任何指定的模式都不匹配,脚本将退出,并显示错误代码97。
我的想法是这一行无法匹配curl_url:
if string_matches_glob“${CURL_URL}”'*/contents/file.name *'
你能帮我修改一下curl文件吗?这样测试就能通过了。

p8ekf7hl

p8ekf7hl1#

当我调用bash abc.sh时,调用似乎可以工作。
但是,当调试(使用TOKEN=foo bash -x abc.sh)显示执行的命令是:

curl -s -H Authorization: token foo -H Accept: application/vnd.github.v3+json -L 'https://some.github.com/api/v3/repos/gimlet-dev-repos/repository-name/contents/file.name?ref=branch-name'

因此,立即突出的一点是,curl_command的构建和执行方式没有正确处理空白。
curl将看到-H Authorization:-H Accept:,但忽略所提供的头的实际值。
在很棒的BashFAQ上有一个页面专门介绍了如何正确地做到这一点的陷阱:http://mywiki.wooledge.org/BashFAQ/050
使用适当的解决方案还可以消除对eval的需求:

curl_command=()

for arg in "$@"; do
    curl_command+=("$arg")
done

curl "${curl_command[@]}"

这将创建预期的curl命令,并使用适当的空格:

curl -s -H 'Authorization: token foo' -H 'Accept: application/vnd.github.v3+json' -L 'https://some.github.com/api/v3/repos/gimlet-dev-repos/repository-name/contents/file.name?ref=branch-name'

不确定这是否会解决您的问题,但至少对curl的调用将是正确的。
接下来突出的是,测试中的调用与curl调用不匹配。
比如,这个调用:

run abc -t TOKEN -d 'some.github.com' -o 'myorg' -r 'myrepo' -g "${RESOURCES_DIR}/mock-global" -b branch -a "${TEMP_DIR}"

将构成此curl调用:

curl --telnet-option TOKEN --data 'some.github.com' --output 'myorg' --range 'myrepo' --globoff "${RESOURCES_DIR}/mock-global" --cookie branch --append "${TEMP_DIR}"

我觉得这不是你想要的
这让我认为,真实的代码中的内容比最小示例中所表示的内容要多。
最有可能的答案是curl_command使用输入来构造正确的URL(-d = 'domain',-o = 'org',-r ='repo'?)但那只是一个猜测。
最后,让我们在string_matches_glob中处理eval。我假设这是为了允许动态匹配$1$2。如果是这种情况,有更简单的方法来做到这一点,没有evalcase。 例如,使用=~`正则表达式匹配运算符:

string_matches_glob() {
    local string="$1"
    local glob="$2"

    [[ "$string" =~ $glob ]]
}

或者,如果不可用或不需要,则使用grep

string_matches_glob() {
    local string="$1"
    local glob="$2"

    echo "$string" | grep -q -E "$glob"
}

由于这两种解决方案都足够小,因此可以内联使用,而不需要单独的函数:

if [[ "${CURL_URL}" =~ */contents/file.name* ]]; then
   ...
fi

或:

if echo "${CURL_URL}" | grep -q -E '*/contents/file.name*'; then
    ...
fi

你可能想知道“为什么这很重要?“但是代码中的魔法越少,调试就越容易。
所有这些都让我觉得我们没有足够的真实的代码来正确地调试这个问题,尽管最有可能的罪魁祸首是curl_command结构。

相关问题