Mercurial > crates > nonstick
diff libpam-sys/libpam-sys-test/build.rs @ 131:a632a8874131
Get all the Linux-PAM functions into libpam-sys, and get tests right.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Wed, 02 Jul 2025 02:24:21 -0400 |
parents | 80c07e5ab22f |
children | 0b6a17f8c894 |
line wrap: on
line diff
--- a/libpam-sys/libpam-sys-test/build.rs Tue Jul 01 06:11:43 2025 -0400 +++ b/libpam-sys/libpam-sys-test/build.rs Wed Jul 02 02:24:21 2025 -0400 @@ -6,11 +6,13 @@ use std::process::Command; use std::str::FromStr; use std::{env, fs}; -use syn::{Item, ItemConst, Type, TypePath}; +use syn::{Item, ItemConst}; // We're using the macro directly so we can match exhaustively. __pam_impl_enum__!(); +const REDIR_FD: &str = "pam_modutil_redirect_fd"; + fn main() { let config = match PamImpl::CURRENT { PamImpl::LinuxPam => TestConfig { @@ -19,7 +21,9 @@ "<security/pam_appl.h>", "<security/pam_ext.h>", "<security/pam_modules.h>", + "<security/pam_modutil.h>", ], + allow_types: vec![REDIR_FD], ignore_consts: vec![ "__LINUX_PAM__", "__LINUX_PAM_MINOR__", @@ -39,12 +43,10 @@ }, PamImpl::Sun => TestConfig { headers: vec!["<security/pam_appl.h>", "<security/pam_modules.h>"], - block_headers: vec!["sys/.*"], ..Default::default() }, PamImpl::XSso => TestConfig { headers: vec!["\"xsso_pam_appl.h\""], - ignore_consts: vec!["PAM_CRED_PRELIM_CHECK"], ..Default::default() }, }; @@ -57,22 +59,28 @@ .header_contents("_.h", &config.header_contents()) .merge_extern_blocks(true) .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) - .blocklist_type(".*") - .blocklist_function(".*") - .allowlist_var(".*") + .allowlist_var("(OPEN)?PAM_.*") .default_macro_constant_type(MacroTypeVariation::Signed); - for hdr in config.block_headers.iter() { - builder = builder.blocklist_file(".*?/".to_owned() + hdr) + + for &typ in config.allow_types.iter() { + builder = builder.allowlist_type(typ); } - let generated = builder.generate().unwrap().to_string(); - let file = syn::parse_file(&generated).unwrap(); + let generated = builder.generate().unwrap(); + generated.write_to_file(test_file("bindgen.rs")).unwrap(); + let file = syn::parse_file(&generated.to_string()).unwrap(); let mut tests = vec![ - "use libpam_sys::*;".into(), - "#[allow(deprecated, overflowing_literals)]".into(), - "fn main() {".into(), + "\ + #[allow(dead_code, non_camel_case_types, non_upper_case_globals)] + mod generated { + include!(\"bindgen.rs\"); + } + #[allow(deprecated, overflowing_literals)] + fn main() { + " + .into(), format!( - "assert_eq!(PamImpl::CURRENT, PamImpl::{:?});", + "assert_eq!(libpam_sys::PamImpl::CURRENT, libpam_sys::PamImpl::{:?});", PamImpl::CURRENT ), ]; @@ -86,18 +94,14 @@ None } }) - .filter(|item| config.should_check_const(item)) - .cloned() - .map(|mut item| { - item.ty = Box::new(Type::Path(TypePath { - qself: None, - path: format_ident!("i32").into(), - })); - format!( - "assert_eq!({tokens}, {name});", - tokens = item.expr.to_token_stream(), - name = item.ident - ) + .filter(|&item| config.should_check_const(item)) + .map(|item| { + let name = item.ident.to_string(); + if let Some(stripped) = name.strip_prefix(&format!("{REDIR_FD}_")) { + format!("assert_eq!(generated::{name} as i32, libpam_sys::{REDIR_FD}::{stripped}.into());") + } else { + format!("assert_eq!(generated::{name}, libpam_sys::{name});") + } }), ); tests.push("}".into()); @@ -108,8 +112,9 @@ fn generate_ctest(config: &TestConfig) { let mut test = ctest::TestGenerator::new(); + test.cfg("_hack_impl", Some(&format!("{:?}", PamImpl::CURRENT))); - for header in config.headers.iter() { + for &header in config.headers.iter() { if header.starts_with('"') { test.include(env::var("CARGO_MANIFEST_DIR").unwrap()); } @@ -118,17 +123,17 @@ // These are opaque structs. test.skip_struct(|name| matches!(name, "pam_handle" | "AppData")); test.skip_type(|name| matches!(name, "ConversationCallback" | "CleanupCallback")); - test.type_name(|name, _is_struct, is_union| { + test.type_name(|name, is_struct, is_union| { assert!(!is_union); // we scabbin' - match name { - "pam_handle" => "struct pam_handle", - "pam_conv" => "struct pam_conv", - "pam_message" => "struct pam_message", - "pam_response" => "struct pam_response", - "AppData" => "void", - other => other, + match (name, is_struct) { + ("AppData", _) => "void".into(), + (REDIR_FD, _) => format!("enum {REDIR_FD}"), + ("passwd", _) => "struct passwd".into(), + ("group", _) => "struct group".into(), + ("spwd", _) => "struct spwd".into(), + (name, true) => format!("struct {name}"), + (other, false) => other.into(), } - .into() }); // @@ -186,7 +191,7 @@ #[derive(Default)] struct TestConfig { headers: Vec<&'static str>, - block_headers: Vec<&'static str>, + allow_types: Vec<&'static str>, ignore_consts: Vec<&'static str>, }