Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/objc2/tests/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 7 kB image not shown  

Quelle  track_caller.rs

  Sprache: Rust
 

#![cfg(all(target_pointer_width = "64", not(feature = "catch-all")))]
#![allow(dead_code)]
//! Test that our use of #[track_caller] is making the correct line number
//! show up.
use std::panic;
use std::process::abort;
use std::ptr;
use std::sync::Mutex;

use objc2::encode::Encode;
use objc2::rc::{self, Allocated, Retained};
use objc2::runtime::{self, NSObject};
use objc2::{class, define_class, msg_send, AnyThread, ClassType};

#[path = "../src/rc/test_object.rs"]
#[allow(dead_code)]
mod test_object;
use self::test_object::RcTestObject;

static EXPECTED_MESSAGE: Mutex<String> = Mutex::new(String::new());
static EXPECTED_LINE: Mutex<u32> = Mutex::new(0);

struct PanicChecker(());

impl PanicChecker {
    fn new() -> Self {
        panic::set_hook(Box::new(|info| {
            let expected_message = EXPECTED_MESSAGE.lock().unwrap();
            let expected_line = EXPECTED_LINE.lock().unwrap();

            let payload = info.payload();
            let message = if let Some(payload) = payload.downcast_ref::<&'static str>() {
                payload.to_string()
            } else if let Some(payload) = payload.downcast_ref::<String>() {
                payload.clone()
            } else {
                format!("could not extract message: {payload:?}")
            };
            let location = info.location().expect("location");

            if !message.contains(&*expected_message) {
                eprintln!("expected {expected_message:?}, got: {message:?}");
                abort();
            }
            if location.file() != file!() {
                eprintln!("expected file {:?}, got: {:?}", file!(), location.file());
                abort();
            }
            if location.line() != *expected_line {
                eprintln!("expected line {expected_line}, got: {}", location.line());
                abort();
            }
        }));
        Self(())
    }

    fn assert_panics(&self, message: &str, line: u32, f: impl FnOnce()) {
        *EXPECTED_MESSAGE.lock().unwrap() = message.to_string();
        *EXPECTED_LINE.lock().unwrap() = line;

        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
            f();
        }));
        assert!(res.is_err());

        *EXPECTED_MESSAGE.lock().unwrap() = "unknown".to_string();
        *EXPECTED_LINE.lock().unwrap() = 0;
    }
}

impl Drop for PanicChecker {
    fn drop(&mut self) {
        let _ = panic::take_hook();
    }
}

#[test]
#[cfg_attr(panic = "abort", ignore = "requires `catch_unwind`")]
fn test_track_caller() {
    let checker = PanicChecker::new();

    if cfg!(debug_assertions) {
        test_nil(&checker);
        if cfg!(not(feature = "disable-encoding-assertions")) {
            test_verify(&checker);
            test_error_methods(&checker);
        }
    }

    test_retained_unwrap(&checker);

    if cfg!(feature = "catch-all") {
        test_catch_all(&checker);
    }

    test_unwind(&checker);

    #[cfg(not(feature = "unstable-static-class"))]
    test_unknown_class(&checker);
}

fn test_nil(checker: &PanicChecker) {
    let nil: *mut NSObject = ptr::null_mut();

    let msg = "messsaging description to nil";
    checker.assert_panics(msg, line!() + 1, || {
        let _: *mut NSObject = unsafe { msg_send![nil, description] };
    });
    checker.assert_panics(msg, line!() + 1, || {
        let _: *mut NSObject = unsafe { msg_send![super(nil, NSObject::class()), description] };
    });
    checker.assert_panics(msg, line!() + 1, || {
        let _: Option<Retained<NSObject>> = unsafe { msg_send![nil, description] };
    });
}

fn test_verify(checker: &PanicChecker) {
    let obj = NSObject::new();

    let msg = "invalid message send to -[NSObject description]: expected return to have type code '@', but found 'v'";
    checker.assert_panics(msg, line!() + 1, || {
        let _: () = unsafe { msg_send![&obj, description] };
    });

    let msg = format!("invalid message send to -[NSObject hash]: expected return to have type code '{}', but found '@'", usize::ENCODING);
    checker.assert_panics(&msg, line!() + 1, || {
        let _: Option<Retained<NSObject>> = unsafe { msg_send![&obj, hash] };
    });
}

