Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file removed tests/artifacts/host-companions/vsock-client-echo
Binary file not shown.
1 change: 1 addition & 0 deletions tests/ci/cases/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ edition = "2021"

[dependencies]
test-utils = { path = "../test-utils" }
vsock = "0.5"
52 changes: 52 additions & 0 deletions tests/ci/cases/tests/vsock_echo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//! Starry CI 测试用例模板。
//!
//! 提示:
//! - 根据需要从 `test_utils` 引入工具函数,例如:
//! `use test_utils::{append_bytes, read_bytes, temp_file, write_bytes};`
//! - 使用 `assert!`/`assert_eq!` 等断言表达预期;失败时测试会自动中断并输出原因。

use std::io::{Read, Write};
use vsock::{VsockAddr, VsockListener, VMADDR_CID_ANY};

const DATA_SIZE: usize = 100 * 1024; // 100KB
const PORT: u32 = 1234;

#[test]
fn vsock_echo_smoke() {
// 1. bind the address
let addr = VsockAddr::new(VMADDR_CID_ANY, PORT);
let listener = VsockListener::bind(&addr).expect("VSOCK-GUEST: Failed to bind to vsock");

// 2. wait for client connection
let (mut stream, client_addr) = listener.accept().expect("VSOCK-GUEST: accept failed");
println!("VSOCK-GUEST: Accepted connection from CID:{} Port:{}", client_addr.cid(), client_addr.port());

// --- Phase 1: Receive from Host ---
let mut received_count = 0;
let mut buffer = [0u8; 4096]; // 4KB buffer
while received_count < DATA_SIZE {
let n = stream.read(&mut buffer).expect("VSOCK-GUEST: read failed");
assert!(n > 0, "VSOCK-GUEST: Guest disconnected unexpectedly during Phase 1");
assert!(buffer[0..n].iter().all(|&x| x == 65u8), "VSOCK-GUEST: Guest received invalid data during Phase 1");
received_count += n;
}
// Send the received length to host for confirmation
let len_bytes = (received_count as u64).to_be_bytes();
stream.write_all(&len_bytes).expect("VSOCK-GUEST: failed to send ack len");

// --- Phase 2: Send to Host ---
let chunk = [66u8; 1024]; // 1KB of 'B'
let mut sent_count = 0;
while sent_count < DATA_SIZE {
stream.write_all(&chunk).expect("VSOCK-GUEST: write failed");
sent_count += chunk.len();
}

// wait for ack message from host
println!("VSOCK-GUEST: [Phase 2] Waiting for Host ack...");
let mut ack_buf = [0u8; 8];
stream.read_exact(&mut ack_buf).expect("VSOCK-GUEST: failed to read ack len");
let ack_len = u64::from_be_bytes(ack_buf);
assert_eq!(ack_len, sent_count as u64, "VSOCK-GUEST: Guest received wrong amount of data!");

}
37 changes: 35 additions & 2 deletions tests/ci/run_case.sh
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,45 @@ COMMAND_TIMEOUT="${STARRY_CASE_TIMEOUT_SECS:-600}"
VM_STDOUT="${CASE_ARTIFACT_DIR}/vm-${RUN_ID}.log"
VM_STDERR="${CASE_ARTIFACT_DIR}/vm-${RUN_ID}.err"

echo "[${CASE_LABEL}] 启动 StarryOS 执行 ${DEST_PATH}" >&2
if ! python3 "${VM_RUNNER}" \
# Build VM runner command with optional host companion
VM_RUNNER_ARGS=(
--root "${STARRYOS_ROOT}" \
--arch "${ARCH}" \
--command "${DEST_PATH}" \
--command-timeout "${COMMAND_TIMEOUT}" \
)

