Mercurial > crates > nonstick
view libpam-sys/libpam-sys-test/build.rs @ 124:f469b8d9ad78 default tip
Add tests for the original X/SSO constants list.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Mon, 30 Jun 2025 04:54:38 -0400 |
parents | 9e05e44050d0 |
children |
line wrap: on
line source
use bindgen::MacroTypeVariation; use libpam_sys::PamImpl; use quote::{format_ident, ToTokens}; use std::path::PathBuf; use std::{env, fs}; use syn::{Item, ItemConst, Type, TypePath}; fn main() { let config = match PamImpl::CURRENT { PamImpl::LinuxPam => TestConfig { headers: vec![ "<security/_pam_types.h>", "<security/pam_appl.h>", "<security/pam_ext.h>", "<security/pam_modules.h>", ], ignore_consts: vec![ "__LINUX_PAM__", "__LINUX_PAM_MINOR__", "PAM_AUTHTOK_RECOVER_ERR", ], ..Default::default() }, PamImpl::OpenPam => TestConfig { headers: vec![ "<security/pam_types.h>", "<security/openpam.h>", "<security/pam_appl.h>", "<security/pam_constants.h>", ], ignore_consts: vec!["OPENPAM_VERSION", "OPENPAM_RELEASE", "PAM_SOEXT"], ..Default::default() }, 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_constants.h\""], ignore_consts: vec!["PAM_CRED_PRELIM_CHECK"], ..Default::default() }, other => panic!("Unknown PAM implementation {other:?}"), }; generate_const_test(&config); } fn generate_const_test(config: &TestConfig) { let mut builder = bindgen::Builder::default() .header_contents("_.h", &config.header_contents()) .merge_extern_blocks(true) .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) .blocklist_type(".*") .blocklist_function(".*") .allowlist_var(".*") .default_macro_constant_type(MacroTypeVariation::Signed); for hdr in config.block_headers.iter() { builder = builder.blocklist_file(".*?/".to_owned() + hdr) } let generated = builder.generate().unwrap().to_string(); let file = syn::parse_file(&generated).unwrap(); let mut tests = vec![]; tests.push("{".into()); tests.extend( file.items .iter() .filter_map(|item| { if let Item::Const(item) = item { Some(item) } else { 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}, libpam_sys::{name});", tokens = item.expr.to_token_stream(), name = item.ident ) }), ); tests.push("}".into()); fs::write( PathBuf::from(env::var("OUT_DIR").unwrap()).join("constant_test.rs"), tests.join("\n"), ) .unwrap(); } #[derive(Default)] struct TestConfig { headers: Vec<&'static str>, block_headers: Vec<&'static str>, ignore_consts: Vec<&'static str>, } impl TestConfig { fn header_contents(&self) -> String { let vec: Vec<_> = self .headers .iter() .map(|h| format!("#include {h}\n")) .collect(); vec.join("") } fn should_check_const(&self, item: &ItemConst) -> bool { !self .ignore_consts .contains(&item.ident.to_string().as_ref()) } }