Skip to content

Commit a315423

Browse files
committed
libc-test: expand DragonFly coverage
1 parent dacc884 commit a315423

2 files changed

Lines changed: 194 additions & 12 deletions

File tree

libc-test/build.rs

Lines changed: 139 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ fn do_cc() {
3636
|| target.contains("android")
3737
|| target.contains("emscripten")
3838
|| target.contains("fuchsia")
39+
|| target.contains("dragonfly")
3940
|| target.contains("bsd")
4041
|| target.contains("cygwin")
4142
{
@@ -1504,7 +1505,17 @@ fn test_netbsd(target: &str) {
15041505
fn test_dragonflybsd(target: &str) {
15051506
assert!(target.contains("dragonfly"));
15061507
let mut cfg = ctest_cfg();
1507-
cfg.flag("-Wno-deprecated-declarations");
1508+
cfg.flag("-Wno-deprecated-declarations")
1509+
.flag_if_supported("-Wno-address-of-packed-member")
1510+
.flag_if_supported("-Wno-unknown-warning-option");
1511+
1512+
let dragonfly_version = if let Ok(version) = env::var("RUST_LIBC_UNSTABLE_DRAGONFLY_VERSION") {
1513+
let vers = parse_dragonfly_version(&version).unwrap();
1514+
println!("cargo:warning=setting DragonFly version to {vers}");
1515+
vers
1516+
} else {
1517+
which_dragonfly().unwrap_or(600_200)
1518+
};
15081519

15091520
headers!(
15101521
cfg,
@@ -1547,6 +1558,7 @@ fn test_dragonflybsd(target: &str) {
15471558
"sched.h",
15481559
"semaphore.h",
15491560
"signal.h",
1561+
"spawn.h",
15501562
"stddef.h",
15511563
"stdint.h",
15521564
"stdio.h",
@@ -1557,6 +1569,7 @@ fn test_dragonflybsd(target: &str) {
15571569
"sys/ioctl.h",
15581570
"sys/cpuctl.h",
15591571
"sys/eui64.h",
1572+
"sys/extattr.h",
15601573
"sys/ipc.h",
15611574
"sys/kinfo.h",
15621575
"sys/ktrace.h",
@@ -1566,6 +1579,7 @@ fn test_dragonflybsd(target: &str) {
15661579
"sys/procctl.h",
15671580
"sys/ptrace.h",
15681581
"sys/reboot.h",
1582+
"sys/random.h",
15691583
"sys/resource.h",
15701584
"sys/rtprio.h",
15711585
"sys/sched.h",
@@ -1591,8 +1605,8 @@ fn test_dragonflybsd(target: &str) {
15911605
"util.h",
15921606
"utime.h",
15931607
"utmpx.h",
1608+
"vm/vm.h",
15941609
"vfs/ufs/quota.h",
1595-
"vm/vm_map.h",
15961610
"wchar.h",
15971611
"iconv.h",
15981612
);
@@ -1613,6 +1627,12 @@ fn test_dragonflybsd(target: &str) {
16131627
match ty {
16141628
// FIXME(dragonflybsd): OSX calls this something else
16151629
"sighandler_t" => Some("sig_t".to_string()),
1630+
"lwpstat" => Some("enum lwpstat".to_string()),
1631+
"procstat" => Some("enum procstat".to_string()),
1632+
"vm_map_t" => Some("struct vm_map *".to_string()),
1633+
"vm_map_entry_t" => Some("struct vm_map_entry *".to_string()),
1634+
"vm_eflags_t" => Some("unsigned int".to_string()),
1635+
"vm_subsys_t" => Some("int".to_string()),
16161636
_ => None,
16171637
}
16181638
});
@@ -1663,11 +1683,34 @@ fn test_dragonflybsd(target: &str) {
16631683
_ => false,
16641684
}
16651685
});
1686+
cfg.alias_is_c_enum(move |e| matches!(e, "lwpstat" | "procstat"));
16661687

16671688
cfg.skip_const(move |constant| {
16681689
match constant.ident() {
16691690
"SIG_DFL" | "SIG_ERR" | "SIG_IGN" => true, // sighandler_t weirdness
16701691

1692+
// Kernel-only symbols in DragonFly headers.
1693+
"DTYPE_VNODE" | "DTYPE_SOCKET" | "DTYPE_PIPE" | "DTYPE_FIFO" | "DTYPE_KQUEUE"
1694+
| "DTYPE_CRYPTO" | "DTYPE_MQUEUE" | "DTYPE_DMABUF" => true,
1695+
1696+
// Not exposed by current DragonFly userland headers.
1697+
"REG_DUMP" | "REG_ASSERT" | "REG_ATOI" | "REG_ITOA" | "REG_TRACE" | "REG_LARGE"
1698+
| "IP_ADD_SOURCE_MEMBERSHIP" | "IP_DROP_SOURCE_MEMBERSHIP" | "IP_BLOCK_SOURCE"
1699+
| "IP_UNBLOCK_SOURCE" | "MAP_RENAME" | "MAP_NORESERVE" | "CTL_UNSPEC"
1700+
| "KERN_PROF" | "CTL_P1003_1B_UNUSED1" | "CTL_P1003_1B_SEM_VALUE_MAX"
1701+
| "DOWNTIME" | "SF_CACHE" => true,
1702+
1703+
// libc exposes the 6.0-compatible value for this version-dependent mask.
1704+
"KERN_PROC_FLAGMASK" => true,
1705+
1706+
// Renamed in current DragonFly headers.
1707+
"CPUCTL_RSMSR" | "UTX_DB_LASTLOG" => true,
1708+
1709+
// Introduced after DragonFly 5.8.
1710+
"AF_ARP" | "PF_ARP" | "IP_SENDSRCADDR" | "F_GETPATH" | "ENOTRECOVERABLE" | "EOWNERDEAD"
1711+
| "SO_PASSCRED" | "PROC_PDEATHSIG_CTL" | "PROC_PDEATHSIG_STATUS"
1712+
| "KERN_STATIC_TLS_EXTRA" | "KERN_MAXID" if dragonfly_version < 600_000 => true,
1713+
16711714
// weird signed extension or something like that?
16721715
"MS_NOUSER" => true,
16731716
"MS_RMT_MASK" => true, // updated in glibc 2.22 and musl 1.1.13
@@ -1688,18 +1731,40 @@ fn test_dragonflybsd(target: &str) {
16881731
"prlimit" | "prlimit64" // non-int in 2nd arg
16891732
=> true,
16901733

1734+
// These are exposed unconditionally by libc, but older DragonFly
1735+
// headers cannot validate them.
1736+
"clock_nanosleep" | "fexecve" | "pthread_getname_np" | "pthread_setname_np"
1737+
if dragonfly_version < 600_000 => true,
1738+
"pthread_getaffinity_np" | "pthread_setaffinity_np" if dragonfly_version < 600_000 => {
1739+
true
1740+
},
1741+
"fdatasync" | "getentropy" | "posix_fallocate" if dragonfly_version < 600_200 => true,
1742+
"malloc_usable_size" if dragonfly_version < 600_400 => true,
16911743
_ => false,
16921744
}
16931745
});
16941746

1695-
cfg.skip_struct_field_type(move |struct_, field| {
1696-
match (struct_.ident(), field.ident()) {
1697-
// This is a weird union, don't check the type.
1698-
("ifaddrs", "ifa_ifu") => true,
1699-
// sighandler_t type is super weird
1700-
("sigaction", "sa_sigaction") => true,
1701-
// aio_buf is "volatile void*" and Rust doesn't understand volatile
1702-
("aiocb", "aio_buf") => true,
1747+
cfg.skip_alias(move |ty| {
1748+
match ty.ident() {
1749+
// sighandler_t is crazy across platforms
1750+
"sighandler_t" => true,
1751+
// Kernel-only or opaque types in userland.
1752+
"kvm_t" | "pmap" | "umtx_t" | "Elf32_Lword" => true,
1753+
_ => false,
1754+
}
1755+
});
1756+
1757+
cfg.skip_struct(move |struct_| {
1758+
match struct_.ident() {
1759+
// FIXME(dragonflybsd): These are tested as part of the linux_fcntl tests since
1760+
// there are header conflicts when including them with all the other
1761+
// structs.
1762+
"termios2" => true,
1763+
1764+
// Not available as userland-complete structs on DragonFly.
1765+
"ip_mreq_source" | "vm_map_entry" | "vmspace" => true,
1766+
"ip_mreqn" if dragonfly_version < 600_000 => true,
1767+
17031768
_ => false,
17041769
}
17051770
});
@@ -1711,13 +1776,77 @@ fn test_dragonflybsd(target: &str) {
17111776
("siginfo_t", "_pad") => true,
17121777
// sigev_notify_thread_id is actually part of a sigev_un union
17131778
("sigevent", "sigev_notify_thread_id") => true,
1779+
// Current DragonFly headers use these names instead.
1780+
("kinfo_cputime", "cp_idel") => true,
1781+
// conflicting with `p_type` macro from <resolve.h>.
1782+
("Elf32_Phdr", "p_type") | ("Elf64_Phdr", "p_type") => true,
1783+
("kinfo_lwp", "kl_stat") | ("kinfo_proc", "kp_stat") => true,
1784+
("utmpx", "ut_type") => true,
1785+
("mcontext_t", "mc_fpregs") => true,
17141786
_ => false,
17151787
}
17161788
});
17171789

1790+
cfg.skip_struct_field_type(move |struct_, field| {
1791+
match (struct_.ident(), field.ident()) {
1792+
// This is a weird union, don't check the type.
1793+
("ifaddrs", "ifa_ifu") => true,
1794+
// sighandler_t type is super weird
1795+
("sigaction", "sa_sigaction") => true,
1796+
// aio_buf is "volatile void*" and Rust doesn't understand volatile
1797+
("aiocb", "aio_buf") => true,
1798+
_ => false,
1799+
}
1800+
});
1801+
1802+
cfg.skip_roundtrip(move |ty| {
1803+
matches!(
1804+
ty,
1805+
"kvm_t"
1806+
| "posix_spawnattr_t"
1807+
| "posix_spawn_file_actions_t"
1808+
| "umtx_t"
1809+
| "pmap"
1810+
| "ip_mreq_source"
1811+
)
1812+
});
1813+
17181814
ctest::generate_test(&mut cfg, "../src/lib.rs", "ctest_output.rs").unwrap();
17191815
}
17201816

1817+
fn parse_dragonfly_version(version: &str) -> Option<u32> {
1818+
let version = version.trim();
1819+
1820+
if let Ok(version) = version.parse::<u32>() {
1821+
// DragonFly's __DragonFly_version uses major * 100_000 + minor * 100.
1822+
// Accept compact test override spellings like 58, 60, 62, and 602.
1823+
return Some(match version {
1824+
0..=9 => version * 100_000,
1825+
10..=99 => (version / 10) * 100_000 + (version % 10) * 100,
1826+
100..=999 => (version / 100) * 100_000 + (version % 100) * 100,
1827+
_ => version,
1828+
});
1829+
}
1830+
1831+
let mut pieces = version.split(['.', '-']);
1832+
let major = pieces.next()?.parse::<u32>().ok()?;
1833+
let minor = pieces.next()?.parse::<u32>().ok()?;
1834+
Some(major * 100_000 + minor * 100)
1835+
}
1836+
1837+
fn which_dragonfly() -> Option<u32> {
1838+
if env::var("CARGO_CFG_TARGET_OS").ok()?.as_str() != "dragonfly" {
1839+
return None;
1840+
}
1841+
1842+
if try_command_output("uname", &["-s"])?.trim() != "DragonFly" {
1843+
return None;
1844+
}
1845+
1846+
let stdout = try_command_output("uname", &["-r"])?;
1847+
parse_dragonfly_version(stdout.trim())
1848+
}
1849+
17211850
fn test_wasi(target: &str) {
17221851
assert!(target.contains("wasi"));
17231852
let p2 = target.contains("wasip2");

0 commit comments

Comments
 (0)