libbpf-rs 0.23.3

libbpf-rs is a safe, idiomatic, and opinionated wrapper around libbpf-sys
Documentation
//! This test is in its own file because the underlying libbpf_set_print function used by
//! set_print() and ObjectBuilder::debug() sets global state. The default is to run multiple tests
//! in different threads, so this test will always race with the others unless its isolated to a
//! different process.
//!
//! For the same reason, all tests here must run serially.

use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;

use libbpf_rs::get_print;
use libbpf_rs::set_print;
use libbpf_rs::ObjectBuilder;
use libbpf_rs::PrintCallback;
use libbpf_rs::PrintLevel;
use serial_test::serial;

#[test]
#[serial]
fn test_set_print() {
    static CORRECT_LEVEL: AtomicBool = AtomicBool::new(false);
    static CORRECT_MESSAGE: AtomicBool = AtomicBool::new(false);

    fn callback(level: PrintLevel, msg: String) {
        if level == PrintLevel::Warn {
            CORRECT_LEVEL.store(true, Ordering::Relaxed);
        }

        if msg.starts_with("libbpf: ") {
            CORRECT_MESSAGE.store(true, Ordering::Relaxed);
        }
    }

    set_print(Some((PrintLevel::Debug, callback)));
    // expect_err requires that OpenObject implement Debug, which it does not.
    let obj = ObjectBuilder::default().open_file("/dev/null");
    assert!(obj.is_err(), "Successfully loaded /dev/null?");

    let correct_level = CORRECT_LEVEL.load(Ordering::Relaxed);
    let correct_message = CORRECT_MESSAGE.load(Ordering::Relaxed);
    assert!(correct_level, "Did not capture a warning");
    assert!(correct_message, "Did not capture the correct message");
}

#[test]
#[serial]
fn test_set_restore_print() {
    fn callback1(_: PrintLevel, _: String) {
        println!("one");
    }
    fn callback2(_: PrintLevel, _: String) {
        println!("two");
    }

    set_print(Some((PrintLevel::Warn, callback1)));
    let prev = get_print();
    assert_eq!(prev, Some((PrintLevel::Warn, callback1 as PrintCallback)));

    set_print(Some((PrintLevel::Debug, callback2)));
    let prev = get_print();
    assert_eq!(prev, Some((PrintLevel::Debug, callback2 as PrintCallback)));
}

#[test]
#[serial]
fn test_set_and_save_print() {
    fn callback1(_: PrintLevel, _: String) {
        println!("one");
    }
    fn callback2(_: PrintLevel, _: String) {
        println!("two");
    }

    set_print(Some((PrintLevel::Warn, callback1)));
    let prev = set_print(Some((PrintLevel::Debug, callback2)));
    assert_eq!(prev, Some((PrintLevel::Warn, callback1 as PrintCallback)));

    let prev = set_print(None);
    assert_eq!(prev, Some((PrintLevel::Debug, callback2 as PrintCallback)));
}