From fb122170801092284d43ee644e72304d943175b1 Mon Sep 17 00:00:00 2001
From: Zhu Huankai <zhuhuankai1@huawei.com>
Date: Mon, 18 Oct 2021 12:12:24 +0800
Subject: [PATCH 4/4] hydropper: adapt stratovirt2.0

add standvm testcases and modify some standvm device
cmdline code.

Signed-off-by: Zhu Huankai <zhuhuankai1@huawei.com>
---
 tests/hydropper/config/config.ini             |   3 +
 tests/hydropper/pytest.ini                    |   1 +
 .../functional/test_microvm_balloon.py        |   6 +-
 .../functional/test_standvm_balloon.py        |  89 ++++++++++
 .../functional/test_standvm_vhost_vsock.py    | 122 +++++++++++++
 .../functional/test_standvm_virtio_blk.py     |  65 +++++++
 .../functional/test_standvm_virtio_net.py     | 162 ++++++++++++++++++
 .../functional/test_standvm_virtio_rng.py     |  75 ++++++++
 .../standvm/functional/test_standvm_vmlife.py |  69 ++++++++
 tests/hydropper/utils/config.py               |   1 +
 tests/hydropper/virt/basevm.py                |   1 +
 tests/hydropper/virt/microvm.py               |   2 +-
 tests/hydropper/virt/standvm.py               |  13 +-
 13 files changed, 599 insertions(+), 10 deletions(-)
 create mode 100644 tests/hydropper/testcases/standvm/functional/test_standvm_balloon.py
 create mode 100644 tests/hydropper/testcases/standvm/functional/test_standvm_vhost_vsock.py
 create mode 100644 tests/hydropper/testcases/standvm/functional/test_standvm_virtio_blk.py
 create mode 100644 tests/hydropper/testcases/standvm/functional/test_standvm_virtio_net.py
 create mode 100644 tests/hydropper/testcases/standvm/functional/test_standvm_virtio_rng.py
 create mode 100644 tests/hydropper/testcases/standvm/functional/test_standvm_vmlife.py

diff --git a/tests/hydropper/config/config.ini b/tests/hydropper/config/config.ini
index 68d40f5..abb9167 100644
--- a/tests/hydropper/config/config.ini
+++ b/tests/hydropper/config/config.ini
@@ -37,6 +37,9 @@ STRATOVIRT_STAND_ROOTFS = /home/standvm_image/openEuler-stratovirt.img
 STRATOVIRT_VMLINUX = /home/microvm_image/vmlinux.bin
 STRATOVIRT_STAND_VMLINUX = /home/standvm_image/std-vmlinuxz
 
+# Standvm code_storage_file
+CODE_STORAGE_FILE = /usr/share/edk2/ovmf/OVMF_CODE.fd
+
 # User-defined parameters.
 # Users can add parameters here. Then adapt configparser in config.py to use them.
 
diff --git a/tests/hydropper/pytest.ini b/tests/hydropper/pytest.ini
index 236e5f1..99f6bcb 100644
--- a/tests/hydropper/pytest.ini
+++ b/tests/hydropper/pytest.ini
@@ -4,5 +4,6 @@ markers=
     acceptance: acceptance test
     system:  system test
     performance: performance test
+    standvm_accept: standvm acceptance test
 
 render_collapsed = False
diff --git a/tests/hydropper/testcases/microvm/functional/test_microvm_balloon.py b/tests/hydropper/testcases/microvm/functional/test_microvm_balloon.py
index 4d0323e..2b6532e 100644
--- a/tests/hydropper/testcases/microvm/functional/test_microvm_balloon.py
+++ b/tests/hydropper/testcases/microvm/functional/test_microvm_balloon.py
@@ -46,8 +46,8 @@ def test_microvm_balloon(microvm):
     5) check if the memory size is less than 2524971008.
     6) set memory size through balloon device to 2524971008, and wait.
     7) check if the memory size is 2524971008.
