246 lines
7.0 KiB
Rust
246 lines
7.0 KiB
Rust
//! Network socket API tests
|
|
//!
|
|
//! Tests for socket, bind, listen, accept, connect system calls
|
|
//! and zero-copy I/O optimizations
|
|
|
|
use crate::tests::{TestResult, test_assert, test_assert_eq};
|
|
|
|
/// Test socket creation
|
|
pub fn test_socket_creation() -> TestResult {
|
|
// Test TCP socket creation
|
|
let args = [
|
|
crate::posix::AF_INET as u64, // domain
|
|
crate::posix::SOCK_STREAM as u64, // type
|
|
0u64, // protocol (default)
|
|
];
|
|
|
|
let result = crate::syscalls::dispatch(0x4000, &args); // socket
|
|
// Should return a valid file descriptor
|
|
test_assert!(result >= 0, "socket creation should return valid FD");
|
|
|
|
// Test UDP socket creation
|
|
let args = [
|
|
crate::posix::AF_INET as u64, // domain
|
|
crate::posix::SOCK_DGRAM as u64, // type
|
|
0u64, // protocol (default)
|
|
];
|
|
|
|
let result = crate::syscalls::dispatch(0x4000, &args); // socket
|
|
test_assert!(result >= 0, "UDP socket creation should return valid FD");
|
|
|
|
// Test invalid domain
|
|
let args = [
|
|
999u64, // invalid domain
|
|
crate::posix::SOCK_STREAM as u64,
|
|
0u64,
|
|
];
|
|
|
|
let result = crate::syscalls::dispatch(0x4000, &args);
|
|
test_assert!(result < 0, "socket with invalid domain should return error");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test socket bind
|
|
pub fn test_socket_bind() -> TestResult {
|
|
// Create a socket first
|
|
let args = [
|
|
crate::posix::AF_INET as u64,
|
|
crate::posix::SOCK_STREAM as u64,
|
|
0u64,
|
|
];
|
|
|
|
let fd = crate::syscalls::dispatch(0x4000, &args);
|
|
if fd < 0 {
|
|
return Err("Failed to create socket for bind test".into());
|
|
}
|
|
|
|
// Bind to localhost:8080
|
|
let mut sockaddr = crate::posix::Sockaddr {
|
|
sa_family: crate::posix::AF_INET as u16,
|
|
sa_data: [0; 14],
|
|
};
|
|
// Port 8080 in network byte order
|
|
sockaddr.sa_data[0] = 0x1F;
|
|
sockaddr.sa_data[1] = 0x90; // 8080 = 0x1F90
|
|
// IP 127.0.0.1
|
|
sockaddr.sa_data[2] = 127;
|
|
sockaddr.sa_data[3] = 0;
|
|
sockaddr.sa_data[4] = 0;
|
|
sockaddr.sa_data[5] = 1;
|
|
|
|
let args = [
|
|
fd as u64,
|
|
&sockaddr as *const crate::posix::Sockaddr as u64,
|
|
core::mem::size_of::<crate::posix::Sockaddr>() as u64,
|
|
];
|
|
|
|
let result = crate::syscalls::dispatch(0x4001, &args); // bind
|
|
// Should succeed or return error if address already in use
|
|
test_assert!(result == 0 || result < 0, "bind should return success or error");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test socket listen
|
|
pub fn test_socket_listen() -> TestResult {
|
|
// Create and bind a socket first
|
|
let args = [
|
|
crate::posix::AF_INET as u64,
|
|
crate::posix::SOCK_STREAM as u64,
|
|
0u64,
|
|
];
|
|
|
|
let fd = crate::syscalls::dispatch(0x4000, &args);
|
|
if fd < 0 {
|
|
return Err("Failed to create socket for listen test".into());
|
|
}
|
|
|
|
// Bind socket
|
|
let mut sockaddr = crate::posix::Sockaddr {
|
|
sa_family: crate::posix::AF_INET as u16,
|
|
sa_data: [0; 14],
|
|
};
|
|
sockaddr.sa_data[0] = 0x1F;
|
|
sockaddr.sa_data[1] = 0x90;
|
|
sockaddr.sa_data[2] = 127;
|
|
sockaddr.sa_data[3] = 0;
|
|
sockaddr.sa_data[4] = 0;
|
|
sockaddr.sa_data[5] = 1;
|
|
|
|
let args = [
|
|
fd as u64,
|
|
&sockaddr as *const crate::posix::Sockaddr as u64,
|
|
core::mem::size_of::<crate::posix::Sockaddr>() as u64,
|
|
];
|
|
|
|
let bind_result = crate::syscalls::dispatch(0x4001, &args);
|
|
if bind_result < 0 {
|
|
// Skip test if bind fails
|
|
return Ok(());
|
|
}
|
|
|
|
// Test listen with valid backlog
|
|
let args = [
|
|
fd as u64,
|
|
10u64, // backlog
|
|
];
|
|
|
|
let result = crate::syscalls::dispatch(0x4002, &args); // listen
|
|
test_assert!(result == 0 || result < 0, "listen should return success or error");
|
|
|
|
// Test listen with invalid backlog
|
|
let args = [
|
|
fd as u64,
|
|
200u64, // backlog too large
|
|
];
|
|
|
|
let result = crate::syscalls::dispatch(0x4002, &args);
|
|
// Should return error for invalid backlog
|
|
test_assert!(result < 0, "listen with invalid backlog should return error");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test socket connect
|
|
pub fn test_socket_connect() -> TestResult {
|
|
// Create a socket
|
|
let args = [
|
|
crate::posix::AF_INET as u64,
|
|
crate::posix::SOCK_STREAM as u64,
|
|
0u64,
|
|
];
|
|
|
|
let fd = crate::syscalls::dispatch(0x4000, &args);
|
|
if fd < 0 {
|
|
return Err("Failed to create socket for connect test".into());
|
|
}
|
|
|
|
// Connect to localhost:8080
|
|
let mut sockaddr = crate::posix::Sockaddr {
|
|
sa_family: crate::posix::AF_INET as u16,
|
|
sa_data: [0; 14],
|
|
};
|
|
sockaddr.sa_data[0] = 0x1F;
|
|
sockaddr.sa_data[1] = 0x90;
|
|
sockaddr.sa_data[2] = 127;
|
|
sockaddr.sa_data[3] = 0;
|
|
sockaddr.sa_data[4] = 0;
|
|
sockaddr.sa_data[5] = 1;
|
|
|
|
let args = [
|
|
fd as u64,
|
|
&sockaddr as *const crate::posix::Sockaddr as u64,
|
|
core::mem::size_of::<crate::posix::Sockaddr>() as u64,
|
|
];
|
|
|
|
let result = crate::syscalls::dispatch(0x4004, &args); // connect
|
|
// Should return success or error (connection refused if no server)
|
|
test_assert!(result == 0 || result < 0, "connect should return success or error");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test zero-copy send optimization
|
|
pub fn test_zero_copy_send() -> TestResult {
|
|
// Create a socket
|
|
let args = [
|
|
crate::posix::AF_INET as u64,
|
|
crate::posix::SOCK_STREAM as u64,
|
|
0u64,
|
|
];
|
|
|
|
let fd = crate::syscalls::dispatch(0x4000, &args);
|
|
if fd < 0 {
|
|
return Err("Failed to create socket for zero-copy test".into());
|
|
}
|
|
|
|
// Test send with large buffer (>4KB) - should use zero-copy path
|
|
let large_buffer = [0u8; 8192]; // 8KB buffer
|
|
|
|
let args = [
|
|
fd as u64,
|
|
large_buffer.as_ptr() as u64,
|
|
large_buffer.len() as u64,
|
|
0u64, // flags
|
|
];
|
|
|
|
let result = crate::syscalls::dispatch(0x4005, &args); // send
|
|
// Should handle large buffer (may return error if not connected, but shouldn't panic)
|
|
test_assert!(result >= 0 || result < 0, "send with large buffer should not panic");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test zero-copy receive optimization
|
|
pub fn test_zero_copy_recv() -> TestResult {
|
|
// Create a socket
|
|
let args = [
|
|
crate::posix::AF_INET as u64,
|
|
crate::posix::SOCK_STREAM as u64,
|
|
0u64,
|
|
];
|
|
|
|
let fd = crate::syscalls::dispatch(0x4000, &args);
|
|
if fd < 0 {
|
|
return Err("Failed to create socket for zero-copy recv test".into());
|
|
}
|
|
|
|
// Test recv with large buffer (>4KB) - should use zero-copy path
|
|
let mut large_buffer = [0u8; 8192]; // 8KB buffer
|
|
|
|
let args = [
|
|
fd as u64,
|
|
large_buffer.as_mut_ptr() as u64,
|
|
large_buffer.len() as u64,
|
|
0u64, // flags
|
|
];
|
|
|
|
let result = crate::syscalls::dispatch(0x4006, &args); // recv
|
|
// Should handle large buffer (may return 0 if no data, but shouldn't panic)
|
|
test_assert!(result >= 0, "recv with large buffer should not panic");
|
|
|
|
Ok(())
|
|
}
|
|
|