Skip to content

Commit d4e8842

Browse files
committed
libc-test: port windows to use ctest-next
1 parent cf82fdf commit d4e8842

File tree

6 files changed

+135
-3
lines changed

6 files changed

+135
-3
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ctest-next/src/template.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::ops::Deref;
22

33
use askama::Template;
4+
use proc_macro2::Span;
45
use quote::ToTokens;
56
use syn::spanned::Spanned;
67

@@ -453,7 +454,11 @@ impl<'a> TranslateHelper<'a> {
453454
// inside of `Fn` when parsed.
454455
MapInput::Fn(_) => unimplemented!(),
455456
// For structs/unions/aliases, their type is the same as their identifier.
456-
MapInput::Alias(a) => (a.ident(), a.ident().to_string()),
457+
// FIXME(ctest): For some specific primitives such as c_uint, they don't exist on the
458+
// C side and have to be manually translated. If they are removed to use `std::ffi`,
459+
// then this becomes unneeded (although it won't break).
460+
MapInput::Alias(a) => (a.ident(), self.translator
461+
.translate_primitive_type(&syn::Ident::new(a.ident(), Span::call_site()))),
457462
MapInput::Struct(s) => (s.ident(), s.ident().to_string()),
458463
MapInput::Union(u) => (u.ident(), u.ident().to_string()),
459464

ctest-next/src/translator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ impl Translator {
228228
}
229229

230230
/// Translate a Rust primitive type into its C equivalent.
231-
fn translate_primitive_type(&self, ty: &syn::Ident) -> String {
231+
pub(crate) fn translate_primitive_type(&self, ty: &syn::Ident) -> String {
232232
match ty.to_string().as_str() {
233233
"usize" => "size_t".to_string(),
234234
"isize" => "ssize_t".to_string(),

ctest-next/templates/test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
mod generated_tests {
1010
#![allow(non_snake_case)]
1111
#![deny(improper_ctypes_definitions)]
12+
#[allow(unused_imports)]
1213
use std::ffi::{CStr, c_char};
1314
use std::fmt::{Debug, LowerHex};
1415
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};

libc-test/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ annotate-snippets = { version = "0.11.5", features = ["testing-colors"] }
2121
[build-dependencies]
2222
cc = "1.2.29"
2323
ctest = { path = "../ctest" }
24+
ctest-next = { path = "../ctest-next" }
2425
regex = "1.11.1"
2526

2627
[features]

libc-test/build.rs

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ fn do_ctest() {
6565
t if t.contains("solaris") => test_solarish(t),
6666
t if t.contains("illumos") => test_solarish(t),
6767
t if t.contains("wasi") => test_wasi(t),
68-
t if t.contains("windows") => test_windows(t),
68+
t if t.contains("windows") => {
69+
test_windows_next(t);
70+
test_windows(t);
71+
}
6972
t if t.contains("vxworks") => test_vxworks(t),
7073
t if t.contains("nto-qnx") => test_neutrino(t),
7174
t if t.contains("aix") => return test_aix(t),
@@ -77,6 +80,10 @@ fn ctest_cfg() -> ctest::TestGenerator {
7780
ctest::TestGenerator::new()
7881
}
7982

83+
fn ctest_next_cfg() -> ctest_next::TestGenerator {
84+
ctest_next::TestGenerator::new()
85+
}
86+
8087
fn do_semver() {
8188
let mut out = PathBuf::from(env::var("OUT_DIR").unwrap());
8289
out.push("semver.rs");
@@ -945,6 +952,123 @@ fn test_windows(target: &str) {
945952
cfg.generate(src_hotfix_dir().join("lib.rs"), "main.rs");
946953
}
947954

955+
fn test_windows_next(target: &str) {
956+
assert!(target.contains("windows"));
957+
let gnu = target.contains("gnu");
958+
let i686 = target.contains("i686");
959+
960+
let mut cfg = ctest_next_cfg();
961+
if target.contains("msvc") {
962+
cfg.flag("/wd4324");
963+
}
964+
cfg.define("_WIN32_WINNT", Some("0x8000"));
965+
966+
headers! { cfg:
967+
"direct.h",
968+
"errno.h",
969+
"fcntl.h",
970+
"io.h",
971+
"limits.h",
972+
"locale.h",
973+
"process.h",
974+
"signal.h",
975+
"stddef.h",
976+
"stdint.h",
977+
"stdio.h",
978+
"stdlib.h",
979+
"sys/stat.h",
980+
"sys/types.h",
981+
"sys/utime.h",
982+
"time.h",
983+
"wchar.h",
984+
[gnu]: "ws2tcpip.h",
985+
[!gnu]: "Winsock2.h",
986+
}
987+
988+
cfg.rename_struct_ty(|ty| {
989+
match ty {
990+
// Just pass all these through, no need for a "struct" prefix
991+
"FILE" | "DIR" | "Dl_info" => ty.to_string().into(),
992+
t if t.ends_with("_t") => t.to_string().into(),
993+
// Windows uppercase structs don't have `struct` in fr.into()ont:
994+
t if ty.chars().next().unwrap().is_uppercase() => t.to_string().into(),
995+
"stat" => "struct __stat64".to_string().into(),
996+
"utimbuf" => "struct __utimbuf64".to_string().into(),
997+
_ => None,
998+
}
999+
});
1000+
cfg.rename_type(move |ty| {
1001+
match ty {
1002+
// FIXME(windows): these don't exist:
1003+
"time64_t" => "__time64_t".to_string().into(),
1004+
"ssize_t" => "SSIZE_T".to_string().into(),
1005+
1006+
"sighandler_t" if !gnu => "_crt_signal_t".to_string().into(),
1007+
"sighandler_t" if gnu => "__p_sig_fn_t".to_string().into(),
1008+
_ => None,
1009+
}
1010+
});
1011+
1012+
cfg.rename_fn(move |func| {
1013+
func.link_name()
1014+
.map(|l| l.to_string())
1015+
.or(func.ident().to_string().into())
1016+
});
1017+
1018+
cfg.skip_alias(move |alias| match alias.ident() {
1019+
"SSIZE_T" if !gnu => true,
1020+
"ssize_t" if !gnu => true,
1021+
// FIXME(windows): The size and alignment of this type are incorrect
1022+
"time_t" if gnu && i686 => true,
1023+
_ => false,
1024+
});
1025+
1026+
cfg.skip_struct(move |struct_| {
1027+
let ty = struct_.ident();
1028+
if ty.starts_with("__c_anonymous_") {
1029+
return true;
1030+
}
1031+
match ty {
1032+
// FIXME(windows): The size and alignment of this struct are incorrect
1033+
"timespec" if gnu && i686 => true,
1034+
_ => false,
1035+
}
1036+
});
1037+
cfg.skip_union(move |union_| union_.ident().starts_with("__c_anonymous_"));
1038+
1039+
cfg.skip_const(move |constant| {
1040+
match constant.ident() {
1041+
// FIXME(windows): API error:
1042+
// SIG_ERR type is "void (*)(int)", not "int"
1043+
"SIG_ERR" |
1044+
// Similar for SIG_DFL/IGN/GET/SGE/ACK
1045+
"SIG_DFL" | "SIG_IGN" | "SIG_GET" | "SIG_SGE" | "SIG_ACK" => true,
1046+
// FIXME(windows): newer windows-gnu environment on CI?
1047+
"_O_OBTAIN_DIR" if gnu => true,
1048+
_ => false,
1049+
}
1050+
});
1051+
1052+
cfg.skip_struct_field(move |s, field| s.ident() == "CONTEXT" && field.ident() == "Fp");
1053+
// FIXME(windows): All functions point to the wrong addresses?
1054+
// cfg.skip_fn_ptr_check(|_| true);
1055+
1056+
cfg.skip_signededness(move |c| {
1057+
match c {
1058+
// windows-isms
1059+
n if n.starts_with("P") => true,
1060+
n if n.starts_with("H") => true,
1061+
n if n.starts_with("LP") => true,
1062+
"sighandler_t" if gnu => true,
1063+
_ => false,
1064+
}
1065+
});
1066+
1067+
cfg.skip_fn(|_| false);
1068+
1069+
ctest_next::generate_test(&mut cfg, "../src/lib.rs", "main.rs").unwrap();
1070+
}
1071+
9481072
fn test_redox(target: &str) {
9491073
assert!(target.contains("redox"));
9501074

0 commit comments

Comments
 (0)