# Add host companion if specified
if [[ -n "${STARRY_HOST_COMPANION:-}" ]]; then
HOST_COMPANION_PATH="${STARRY_HOST_COMPANION}"
if [[ "${HOST_COMPANION_PATH}" != /* ]]; then
HOST_COMPANION_PATH="${WORKSPACE}/${HOST_COMPANION_PATH}"
fi

if [[ ! -f "${HOST_COMPANION_PATH}" ]]; then
echo "[${CASE_LABEL}] host companion not found: ${HOST_COMPANION_PATH}" >&2
exit 1
fi

if [[ ! -x "${HOST_COMPANION_PATH}" ]]; then
echo "[${CASE_LABEL}] host companion not executable: ${HOST_COMPANION_PATH}" >&2
exit 1
fi

echo "[${CASE_LABEL}] using host companion: ${HOST_COMPANION_PATH}" >&2
VM_RUNNER_ARGS+=(--host-companion "${HOST_COMPANION_PATH}")

if [[ -n "${STARRY_COMPANION_DELAY:-}" ]]; then
VM_RUNNER_ARGS+=(--companion-delay "${STARRY_COMPANION_DELAY}")
fi

if [[ -n "${STARRY_COMPANION_TIMEOUT:-}" ]]; then
VM_RUNNER_ARGS+=(--companion-timeout "${STARRY_COMPANION_TIMEOUT}")
fi
fi

echo "[${CASE_LABEL}] 启动 StarryOS 执行 ${DEST_PATH}" >&2
if ! python3 "${VM_RUNNER}" "${VM_RUNNER_ARGS[@]}" \
2> >(tee "${VM_STDERR}" >&2) | tee "${VM_STDOUT}"; then
echo "[${CASE_LABEL}] 虚拟机执行失败,详见 ${VM_STDERR}" >&2
# Your change: find the exact error case
Expand Down
39 changes: 39 additions & 0 deletions tests/ci/run_vsock_case.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
# Wrapper script for running VSOCK tests with host companion
set -euo pipefail

if [[ $# -lt 1 ]]; then
echo "用法: $0 <binary-name> [companion-name]" >&2
exit 1
fi

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WORKSPACE="$(cd "${SCRIPT_DIR}/../.." && pwd)"

BINARY_NAME="$1"
COMPANION_NAME="$2"

# Ensure vhost-vsock device is accessible for VSOCK tests
#if [[ -e /dev/vhost-vsock ]]; then
# sudo chmod 666 /dev/vhost-vsock || true
#fi
# todo!(): 目前 CI 环境不确定有没有 /dev/vhost-vsock,先注释掉上述代码,等以后有了再放开

# Build host companion and verify it exists
COMPANION_PATH="${WORKSPACE}/artifacts/host-companions/${COMPANION_NAME}"
echo "[vsock-test] Building host companion: ${COMPANION_NAME}" >&2
"${WORKSPACE}/tests/ci-test-iter/host-companions/build.sh"

if [[ ! -x "${COMPANION_PATH}" ]]; then
echo "[vsock-test] Failed to build or find host companion: ${COMPANION_PATH}" >&2
exit 1
fi

# Export host companion path for run_case.sh
export STARRY_HOST_COMPANION="${COMPANION_PATH}"
export STARRY_COMPANION_DELAY="${STARRY_COMPANION_DELAY:-3}"
export STARRY_COMPANION_TIMEOUT="${STARRY_COMPANION_TIMEOUT:-30}"

# Run the actual test case
exec "${SCRIPT_DIR}/run_case.sh" "${BINARY_NAME}" "${COMPANION_NAME}"

6 changes: 6 additions & 0 deletions tests/ci/suite.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,9 @@ name = "libc-test-regression"
description = "libc-test regression 模块测试"
path = "tests/ci/run_libc_test.sh"
args = ["regression"]

[[cases]]
name = "vsock-echo"
description = "测试 VSOCK 通信:host 客户端连接到 guest 服务端并发送数据"
path = "tests/ci/run_vsock_case.sh"
args = ["vsock_echo", "vsock-client-echo"]
Loading