fn test_error_methods(checker: &PanicChecker) {
    let nil: *mut NSObject = ptr::null_mut();

    let msg = "messsaging someSelectorWithError: to nil";
    checker.assert_panics(msg, line!() + 1, || {
        let _: Result<(), Retained<NSObject>> = unsafe { msg_send![nil, someSelectorWithError: _] };
    });
    checker.assert_panics(msg, line!() + 2, || {
        let _: Result<(), Retained<NSObject>> =
            unsafe { msg_send![super(nil, NSObject::class()), someSelectorWithError: _] };
    });
    checker.assert_panics(msg, line!() + 2, || {
        let _: Result<Retained<NSObject>, Retained<NSObject>> =
            unsafe { msg_send![nil, someSelectorWithError: _] };
    });

    let msg = "invalid message send to -[NSObject someSelectorWithError:]: method not found";
    checker.assert_panics(msg, line!() + 3, || {
        let obj = RcTestObject::new();
        let _: Result<(), Retained<NSObject>> =
            unsafe { msg_send![super(&obj), someSelectorWithError: _] };
    });
}

fn test_retained_unwrap(checker: &PanicChecker) {
    let cls = RcTestObject::class();
    let obj = RcTestObject::new();

    let msg = "failed creating new instance using +[__RcTestObject newReturningNull]";
    checker.assert_panics(msg, line!() + 1, || {
        let _obj: Retained<RcTestObject> = unsafe { msg_send![cls, newReturningNull] };
    });

    let msg = if cfg!(debug_assertions) {
        "messsaging init to nil"
    } else {
        "failed allocating object"
    };
    checker.assert_panics(msg, line!() + 2, || {
        let obj: Allocated<RcTestObject> = unsafe { msg_send![cls, allocReturningNull] };
        let _obj: Retained<RcTestObject> = unsafe { msg_send![obj, init] };
    });

    let msg = "failed initializing object with -initReturningNull";
    checker.assert_panics(msg, line!() + 2, || {
        let _obj: Retained<RcTestObject> =
            unsafe { msg_send![RcTestObject::alloc(), initReturningNull] };
    });

    let msg = "failed copying object";
    checker.assert_panics(msg, line!() + 1, || {
        let _obj: Retained<RcTestObject> = unsafe { msg_send![&obj, copyReturningNull] };
    });

    let msg = "unexpected NULL returned from -[__RcTestObject methodReturningNull]";
    checker.assert_panics(msg, line!() + 1, || {
        let _obj: Retained<RcTestObject> = unsafe { msg_send![&obj, methodReturningNull] };
    });
}

fn test_catch_all(checker: &PanicChecker) {
    let obj: Retained<NSObject> = unsafe { msg_send![class!(NSArray), new] };

    let msg = "NSRangeException";
    checker.assert_panics(msg, line!() + 1, || {
        let _: *mut NSObject = unsafe { msg_send![&obj, objectAtIndex: 0usize] };
    });

    let msg = "NSRangeException";
    checker.assert_panics(msg, line!() + 1, || {
        let _: Retained<NSObject> = unsafe { msg_send![&obj, objectAtIndex: 0usize] };
    });
}

define_class!(
    #[unsafe(super(NSObject))]
    struct PanickingClass;

    impl PanickingClass {
        #[unsafe(method(panic))]
        fn _panic() -> *mut Self {
            panic!("panic in PanickingClass")
        }
    }
);

fn test_unwind(checker: &PanicChecker) {
    let msg = "panic in PanickingClass";
    let line = line!() - 7;
    checker.assert_panics(msg, line, || {
        let _: *mut NSObject = unsafe { msg_send![PanickingClass::class(), panic] };
    });
    checker.assert_panics(msg, line, || {
        let _: Retained<NSObject> = unsafe { msg_send![PanickingClass::class(), panic] };
    });
}

#[cfg(not(feature = "unstable-static-class"))]
fn test_unknown_class(checker: &PanicChecker) {
    let msg = "class NonExistentClass could not be found";
    checker.assert_panics(msg, line!() + 1, || {
        let _ = class!(NonExistentClass);
    });
}

Messung V0.5 in Prozent
C=83 H=86 G=83

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.