os/kernel/tests/network_socket_tests.rs

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(())
}