Skip to content
Snippets Groups Projects
Commit 38cf5b15 authored by Alan Somers's avatar Alan Somers
Browse files

Add an integration test for the cmsg(3) functions.

Since these are defined in C as macros, they must be reimplemented in
libc as Rust functions.  They're hard to get exactly right, and they
vary from platform to platform.  The test builds custom C code that uses
the real macros, and compares its output to the Rust versions' output
for various inputs.

Skip the CMSG_NXTHDR test on sparc64 linux because it hits a Bus Error.

Issue #1239

Skip the entire cmsg test program on s390x because it dumps core
seemingly before the kernel finishes booting.

Issue #1240
parent eddc8d34
No related branches found
No related tags found
No related merge requests found
......@@ -47,7 +47,8 @@ fn find_ok(input: &mut Read, tx: mpsc::Sender<()>) {
for line in BufReader::new(input).lines() {
let line = line.unwrap();
println!("{}", line);
if line.starts_with("PASSED ") && line.contains(" tests") {
if (line.starts_with("PASSED ") && line.contains(" tests")) ||
line.starts_with("test result: ok"){
tx.send(()).unwrap();
}
}
......
......@@ -129,8 +129,11 @@ fn run_app_on_simulator() {
let stdout = String::from_utf8_lossy(&output.stdout);
let passed = stdout.lines()
.find(|l| l.contains("PASSED"))
.map(|l| l.contains("tests"))
.find(|l|
(l.contains("PASSED") &&
l.contains("tests")) ||
l.contains("test result: ok")
)
.unwrap_or(false);
println!("Shutting down simulator");
......
......@@ -77,7 +77,7 @@ if [ "$QEMU" != "" ]; then
-net user \
-nographic \
-vga none 2>&1 | tee "${CARGO_TARGET_DIR}/out.log"
exec grep "^PASSED .* tests" "${CARGO_TARGET_DIR}/out.log"
exec egrep "^(PASSED)|(test result: ok)" "${CARGO_TARGET_DIR}/out.log"
fi
# FIXME: x86_64-unknown-linux-gnux32 fail to compile without --release
......
......@@ -38,8 +38,10 @@ fn main() {
String::from_utf8_lossy(&output.stderr));
let stdout = String::from_utf8_lossy(&output.stdout);
let mut lines = stdout.lines().filter(|l| l.starts_with("PASSED "));
if !lines.any(|l| l.contains(" tests")) {
let passed = stdout.lines().find(|l|
(l.starts_with("PASSED ") && l.contains(" tests")) ||
l.starts_with("test result: ok")
).unwrap_or_else(|| {
panic!("failed to find successful test run");
}
});
}
......@@ -5,7 +5,18 @@ set -e
arch=$1
prog=$2
# Skip cmsg test on linux-s390x
# https://github.com/rust-lang/libc/issues/1240
if [ "$arch" = "s390x" ]; then
progbasename=`basename $prog`
if [ "${progbasename%%-*}" = "cmsg" ]; then
exit 0
fi
fi
cd /qemu/init
echo "#!/bin/sh\n/prog --color=never" > run_prog.sh
chmod +x run_prog.sh
cp -f $2 prog
find . | cpio --create --format='newc' --quiet | gzip > ../initrd.gz
cd ..
......@@ -15,9 +26,9 @@ timeout 30s qemu-system-$arch \
-nographic \
-kernel kernel \
-initrd initrd.gz \
-append init=/prog > output || true
-append init=/run_prog.sh > output || true
# remove kernel messages
tr -d '\r' < output | egrep -v '^\['
grep PASSED output > /dev/null
egrep "(PASSED)|(test result: ok)" output > /dev/null
......@@ -9,6 +9,7 @@ path = ".."
default-features = false
[build-dependencies]
cc = "1.0"
ctest = "0.2.8"
[features]
......@@ -27,3 +28,7 @@ name = "linux-fcntl"
path = "test/linux_fcntl.rs"
harness = false
[[test]]
name = "cmsg"
path = "test/cmsg.rs"
harness = true
#![deny(warnings)]
extern crate cc;
extern crate ctest;
use std::env;
fn main() {
#[cfg(unix)]
fn do_cc() {
cc::Build::new()
.file("src/cmsg.c")
.compile("cmsg");
}
#[cfg(not(unix))]
fn do_cc() {
}
fn do_ctest() {
let target = env::var("TARGET").unwrap();
let aarch64 = target.contains("aarch64");
let i686 = target.contains("i686");
......@@ -975,3 +986,8 @@ fn main() {
}
cfg.generate("../src/lib.rs", "linux_fcntl.rs");
}
fn main() {
do_cc();
do_ctest();
}
#include <sys/param.h>
#include <sys/socket.h>
// Since the cmsg(3) macros are macros instead of functions, they aren't
// available to FFI. libc must reimplement them, which is error-prone. This
// file provides FFI access to the actual macros so they can be tested against
// the Rust reimplementations.
struct cmsghdr *cmsg_firsthdr(struct msghdr *msgh) {
return CMSG_FIRSTHDR(msgh);
}
struct cmsghdr *cmsg_nxthdr(struct msghdr *msgh, struct cmsghdr *cmsg) {
return CMSG_NXTHDR(msgh, cmsg);
}
size_t cmsg_space(size_t length) {
return CMSG_SPACE(length);
}
size_t cmsg_len(size_t length) {
return CMSG_LEN(length);
}
unsigned char *cmsg_data(struct cmsghdr *cmsg) {
return CMSG_DATA(cmsg);
}
//! Compare libc's CMSG(3) family of functions against the actual C macros, for
//! various inputs.
extern crate libc;
#[cfg(unix)]
mod t {
use libc::{self, c_uchar, c_uint, c_void, cmsghdr, msghdr};
use std::mem;
extern {
pub fn cmsg_firsthdr(msgh: *const msghdr) -> *mut cmsghdr;
pub fn cmsg_nxthdr(mhdr: *const msghdr,
cmsg: *const cmsghdr) -> *mut cmsghdr;
pub fn cmsg_space(length: c_uint) -> usize;
pub fn cmsg_len(length: c_uint) -> usize;
pub fn cmsg_data(cmsg: *const cmsghdr) -> *mut c_uchar;
}
#[test]
fn test_cmsg_data() {
for l in 0..128 {
let pcmsghdr = l as *const cmsghdr;
unsafe {
assert_eq!(libc::CMSG_DATA(pcmsghdr), cmsg_data(pcmsghdr));
}
}
}
#[test]
fn test_cmsg_firsthdr() {
let mut mhdr: msghdr = unsafe{mem::zeroed()};
mhdr.msg_control = 0xdeadbeef as *mut c_void;
let pmhdr = &mhdr as *const msghdr;
for l in 0..128 {
mhdr.msg_controllen = l;
unsafe {
assert_eq!(libc::CMSG_FIRSTHDR(pmhdr), cmsg_firsthdr(pmhdr));
}
}
}
#[test]
fn test_cmsg_len() {
for l in 0..128 {
unsafe {
assert_eq!(libc::CMSG_LEN(l) as usize, cmsg_len(l));
}
}
}
// Skip on sparc64
// https://github.com/rust-lang/libc/issues/1239
#[cfg(not(target_arch = "sparc64"))]
#[test]
fn test_cmsg_nxthdr() {
use std::ptr;
let mut buffer = [0u8; 256];
let mut mhdr: msghdr = unsafe{mem::zeroed()};
let pmhdr = &mhdr as *const msghdr;
for start_ofs in 0..64 {
let pcmsghdr = &mut buffer[start_ofs] as *mut u8 as *mut cmsghdr;
mhdr.msg_control = pcmsghdr as *mut c_void;
mhdr.msg_controllen = (160 - start_ofs) as _;
for cmsg_len in 0..64 {
for next_cmsg_len in 0..32 {
for i in buffer[start_ofs..].iter_mut() {
*i = 0;
}
unsafe {
(*pcmsghdr).cmsg_len = cmsg_len;
let libc_next = libc::CMSG_NXTHDR(pmhdr, pcmsghdr);
let next = cmsg_nxthdr(pmhdr, pcmsghdr);
assert_eq!(libc_next, next);
if libc_next != ptr::null_mut() {
(*libc_next).cmsg_len = next_cmsg_len;
let libc_next = libc::CMSG_NXTHDR(pmhdr, pcmsghdr);
let next = cmsg_nxthdr(pmhdr, pcmsghdr);
assert_eq!(libc_next, next);
}
}
}
}
}
}
#[test]
fn test_cmsg_space() {
unsafe {
for l in 0..128 {
assert_eq!(libc::CMSG_SPACE(l) as usize, cmsg_space(l));
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment