#![allow(clippy::unwrap_used, clippy::expect_used)]
use std::path::PathBuf;
const REQUIRED_SYMBOLS: &[&str] = &[
"tq_codec_config_new",
"tq_codec_config_free",
"tq_codec_config_bit_width",
"tq_codec_config_seed",
"tq_codec_config_dimension",
"tq_codec_config_residual_enabled",
"tq_codec_config_hash",
"tq_codebook_train",
"tq_codebook_free",
"tq_codebook_bit_width",
"tq_codec_compress",
"tq_codec_decompress",
"tq_compressed_vector_dimension",
"tq_compressed_vector_bit_width",
"tq_compressed_vector_free",
"tq_compressed_vector_to_bytes",
"tq_compressed_vector_from_bytes",
"tq_bytes_free",
"tq_corpus_new",
"tq_corpus_insert",
"tq_corpus_vector_count",
"tq_corpus_contains",
"tq_corpus_free",
"tq_error_free",
"tq_error_free_message",
"tq_version",
];
fn header_path() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("include")
.join("tinyquant.h")
}
#[test]
fn header_parses_and_exposes_every_entry_point() {
let header = header_path();
assert!(
header.is_file(),
"missing generated header at {}",
header.display()
);
let header_str = header.to_string_lossy().into_owned();
let generate_result = std::panic::catch_unwind(|| {
bindgen::Builder::default()
.header(header_str.clone())
.allowlist_function("tq_.*")
.allowlist_type("TinyQuant.*")
.allowlist_type(".*Handle")
.layout_tests(false)
.generate_comments(false)
.generate()
});
let bindings = match generate_result {
Ok(Ok(b)) => b,
Ok(Err(e)) => {
eprintln!(
"bindgen skipped: {e} \
(this usually means libclang is not installed on the host)"
);
return;
}
Err(_) => {
eprintln!(
"bindgen skipped: libclang not found. Set LIBCLANG_PATH \
to enable the full header-compile check."
);
return;
}
};
let generated = bindings.to_string();
for sym in REQUIRED_SYMBOLS {
assert!(
generated.contains(&format!("pub fn {sym}")),
"symbol `{sym}` missing from bindgen output of tinyquant.h"
);
}
}
#[test]
fn header_version_macro_matches_crate_version() {
let header = header_path();
let src = std::fs::read_to_string(&header).expect("read header");
assert!(
src.contains("#define TINYQUANT_H_VERSION"),
"header must expose TINYQUANT_H_VERSION"
);
let expected = format!(
"#define TINYQUANT_H_VERSION \"{}\"",
env!("CARGO_PKG_VERSION")
);
assert!(
src.contains(&expected),
"header version macro out of sync with crate version (expected `{expected}`)"
);
assert!(
!src.contains("@version@"),
"header contains a literal `@version@` placeholder — \
build.rs substitution regressed"
);
}
#[test]
fn header_contains_required_enum_kinds() {
let src = std::fs::read_to_string(header_path()).expect("read header");
for needle in [
"TINY_QUANT_ERROR_KIND_OK",
"TINY_QUANT_ERROR_KIND_INVALID_HANDLE",
"TINY_QUANT_ERROR_KIND_INVALID_ARGUMENT",
"TINY_QUANT_ERROR_KIND_PANIC",
"TINY_QUANT_COMPRESSION_POLICY_COMPRESS",
"TINY_QUANT_COMPRESSION_POLICY_PASSTHROUGH",
"TINY_QUANT_COMPRESSION_POLICY_FP16",
] {
assert!(
src.contains(needle),
"expected `{needle}` in generated header"
);
}
}