diff --git a/README.md b/README.md index 8597cde318ca878902ff2980c0e1c9c1ef26c70a..2bb6c6b43340a8613e958cc05058fce68bec2a9a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,64 @@ -# TencentOS发行版检查 -检查项目包括 -- KABI -- 软件包安装 -- 内核模块加载 -- systemd服务启动 \ No newline at end of file +# TencentOS发行版检查 +检查项目包括 +- KABI +- 软件包安装 +- 内核模块加载 +- systemd服务启动 + + +## command-execute-docker.sh + +Script path: + +```bash +testcase/command-execute-docker.sh +``` + +Function: + +This script starts one independent Docker container for each package and runs the package test flow inside the container: +install, command, service, and remove. It supports concurrent package testing. + +Options and arguments: + +- `-j N`: number of concurrent containers. Default: `1`. +- `--image IMAGE`: Docker image. This overrides `OC_IMAGE`. +- `OC_IMAGE`: environment variable for the Docker image. +- `--timeout SEC`: per-package container timeout. Default: `300`. +- `--cpus VALUE`: pass `VALUE` to `docker run --cpus`. +- `--memory VALUE`: pass `VALUE` to `docker run --memory`. +- `pkg_list`: package list to test. +- `desktop_whitelist`: packages whose command test should be skipped. +- `service_pkg_list`: service packages that require special configuration. + +Default image: + +```bash +opencloudos9-local:latest +``` + +Example: + +```bash +OC_IMAGE=opencloudos9-local:latest bash testcase/command-execute-docker.sh -j 2 \ + pkg-list.txt desktop-whitelist.txt service-pkg-list.txt +``` + +Outputs: + +- `package-command-result-docker-*.txt` +- `logs/docker-command-execute-*/` + +Service test limitations: + +A normal Docker container usually does not have a full systemd environment. If systemd is not available in the container, service start testing is recorded as `SKIP` with reason `container without systemd`. + +Packages listed in `service_pkg_list` are recorded as `SKIP` with reason `service package requires special configuration`. + +These `SKIP` results are not treated as `FAIL`. + +Notes: + +The script and report fixed text use English ASCII to avoid encoding display issues. + +The script writes test framework bookkeeping results into the current `logs/docker-command-execute-*` directory, so it does not modify the existing tracked `logs/report.result` file. diff --git a/testcase/command-execute-docker.sh b/testcase/command-execute-docker.sh new file mode 100755 index 0000000000000000000000000000000000000000..ef294375a577df0f4c2684686012291d5afb359d --- /dev/null +++ b/testcase/command-execute-docker.sh @@ -0,0 +1,636 @@ +#!/usr/bin/env bash +############################################################################### +# @CaseName: command-execute-docker +# @CaseLevel: 3 +# @CaseType: functional +# @Automated: 1 +############################################################################### +set -u +set -o pipefail + +[ -z "${TST_TS_TOPDIR:-}" ] && { + TST_TS_TOPDIR="$(realpath "$(dirname "$0")/..")" + export TST_TS_TOPDIR +} + +set +u +source "${TST_TS_TOPDIR}/tst_common/lib/common.sh" || exit 1 +set -u + +DEFAULT_IMAGE="opencloudos9-local:latest" +JOBS=1 +OC_IMAGE="${OC_IMAGE:-$DEFAULT_IMAGE}" +TIMEOUT_SEC=300 +CPUS="" +MEMORY="" + +g_tmpdir="$(mktemp -d)" +g_run_stamp="$(date '+%Y%m%d-%H%M%S')" +g_log_root="${TST_TS_TOPDIR}/logs/docker-command-execute-${g_run_stamp}" +g_result_file="${TST_TS_TOPDIR}/package-command-result-docker-${g_run_stamp}.txt" + +# Keep the shell test framework bookkeeping inside this run's log directory. +# The upstream helper defaults to logs/report.result, which is tracked here. +_get_tst_result_file() { + TST_RESULT_FILE="$g_log_root/report.result" + export TST_RESULT_FILE + mkdir -p "$g_log_root" + if [ ! -f "$TST_RESULT_FILE" ]; then + { + echo "TESTSUITE" + echo "suite-name: $TST_TS_NAME" + echo "suite-start-time: $(get_timestamp_ms)" + echo "suite-end-time:" + echo "" + } >>"$TST_RESULT_FILE" + fi + echo "$TST_RESULT_FILE" + + TST_TC_CWD="$(realpath "$(dirname "$0")")" + export TST_TC_CWD + TST_TC_FILE_FULL="$(realpath "$0")" + export TST_TC_FILE_FULL + TST_TC_FILE="${TST_TC_FILE_FULL#"${TST_TS_TOPDIR}/"}" + export TST_TC_FILE + TST_TS_NAME="$(get_suite_name)" + export TST_TS_NAME + TST_TC_NAME="$(get_case_attr "CaseName")" + [ -n "$TST_TC_NAME" ] || TST_TC_NAME="command-execute-docker" + export TST_TC_NAME + TST_TC_SYSDIR="$g_log_root/testcase/.tc.${TST_TC_PID}.sysdir" + export TST_TC_SYSDIR + TST_TC_TIMEOUT="$(get_case_attr "Timeout")" + export TST_TC_TIMEOUT + ALLURE_DATA_DIR="$g_log_root/allure_data" + export ALLURE_DATA_DIR + + mkdir -p "$TST_TC_SYSDIR" "$ALLURE_DATA_DIR" + _set_tcstat "$TST_INIT" + _show_case_attr +} + +usage() { + cat <<'EOF' +Usage: bash testcase/command-execute-docker.sh [options] + +Options: + -j N Number of concurrent Docker containers, default: 1 + --image IMAGE Docker image, overrides OC_IMAGE + --timeout SEC Per-package container timeout, default: 300 + --cpus VALUE Pass VALUE to docker run --cpus + --memory VALUE Pass VALUE to docker run --memory + -h, --help Show this help +EOF +} + +die() { + err "$*" + exit 1 +} + +is_positive_integer() { + case "$1" in + ''|*[!0-9]*) return 1 ;; + *) [ "$1" -gt 0 ] ;; + esac +} + +safe_name() { + local index="$1" + local name="$2" + local safe + safe="$(printf '%s' "$name" | sed 's/[^A-Za-z0-9_.-]/_/g' | cut -c 1-120)" + [ -n "$safe" ] || safe="pkg" + printf '%04d-%s' "$index" "$safe" +} + +write_tsv_result() { + local output_file="$1" + local src_pkg="$2" + local bin_pkg="$3" + local install_status="$4" + local command_status="$5" + local service_status="$6" + local remove_status="$7" + local result_status="$8" + local reason="$9" + + reason="$(printf '%s' "$reason" | tr '\t\n' ' ')" + printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \ + "$src_pkg" "$bin_pkg" "$install_status" "$command_status" \ + "$service_status" "$remove_status" "$result_status" "$reason" >"$output_file" +} + +parse_args() { + while [ "$#" -gt 0 ]; do + case "$1" in + -j) + [ "$#" -ge 2 ] || die "missing value for -j" + JOBS="$2" + shift 2 + ;; + --image) + [ "$#" -ge 2 ] || die "missing value for --image" + OC_IMAGE="$2" + shift 2 + ;; + --image=*) + OC_IMAGE="${1#--image=}" + shift + ;; + --timeout) + [ "$#" -ge 2 ] || die "missing value for --timeout" + TIMEOUT_SEC="$2" + shift 2 + ;; + --timeout=*) + TIMEOUT_SEC="${1#--timeout=}" + shift + ;; + --cpus) + [ "$#" -ge 2 ] || die "missing value for --cpus" + CPUS="$2" + shift 2 + ;; + --cpus=*) + CPUS="${1#--cpus=}" + shift + ;; + --memory) + [ "$#" -ge 2 ] || die "missing value for --memory" + MEMORY="$2" + shift 2 + ;; + --memory=*) + MEMORY="${1#--memory=}" + shift + ;; + -h|--help) + usage + exit 0 + ;; + --) + shift + break + ;; + -*) + die "unknown option: $1" + ;; + *) + break + ;; + esac + done + + [ "$#" -eq 3 ] || { + usage + die "expected 3 required arguments" + } + + PKG_LIST="$(realpath "$1")" + DESKTOP_WHITELIST="$(realpath "$2")" + SERVICE_PKG_LIST="$(realpath "$3")" + export PKG_LIST DESKTOP_WHITELIST SERVICE_PKG_LIST +} + +create_container_runner() { + local runner_file="$1" + + cat >"$runner_file" <<'CONTAINER_RUNNER' +#!/usr/bin/env bash +set -u +set -o pipefail + +set +u +source "${TST_TS_TOPDIR}/tst_common/lib/common.sh" || exit 1 +set -u + +pkg_name="${PKG_NAME}" +desktop_whitelist="${DESKTOP_WHITELIST_IN_CONTAINER}" +service_pkg_list="${SERVICE_PKG_LIST_IN_CONTAINER}" +log_dir="${PKG_LOG_DIR}" + +install_status="SKIP" +command_status="SKIP" +service_status="SKIP" +remove_status="SKIP" +result_status="FAIL" +reason="" +source_pkg="$pkg_name" +was_installed=0 + +append_reason() { + local old_reason="$1" + local new_reason="$2" + if [ -z "$old_reason" ]; then + printf '%s' "$new_reason" + else + printf '%s; %s' "$old_reason" "$new_reason" + fi +} + +write_result() { + local output_file="$log_dir/result.tsv" + local clean_reason + + if [ "$install_status" = "FAIL" ] || [ "$command_status" = "FAIL" ] || \ + [ "$service_status" = "FAIL" ] || [ "$remove_status" = "FAIL" ]; then + result_status="FAIL" + elif [ "$install_status" = "SKIP" ] || [ "$command_status" = "SKIP" ] || \ + [ "$service_status" = "SKIP" ] || [ "$remove_status" = "SKIP" ]; then + result_status="SKIP" + else + result_status="PASS" + fi + + [ -n "$reason" ] || reason="ok" + clean_reason="$(printf '%s' "$reason" | tr '\t\n' ' ')" + printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \ + "$source_pkg" "$pkg_name" "$install_status" "$command_status" \ + "$service_status" "$remove_status" "$result_status" "$clean_reason" >"$output_file" +} + +pkg_without_arch() { + printf '%s' "$1" | sed -E 's/\.(x86_64|aarch64|noarch|i[0-9]86)$//' +} + +list_has_pkg() { + local list_file="$1" + local candidate="$2" + [ -s "$list_file" ] || return 1 + awk -v p="$candidate" '$1 == p { found = 1 } END { exit(found ? 0 : 1) }' "$list_file" +} + +pkg_matches_list() { + local list_file="$1" + local base_name="$2" + local no_arch_name="$3" + + list_has_pkg "$list_file" "$pkg_name" && return 0 + list_has_pkg "$list_file" "$base_name" && return 0 + list_has_pkg "$list_file" "$no_arch_name" && return 0 + return 1 +} + +systemd_available() { + command -v systemctl >/dev/null 2>&1 || return 1 + [ "$(ps -p 1 -o comm= 2>/dev/null | awk '{print $1}')" = "systemd" ] || return 1 + systemctl --no-pager is-system-running >"$log_dir/systemd-probe.log" 2>&1 + if grep -Eiq 'system has not been booted with systemd|failed to connect to bus' "$log_dir/systemd-probe.log"; then + return 1 + fi + return 0 +} + +rpm -q "$pkg_name" >/dev/null 2>&1 && was_installed=1 +rpm -qa | sort >"$log_dir/installed-before.list" 2>/dev/null || true + +yum install -y strace file >"$log_dir/strace.log" 2>&1 || true + +if test_single_rpm_install "" "$pkg_name" "$log_dir/install"; then + install_status="PASS" +else + cp -f "$log_dir/install.install" "$log_dir/install.log" 2>/dev/null || touch "$log_dir/install.log" + install_status="FAIL" + command_status="SKIP" + service_status="SKIP" + remove_status="SKIP" + reason="$(append_reason "$reason" "install failed")" + source_pkg="$(get_src_pkg_by_bin "$pkg_name" 2>/dev/null || true)" + [ -n "$source_pkg" ] || source_pkg="$pkg_name" + write_result + exit 0 +fi +cp -f "$log_dir/install.install" "$log_dir/install.log" 2>/dev/null || touch "$log_dir/install.log" + +source_pkg="$(get_src_pkg_by_bin "$pkg_name" 2>/dev/null || true)" +[ -n "$source_pkg" ] || source_pkg="$pkg_name" + +base_pkg="$(rpm -q --qf '%{NAME}\n' "$pkg_name" 2>/dev/null | head -n 1 || true)" +[ -n "$base_pkg" ] || base_pkg="$(pkg_without_arch "$pkg_name")" +no_arch_pkg="$(pkg_without_arch "$pkg_name")" + +if pkg_matches_list "$desktop_whitelist" "$base_pkg" "$no_arch_pkg"; then + command_status="SKIP" + reason="$(append_reason "$reason" "desktop whitelist")" + : >"$log_dir/command.log" +else + rpm -ql "$pkg_name" 2>"$log_dir/rpm-ql-command.err" | \ + grep '/usr/bin/\|/usr/sbin/' | grep -v '\.so' | grep -v '/usr/bin/nde-' \ + >"$log_dir/command-files.list" || true + : >"$log_dir/commands.list" + if [ -s "$log_dir/command-files.list" ]; then + get_elf_executable "$log_dir/command-files.list" "$log_dir/commands.list" \ + >"$log_dir/get-elf.log" 2>&1 || true + fi + + if [ ! -s "$log_dir/commands.list" ]; then + command_status="SKIP" + reason="$(append_reason "$reason" "no executable command")" + : >"$log_dir/command.log" + elif test_command_execute "$log_dir/command-logs" "$log_dir/commands.list" \ + >"$log_dir/command.log" 2>&1; then + command_status="PASS" + elif grep -REiqw 'invalid|argument|Unknown|option|Usage|usage|version' \ + "$log_dir/command.log" "$log_dir/command-logs" 2>/dev/null && \ + ! grep -REiq 'core dump|error while loading shared libraries|realpath fail' \ + "$log_dir/command.log" "$log_dir/command-logs" 2>/dev/null; then + command_status="PASS" + else + command_status="FAIL" + reason="$(append_reason "$reason" "command failed")" + fi +fi + +rpm -ql "$pkg_name" 2>"$log_dir/rpm-ql-service.err" | \ + grep -E '\.(service|socket|target)$' | awk -F/ '{print $NF}' | sort -u \ + >"$log_dir/systemd-units.list" || true + +if [ ! -s "$log_dir/systemd-units.list" ]; then + service_status="PASS" + reason="$(append_reason "$reason" "no systemd unit")" +elif pkg_matches_list "$service_pkg_list" "$base_pkg" "$no_arch_pkg"; then + service_status="SKIP" + reason="$(append_reason "$reason" "special configuration")" +elif ! systemd_available; then + service_status="SKIP" + reason="$(append_reason "$reason" "container without systemd")" +else + service_status="PASS" + : >"$log_dir/service.log" + while read -r unit_name; do + [ -n "$unit_name" ] || continue + if ! timeout -s SIGKILL 30 systemctl --no-pager start "$unit_name" \ + >>"$log_dir/service.log" 2>&1; then + service_status="FAIL" + reason="$(append_reason "$reason" "service $unit_name start failed")" + continue + fi + if ! timeout -s SIGKILL 30 systemctl --no-pager status "$unit_name" \ + >>"$log_dir/service.log" 2>&1; then + service_status="FAIL" + reason="$(append_reason "$reason" "service $unit_name status failed")" + fi + if ! timeout -s SIGKILL 30 systemctl --no-pager stop "$unit_name" \ + >>"$log_dir/service.log" 2>&1; then + if grep -iqw 'it is configured to refuse manual start/stop' "$log_dir/service.log"; then + : + else + service_status="FAIL" + reason="$(append_reason "$reason" "service $unit_name stop failed")" + fi + fi + done <"$log_dir/systemd-units.list" +fi +[ -f "$log_dir/service.log" ] || : >"$log_dir/service.log" + +if [ "$install_status" = "PASS" ]; then + if [ "$was_installed" -eq 1 ]; then + remove_status="SKIP" + reason="$(append_reason "$reason" "preinstalled package")" + : >"$log_dir/remove.log" + else + : >"$log_dir/installed-empty.list" + if test_single_rpm_remove "$pkg_name" "$pkg_name" "$log_dir/remove" "$log_dir/installed-empty.list"; then + remove_status="PASS" + else + remove_status="FAIL" + reason="$(append_reason "$reason" "remove failed")" + fi + cp -f "$log_dir/remove.remove" "$log_dir/remove.log" 2>/dev/null || touch "$log_dir/remove.log" + fi +else + remove_status="SKIP" +fi + +write_result +exit 0 +CONTAINER_RUNNER + chmod +x "$runner_file" +} + +run_one_package() { + local index="$1" + local pkg_name="$2" + local safe_pkg + local pkg_log_dir + local container_name + local runner_file + local docker_ret + + safe_pkg="$(safe_name "$index" "$pkg_name")" + pkg_log_dir="${g_log_root}/${safe_pkg}" + mkdir -p "$pkg_log_dir" + + if printf '%s\n' "$pkg_name" | grep -Eq '(^livepatch-kernel-|(-debuginfo|-debugsource)(\.|-|$))'; then + : >"$pkg_log_dir/install.log" + : >"$pkg_log_dir/command.log" + : >"$pkg_log_dir/service.log" + : >"$pkg_log_dir/remove.log" + : >"$pkg_log_dir/container.log" + write_tsv_result "$pkg_log_dir/result.tsv" "$pkg_name" "$pkg_name" \ + "SKIP" "SKIP" "SKIP" "SKIP" "SKIP" "filtered package" + return 0 + fi + + runner_file="$pkg_log_dir/container-runner.sh" + create_container_runner "$runner_file" + container_name="yum-ci-${g_run_stamp}-${safe_pkg}" + container_name="$(printf '%s' "$container_name" | sed 's/[^A-Za-z0-9_.-]/-/g' | cut -c 1-120)" + + docker_args=(run --rm --security-opt label=disable --name "$container_name") + [ -n "$CPUS" ] && docker_args+=(--cpus "$CPUS") + [ -n "$MEMORY" ] && docker_args+=(--memory "$MEMORY") + docker_args+=( + -e "TST_TS_TOPDIR=${TST_TS_TOPDIR}" + -e "PKG_NAME=${pkg_name}" + -e "PKG_LOG_DIR=${pkg_log_dir}" + -e "DESKTOP_WHITELIST_IN_CONTAINER=${g_log_root}/inputs/desktop-whitelist.txt" + -e "SERVICE_PKG_LIST_IN_CONTAINER=${g_log_root}/inputs/service-pkg-list.txt" + -v "${TST_TS_TOPDIR}:${TST_TS_TOPDIR}" + -w "${TST_TS_TOPDIR}" + "$OC_IMAGE" + /usr/bin/env bash "$runner_file" + ) + + timeout --kill-after=10s "$TIMEOUT_SEC" docker "${docker_args[@]}" \ + >"$pkg_log_dir/container.log" 2>&1 + docker_ret=$? + + if [ "$docker_ret" -ne 0 ]; then + docker rm -f "$container_name" >>"$pkg_log_dir/container.log" 2>&1 || true + if [ ! -s "$pkg_log_dir/result.tsv" ]; then + if [ "$docker_ret" -eq 124 ] || [ "$docker_ret" -eq 137 ]; then + write_tsv_result "$pkg_log_dir/result.tsv" "$pkg_name" "$pkg_name" \ + "FAIL" "SKIP" "SKIP" "SKIP" "FAIL" "timeout" + else + write_tsv_result "$pkg_log_dir/result.tsv" "$pkg_name" "$pkg_name" \ + "FAIL" "SKIP" "SKIP" "SKIP" "FAIL" "docker run failed" + fi + fi + fi + +} + +wait_for_slot() { + if help wait 2>/dev/null | grep -q -- '-n'; then + while [ "$(jobs -rp | wc -l)" -ge "$JOBS" ]; do + wait -n || true + done + else + while [ "$(jobs -rp | wc -l)" -ge "$JOBS" ]; do + sleep 1 + done + fi +} + +wait_for_all_jobs() { + if help wait 2>/dev/null | grep -q -- '-n'; then + while [ "$(jobs -rp | wc -l)" -gt 0 ]; do + wait -n || true + done + else + while [ "$(jobs -rp | wc -l)" -gt 0 ]; do + sleep 1 + done + wait || true + fi +} + +build_package_queue() { + local queue_file="$1" + : >"$queue_file" + awk ' + /^[[:space:]]*$/ { next } + /^[[:space:]]*#/ { next } + $1 == "Installed" || $1 == "Available" { next } + { print $1 } + ' "$PKG_LIST" >"$queue_file" +} + +print_category() { + local title="$1" + local awk_expr="$2" + local data_file="$3" + local tmp_file="${g_tmpdir}/category.$$" + + echo "[${title}]" + awk -F '\t' "$awk_expr" "$data_file" >"$tmp_file" + if [ -s "$tmp_file" ]; then + cat "$tmp_file" + else + echo "(none)" + fi + echo +} + +write_summary() { + local data_file="$1" + local total_count + local pass_count + local fail_count + local skip_count + local summary_file="${g_tmpdir}/summary.txt" + + total_count="$(wc -l <"$data_file")" + pass_count="$(awk -F '\t' '$7 == "PASS" { c++ } END { print c + 0 }' "$data_file")" + fail_count="$(awk -F '\t' '$7 == "FAIL" { c++ } END { print c + 0 }' "$data_file")" + skip_count="$(awk -F '\t' '$7 == "SKIP" { c++ } END { print c + 0 }' "$data_file")" + + { + echo + echo "========== TEST FAILURE SUMMARY ($(date '+%Y-%m-%d %H:%M:%S')) ==========" + echo "Environment: docker | Concurrency: ${JOBS} | Total: ${total_count} | PASS: ${pass_count} | FAIL: ${fail_count} | SKIP: ${skip_count}" + echo + print_category "INSTALL FAILED ($(awk -F '\t' '$3 == "FAIL" { c++ } END { print c + 0 }' "$data_file"))" \ + '$3 == "FAIL" { print $2 " reason: " $8 }' "$data_file" + print_category "REMOVE FAILED ($(awk -F '\t' '$6 == "FAIL" { c++ } END { print c + 0 }' "$data_file"))" \ + '$6 == "FAIL" { print $2 " reason: " $8 }' "$data_file" + print_category "COMMAND FAILED ($(awk -F '\t' '$4 == "FAIL" { c++ } END { print c + 0 }' "$data_file"))" \ + '$4 == "FAIL" { print $2 " command: see logs reason: " $8 }' "$data_file" + print_category "SERVICE FAILED ($(awk -F '\t' '$5 == "FAIL" { c++ } END { print c + 0 }' "$data_file"))" \ + '$5 == "FAIL" { print $2 " service: see logs reason: " $8 }' "$data_file" + print_category "SKIPPED ($(awk -F '\t' '$7 == "SKIP" { c++ } END { print c + 0 }' "$data_file"))" \ + '$7 == "SKIP" { print $2 " (" $8 ")" }' "$data_file" + echo "=======================================================" + } >"$summary_file" + + cat "$summary_file" + cat "$summary_file" >>"$g_result_file" + + if [ $((pass_count + fail_count + skip_count)) -ne "$total_count" ]; then + err "summary count mismatch: PASS + FAIL + SKIP != TOTAL" + return 1 + fi + return 0 +} + +do_test() { + parse_args "$@" + + is_positive_integer "$JOBS" || die "-j must be a positive integer: $JOBS" + is_positive_integer "$TIMEOUT_SEC" || die "--timeout must be a positive integer: $TIMEOUT_SEC" + [ -f "$PKG_LIST" ] || die "pkg_list not found: $PKG_LIST" + [ -f "$DESKTOP_WHITELIST" ] || die "desktop_whitelist not found: $DESKTOP_WHITELIST" + [ -f "$SERVICE_PKG_LIST" ] || die "service_pkg_list not found: $SERVICE_PKG_LIST" + command -v docker >/dev/null 2>&1 || die "docker not found" + command -v timeout >/dev/null 2>&1 || die "timeout not found" + + mkdir -p "$g_log_root/inputs" + cp -f "$PKG_LIST" "$g_log_root/inputs/pkg-list.txt" + cp -f "$DESKTOP_WHITELIST" "$g_log_root/inputs/desktop-whitelist.txt" + cp -f "$SERVICE_PKG_LIST" "$g_log_root/inputs/service-pkg-list.txt" + + local queue_file="${g_tmpdir}/pkg.queue" + local data_file="${g_tmpdir}/all-results.tsv" + local index=0 + local pkg_name + + build_package_queue "$queue_file" + msg "docker image: $OC_IMAGE" + msg "log root: $g_log_root" + msg "result: $g_result_file" + msg "packages: $(wc -l <"$queue_file")" + + while read -r pkg_name; do + [ -n "$pkg_name" ] || continue + index=$((index + 1)) + wait_for_slot + run_one_package "$index" "$pkg_name" & + done <"$queue_file" + + wait_for_all_jobs + + find "$g_log_root" -mindepth 2 -maxdepth 2 -name result.tsv | sort -V | \ + xargs -r cat >"$data_file" + + { + echo -e "# source-package\tbinary_package\tinstall\tcommand\tservice\tremove\tresult\treason" + cat "$data_file" + } >"$g_result_file" + + write_summary "$data_file" || return 1 + if awk -F '\t' '$7 == "FAIL" { found = 1 } END { exit(found ? 0 : 1) }' "$data_file"; then + return 1 + fi + assert_true true + return 0 +} + +tc_setup() { + msg "this is tc_setup" + return 0 +} + +tc_teardown() { + msg "this is tc_teardown" + return 0 +} + +############################################################################### +set +u +tst_main "$@" +tst_ret=$? +rm -rf "${TST_TS_TOPDIR}/logs/testcase/.tc.$$.sysdir" +exit "$tst_ret" +###############################################################################