-    Note that balloon device may not inflate as many as the given argument, but it can deflate until  
-    no page left in balloon device. Therefore, memory in step 5 is less than 2524971008, 
+    Note that balloon device may not inflate as many as the given argument, but it can deflate until
+    no page left in balloon device. Therefore, memory in step 5 is less than 2524971008,
     while that in step 7 equals 2524971008.
 
     """
@@ -86,4 +86,4 @@ def test_microvm_balloon_active(microvm):
     resp = test_vm.query_balloon()
     assert resp["error"]["desc"] == "No balloon device has been activated"
     resp = test_vm.balloon_set(value=2524971008)
-    assert resp["error"]["desc"] == "No balloon device has been activated"
\ No newline at end of file
+    assert resp["error"]["desc"] == "No balloon device has been activated"
diff --git a/tests/hydropper/testcases/standvm/functional/test_standvm_balloon.py b/tests/hydropper/testcases/standvm/functional/test_standvm_balloon.py
new file mode 100644
index 0000000..f007127
--- /dev/null
+++ b/tests/hydropper/testcases/standvm/functional/test_standvm_balloon.py
@@ -0,0 +1,89 @@
+# Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved.
+#
+# StratoVirt is licensed under Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan
+# PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+#         http:#license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE 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.
+
+"""Test standvm balloon"""
+import time
+import logging
+import pytest
+
+LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
+logging.basicConfig(filename='/var/log/pytest.log', level=logging.DEBUG, format=LOG_FORMAT)
+
+@pytest.mark.acceptance
+def test_standvm_balloon_query(standvm):
+    """
+    Test qmp command of querying balloon
+
+    steps:
+    1) launch standvm with argument: "-balloon deflate-on-oom=true".
+    2) query the memory size, and check if it is 2524971008 which is the default memory size.
+    """
+    test_vm = standvm
+    test_vm.basic_config(balloon=True, deflate_on_oom=True)
+    test_vm.launch()
+    resp = test_vm.query_balloon()
+    assert int(resp["return"]["actual"]) == int(standvm.memsize) * 1024 * 1024
+
+@pytest.mark.acceptance
+def test_standvm_balloon(standvm):
+    """
+    Test qmp command of setting balloon
+
+    steps:
+    1) launch standvm with argument: "-balloon deflate-on-oom=true".
+    2) query memory size, and save.
+    3) set memory size through balloon device to 814748368.
+    4) wait 5 seconds for ballooning.
+    5) check if the memory size is less than 2524971008.
+    6) set memory size through balloon device to 2524971008, and wait.
+    7) check if the memory size is 2524971008.
+    Note that balloon device may not inflate as many as the given argument, but it can deflate until
+    no page left in balloon device. Therefore, memory in step 5 is less than 2524971008,
+    while that in step 7 equals 2524971008.
+
+    """
+    test_vm = standvm
+    test_vm.basic_config(balloon=True, deflate_on_oom=True)
+    test_vm.launch()
+    resp = test_vm.query_balloon()
+    ori = int(resp["return"]["actual"])
+
+    resp = test_vm.balloon_set(value=814748368)
+    time.sleep(5)
+    test_vm.event_wait(name='BALLOON_CHANGED', timeout=2.0)
+    resp = test_vm.query_balloon()
+    set1 = int(resp["return"]["actual"])
+    assert set1 < 2524971008
+
+    resp = test_vm.balloon_set(value=2524971008)
+    time.sleep(5)
+    resp = test_vm.query_balloon()
+    logging.debug(resp)
+    set2 = int(resp["return"]["actual"])
+    assert ori == set2
+
+@pytest.mark.acceptance
+def test_standvm_balloon_active(standvm):
+    """
+    Test qmp command of setting balloon
+
+    steps:
+    1) launch standvm without active balloon device.
+    2) check if balloon device is activated.
+    """
+    test_vm = standvm
+    test_vm.basic_config()
+    test_vm.launch()
+    resp = test_vm.query_balloon()
+    assert resp["error"]["desc"] == "No balloon device has been activated"
+    resp = test_vm.balloon_set(value=2524971008)
+    assert resp["error"]["desc"] == "No balloon device has been activated"
diff --git a/tests/hydropper/testcases/standvm/functional/test_standvm_vhost_vsock.py b/tests/hydropper/testcases/standvm/functional/test_standvm_vhost_vsock.py
new file mode 100644
index 0000000..d96f3ff
--- /dev/null
+++ b/tests/hydropper/testcases/standvm/functional/test_standvm_vhost_vsock.py
@@ -0,0 +1,122 @@
+# Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved.
+#
+# StratoVirt is licensed under Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan
+# PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+#         http:#license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE 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.
+"""Test standvm vhost vsock"""
+
+import os
+import time
+import logging
+from subprocess import run
+from threading import Thread
+import pytest
+# Constants for nc-vsock setup and usage
+NC_VSOCK_DIR = '/tmp/nc-vsock'
+NC_VSOCK_CMD = os.path.join(NC_VSOCK_DIR, 'nc-vsock')
+NC_VSOCK_SRV_OUT = os.path.join(NC_VSOCK_DIR, "server_out.txt")
+NC_VSOCK_CLI_TXT = "/tmp/client_in.txt"
+VSOCK_PORT = 1234
+BLOB_SIZE = 2000
+
+
+def _check_vsock_enable(standvm):
+    """Check virtio rng device in Guest"""
+    _cmd = "ls /dev/vsock"
+    status, _ = standvm.serial_cmd(_cmd)
+    if status != 0:
+        status1, _ = standvm.serial_cmd("modprobe vhost_vsock")
+        if status1 != 0:
+            logging.debug("vsock can't enable in guest, ignore to test")
+            return False
+
+    status, _ = standvm.serial_cmd(_cmd)
+    assert  status == 0
+    return True
+
+
+def _start_vsock_server_in_guest(standvm):
+    """Start vsock server in guest"""
+    _cmd = "%s -l %s > %s" % (NC_VSOCK_CMD, VSOCK_PORT, NC_VSOCK_SRV_OUT)
+    try:
+        ssh_session = standvm.create_ssh_session()
+        _ = ssh_session.cmd(_cmd, timeout=10, internal_timeout=10)
+    finally:
+        if ssh_session is not None:
+            ssh_session.close()
+
+
+def _write_from_host_to_guest(nc_vsock_path, cid):
+    """Write data from host to guest"""
+    msg = "message from client"
+    _cmd = "echo %s > %s" % (msg, NC_VSOCK_CLI_TXT)
+    logging.debug("start to run %s", _cmd)
+    run(_cmd, shell=True, check=False)
+    _cmd = "%s %d %s < %s" % (nc_vsock_path, int(cid), VSOCK_PORT, NC_VSOCK_CLI_TXT)
+    logging.debug("start to run %s", _cmd)
+    output = run(_cmd, shell=True, check=False).stdout
+    logging.debug(output)
+    return msg
+
+
+def _get_recv_data_from_guest(standvm):
+    _cmd = "cat %s" % NC_VSOCK_SRV_OUT
+    try:
+        ssh_session = standvm.create_ssh_session()
+        _, output = ssh_session.cmd_status_output(_cmd)
+        logging.debug("recv data from guest is %s", output.strip())
+        return output.strip()
+    finally:
+        if ssh_session is not None:
+            ssh_session.close()
+
+@pytest.mark.acceptance
+def test_standvm_virtio_vsock(standvm, nc_vsock_path, test_session_root_path):
+    """Test virtio-rng device"""
+    test_vm = standvm
+    test_vm.basic_config(vsocknums=1)
+    test_vm.launch()
+
+    # check virtio-vsock device
+    if not _check_vsock_enable(test_vm):
+        pytest.skip("vhost-vsock init failed, skip this testcase")
+
+    # generate the blob file.
+    blob_path = os.path.join(test_session_root_path, "vsock-test.blob")
+    run("rm -rf %s; dd if=/dev/urandom of=%s bs=1 count=%d" %
+        (blob_path, blob_path, BLOB_SIZE), shell=True, check=True)
+    vm_blob_path = "/tmp/nc-vsock/test.blob"
+
+    #  set up a tmpfs drive on the guest, then we can copy the blob file there.
+    session = test_vm.create_ssh_session()
+    cmd = "mkdir -p /tmp/nc-vsock"
+    cmd += " && mount -t tmpfs tmpfs -o size={} /tmp/nc-vsock".format(
+        BLOB_SIZE + 1024*1024
+    )
+    status, _ = session.cmd_status_output(cmd)
+    session.close()
+    assert status == 0
+
+    # copy nc-vsock tool and the blob file to the guest.
+    test_vm.scp_file(nc_vsock_path, NC_VSOCK_CMD)
+    test_vm.scp_file(blob_path, vm_blob_path)
+
+    # start vsock server in guest
+    server = Thread(target=_start_vsock_server_in_guest, args=(test_vm,))
+    server.start()
+    time.sleep(5)
+
+    # write data from host to guest
+    msg = _write_from_host_to_guest(nc_vsock_path, test_vm.vsock_cid[0])
+
+    server.join(10)
+    if server.is_alive():
+        logging.error("The server thread is still running in the guest")
+    msg_recv = _get_recv_data_from_guest(test_vm)
+    assert msg == msg_recv
diff --git a/tests/hydropper/testcases/standvm/functional/test_standvm_virtio_blk.py b/tests/hydropper/testcases/standvm/functional/test_standvm_virtio_blk.py
new file mode 100644
index 0000000..e8c44de
--- /dev/null
+++ b/tests/hydropper/testcases/standvm/functional/test_standvm_virtio_blk.py
@@ -0,0 +1,65 @@
+# Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved.
+#
+# StratoVirt is licensed under Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan
+# PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+#         http:#license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE 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.
+"""Test standvm virtio block"""
+
+import os
+from subprocess import run
+import pytest
+
+def _get_lsblk_info(test_vm):
+    """
+    Get lsblk info
+
+    Returns:
+        {
+            "vdx": {"size": xx, "readonly": xx},
+        }
+    """
+    retdict = {}
+    if test_vm.ssh_session is not None:
+        _output = test_vm.ssh_session.cmd_output("lsblk")
+        for line in _output.split("\n"):
+            temp = line.split()
+            if len(temp) == 6:
+                name = temp[0]
+                size = temp[3]
+                readonly = temp[4]
+                if name not in retdict:
+                    retdict[name] = {"size": size, "readonly": readonly}
+
+    return retdict
+
+@pytest.mark.standvm_accept
+@pytest.mark.parametrize("readonly", [True, False])
+def test_standvm_virtio_blk_configuration(test_session_root_path, standvm, readonly):
+    """
+    Test virtio-blk configuration:
+
+    1) Generate a temp disk
+    2) Configure temp disk read_only and Add it to test_vm
+    3) Launch to test_vm and get block information
+    4) Assert temp disk readonly as expect
+    """
+    test_vm = standvm
+    temp_disk = os.path.join(test_session_root_path, "test_image")
+    run("rm -rf %s; dd if=/dev/zero of=%s bs=1M count=16" %
+        (temp_disk, temp_disk), shell=True, check=True)
+    test_vm.add_drive(path_on_host=temp_disk, read_only=readonly)
+    test_vm.launch()
+    _cmd = "ls /sys/bus/virtio/drivers/virtio_blk/ | grep -c virtio[0-9]*"
+    _, output = test_vm.serial_cmd(_cmd)
+
+    # check readonly
+    _cmd = "lsblk | grep vdb | awk '{print $5}'"
+    _, output = test_vm.serial_cmd(_cmd)
+    expect_ro = 1 if readonly else 0
+    assert int(output.split('\n')[0].strip()) == expect_ro
diff --git a/tests/hydropper/testcases/standvm/functional/test_standvm_virtio_net.py b/tests/hydropper/testcases/standvm/functional/test_standvm_virtio_net.py
new file mode 100644
index 0000000..2cadf26
--- /dev/null
+++ b/tests/hydropper/testcases/standvm/functional/test_standvm_virtio_net.py
@@ -0,0 +1,162 @@
+# Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved.
+#
+# StratoVirt is licensed under Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan
+# PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+#         http:#license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE 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.
+"""Test standvm net"""
+
+import logging
+from subprocess import run
+from subprocess import PIPE
+import pytest
+from utils.resources import NETWORKS
+
+def _start_iperf_on_guest(standvm):
+    """Start iperf in server mode on guest through serial session"""
+    _cmd = "which iperf3"
+    status, _ = standvm.serial_cmd(_cmd)
+    if status != 0:
+        logging.warning("iperf3 is not running, ignore to test")
+        return False
+
+    iperf_cmd = "iperf3 -sD -f KBytes\n"
+    status, _ = standvm.serial_cmd(iperf_cmd)
+    return not bool(status)
+
+
+def _run_iperf_on_local(iperf_cmd):
+    process = run(iperf_cmd, shell=True, stdout=PIPE, check=True)
+    return process.stdout.decode("utf-8")
+
+
+def _check_virtio_net_vectors(standvm, mqueue=1):
+    _cmd = "lspci |grep -w Virtio"
+    _, output = standvm.serial_cmd(_cmd)
+    index = 0
+    for line in output.splitlines():
+        if "network" in line.strip():
+            _check_vec_cmd = "grep -w virtio%d /proc/interrupts | wc -l" % index
+            _status, _output = standvm.serial_cmd(_check_vec_cmd)
+            vecs = int(_output.splitlines()[-2].strip())
+            expect_vecs = 2 * mqueue + 1
+            assert vecs == expect_vecs
+        index += 1
+
+
+@pytest.mark.standvm_accept
+@pytest.mark.parametrize("vhost_type", [None])
+def test_standvm_vnet_send_recv(standvm, vhost_type):
+    """
+    Test virtio-net send and recv:
+
+    1) Set vhost_type and launch to test_vm
+    2) Check nic numbers
+    3) Test the vnet by ping
+    4) Test TCP/UDP by iperf3
+    """
+    test_vm = standvm
+    test_vm.basic_config(vhost_type=vhost_type)
+    test_vm.launch()
+    # check nic numbers
+    _cmd = "ls /sys/bus/virtio/drivers/virtio_net/ | grep -c virtio[0-9]*"
+    _, output = test_vm.serial_cmd(_cmd)
+    logging.debug("virtio net output is %s", output)
+    virtio_net_number_in_guest = int(output.split('\n')[-2].strip())
+    assert virtio_net_number_in_guest == len(test_vm.get_interfaces_inner())
+
+    # test ICMP (ping to vm)
+    run("ping -c 2 %s" % test_vm.guest_ip, shell=True, check=True)
+    status, output = test_vm.serial_cmd("ping -c 2 %s" % NETWORKS.ipaddr)
+    assert status == 0
+    # test TCP/UDP by iperf3
+    if not _start_iperf_on_guest(test_vm):
+        return
+
+    iperf_cmd = "/usr/bin/iperf3 -c %s -t 5" % test_vm.guest_ip
+    output = _run_iperf_on_local(iperf_cmd)
+    logging.debug(output)
+
+    iperf_cmd = "iperf3 -c %s -u -t 5" % test_vm.guest_ip
+    output = _run_iperf_on_local(iperf_cmd)
+    logging.debug(output)
+
+    iperf_cmd = "iperf3 -c %s -t 5 -R" % test_vm.guest_ip
+    output = _run_iperf_on_local(iperf_cmd)
+    logging.debug(output)
+
+    iperf_cmd = "iperf3 -c %s -u -t 5 -R" % test_vm.guest_ip
+    output = _run_iperf_on_local(iperf_cmd)
+    logging.debug(output)
+
+
+@pytest.mark.system
+def test_standvm_vnet_stop_cont(standvm):
+    """
+    Test virtio-net stop and continue, check vnet with mac:
+
+    1) Launch to testvm
+    2) Test the vnet by ping
+    3) Restart vnet and execute step 2 again
+    4) Stop and continue test_vm
+    5) Execute step 2 again
+    """
+    test_vm = standvm
+    test_vm.basic_config()
+    test_vm.launch()
+    # test ICMP (ping to vm)
+    run("ping -c 2 %s" % test_vm.guest_ip, shell=True, check=True)
+    status, _ = test_vm.serial_cmd("ping -c 2 %s" % NETWORKS.ipaddr)
+    assert status == 0
+    test_vm.serial_cmd("systemctl restart network")
+    # test ICMP (ping to vm)
+    run("ping -c 2 %s" % test_vm.guest_ip, shell=True, check=True)
+    status, _ = test_vm.serial_cmd("ping -c 2 %s" % NETWORKS.ipaddr)
+    assert status == 0
+    test_vm.stop()
+    test_vm.event_wait(name='STOP')
+    test_vm.cont()
+    test_vm.event_wait(name='RESUME')
+    # test ICMP (ping to vm)
+    run("ping -c 2 %s" % test_vm.guest_ip, shell=True, check=True)
+    status, _ = test_vm.serial_cmd("ping -c 2 %s" % NETWORKS.ipaddr)
+    assert status == 0
+
+
+@pytest.mark.standvm_accept
+@pytest.mark.parametrize("usemac", [True, False])
+def test_standvm_with_multi_vnet(standvm, usemac):
+    """
+    Test standvm with multi vnet:
+
+    1) Configure some vnets for test_vm
+    2) Check mac address
+    3) Check nic numbers
+    4) Test vnets by ping
+    5) Delete vnet from test_vm
+    """
+    test_vm = standvm
+    test_vm.basic_config(vnetnums=2, withmac=usemac)
+    test_vm.launch()
+    # check mac address
+    _cmd = "ls"
+    for tap in test_vm.taps:
+        _cmd += " && (ip addr | grep %s) " % tap["mac"]
+    status = test_vm.serial_session.run_func("cmd_status", _cmd)
+    expect_status = 0 if usemac else 1
+    assert status == expect_status
+
+    # check nic numbers
+    _cmd = "ls /sys/bus/virtio/drivers/virtio_net/ | grep -c virtio[0-9]*"
+    _, output = test_vm.serial_cmd(_cmd)
+    virtio_net_number_in_guest = int(output.split('\n')[-2].strip())
+    assert virtio_net_number_in_guest == len(test_vm.get_interfaces_inner())
+    # test ICMP (ping to vm)
+    run("ping -c 2 %s" % test_vm.guest_ip, shell=True, check=True)
+    status, output = test_vm.serial_cmd("ping -c 2 %s" % NETWORKS.ipaddr)
+    assert status == 0
diff --git a/tests/hydropper/testcases/standvm/functional/test_standvm_virtio_rng.py b/tests/hydropper/testcases/standvm/functional/test_standvm_virtio_rng.py
new file mode 100644
index 0000000..95dd13c
--- /dev/null
+++ b/tests/hydropper/testcases/standvm/functional/test_standvm_virtio_rng.py
@@ -0,0 +1,75 @@
+# Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved.
+#
+# StratoVirt is licensed under Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan
+# PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+#         http:#license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE 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.
+
+"""Test standvm rng"""
+
+import logging
+import pytest
+
+def _check_virtio_rng_device(test_vm):
+    """Check virtio rng device in Guest"""
+    _cmd = "ls /dev/hwrng"
+    status, _ = test_vm.serial_cmd(_cmd)
+    assert status == 0
+
+    rng_files = (
+        "/sys/devices/virtual/misc/hw_random/rng_available",
+        "/sys/devices/virtual/misc/hw_random/rng_current")
+    _, rng_avail = test_vm.serial_cmd("cat %s" % rng_files[0])
+    _, rng_curr = test_vm.serial_cmd("cat %s" % rng_files[1])
+    rng_avail = rng_avail.strip()
+    rng_curr = rng_curr.strip()
+    logging.debug("rng avail: %s, rng current: %s", rng_avail, rng_curr)
+    if not rng_curr.count("virtio") or rng_curr not in rng_avail:
+        pytest.xfail(reason="Failed to check rng file on guest")
+
+    _cmd = ("dd if=/dev/hwrng of=rng.test count=100 && rm -f rng.test")
+    try:
+        ret, _ = test_vm.serial_cmd(_cmd)
+        assert ret == 0
+    finally:
+        test_vm.serial_cmd("rm -f rng.test")
+
+@pytest.mark.standvm_accept
+def test_standvm_virtio_rng(standvm):
+    test_vm = standvm
+    test_vm.basic_config(rng=True)
+    test_vm.launch()
+
+    # check virtio rng device
+    _check_virtio_rng_device(test_vm)
+
+    test_vm.stop()
+    test_vm.event_wait(name='STOP')
+    test_vm.cont()
+    test_vm.event_wait(name='RESUME')
+
+    # check virtio rng device
+    _check_virtio_rng_device(test_vm)
+
+@pytest.mark.standvm_accept
+@pytest.mark.parametrize("max_bytes", [1000000000, 200000000])
+def test_standvm_virtio_rng_bytes_limit(standvm, max_bytes):
+    test_vm = standvm
+    test_vm.basic_config(rng=True, max_bytes=max_bytes)
+    test_vm.launch()
+
+    # check virtio rng device
+    _check_virtio_rng_device(test_vm)
+
+    test_vm.stop()
+    test_vm.event_wait(name='STOP')
+    test_vm.cont()
+    test_vm.event_wait(name='RESUME')
+
+    # check virtio rng device
+    _check_virtio_rng_device(test_vm)
diff --git a/tests/hydropper/testcases/standvm/functional/test_standvm_vmlife.py b/tests/hydropper/testcases/standvm/functional/test_standvm_vmlife.py
new file mode 100644
index 0000000..74c1d51
--- /dev/null
+++ b/tests/hydropper/testcases/standvm/functional/test_standvm_vmlife.py
@@ -0,0 +1,69 @@
+# Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved.
+#
+# StratoVirt is licensed under Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan
+# PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+#         http:#license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE 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.
+"""Test standvm vmlife"""
+
+import logging
+import pytest
+from utils import utils_qmp
+from utils.config import CONFIG
+from utils.exception import QMPTimeoutError
+
+def _get_guest_hwinfo(test_vm):
+    """
+    Get guest hwinfo via ssh_session
+
+    Returns:
+        {"cpu": {"vcpu_count": xx, "maxvcpu": xx},
+        "mem": {"memsize": xx, "maxmem": xx},
+        "virtio": {"virtio_blk": [{"name": "virtio0"}],
+                "virtio_console": [{"name": "virtio1"}],
+                "virtio_net": [{"name": "virtio2"}],
+                "virtio_rng": [{"name": "virtio3"}],
+                }
+        }
+    """
+    retdict = {"cpu": {}, "mem": {}, "virtio": {}}
+    if test_vm.ssh_session is not None:
+        vcpu_count = int(test_vm.ssh_session.cmd_output("grep -c processor /proc/cpuinfo"))
+        memsize = int(test_vm.ssh_session.cmd_output("grep MemTotal /proc/meminfo | awk '{print $2}'"))
+        retdict["cpu"] = {"vcpu_count": vcpu_count}
+        retdict["mem"] = {"memsize": memsize}
+        # ignore virtio_rng device now
+        for dev in ["virtio_blk", "virtio_net", "virtio_console"]:
+            devdir = "/sys/bus/virtio/drivers/%s" % dev
+            _cmd = "test -d %s && ls %s | grep virtio" % (devdir, devdir)
+            virtiodevs = test_vm.ssh_session.cmd_output(_cmd).strip().split()
+            for virtiodev in virtiodevs:
+                _tempdev = {"name": virtiodev}
+                if dev not in retdict["virtio"]:
+                    retdict["virtio"][dev] = list()
+                retdict["virtio"][dev].append(_tempdev)
+
+    return retdict
+
+@pytest.mark.standvm_accept
+@pytest.mark.parametrize("vcpu_count, memsize, vnetnums",
+                         [(1, 1024, 1),
+                          (2, 2048, 2)])
+def test_standvm_start(standvm, vcpu_count, memsize, vnetnums):
+    """Test a normal microvm start"""
+    test_vm = standvm
+    test_vm.basic_config(vcpu_count=vcpu_count, mem_size=memsize, vnetnums=vnetnums)
+    test_vm.launch()
+    vmhwinfo = _get_guest_hwinfo(test_vm)
+    logging.debug("current vmhwinfo is %s", vmhwinfo)
+    assert vmhwinfo["cpu"]["vcpu_count"] == vcpu_count
+    assert vmhwinfo["mem"]["memsize"] > (memsize * 1024 * 90 / 100)
+    assert len(vmhwinfo["virtio"]["virtio_blk"]) == 1
+    assert len(vmhwinfo["virtio"]["virtio_net"]) == vnetnums
+    assert len(vmhwinfo["virtio"]["virtio_console"]) == 1
+    test_vm.shutdown()
diff --git a/tests/hydropper/utils/config.py b/tests/hydropper/utils/config.py
index 9c3ad7a..cb66147 100644
--- a/tests/hydropper/utils/config.py
+++ b/tests/hydropper/utils/config.py
@@ -92,6 +92,7 @@ class ParserConfig(Singleton):
                                                        "true") == "true")
         self.rust_san_check = bool(self.get_option("stratovirt.params", "RUST_SAN_CHECK",
                                                    "false") == "true")
+        self.code_storage_file = self.get_option("stratovirt.params", "CODE_STORAGE_FILE", None)
 
 
         # parser network params
diff --git a/tests/hydropper/virt/basevm.py b/tests/hydropper/virt/basevm.py
index b360d97..6c95c53 100644
--- a/tests/hydropper/virt/basevm.py
+++ b/tests/hydropper/virt/basevm.py
@@ -103,6 +103,7 @@ class BaseVM:
         self.vnetnums = vnetnums
         self.rng = rng
         self.max_bytes = max_bytes
+        self.rng_files = '/dev/urandom'
         self.vsock_cid = list()
         self.vsocknums = vsocknums
         self.withmac = False
diff --git a/tests/hydropper/virt/microvm.py b/tests/hydropper/virt/microvm.py
index 7b83989..e481a26 100644
--- a/tests/hydropper/virt/microvm.py
+++ b/tests/hydropper/virt/microvm.py
@@ -172,7 +172,7 @@ class MicroVM(BaseVM):
                 args.extend(['-netdev', _temp_net_args, '-device', _temp_device_args])
 
         if self.rng:
-            _temp_rng_args = 'rng-random,id=objrng0,filename=/dev/urandom'
+            _temp_rng_args = 'rng-random,id=objrng0,filename=%s' % self.rng_files
             if self.max_bytes == 0:
                 _temp_device_args = 'virtio-rng-device,rng=objrng0'
             else:
diff --git a/tests/hydropper/virt/standvm.py b/tests/hydropper/virt/standvm.py
index a57af85..6e40569 100644
--- a/tests/hydropper/virt/standvm.py
+++ b/tests/hydropper/virt/standvm.py
@@ -47,7 +47,7 @@ class StandVM(BaseVM):
         self.memsize = memsize
         self.multifunction = {"net": False, "console": False, "vsock": False,
                               "balloon": False, "rng": False, "pcie_root_port": False, "vfio": False}
-        self.code_storage_file = None
+        self.code_storage_file = CONFIG.code_storage_file
         self.code_storage_readonly = True
         self.data_storage_file = None
         self.inited = False
@@ -183,11 +183,12 @@ class StandVM(BaseVM):
                 args.extend(['-netdev', _temp_net_args, '-device', _temp_device_args])
 
         if self.rng:
-            _temp_rng_args = 'rng-random,id=objrng0,filename=/dev/urandom'
+            self.bus_slot[0] = 'rng'
+            _temp_rng_args = 'rng-random,id=objrng0,filename=%s' % self.rng_files
             if self.max_bytes == 0:
-                _temp_device_args = 'virtio-rng-pci,rng=objrng0'
+                _temp_device_args = 'virtio-rng-pci,rng=objrng0,bus=pcie.0,addr=0x9.0x0'
             else:
-                _temp_device_args = 'virtio-rng-pci,rng=objrng0,max-bytes=%s,period=1000,id=pcie.0,addr=0x1.0x0' % self.max_bytes
+                _temp_device_args = 'virtio-rng-pci,rng=objrng0,max-bytes=%s,period=1000,bus=pcie.0,addr=0x9.0x0' % self.max_bytes
             if self.multifunction["rng"]:
                 _temp_device_args += ",multifunction=on"
             args.extend(['-object', _temp_rng_args, '-device', _temp_device_args])
@@ -207,9 +208,9 @@ class StandVM(BaseVM):
             self.bus_slot[2] = 'balloon'
             _temp_balloon_args = "virtio-balloon-pci,bus=pcie.0,addr=0x2.0x0"
             if self.deflate_on_oom:
-                _temp_balloon_args = 'deflate-on-oom=true'
+                _temp_balloon_args += ',deflate-on-oom=true'
             else:
-                _temp_balloon_args = 'deflate-on-oom=false'
+                _temp_balloon_args += ',deflate-on-oom=false'
             if self.multifunction["balloon"]:
                 _temp_balloon_args += ",multifunction=on"
             args.extend(['-device', _temp_balloon_args])
-- 
2.30.0

