40 Commits
main ... main

Author SHA1 Message Date
d2caf64443 ci: fix qemu url 2026-04-22 17:56:26 +08:00
249e5ffc0a ci: test qemu start 2026-04-22 17:45:48 +08:00
bba3f5af67 ci: fix version in qemu 2026-04-20 16:57:29 +08:00
9926d7781a ci: fix qemu image download 2026-04-17 18:06:27 +08:00
464b03bbbd ci: fix install error on ubuntu 2026-04-17 17:46:33 +08:00
dc3ae752a2 ci: no var in runs-on 2026-04-17 17:45:08 +08:00
c21128b8a6 ci: qemu-test 2026-04-17 17:28:47 +08:00
44dcfde756 ci:log-report.sh 2026-04-17 15:24:50 +08:00
d1026583f9 ci: fix summary 2026-04-17 12:13:58 +08:00
2e2b83387d ci: fix python pkg missing 2026-04-17 11:22:05 +08:00
64567f0f17 ci: init summary and stats 2026-04-17 11:06:12 +08:00
7433480309 not rm results for load_conf 2026-04-17 10:40:23 +08:00
d72af21ac0 ci: fix 2026-04-17 10:20:34 +08:00
472685ee2e openruyi: smoke_pkg_install test into one folder 2026-04-17 09:56:09 +08:00
270ae3eec4 fix test error 2026-04-16 18:16:12 +08:00
67d79fa231 ci: run test 2026-04-16 16:59:48 +08:00
72b4037183 sudo 2026-04-16 15:25:07 +08:00
44133fb9fc fail to clone actions/checkout 2026-04-16 15:22:28 +08:00
c456fd112f openruyi:ci:init 2026-04-16 11:48:28 +08:00
57cebd9124 openruyi: fix file link 2026-04-16 10:13:21 +08:00
b5dc2e8491 openruyi: rename moke_pkg_openruyi as smoke_pkg_install 2026-04-14 18:16:28 +08:00
71ec8e0025 openruyi: disable root ssh 2026-04-14 18:10:15 +08:00
cc0077006a openruyi: unixbench 2026-04-14 17:59:51 +08:00
69dd733af2 openruyi: pkg install test as a testsuit 2026-04-14 17:59:05 +08:00
926b6876a6 openruyi: fix ssh_disable test 2026-04-14 17:58:33 +08:00
18db9f5568 openruyi: rm pkg install test from smoke_openruyi 2026-04-14 17:58:04 +08:00
675d0a7207 OrderedDict instead of dict 2026-04-14 17:57:04 +08:00
caf3b423af openruyi: rename testsuit name as smoke_openruyi 2026-04-14 16:42:12 +08:00
cf340f1547 openruyi: rename testsuit as openruyi 2026-04-14 16:29:28 +08:00
33b153652b openruyi: set -e and set +e 2026-04-14 15:54:15 +08:00
72a1c28f79 openruyi: fix exit 1 for llvm test 2026-04-14 15:42:08 +08:00
fbde8a1a14 dnf install --refresh 2026-04-14 15:41:51 +08:00
efe2f539c4 openruyi: fix DNF_INSTALL in gcc/llvm 2026-04-14 10:39:00 +08:00
40347e7a88 openruyi: fix install pkg test 2026-04-14 10:23:13 +08:00
ad391aaee2 openruyi: fix openruyi-test 2026-04-13 17:05:22 +08:00
87a0feb5c2 openruyi: fix libs 2026-04-13 17:04:46 +08:00
786d391d8f openruyi: not detect lshw and fix rpm_manage 2026-04-13 16:43:04 +08:00
5a3d8e1dc1 openruyi:fix pkg install 2026-04-13 16:36:30 +08:00
751cff3f31 openruyi: rename testsuit name 2026-04-13 16:31:02 +08:00
5acfa31e6e openruyi 2026-04-13 16:19:09 +08:00
23 changed files with 1288 additions and 25 deletions

98
.github/workflows/qemy-test.yml vendored Normal file
View File

@@ -0,0 +1,98 @@
name: Run test
on:
workflow_dispatch:
env:
TESTSUITE: ${{ vars.TESTSUITE }}
QEMU_IMG: ${{ secrets.QEMU_IMG }}
jobs:
build:
runs-on: ubuntu-qemu
timeout-minutes: 4320
steps:
- name: install tools
run: apt update && apt install -y wget iproute2 expect && pip3 install requests --break-system-packages
- uses: https://gitee.com/ci-actions/checkout.git@v3
- name: get the latest qemu image
run: |
BASE_URL="${QEMU_IMG%/*}"
VERSION=$(wget -qO- "$BASE_URL" \
| grep -oP '[^"]+\.qcow2' \
| grep -v 'sha256' \
| sed -E 's/^[^-]+-//; s/\.qcow2$//' \
| grep -E '^[0-9]' \
| sort -u \
| head -n1)
echo "The latest version: $VERSION"
pushd /test/images/openruyi
FILE_NAME=$(basename $QEMU_IMG)
echo "Download $FILE_NAME ..."
rm -f openruyi-virt_riscv64.qcow2*
wget -q --show-progress -O "/test/images/openruyi/openruyi-virt_riscv64.qcow2" "${QEMU_IMG}"
export PATH="$PATH:/usr/local/qemu/bin"
bash "$GITHUB_WORKSPACE/.github/workflows/scripts/qemu.sh" "${{ secrets.RISCV_DEFAULT_USERNAME }}" "${{ secrets.RISCV_DEFAULT_PASSWORD }}"
if [ $? -ne 0 ]; then
echo "Fail to start QEMU VM!"
exit $?
fi
xz -9 -T 0 -k openruyi-virt_riscv64.qcow2
popd
- name: run tests
timeout-minutes: 4320
run: |
set -x
timeout 10 curl -s "${{ secrets.IMAGE_URL }}" || echo "no ${{ secrets.IMAGE_URL }}"
SUB_DIR=qemu/${{ github.run_number}}-${DATA_STR}
echo "SUB_DIR=$SUB_DIR" >> $GITHUB_ENV
RESULT_DIR="/test/${SUB_DIR}"
export RESULT_DIR="${RESULT_DIR}"
mkdir -p "$RESULT_DIR"
chmod +w "$RESULT_DIR"
ls -la "$RESULT_DIR" || echo "no $RESULT_DIR"
docker run --rm \
-e OS_VERSION="${{ vars.OS_VERSION }}" \
-e OS_ARCH="${{ vars.OS_ARCH }}" \
-e CLOUDPODS_KEYSTONE_URL="${{ secrets.CLOUDPODS_KEYSTONE_URL }}" \
-e CLOUDPODS_USER="${{ secrets.CLOUDPODS_USER }}" \
-e CLOUDPODS_PASSWORD="${{ secrets.CLOUDPODS_PASSWORD }}" \
-e GUEST_IMAGE_ID="${{ secrets.GUEST_IMAGE_ID }}" \
-e DISK_IMAGE_ID="${{ secrets.DISK_IMAGE_ID }}" \
-e CLOUDPODS_KVM_NET_LIST="${{ secrets.CLOUDPODS_KVM_NET_LIST }}" \
-e SERVER_SKU="${{ secrets.SERVER_SKU }}" \
-e SERVER_NAME_PREFIX="${{ github.event.repository.name }}-${{ github.run_number}}" \
-e PASSWORD="${{ secrets.PASSWORD }}" \
-e USER="${{ secrets.USER }}" \
-e DELETE_DEFAULT_YUM_REPOS="yes" \
-e ADD_YUM_REPOS="${{ secrets.ADD_YUM_REPOS }}" \
-e OS_AUTOTEST_REPO_HTTPS="${{ vars.OS_AUTOTEST_REPO_HTTPS }}" \
-e OS_AUTOTEST_BRANCH="${{ vars.OS_AUTOTEST_BRANCH }}" \
-e CONCURRENCY="${{ vars.CONCURRENCY }}" \
-e ONLY_TEST_EXIST_RPM="${{ vars.ONLY_TEST_EXIST_RPM }}" \
-e EXIST_RPM_URLS="${{ secrets.EXIST_RPM_URLS }}" \
-e TESTSUITE_MAX_TIMEOUT="${{ vars.TESTSUITE_MAX_TIMEOUT }}" \
-e RISCV_BIOS="${{ vars.RISCV_BIOS }}" \
${TESTSUITE:+-e TESTSUITE="$TESTSUITE"} \
-e RISCV_DEFAULT_PASSWORD="${{ secrets.RISCV_DEFAULT_PASSWORD }}" \
-e RISCV_DEFAULT_USERNAME="${{ secrets.RISCV_DEFAULT_USERNAME }}" \
-e RISCV_IMAGE_URL="${{ secrets.IMAGE_URL }}/openruyi-virt_riscv64.qcow2.xz" \
-e RISCV_VIRT_CODE_URL="${{ secrets.IMAGE_URL }}/RISCV_VIRT_CODE.fd" \
-e RISCV_VIRT_VARS_URL="${{ secrets.IMAGE_URL }}/RISCV_VIRT_VARS.fd" \
-v "$RESULT_DIR:/opt/os-autotest" \
"${{ vars.OS_AUTOTEST_IMAGE }}" \
bash -c 'python3 -m os-autotest-runner.run_autotest'
ls -la "$RESULT_DIR" || echo "no $RESULT_DIR"
ls -la /test || echo "no /test"
ls -la $RESULT_DIR || echo "no $RESULT_DIR"
- name: run test in github workflow
run: |
TITLE="qemu:os-autotest"
if [ -n "$TESTSUITE" ]; then
testsuites=$(awk -F, -v OFS=, 'NF>4{print $1,$2,$3,$4 "..."; next} 1' <<< "$TESTSUITE")
TITLE="$TITLE:$testsuites"
fi
TITLE="$TITLE $RELEASE_VERSION ${DATA_STR:0:4}-${DATA_STR:4:2}-${DATA_STR:6:2} ${DATA_STR:8:2}-${DATA_STR:10:2}"
python .github/workflows/scripts/stats.py --gitea-url "${{ github.api_url }}" --repo "${{ github.repository }}" --token "${{ secrets.RELEASE_TOKEN }}" --result "$RESULT_DIR" --log-url "${{ secrets.LOG_URL }}/$SUB_DIR" --title "$TITLE"

