diff --git a/ci/docker/x86_64-rumprun-netbsd/runtest.rs b/ci/docker/x86_64-rumprun-netbsd/runtest.rs index 94b5946080b691e37dccdfb11e6fdbf41203930d..7e96fbfab442d2bd704e95f38644acbacef75ec5 100644 --- a/ci/docker/x86_64-rumprun-netbsd/runtest.rs +++ b/ci/docker/x86_64-rumprun-netbsd/runtest.rs @@ -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(); } } diff --git a/ci/ios/deploy_and_run_on_ios_simulator.rs b/ci/ios/deploy_and_run_on_ios_simulator.rs index 95df52d76d593e29358525dc324642746197f099..2075be6d62007c726dfb4a48d9dc83bca64155e3 100644 --- a/ci/ios/deploy_and_run_on_ios_simulator.rs +++ b/ci/ios/deploy_and_run_on_ios_simulator.rs @@ -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"); diff --git a/ci/run.sh b/ci/run.sh index 853b7c10537ff1e68329c252caec446a3a4c1103..1fb5e127a254e1da968c38557f10a3a084234e5f 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -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 diff --git a/ci/runtest-android.rs b/ci/runtest-android.rs index a68b854cf68a0eb792c3a825d9c0e3accdaf4da6..18d39bfdfe89c06d5033f5bd9f46c3189d890326 100644 --- a/ci/runtest-android.rs +++ b/ci/runtest-android.rs @@ -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"); - } + }); } diff --git a/ci/test-runner-linux b/ci/test-runner-linux index 5f1fb237c28eadce3b8b16791da228484a83e0c5..569fa0077006f6da15dd76763cb6aa42fb346b1a 100755 --- a/ci/test-runner-linux +++ b/ci/test-runner-linux @@ -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 diff --git a/libc-test/Cargo.toml b/libc-test/Cargo.toml index f8bd11b5edc908877d89a2ee9e429a1961245add..7eecc4994cabe7427545704b487a1c66472cf1cc 100644 --- a/libc-test/Cargo.toml +++ b/libc-test/Cargo.toml @@ -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 diff --git a/libc-test/build.rs b/libc-test/build.rs index d81a54d71622495aef3e5c65b21772bbf1bb2881..eab5b762f0db2323f8481f1d78fbf5ec5e6eef4b 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -1,10 +1,21 @@ #![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(); +} diff --git a/libc-test/src/cmsg.c b/libc-test/src/cmsg.c new file mode 100644 index 0000000000000000000000000000000000000000..a8b1c371736c84f55e46210e0644225b2b909f66 --- /dev/null +++ b/libc-test/src/cmsg.c @@ -0,0 +1,28 @@ +#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); +} + diff --git a/libc-test/test/cmsg.rs b/libc-test/test/cmsg.rs new file mode 100644 index 0000000000000000000000000000000000000000..c9eecb628d97599976889884cf924c2c981ddb97 --- /dev/null +++ b/libc-test/test/cmsg.rs @@ -0,0 +1,99 @@ +//! 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)); + } + } +} + +}