Skip to content

hakugyokurou-lug/ruyi-mugen-fork

 
 

Repository files navigation

mugen

Build Status

RuyiSDK mugen 测试分支

测试平台:

  • x86_64 Debian 12
  • x86_64 Fedora 38
  • x86_64 Ubuntu 22.04 LTS
  • x86_64 openEuler 23.09
  • x86_64 Archlinux
  • riscv64 Debian sid
  • riscv64 Fedora 38
  • riscv64 Ubuntu 22.04 LTS
  • riscv64 RevyOS 20231210
  • riscv64 openEuler 23.09
  • riscv64 Archlinux
  • aarch64 Debian 12

对上游 mugen 的更改

使用 ruyi-mugen 测试时,应当使用普通用户运行,且该普通用户应当可以 NOPASSWD 调用 sudo 提权。

在测试用例中显示安装软件包示例如下

DNF_INSTALL git
APT_INSTALL git
PACMAN_INSTALL git

由于软件包名称可能不同,两个函数都需要调用

在测试用例运行结束时移除因测试需求而安装的软件包示例如下

PKG_REMOVE

不需要任何参数

注意,这样的设计假定了你的发行版中 dnfapt-getpacman 三种包管理只存在一种

mugen介绍

mugen是openEuler社区开放的测试框架,提供公共配置和方法以便社区开发者进行测试代码的编写和执行

mugen更新说明

  • 优化了mugen框架的入口函数
  • 当前版本添加了对测试套路径和测试用例环境的添加
  • 新增python公共函数
  • 新增组合测试

mugen使用教程

安装依赖软件

bash dep_install.sh

配置测试套环境变量

  • 命令执行:bash mugen.sh -c --ip $ip --password $passwd --user $user --port $port
  • 参数说明:
    • ip:测试机的ip地址
    • user:测试机的登录用户,默认为root
    • password: 测试机的登录密码
    • port:测试机ssh登陆端口,默认为22
  • 环境变量文件:./conf/env.json
{
    "NODE": [
        {
            "ID": 1,
            "LOCALTION": "local",
            "MACHINE": "physical",
            "FRAME": "aarch64",
            "NIC": "eth0",
            "MAC": "55:54:00:c8:a9:21",
            "IPV4": "192.168.0.10",
            "USER": "root",
            "PASSWORD": "openEuler12#$",
            "SSH_PORT": 22,
            "BMC_IP": "",
            "BMC_USER": "",
            "BMC_PASSWORD": ""
        },
        {
            "ID": 2,
            "LOCALTION": "remote",
            "MACHINE": "kvm",
            "FRAME": "aarch64",
            "NIC": "eth0",
            "MAC": "55:54:00:c8:a9:22",
            "IPV4": "192.168.0.11",
            "USER": "root",
            "PASSWORD": "openEuler12#$",
            "SSH_PORT": 22,
            "HOST_IP": "",
            "HOST_USER": "",
            "HOST_PASSWORD": "",
            "HOST_SSH_PORT": ""
        }
    ]
}
  • 在用例中的使用:NODE${id}_${LOCALTION}

用例执行

  • 执行所有用例 bash mugen.sh -a
  • 执行指定测试套 bash mugen.sh -f testsuite
  • 执行单条用例 bash mugen.sh -f testsuite -r testcase
  • 日志输出shell脚本的执行过程
bash mugen.sh -a -x 
bash mugen.sh -f testsuite -x
bash mugen.sh -f testsuite -r testcase -x

用例添加

  • 根据模板编写用例脚本(推荐)
source ${OET_PATH}/libs/locallibs/common_lib.sh

# 需要预加载的数据、参数配置
function config_params() {
    LOG_INFO "Start to config params of the case."

    LOG_INFO "No params need to config."

    LOG_INFO "End to config params of the case."
}

# 测试对象、测试需要的工具等安装准备
function pre_test() {
    LOG_INFO "Start to prepare the test environment."

    LOG_INFO "No pkgs need to install."

    LOG_INFO "End to prepare the test environment."
}

# 测试点的执行
function run_test() {
    LOG_INFO "Start to run test."

    # 测试命令:ls
    ls -CZl -all
    CHECK_RESULT 0

    # 测试/目录下是否存在proc|usr|roor|var|sys|etc|boot|dev目录
    CHECK_RESULT "$(ls / | grep -cE 'proc|usr|roor|var|sys|etc|boot|dev')" 7

    LOG_INFO "End to run test."
}

# 后置处理,恢复测试环境
function post_test() {
    LOG_INFO "Start to restore the test environment."

    LOG_INFO "Nothing to do."

    LOG_INFO "End to restore the test environment."
}

main "$@"
  • 单纯的shell脚本或python脚本,通过脚本执行的返回码判断用例是否成功。
    • 可参考样例:testsuite测试套下用例oe_test_casename_02和oe_test_casename_03

suite2cases中json文件的写法

  • 文件名为测试套名,文件后缀.json
  • 文件内容说明:

框架的公共函数

  • 如何加载到用例中,以供调用
# bash
source ${OET_PATH}/libs/locallibs/common_lib.sh

# python
import os, sys, subprocess

LIBS_PATH = os.environ.get("OET_PATH") + "/libs/locallibs"
sys.path.append(LIBS_PATH)
import xxx
  • 公共函数
    • 日志打印
    # bash 
    LOG_INFO "$message"
    LOG_WARN "$message"
    LOG_DEBUG "$message"
    LOG_ERROR "$message"
    # python
    import mugen_log
    mugen_log.logging(level, message) # level:INFO,WARN,DEBUG,ERROR;message:日志输出
    
    • 结果检查
    # bash
    CHECK_RESULT $1 $2 $3 $4 $5
    # $1:测试点的返回结果
    # $2:预期结果
    # $3:对比模式,0:返回结果和预期结果相等;1:返回结果和预期结果不等
    # $4:发现问题,日志输出
    # $5:退出模式,0:不管问题继续执行后续程序;1:发现问题后中断并退出此代码块
    
    • rpm包安装卸载
    # bash
    ## func 1
    DNF_INSTALL "vim bc" "$node_id"
    DNF_REMOVE "$node_id" "jq" "$mode"
    
    # mode:默认为0,会删除用例中安装的包,当为非0时,则只卸载当软件包
    # python
    import rpm_manage
    tpmfile = rpm_manage.rpm_install(pkgs, node, tmpfile)
    rpm_manage.rpm_remove(node, pkgs, tmpfile)
    
    • 远程命令执行
    # bash
    ## func 1
    SSH_CMD "$cmd" $remote_ip $remote_password $remote_user $time_out $remote_port`
    ## func 2
    P_SSH_CMD --cmd $cmd --node $node(远端节点号)
    P_SSH_CMD --cmd $cmd --ip $remote_ip --password $remote_password --port $remote_port --user $remote_user --timeout $timeout
    # python
    conn = ssh_cmd.pssh_conn(remote_ip, remote_password,remote_port,remote_user,remote_timeout)
    exitcode, output = ssh_cmd.pssh_cmd(conn, cmd)
    
    # port:默认为22
    # user:默认为root
    # timeout: 默认不限制
    
    • 目录文件传输
    # bash
    ## func 1
    ### 本地文件传输到远端  
    `SSH_SCP $local_path/$file $REMOTE_USER@$REMOTE_IP:$remote_path "$REMOTE_PASSWD"`
    ### 远端文件传输到本地  
    `SSH_SCP $REMOTE_USER@$REMOTE_IP:$remote_path/$file $local_path "$REMOTE_PASSWD"`
    ## func 2
    ### 目录传输
    SFTP get/put --localdir $localdir --remotedir $remotedir
    ### 文件传输
    SFTP get/put --localdir $localdir --remotedir $remotedir --localfile/remotefile $localfile/$remotefile
    # python
    ### 目录传输
    import ssh_cmd, sftp
    conn = ssh_cmd.pssh_conn(remote_ip, remote_password,remote_port,remote_user,remote_timeout)
    psftp_get(conn,remote_dir, local_dir)
    psftp_put(local_dir=local_dir, remote_dir=remote_dir)
    ### 文件传输
    import ssh_cmd, sftp
    psftp_get(remote_dir, remote_file, local_dir)
    psftp_put(local_dir=local_dir, local_file=local_file, remote_dir=remote_dir)
    
    
    # get:从远端获取
    # put:传输到远端
    # localdir: 默认为当前目录
    # remotedir:默认为远端根目录
    
    • 获取空闲端口
    # bash
    GET_FREE_PORT $ip
    # python
    import free_port
    free_port.find_free_port(ip)
    
    • 检查端口是否被占用
    # bash 
    IS_FREE_PORT $port $ip
    # python
    import free_port
    free_port.is_free_port(port, ip)
    
    • 获取测试网卡
    # bash
    TEST_NIC $node_id
    # python
    import get_test_device
    get_test_nic(node_id)
    
    # node_id:默认为1号节点
    
    • 获取测试磁盘
    # bash
    TEST_DISK $node_id
    # python
    import get_test_device
    get_test_disk(node_id)
    
    # node_id:默认为1号节点
    
    • 睡眠等待
    # bash
    SLEEP_WAIT $wait_time $cmd
    # python
    import sleep_wait
    sleep_wait.sleep_wait(wait_time,cmd)
    
    • 远端重启等待
    # bash
    REMOTE_REBOOT_WAIT $node_id $wait_time
    

用例如何调试

  • 设置OET_PATH(mugen框架路径环境变量)之后,就可以在用例所在目录直接执行用例脚本

用例超时说明

  • 默认超时30m
  • 如果某条用例执行超过30m,在用例对TIMEOUT重新赋值

FAQ

  • 远程后台执行命令时,用例执行卡住,导致用例超时失败
    • 原因:ssh远程执行命令不会自动退出,会一直等待命令的控制台标准输出,直至命令运行信号结束
    • 解决方案:可以将标准输出与标准错误输出重定向到/dev/null,如此ssh就不会一直等待cmd > /dev/nul 2>&1 &

组合测试

安装依赖软件

bash dep_install.sh bash dep_install.sh -e (嵌入式)

组合设置配置

组合配置使用json文件对组合测试进行配置,json文件示例

{
    // 配置运行环境需要export的环境变量
    "export": {
        "FIND_TINY_DIR":"/home/openeuler/tmp_image/tiny"
    },
    // 运行环境配置,可选,支持host、qemu(嵌入式场景),必须为列表,即使只有一个
    "env": [ 
        {
            // 类型 type 必须配置,qemu类型kernal_img_path、initrd_path、qemu_type必配,其他参数参考qemu_ctl.sh参数
            "type": "qemu",
            // 名称 name 必须配置
            "name": "qemu_1",
            // kernal_img_path、initrd_path可以为本机目录,也可以是网络地址,如果配置目录不存在则会使用wget下载
            "kernal_img_path": "https://mirrors.nju.edu.cn/openeuler/openEuler-22.03-LTS-SP1/embedded_img/arm64/aarch64-std/zImage",
            "initrd_path": "https://mirrors.nju.edu.cn/openeuler/openEuler-22.03-LTS-SP1/embedded_img/arm64/aarch64-std/openeuler-image-qemu-aarch64-20221228125551.rootfs.cpio.gz",
            "option_wait_time": "180",
            "login_wait_str": "openEuler Embedded(openEuler Embedded Reference Distro)",
            "qemu_type": "aarch64",
            // 嵌入式sdk路径配置,可以为本机目录,也可以是网络地址,如果配置目录不存在则会使用wget下载
            "sdk_path":"https://mirrors.nju.edu.cn/openeuler/openEuler-22.03-LTS-SP1/embedded_img/arm64/aarch64-std/openeuler-glibc-x86_64-openeuler-image-aarch64-qemu-aarch64-toolchain-22.03.sh",
            "put_all":true
        },
        {
            // 类型 type 必须配置,host类型,ip、password比配,其他参数参考bash mugen.sh -c
            "type": "host",
            // 名称 name 必须配置
            "name": "host_1",
            "ip": "192.168.10.100",
            "password": "openEuler@123",
            "port": "22",
            "user": "root",
            "run_remote": true,
            "copy_all": true
        }
    ],
    // 测试套组合配置,必配,必须为列表,可为多个组合
    "combination": [
        {
            // 组合名称 name
            "name": "normal_test",
            // 测试用例组合, 必须为列表
            "testcases": [
                {
                    // 使用全部测试套
                    "testsuite": "embedded_os_basic_test"
                },
                {
                    // 使用testsuite指定测试套中add里包含的测试用例组成一个新的测试套
                    "testsuite": "embedded_os_basic_extra_test",
                    "add": ["oe_test_kmod_depmod", "oe_test_libcap_libcap"]
                },
                {
                    // 使用testsuite指定测试套中删除del里包含的测试用例组成一个新的测试套
                    "testsuite": "embedded_security_config_test",
                    "del": "oe_test_check_file_sys_protect_003"
                }
            ]
        },
        {
            "name": "easy_test",
            "testcases": [
                {
                    "testsuite": "embedded_os_basic_test"
                }
            ]
        }
    ],
    // 执行关系,可选,必须为列表
    "execute":[
        {
            // 执行环境,必须为列表,env中应为前面运行环境配置中的运行环境名称
            "env":["qemu_1", "qemu_2"],
            // 执行组合名称,仅支持配置一个
            "combination":"normal_test"
        },
        {
            "env":["qemu_2"],
            "combination":"easy_test"
        },
        {
            "env":["host_1"],
            "combination":"easy_test"
        }
    ]
}

执行组合测试

bash combination.sh 组合配置名(在combination目录中,不需要.json) 生成配置组合文件夹及执行脚本 示例:

bash combination.sh embedded_ci_test

bash combination.sh --all 执行所有在combination目录中的配置文件

bash combination.sh -f 组合配置文件(不在combination目录中,需要绝对路径,包含.json后最) 示例:

bash combination.sh -f /home/openeuler/test.json

bash combination.sh -d 组合配置文件所在目录(不在combination目录中,需要绝对路径,配置文件必须为.json后缀) 示例:

bash combination.sh -d /home/openeuler/

bash combination.sh 组合配置名 -r 生成配置组合文件夹及执行脚本并执行脚本,并打印执行结果 示例:

bash combination.sh -r embedded_ci_test
bash combination.sh -r -a
bash combination.sh -r -f /home/openeuler/test.json
bash combination.sh -r -d /home/openeuler/

bash combination.sh -p 打印配置执行脚本执行结果 示例:

bash combination.sh -p

About

Mugen testcases for RUYISDK

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Shell 51.2%
  • Python 48.8%