43
.github/workflows/scripts/log-report.sh vendored Normal file
View File

@@ -0,0 +1,43 @@
#!/bin/bash
# 1. 定义根目录路径 (请根据实际情况修改)
ROOT_DIR="${1:-$(pwd)/logs}"
# 2. 检查目录是否存在
if [ ! -d "$ROOT_DIR" ]; then
echo "错误: 目录 $ROOT_DIR 不存在"
exit 1
fi
echo "正在分析目录: $ROOT_DIR"
echo "----------------------------------------"
# 3. 遍历根目录下的所有一级子目录
# 使用 -mindepth 1 -maxdepth 1 确保只遍历第一层子目录
# 使用 -type d 确保只处理目录
for subdir in "$ROOT_DIR"/*/; do
# 如果没有子目录,循环可能会直接跳过,这里做一个安全检查
[ -d "$subdir" ] || continue
# 4. 查找该子目录下最大的 .log 文件
# ls -1 列出文件
# sort 按名称排序 (因为你要的是"按名称排序最大",即字母顺序最后)
# tail -n 1 取最后一行,即最大的那个
max_log_file=$(ls -1 "$subdir"*.log 2>/dev/null | sort | tail -n 1)
# 5. 检查是否找到了 log 文件
if [ -n "$max_log_file" ] && [ -f "$max_log_file" ]; then
echo ">>> 正在分析文件: $max_log_file"
# 6. 使用 grep 获取 warn 和 error 信息及其前后 5 行
# -i : 忽略大小写 (匹配 Warn, WARN, warn)
# -E : 使用扩展正则表达式 (匹配 warn 或 error)
# -C 5 : 显示匹配行的前后 5 行 (Context)
# --color=auto : 高亮显示关键词 (可选,方便查看)
grep -n -E -C 5 --color=auto "Failed |Error:" "$max_log_file" | sed 's/^--$/----------------------------------------/'
echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
else
echo ">>> 在 $subdir 中未找到 .log 文件"
fi
done

87
.github/workflows/scripts/qemu.sh vendored Normal file
View File

@@ -0,0 +1,87 @@
#!/bin/bash
USER="$1"
PASS="$2"
START_PORT=12060
PORT=$START_PORT
while ss -tln | grep -qE ":${PORT}\b"; do
((PORT++))
done
QEMU_CMD="qemu-system-riscv64"
VM_ARGS="-nographic -machine virt,pflash0=pflash0,pflash1=pflash1 \
-smp 8 -m 12G \
-cpu rva23s64 \
-blockdev node-name=pflash0,driver=file,read-only=on,filename=RISCV_VIRT_CODE.fd \
-blockdev node-name=pflash1,driver=file,filename=RISCV_VIRT_VARS.fd \
-drive file=openRuyi-2026.03-Server-cloud.qcow2,format=qcow2,id=hd0,if=none \
-object rng-random,filename=/dev/urandom,id=rng0 \
-device virtio-vga \
-device virtio-rng-device,rng=rng0 \
-device virtio-blk-device,drive=hd0 \
-device virtio-net-device,netdev=usernet \
-netdev user,id=usernet,hostfwd=tcp::${PORT}-:22 \
-device qemu-xhci -usb -device usb-kbd -device usb-tablet"
expect <<-EOF
set timeout 600
puts "正在启动虚拟机..."
spawn $QEMU_CMD $VM_ARGS
expect {
"Press Control-D to continue" {
puts "\n检测到 Emergency Mode发送 Ctrl+D..."
send "\004"
exp_continue
}
-re "login:|Username:" {
puts "\n发现登录界面输入用户名..."
send "${USER}\r"
exp_continue
}
-re "\[Pp\]assword:" {
puts "\n输入密码..."
send "${PASS}\r"
exp_continue
}
"Login incorrect" {
puts "\n登录失败用户名或密码错误"
exit 2
}
-re {[#$]|root@.*#} {
puts "\n登录成功"
exit 0
}
-re {\x1b\[[0-9;]*[RfH]} {
exp_continue
}
timeout {
puts "\n虚拟机启动或登录超时"
exit 1
}
eof {
puts "\nQEMU 进程意外关闭"
exit 1
}
}
EOF
RET=$?
if [ $RET -eq 0 ]; then
echo "虚拟机启动成功"
elif [ $RET -eq 2 ]; then
echo "用户名或密码错误,登录失败"
else
echo "启动失败,退出码 $RET"
fi
exit $RET

128
.github/workflows/scripts/runtest.sh vendored Normal file
View File

@@ -0,0 +1,128 @@
#!/usr/bin/bash
set -x
RUNDIR="$(pwd)"
TESTSUITE_FILE="${RUNDIR}/.os-autotest/testsuite"
PKGTEST_FILE="${RUNDIR}/.os-autotest/pkg-install"
SUITE_DIR="${RUNDIR}/suite2cases"
LOG_INFO() {
printf "$(date +'%Y-%m-%d %T') $0 [ INFO ] %s\n" "$@"
}
LOG_WARN() {
printf "$(date +'%Y-%m-%d %T') $0 [ WARN ] %s\n" "$@"
}
LOG_ERROR() {
printf "$(date +'%Y-%m-%d %T') $0 [ ERROR ] %s\n" "$@"
}
if [ -z "${RESULT_DIR}" ]; then
LOG_ERROR "Please export RESULT_DIR!"
exit 1
else
rm -rf "${RESULT_DIR}/*"
fi
LOGFILE="${RESULT_DIR}/os-autotest.log"
dnf install -y lshw rsync jq --refresh
mkdir -p "${RESULT_DIR}/source/suite2cases"
if [ ! -s "${TESTSUITE_FILE}" ] && [ ! -s "${PKGTEST_FILE}" ]; then
LOG_WARN "No info from ${TESTSUITE_FILE}/${PKGTEST_FILE}, no need to run testsuite."
exit 0
fi
pushd "$RUNDIR"
bash dep_install.sh
dnf install -y hostname --refresh
[ -f /usr/bin/yum ] || ln -sf /usr/bin/dnf /usr/bin/yum
rm -rf conf results logs
bash mugen.sh -c --ip $(hostname -I | awk '{print $1}') --password openruyi --user openruyi --port 22
if [ -s "$TESTSUITE_FILE" ]; then
mapfile -t patterns < <(sort -u "$TESTSUITE_FILE" | sed '/^\s*$/d')
LOG_INFO "start match $TESTSUITE_FILE ..."
pushd "$SUITE_DIR" || { LOG_INFO "no $SUITE_DIR found and exit."; exit 0; }
for item in "${patterns[@]}"; do
LOG_INFO ">>> $item:"
found=false
if [[ "$item" == *\* ]]; then
item="${item%\*}"
matches=$(find . -type f -name "${item}*.json")
else
matches=$(find . -type f -name "${item}.json")
fi
if [ -n "$matches" ]; then
for file in $matches; do
if [ -f "$file" ]; then
full_name=$(basename "$file")
suite_name="${full_name%.json}"
suite2cases_path=$(jq -r '.path' "$file")
LOG_INFO "[FOUND] run suitecases $suite_name"
found=true
pushd "$RUNDIR" || continue
LOG_INFO "start to run bash mugen.sh -f $suite_name -x"
if [ "$suite_name" == "smoke_pkg_install" ]; then
if [ -s "$PKGTEST_FILE" ]; then
while IFS= read -r line; do
[ -n "$line" ] || continue
export PKG_INSTALL=$line
ORIGIN_LOGS=logs/${suite_name}/test_pkg_install_uninstall
TARGET_LOGS=logs/${suite_name}/test_${PKG_INSTALL}_install_uninstall
[ -d $ORIGIN_LOGS ] && rm -rf $ORIGIN_LOGS
[ -d $TARGET_LOGS ] && rm -rf $TARGET_LOGS
for status in succeed fail; do
rst_file="results/${suite_name}/${status}/test_pkg_install_uninstall"
[ -f "$rst_file" ] && rm -f "$rst_file"
done
LOG_INFO " package: ${PKG_INSTALL}" | tee -a "${LOGFILE}"
bash mugen.sh -f "$suite_name" -x 2>&1 | tee -a "${LOGFILE}"
[ -d $ORIGIN_LOGS ] && mv $ORIGIN_LOGS $TARGET_LOGS
for status in succeed fail; do
target="results/${suite_name}/${status}/test_pkg_install_uninstall"
[ -f "$target" ] && mv "$target" "results/${suite_name}/${status}/test_${PKG_INSTALL}_install_uninstall"
done
done < "$PKGTEST_FILE"
else
LOG_INFO " No info in .os-autotest/pkg-install!"
continue
fi
else
bash mugen.sh -f "$suite_name" -x 2>&1 | tee -a "${LOGFILE}"
fi
LOG_INFO "end to run bash mugen.sh -f $suite_name -x"
suite2cases_path=$(echo "$suite2cases_path" | sed 's|.*testcases/|testcases/|')
rsync -RravL "$suite2cases_path" "$RESULT_DIR/source/"
echo "$suite_name" >> "$RESULT_DIR/testsuits"
popd
cp "$file" "$RESULT_DIR/source/suite2cases"
fi
done
fi
if [ "$found" = false ]; then
LOG_WARN "[UNFOUND] no suitecases for $item"
fi
done
popd
fi
popd
LOG_INFO "start to copy results ..."
mkdir -p "$RESULT_DIR/results" "$RESULT_DIR/logs"
cp -r "$RUNDIR"/results/* "$RESULT_DIR/results/"
cp -r "$RUNDIR"/logs/* "$RESULT_DIR/logs/"
LOG_INFO "end to copy results."
exit 0

94
.github/workflows/scripts/stats.py vendored Normal file
View File

@@ -0,0 +1,94 @@
#!/usr/bin/python3
import os
import json
import argparse
import requests
from datetime import datetime
_SUMMARY_FILE = "summary_results.json"
def parse_json_files(result_path, filename=_SUMMARY_FILE):
if result_path.startswith("http") or result_path.startswith("ftp"):
try:
response = requests.get(result_path + "/" + _SUMMARY_FILE, timeout=10)
response.raise_for_status()
data = response.json()
return data
except requests.exceptions.RequestException as e:
print(f"request for {result_path}/{_SUMMARY_FILE} failed: ", e)
raise
except ValueError as e: # 包括 JSONDecodeError
print("get json info failed:", e)
raise
else:
file_path = os.path.join(result_path, filename)
if os.path.isfile(file_path):
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
print(f"read {file_path} successfully")
return data
except (json.JSONDecodeError, OSError) as e:
print(f"read {file_path} failed: {e}")
raise
else:
print(f"{file_path} does not exist")
raise FileNotFoundError(f"{file_path} does not exist")
def generate_markdown_table(headers, rows, log_url):
if not rows:
return ""
header_line = "| " + " | ".join(headers) + " |"
separator_line = "| " + " | ".join(["---"] * len(headers)) + " |"
body_lines = ["| " + " | ".join(row[:-1]) + " | [" + ("\u2705" if row[-1] == "passed" else "\u274C") + row[-1] + "](" + "/".join([log_url, "logs", row[0], row[1]]) + ")" for row in rows]
return "\n".join([header_line, separator_line] + body_lines)
def create_gitea_issue(gitea_url, token, repo, title, body):
"""create issue"""
api_url = f"{gitea_url.rstrip('/')}/repos/{repo}/issues"
headers = {
"Authorization": f"token {token}",
"Content-Type": "application/json",
"Accept": "application/json"
}
payload = {
"title": title,
"body": body
}
response = requests.post(api_url, headers=headers, json=payload)
if response.status_code == 201:
issue = response.json()
print(f"create issue successfully: #{issue['number']} - {issue['html_url']}")
return 0, issue["number"]
else:
print(f"fail to create issuse (HTTP {response.status_code}): {response.text}")
# response.raise_for_status()
raise RuntimeError(f"Unexpected status code: {response.status_code}", response=response)
def main():
parser = argparse.ArgumentParser(description="测试结果")
parser.add_argument("--result", required=True, help="测试结果存放目录路径")
parser.add_argument("--gitea-url", required=True, help="Gitea 实例 URL例如 https://gitea.example.com")
parser.add_argument("--repo", required=True, help="完整的仓库名")
parser.add_argument("--token", required=True, help="Gitea Personal Access Token")
parser.add_argument("--title", default=f"openRuyi 测试报告 {datetime.now()}", help="Issue 标题")
parser.add_argument("--log-url", required=True, default="测试报告存放地址", help="Issue 标题")
args = parser.parse_args()
data = parse_json_files(args.result)
if "data" not in data.keys() or data["data"] is None or len(data["data"]) == 0:
print(f"no test result, exit 0")
return
markdown_stats = generate_markdown_table(data["head"], data["data"], args.log_url)
issue_number = create_gitea_issue(args.gitea_url, args.token, args.repo, args.title, markdown_stats)
print(f"created issue number: {issue_number}")
if __name__ == "__main__":
main()

137
.github/workflows/scripts/summary.py vendored Normal file
View File

@@ -0,0 +1,137 @@
# -*- coding: utf-8 -*-
import os
import json
import csv
from pathlib import Path
import subprocess
import argparse
SOURCE_DIR = "./"
RESULT_DIR = "./"
# os.environ['LOG_DIR'] = os.path.join(os.getcwd(), "log")
os.environ['LOG_DIR'] = "./log"
os.environ['LOG_NAME'] = "os-autotest"
from log import log
def get_testsuite_info(testsuite):
json_file = os.path.join(SOURCE_DIR, "suite2cases", testsuite + ".json")
if os.path.exists(json_file):
with open(json_file, 'r', encoding='utf-8') as f:
suite_data = json.load(f)
return suite_data
else:
log.warning(f"{testsuite} not exists")
return None
def get_os_autotest_testsuite_result_data(testsuite):
log.info(f"begin to get testsuite {testsuite} result data...")
data=[]
all_cases = []
succeed_path = f"{RESULT_DIR}/results/{testsuite}/succeed"
failed_path = f"{RESULT_DIR}/results/{testsuite}/failed"
skipped_path = f"{RESULT_DIR}/results/{testsuite}/skipped"
if os.path.exists(succeed_path):
for file_name in os.listdir(succeed_path):
if file_name in all_cases:
continue
temp = [testsuite, file_name, "passed"]
data.append(temp)
all_cases.append(file_name)
else:
log.warning(f"{succeed_path} not exists")
if os.path.exists(failed_path):
for file_name in os.listdir(failed_path):
if file_name in all_cases:
continue
temp = [testsuite, file_name, "failed"]
data.append(temp)
all_cases.append(file_name)
else:
log.warning(f"{failed_path} not exists")
if os.path.exists(skipped_path):
for file_name in os.listdir(skipped_path):
if file_name in all_cases:
continue
temp = [testsuite, file_name, "skipped"]
data.append(temp)
all_cases.append(file_name)
else:
log.warning(f"{skipped_path} not exists")
suite_data=get_testsuite_info(testsuite)
if not suite_data:
log.warning(f"{testsuite} not found in mugen sources.")
return None
script_path_origin=suite_data["path"]
script_dir=SOURCE_DIR+ "/" +"/".join(script_path_origin.split("/")[1:])
for elem in suite_data["cases"]:
case_name=elem["name"]
result = subprocess.run(['find', script_dir, '-name', f"{case_name}.sh"], capture_output=True, text=True,
check=True)
found_files = result.stdout.splitlines()
if not found_files:
log.warning(f"{case_name}.sh not found in {script_dir}")
continue
if case_name not in all_cases:
if testsuite == "smoke_pkg_install" and case_name == "test_pkg_install_uninstall":
continue
temp = [testsuite, case_name, "not run or exception in running, please run manual"]
data.append(temp)
return data
def get_os_autotest_summary_results(testsuite_list):
summary_results_json_path = f"{RESULT_DIR}/summary_results.json"
summary_results_csv_path = f"{RESULT_DIR}/summary_results.csv"
header = ["testsuite", "testcase", "result"]
datas={
"head": header,
"data": []
}
for testsuite in testsuite_list:
data = get_os_autotest_testsuite_result_data(testsuite)
if data is not None:
datas["data"].extend(data)
with open(summary_results_json_path, "w+", encoding="utf-8") as f:
json.dump(datas, f, ensure_ascii=False, indent=4)
with open(summary_results_csv_path, "w+", encoding="utf-8") as f:
csv_writer = csv.writer(f)
csv_writer.writerow(header)
csv_writer.writerows(datas["data"])
def main():
parser = argparse.ArgumentParser(description="整理测试结果")
parser.add_argument("--testsuits", required=True, help="测试套名称文件路径")
parser.add_argument("--result", required=True, help="测试结果存放目录路径")
parser.add_argument("--source", required=True, help="测试用例源码路径")
args = parser.parse_args()
testsuits_file = args.testsuits
global SOURCE_DIR
SOURCE_DIR = args.source
global RESULT_DIR
RESULT_DIR = args.result
with open(testsuits_file, 'r', encoding='utf-8') as f:
testsuit_names = f.read().splitlines()
print(testsuit_names)
get_os_autotest_summary_results(testsuit_names)
if __name__ == "__main__":
main()
# python summary.py --testsuits "./mugen/testsuits" --result "./mugen" --source "/home/xlab/workspaces/ruyi/mugen"
# path = "./mugen/testsuits"
# json_files = [f for f in os.listdir(path) if f.endswith('.json')]
# print(json_files)
# from pathlib import Path
# path = Path("./mugen/testsuits")
# testsuit_names = [f.stem for f in path.glob("*.json")]
# print(testsuit_names)
# with open('./mugen/testsuits', 'r', encoding='utf-8') as f:
# testsuit_names = f.read().splitlines()
# print(testsuit_names)
# get_os_autotest_summary_results(testsuit_names)

45
.github/workflows/smoke-test.yml vendored Normal file
View File

@@ -0,0 +1,45 @@
name: Run smoke test on SG2044
on:
workflow_dispatch:
env:
TESTSUITE: ${{ vars.TESTSUITE }}
PKGTEST: ${{ vars.PKGTEST }}
LOGDIR: ${{ secrets.LOGDIR }}
jobs:
build:
runs-on: openruyi-175
timeout-minutes: 4320
steps:
- name: install tools
run: sudo dnf install -y git nodejs rsync sshpass --refresh && pip3 install requests python3-log --break-system-packages
- uses: https://gitee.com/ci-actions/checkout.git@v3
- name: run tests
run: |
set -x
DATA_STR="$(date +%Y%m%d%H%M%S)"
SUB_DIR=${{ github.run_number}}-${DATA_STR}
RESULT_DIR="${LOGDIR}/${SUB_DIR}"
export RESULT_DIR="${RESULT_DIR}"
mkdir -p .os-autotest ${RESULT_DIR}
echo "$TESTSUITE" | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | sed '/^\s*$/d' > .os-autotest/testsuite
echo "$PKGTEST" | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | sed '/^\s*$/d' > .os-autotest/pkg-install
bash .github/workflows/scripts/runtest.sh
if [ -n "$(find "${RESULT_DIR}/source/suite2cases" -maxdepth 0 -empty)" ]; then
LOG_WARN "<<< no suite2cases found"
exit 0
fi
bash .github/workflows/scripts/log-report.sh "${RESULT_DIR}/logs"
python .github/workflows/scripts/summary.py --testsuits ".os-autotest/testsuite" --result "${RESULT_DIR}" --source "${RESULT_DIR}/source"
sshpass -p "${{ secrets.IMAGE_BACKUP_HOST_PWD }}" rsync -av -e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" "${RESULT_DIR}" "${{ secrets.IMAGE_BACKUP_HOST_USER }}@${{ secrets.IMAGE_BACKUP_HOST }}:${{ secrets.LOGDIR }}/sg2044/"
TITLE="sg2044:os-autotest"
if [ -n "$TESTSUITE" ]; then
testsuites=$(awk -F, -v OFS=, 'NF>4{print $1,$2,$3,$4 "..."; next} 1' <<< "$TESTSUITE")
TITLE="$TITLE:$testsuites"
fi
TITLE="$TITLE $RELEASE_VERSION ${DATA_STR:0:4}-${DATA_STR:4:2}-${DATA_STR:6:2} ${DATA_STR:8:2}-${DATA_STR:10:2}"
python .github/workflows/scripts/stats.py --gitea-url "${{ github.api_url }}" --repo "${{ github.repository }}" --token "${{ secrets.RELEASE_TOKEN }}" --result "${RESULT_DIR}" --log-url "${{ secrets.LOG_URL }}/sg2044/${SUB_DIR}" --title "$TITLE"

View File

@@ -38,14 +38,6 @@ def get_test_nic(node=1):
Returns:
[str]: 网卡名
"""
exitcode, tmpfile = rpm_manage.rpm_install(pkgs="lshw", node=node)
if exitcode != 0:
mugen_log.logging(
"error",
"Failed to install the dependent software package required to obtain the network card.",
)
sys.exit(exitcode)
if os.environ.get("NODE" + str(node) + "_LOCALTION") == "local":
dev_info = subprocess.getoutput("cat /proc/device-tree/model")
if "Lichee Pi 4A" in dev_info:
@@ -90,9 +82,6 @@ def get_test_nic(node=1):
ssh_cmd.pssh_close(conn)
if tmpfile is not None:
rpm_manage.rpm_remove(node=node, tmpfile=tmpfile)
return output
@@ -107,12 +96,12 @@ def get_test_disk(node=1):
"""
if os.environ.get("NODE" + str(node) + "_LOCALTION") == "local":
used_disk = subprocess.getoutput(
"lsblk -l | grep -e '/.*\|\[.*\]' | awk '{print $1}' | tr -d '[0-9]' | uniq | sed -e ':a;N;$!ba;s/\\n/ /g'"
r"lsblk -l | grep -e '/.*\|\[.*\]' | awk '{print $1}' | tr -d '[0-9]' | uniq | sed -e ':a;N;$!ba;s/\\n/ /g'"
)
test_disk = subprocess.getoutput(
"lsblk -n | grep 'disk' | grep -v '└─.*\|"
+ used_disk.replace(" ", "\|")
r"lsblk -n | grep 'disk' | grep -v '└─.*\|"
+ used_disk.replace(" ", r"\|")
+ "' | awk '{print $1}' | sed -e ':a;N;$!ba;s/\\n/ /g'"
)
else:
@@ -124,12 +113,12 @@ def get_test_disk(node=1):
)
used_disk = ssh_cmd.pssh_cmd(
conn,
"lsblk -l | grep -e '/.*\|\[.*\]' | awk '{print $1}' | tr -d '[0-9]' | uniq | sed -e ':a;N;$!ba;s/\\n/ /g'",
r"lsblk -l | grep -e '/.*\|\[.*\]' | awk '{print $1}' | tr -d '[0-9]' | uniq | sed -e ':a;N;$!ba;s/\\n/ /g'",
)[1]
test_disk = ssh_cmd.pssh_cmd(
conn,
"lsblk -n | grep 'disk' | grep -v '└─.*\|"
+ used_disk.replace(" ", "\|")
r"lsblk -n | grep 'disk' | grep -v '└─.*\|"
+ used_disk.replace(" ", r"\|")
+ "' | awk '{print $1}' | sed -e ':a;N;$!ba;s/\\n/ /g'",
)[1]

View File

@@ -95,25 +95,25 @@ def rpm_install(pkgs, node=1, tmpfile=""):
conn=conn,
cmd="dnf --assumeno install "
+ pkgs
+ ' 2>&1 | grep -wE "$(echo '
+ " 2>&1 | grep -wE \"$(echo '"
+ repoList
+ " | sed 's/ /|/g')\" | grep -wE \"$(uname -m)|noarch\"| awk '{print $1}'",
+ "' | sed 's/ /|/g')\" | grep -wE \"$(uname -m)|noarch\"| awk '{print $1}'",
)
else:
depCode, depList = func(
conn=conn,
cmd="dnf --assumeno install "
+ pkgs
+ ' 2>&1 | grep -wE "$(echo '
+ " 2>&1 | grep -wE \"$(echo '"
+ repoList
+ " | sed 's/ /|/g')\" | grep -wE \"$(uname -m)|noarch\"| grep -vE \"$(echo "
+ "' | sed 's/ /|/g')\" | grep -wE \"$(uname -m)|noarch\"| grep -vE \"$(echo "
+ upList
+ " | sed 's/ /|/g')\" | awk '{print $1}'",
)
if depCode != 0:
return depCode, depList
exitcode, result = func(conn=conn, cmd="dnf -y install " + pkgs)
exitcode, result = func(conn=conn, cmd="dnf --refresh -y install " + pkgs)
if tmpfile == "":
tmpfile = tempfile.mkstemp(dir="/tmp")[1]

View File

@@ -23,6 +23,7 @@ import json
import re
import argparse
from pathlib import Path
from collections import OrderedDict
SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__))
sys.path.append(SCRIPT_PATH)
@@ -67,7 +68,7 @@ def suite_path(suite):
try:
with open(suite_json, "r") as f:
suite_data = json.loads(f.read())
suite_data = json.loads(f.read(), object_pairs_hook=OrderedDict)
if suite_data["path"] is None:
mugen_log.logging("error", "json文件:%s中没有path值." % suite_json)
sys.exit(1)
@@ -109,7 +110,7 @@ def suite_cases(suite):
try:
with open(suite_json, "r") as f:
suite_data = json.loads(f.read())
suite_data = json.loads(f.read(), object_pairs_hook=OrderedDict)
if suite_data["cases"] is None:
mugen_log.logging("error", "json文件:%s中没有cases值." % suite_json)
sys.exit(1)

View File

@@ -106,7 +106,7 @@ function modify_conf() {
}
function load_conf() {
rm -rf "${OET_PATH}"/results
# rm -rf "${OET_PATH}"/results
export_var=$(python3 "${OET_PATH}"/libs/locallibs/read_conf.py env-var)
test $? -ne 0 && exit 1

View File

@@ -0,0 +1,12 @@
{
"path": "$OET_PATH/testcases/performance_test/openruyi_unixbench",
"machine num": 1,
"cases": [
{
"name": "test_perf_unixbench",
"desc": "执行 unixbench 跑分测试",
"machine num": 1,
"timeout": 3600
}
]
}

View File

@@ -0,0 +1,33 @@
{
"path": "$OET_PATH/testcases/smoke_test/smoke_openruyi",
"machine num": 1,
"cases": [
{
"name": "or_test_timedatectl",
"machine num": 1,
"add network interface": 0,
"add disk": []
},
{
"name": "oe_test_home_directory",
"machine num": 1,
"add network interface": 0,
"add disk": []
},
{
"name": "or_test_ssh_disable_root",
"machine num": 1,
"desc": "ssh 默认关闭 root 用户登录"
},
{
"name": "or_test_gcc_build",
"machine num": 1,
"desc": "gcc 编译链测试"
},
{
"name": "or_test_llvm_build",
"machine num": 1,
"desc": "LLVM 编译链测试"
}
]
}

View File

@@ -0,0 +1,10 @@
{
"path": "$OET_PATH/testcases/smoke_test/smoke_pkg_install",
"machine num": 1,
"cases": [
{
"name": "test_pkg_install_uninstall",
"desc": "测试软件包的安装功能"
}
]
}

View File

@@ -0,0 +1,129 @@
#!/usr/bin/bash
# Copyright (c) 2024 ISCAS .ALL rights reserved.
# This program is licensed under Mulan PSL v2.
# You can use it according to the terms and conditions of the Mulan PSL v2.
# http://license.coscl.org.cn/MulanPSL2
# THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# #############################################
# @Author : honghua
# @Contact : honghua@iscas.ac.cn
# @Date : 2026-01-07
# @License : Mulan PSL v2
# @Desc : 执行 unixbench 跑分工具,评估。
# ############################################
source "$OET_PATH/libs/locallibs/common_lib.sh"
function pre_test() {
LOG_INFO "Start to prepare the test environment."
DNF_INSTALL "unixbench"
LOG_INFO "End to prepare the test environment."
}
function get_system_info() {
os_name=$(grep "^PRETTY_NAME=" /etc/os-release | cut -d'"' -f2 | awk '{print $1}')
os_version=$(grep "^VERSION=" /etc/os-release | cut -d'"' -f2)
os_arch=$(uname -m)
cpu=$(nproc)
memory=$(free -g | awk '/^Mem:/{print $2}')
}
function escape_json_string() {
local str="$1"
str="${str//\\/\\\\}"
str="${str//\"/\\\"}"
str="${str//$'\n'/\\n}"
str="${str//$'\r'/\\r}"
str="${str//$'\t'/\\t}"
printf '%s' "$str"
}
function parse_unixbench_result() {
local log_content="$1"
score=$(echo "$log_content" | grep "System Benchmarks Index Score" | awk '{print $NF}')
[ -z "$score" ] && score="unknown"
}
function send_result() {
local api_url="https://data-baicao-verify.verify.oepkgs.net/api/v1/unixbench"
local parallel="$1"
local detail="$2"
local json_data=$(cat <<EOF
{
"os_name": "${os_name}",
"os_version": "${os_version}",
"os_arch": "${os_arch}",
"cpu": ${cpu},
"memory": ${memory},
"parallel": ${parallel},
"score": "${score}",
"detail": "${detail}"
}
EOF
)
local response=$(curl -X POST "${api_url}" \
-H "Content-Type: application/json" \
-d "${json_data}" \
-w "%{http_code}" \
-o /tmp/curl_response.txt \
-s 2>&1)
local curl_exit_code=$?
local http_code="${response: -3}"
if [ $curl_exit_code -ne 0 ] || [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
LOG_INFO "发送测试结果到 API 失败 (HTTP 状态码:${http_code}, curl 退出码:${curl_exit_code}),但不影响测试流程"
return 0
else
LOG_INFO "测试结果已成功发送到 API"
return 0
fi
}
function run_test() {
LOG_INFO "基础环境准备..."
EXECUTE_T="60m"
cd /opt/unixbench
LOG_INFO "开始执行 unixbench 工具 ..."
LOG_INFO "开始执行 ./Run -c 1"
local result_c1=$(./Run -c 1 2>&1 | tee /dev/tty)
if [ $? -ne 0 ]; then
LOG_ERROR "执行 ./Run -c 1 测试失败"
exit 255
fi
get_system_info
parse_unixbench_result "$result_c1"
local escaped_detail=$(escape_json_string "$result_c1")
send_result "1" "$escaped_detail"
LOG_INFO "开始执行 ./Run -c $(getconf _NPROCESSORS_ONLN)"
local result_multi=$(./Run -c $(getconf _NPROCESSORS_ONLN) 2>&1 | tee /dev/tty)
if [ $? -ne 0 ]; then
LOG_ERROR "执行 ./Run -c $(getconf _NPROCESSORS_ONLN) 测试失败"
exit 255
fi
parse_unixbench_result "$result_multi"
escaped_detail=$(escape_json_string "$result_multi")
send_result "$(getconf _NPROCESSORS_ONLN)" "$escaped_detail"
}
function post_test() {
LOG_INFO "Start to restore the test environment."
DNF_REMOVE "$@"
LOG_INFO "Finish restoring the test environment."
}
main "$@"

View File

@@ -0,0 +1 @@
../../function_test/basic_test/basic_mugen/os-basic/oe_test_home_directory/oe_test_home_directory.sh

View File

@@ -0,0 +1,52 @@
#!/usr/bin/bash
# Copyright (c) 2026 ISCAS .ALL rights reserved.
# This program is licensed under Mulan PSL v2.
# You can use it according to the terms and conditions of the Mulan PSL v2.
# http://license.coscl.org.cn/MulanPSL2
# THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# #############################################
# @Author : yafen
# @Contact : yafen@iscas.ac.cn
# @Date : 2026-04-13
# @License : Mulan PSL v2
# @Desc : gcc 编译测试,编译 UnixBench
# ############################################
source "${OET_PATH}"/libs/locallibs/common_lib.sh
function pre_test() {
LOG_INFO "Start to prepare the test environment."
DNF_INSTALL "gcc make git"
UNIXBENCH_DIR="/opt/UnixBench"
LOG_INFO "End to prepare the test environment."
}
function run_test() {
set -e
LOG_INFO "start to run test."
if git clone -b v6.0.0 https://github.com/kdlucas/byte-unixbench.git "${UNIXBENCH_DIR}"; then
LOG_INFO "UnixBench 仓库克隆成功"
cd $UNIXBENCH_DIR/UnixBench
sed -i 's/rv64g/rva23u64/g' Makefile
make all CC='gcc -std=gnu99'
CHECK_RESULT $? 0 0 "compile UnixBench failed"
else
LOG_ERROR "UnixBench 仓库克隆失败,脚本退出"
exit 1
fi
LOG_INFO "End to run test."
set +e
}
function post_test() {
LOG_INFO "Start to restore the test environment."
DNF_REMOVE "$@"
rm -rf $UNIXBENCH_DIR
LOG_INFO "Finish restoring the test environment."
}
main "$@"

View File

@@ -0,0 +1,68 @@
From 24223c0b3ca110af04e34f008943979fc6b71598 Mon Sep 17 00:00:00 2001
From: Tom Rix <trix@redhat.com>
Date: Sat, 30 Dec 2023 08:58:47 -0500
Subject: [PATCH] Fix signatures of functions
Signed-off-by: Tom Rix <trix@redhat.com>
---
foxi/onnxifi_dummy.c | 11 ++++++++---
foxi/onnxifi_wrapper.c | 8 ++++++--
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/foxi/onnxifi_dummy.c b/foxi/onnxifi_dummy.c
index 2115af9..7cc81dc 100644
--- a/foxi/onnxifi_dummy.c
+++ b/foxi/onnxifi_dummy.c
@@ -103,7 +103,10 @@ ONNXIFI_PUBLIC ONNXIFI_CHECK_RESULT onnxStatus ONNXIFI_ABI onnxInitGraph(
const void* onnxModel,
uint32_t weightCount,
const onnxTensorDescriptorV1* weightDescriptors,
- onnxGraph* graph) {
+ onnxGraph* graph,
+ uint32_t maxSeqLength,
+ void* deferredWeightReader) {
+
if (graph == NULL) {
return ONNXIFI_STATUS_INVALID_POINTER;
}
@@ -215,6 +218,8 @@ ONNXIFI_PUBLIC ONNXIFI_CHECK_RESULT onnxStatus ONNXIFI_ABI
onnxWaitEventFor(onnxEvent event,
uint32_t timeoutMs,
onnxEventState* eventState,
- onnxStatus* eventStatus) {
+ onnxStatus* eventStatus,
+ char* message,
+ size_t* messageLength) {
return ONNXIFI_STATUS_SUCCESS;
-}
\ No newline at end of file
+}
diff --git a/foxi/onnxifi_wrapper.c b/foxi/onnxifi_wrapper.c
index 98a9325..abe1440 100644
--- a/foxi/onnxifi_wrapper.c
+++ b/foxi/onnxifi_wrapper.c
@@ -761,7 +761,9 @@ ONNXIFI_PUBLIC onnxStatus ONNXIFI_ABI onnxInitGraph(
const void* onnxModel,
uint32_t weightsCount,
const onnxTensorDescriptorV1* weightDescriptors,
- onnxGraph* graph)
+ onnxGraph* graph,
+ uint32_t maxSeqLength,
+ void* deferredWeightReader)
{
if (graph == NULL) {
return ONNXIFI_STATUS_INVALID_POINTER;
@@ -797,7 +799,9 @@ ONNXIFI_PUBLIC onnxStatus ONNXIFI_ABI onnxInitGraph(
onnxModel,
weightsCount,
weightDescriptors,
- &graph_wrapper->graph);
+ &graph_wrapper->graph,
+ maxSeqLength,
+ deferredWeightReader);
switch (status) {
case ONNXIFI_STATUS_SUCCESS:
case ONNXIFI_STATUS_FALLBACK:
--
2.43.0

View File

@@ -0,0 +1,66 @@
# SPDX-FileCopyrightText: (C) 2026 Institute of Software, Chinese Academy of Sciences (ISCAS)
# SPDX-FileCopyrightText: (C) 2026 openRuyi Project Contributors
# SPDX-FileContributor: CHEN Xuan <chenxuan@iscas.ac.cn>
#
# SPDX-License-Identifier: MulanPSL-2.0
%global commit0 c278588e34e535f0bb8f00df3880d26928038cad
%global date0 20260211
%global shortcommit0 c278588
# Use pytorch's toolchain
%global toolchain clang
Name: foxi
Version: 0+git%{date0}.%{shortcommit0}
Release: 1
Summary: ONNXIFI with Facebook Extension
License: MIT
URL: https://github.com/houseroad/foxi
#!RemoteAsset
Source0: %{url}/archive/%{commit0}/%{name}-%{shortcommit0}.tar.gz
BuildSystem: cmake
# https://github.com/houseroad/foxi/pull/25
Patch0: 0001-Fix-signatures-of-functions.patch
BuildOption(conf): -DONNX_USE_LITE_PROTO=OFF
BuildRequires: cmake
BuildRequires: clang
%description
%{summary}
%package devel
Summary: Headers and libraries for %{name}
Requires: %{name}%{?_isa} = %{version}-%{release}
%description devel
%{summary}
%prep -a
# Change static library to shared
sed -i -e 's/foxi_loader STATIC/foxi_loader SHARED/' CMakeLists.txt
# Disable hidden so shared foxi_loader will find onnxifi_load
sed -i -e 's/__ELF_/__NO_ELF_DISABLING_HIDDEN__/' foxi/onnxifi_loader.h
# Fix the destination lib
sed -i -e 's/DESTINATION lib/DESTINATION lib64/' CMakeLists.txt
# Just install libfoxi_loader
sed -i -e 's/foxi foxi_dummy foxi_loader/foxi_loader/' CMakeLists.txt
# version *.so
echo "set_target_properties(foxi_loader PROPERTIES SOVERSION \"1.4.1\")" >> CMakeLists.txt
# For CMake 4
sed -i 's@cmake_minimum_required(VERSION 3.1@cmake_minimum_required(VERSION 3.5@' CMakeLists.txt
%files
%license LICENSE
%exclude %{_libdir}/libfoxi.so
%{_libdir}/libfoxi_loader.so.*
%files devel
%{_includedir}/%{name}/
%{_libdir}/libfoxi_loader.so
%changelog

View File

@@ -0,0 +1,53 @@
#!/usr/bin/bash
# Copyright (c) 2026 ISCAS .ALL rights reserved.
# This program is licensed under Mulan PSL v2.
# You can use it according to the terms and conditions of the Mulan PSL v2.
# http://license.coscl.org.cn/MulanPSL2
# THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# #############################################
# @Author : yafen
# @Contact : yafen@iscas.ac.cn
# @Date : 2026-04-13
# @License : Mulan PSL v2
# @Desc : llvm 编译测试,编译 UnixBench
# ############################################
source "${OET_PATH}"/libs/locallibs/common_lib.sh
function pre_test() {
LOG_INFO "Start to prepare the test environment."
DNF_INSTALL "clang cmake wget tar rpm-build dnf5-plugins"
LOG_INFO "End to prepare the test environment."
}
function run_test() {
set -e
LOG_INFO "start to run test."
BUILD_DIR="$(pwd)/build"
rm -rf $BUILD_DIR
mkdir -p $BUILD_DIR/SOURCES/
if wget -P $BUILD_DIR/SOURCES/ https://github.com/houseroad/foxi/archive/c278588/foxi-c278588.tar.gz; then
LOG_INFO "foxi-c278588.tar.gz 下载成功"
cp 0001-Fix-signatures-of-functions.patch -p $BUILD_DIR/SOURCES/
rpmbuild --define "_topdir $BUILD_DIR" -ba foxi.spec
CHECK_RESULT $? 0 0 "build foxi rpm failed"
else
LOG_ERROR "foxi-c278588.tar.gz 下载失败,脚本退出"
exit 1
fi
LOG_INFO "End to run test."
set +e
}
function post_test() {
LOG_INFO "Start to restore the test environment."
DNF_REMOVE "$@"
[ -d $BUILD_DIR ] && rm -rf $BUILD_DIR
LOG_INFO "Finish restoring the test environment."
}
main "$@"

View File

@@ -0,0 +1,58 @@
#!/usr/bin/bash
# Copyright (c) 2026 ISCAS .ALL rights reserved.
# This program is licensed under Mulan PSL v2.
# You can use it according to the terms and conditions of the Mulan PSL v2.
# http://license.coscl.org.cn/MulanPSL2
# THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# #############################################
# @Author : yafen
# @Contact : yafen@iscas.ac.cn
# @Date : 2026-04-13
# @License : Mulan PSL v2
# @Desc : Don't allow root account to log in to the system directly using SSH
# ############################################
source "$OET_PATH/libs/locallibs/common_lib.sh"
function pre_test() {
LOG_INFO "Start environmental preparation."
LOG_INFO "End of environmental preparation!"
}
function run_test() {
LOG_INFO "Start executing testcase."
grep -qE "^\s*PermitRootLogin\s+yes" /etc/ssh/sshd_config
CHECK_RESULT $? 1 0 "Root login should be disabled"
expect <<EOF
set timeout 15
log_file testlog
spawn ssh root@${NODE1_IPV4}
expect {
"*yes/no*" {
send "yes\\r"
}
}
expect {
"password" {
send "${NODE1_PASSWORD}\\r";
exp_continue
}
}
expect eof
EOF
grep "Permission denied, please try again." testlog
CHECK_RESULT $?
LOG_INFO "Finish testcase execution."
}
function post_test() {
LOG_INFO "Start cleanning environment."
rm -rf testlog
LOG_INFO "Finish environment cleanup!"
}
main "$@"

View File

@@ -0,0 +1,31 @@
#!/usr/bin/bash
# Copyright (c) 2026 ISCAS .ALL rights reserved.
# This program is licensed under Mulan PSL v2.
# You can use it according to the terms and conditions of the Mulan PSL v2.
# http://license.coscl.org.cn/MulanPSL2
# THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# #############################################
# @Author : yafen
# @Contact : yafen@iscas.ac.cn
# @Date : 2026-04-13
# @License : Mulan PSL v2
# @Desc : Ensure clock synchronization is complete
# ############################################
source "${OET_PATH}/libs/locallibs/common_lib.sh"
function run_test() {
LOG_INFO "Start to run test."
timedatectl | grep "Local time"
CHECK_RESULT $?
timedatectl | grep "NTP service" | grep " active"
CHECK_RESULT $?
LOG_INFO "End to run test."
}
main "$@"

View File

@@ -0,0 +1,128 @@
#!/usr/bin/bash
# Copyright (c) 2026 ISCAS .ALL rights reserved.
# This program is licensed under Mulan PSL v2.
# You can use it according to the terms and conditions of the Mulan PSL v2.
# http://license.coscl.org.cn/MulanPSL2
# THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# #############################################
# @Author : yafen
# @Contact : yafen@iscas.ac.cn
# @Date : 2026-04-13
# @License : Mulan PSL v2
# @Desc : 测试软件包的安装功能
# ############################################
source "$OET_PATH/libs/locallibs/common_lib.sh"
function pkg_install() {
PKG_TEST=$1
LOG_INFO "开始测试 ${PKG_TEST} 软件包的安装功能"
dnf clean all
dnf makecache
# 检查是否已安装
if dnf list installed "${PKG_TEST}" &>/dev/null; then
LOG_INFO "检测到 ${PKG_TEST} 已安装,脚本将保持安装状态"
INSTALLED_BEFORE=true
else
LOG_INFO "检测到 ${PKG_TEST} 未安装,将在测试中安装"
INSTALLED_BEFORE=false
fi
# 检查 yum 源中是否存在软件包
LOG_INFO "检查 yum 源中是否存在 ${PKG_TEST} 软件包"
if ! dnf list available "${PKG_TEST}" &>/dev/null; then
LOG_ERROR "yum 源中未找到 ${PKG_TEST} 软件包"
exit 255
fi
# 如果之前已经安装,则执行卸载步骤
if [ "$INSTALLED_BEFORE" = true ]; then
LOG_INFO "卸载 ${PKG_TEST} 软件包"
dnf remove -y ${PKG_TEST}
CHECK_RESULT $? 0 0 "卸载 ${PKG_TEST} 失败"
LOG_INFO "环境已恢复到未安装状态"
fi
LOG_INFO "执行安装 ${PKG_TEST} 软件包"
dnf install -y ${PKG_TEST} --refresh
CHECK_RESULT $? 0 0 "安装 ${PKG_TEST} 失败"
# 验证安装是否成功
LOG_INFO "验证 ${PKG_TEST} 安装是否成功"
if dnf list installed ${PKG_TEST} &>/dev/null; then
LOG_INFO "${PKG_TEST} 安装验证成功"
else
LOG_ERROR "${PKG_TEST} 安装验证失败"
exit 1
fi
# 验证卸载功能
LOG_INFO "卸载 ${PKG_TEST} 软件包"
dnf remove -y ${PKG_TEST}
CHECK_RESULT $? 0 0 "卸载 ${PKG_TEST} 失败"
# 环境恢复:如果之前已安装,则重新安装软件包
if [ "$INSTALLED_BEFORE" = true ]; then
LOG_INFO "恢复环境:安装 ${PKG_TEST} 软件包"
dnf install -y ${PKG_TEST}
CHECK_RESULT $? 0 0 "安装 ${PKG_TEST} 失败"
LOG_INFO "环境已恢复到已安装状态"
else
LOG_INFO "保持 ${PKG_TEST} 未安装状态"
fi
INSTALLED_BEFORE=""
LOG_INFO "${PKG_TEST} 软件包安装功能测试完成"
}
function run_test() {
set -e
if [ -n "$PKG_INSTALL" ]; then
echo "优先使用环境变量 PKG_INSTALL: $PKG_INSTALL"
echo "$PKG_INSTALL" | tr ',' '\n' | while read -r pkg; do
[ -n "$pkg" ] && pkg_install "$pkg"
done
else
echo "环境变量未设置,使用默认文件路径"
FILE_PATH="$OET_PATH/.os-autotest/pkg-install"
if [ -f "$FILE_PATH" ]; then
while IFS= read -r line; do
[ -n "$line" ] && pkg_install "$line"
done < "$FILE_PATH"
else
LOG_ERROR "文件路径不存在: $FILE_PATH"
fi
fi
set +e
}
function post_test() {
if [ -z "$PKG_TEST" ]; then
return
fi
if [ "$INSTALLED_BEFORE" = true ]; then
LOG_INFO "恢复环境:安装 ${PKG_TEST} 软件包"
dnf install -y ${PKG_TEST} --refresh
CHECK_RESULT $? 0 0 "安装 ${PKG_TEST} 失败"
LOG_INFO "环境已恢复到已安装状态"
elif [ "$INSTALLED_BEFORE" = false ]; then
if dnf list installed "${PKG_TEST}" &>/dev/null; then
LOG_INFO "清理环境:卸载 ${PKG_TEST} 软件包"
dnf remove -y ${PKG_TEST}
CHECK_RESULT $? 0 0 "卸载 ${PKG_TEST} 失败"
LOG_INFO "环境已恢复到未安装状态"
fi
fi
}
INSTALLED_BEFORE=""
PKG_TEST=""
main "$@"