anystack 0.6.0-alpha.3

Flexible and comprehensive error handling.
Documentation
mod common;

use common::*;

#[test]
fn downcast() {
    // downcast to contexts:
    let report = create_report();
    assert!(report.contains::<RootError>());
    let Err(report) = report.downcast::<ContextA>() else {
        panic!("ContextA should not be found")
    };
    assert_eq!(
        report
            .downcast::<RootError>()
            .expect("RootError should be found"),
        RootError
    );

    // downcast to attachments:
    let mut report = create_report();
    report = report.attach(AttachmentA(10));
    let report = report.change_context(ContextA(20));
    let Err(report) = report.downcast::<AttachmentB>() else {
        panic!("AttachmentB should not be found")
    };
    assert!(report.contains::<AttachmentA>());
    assert_eq!(
        report
            .downcast::<AttachmentA>()
            .expect("AttachmentA should be found")
            .0,
        10
    );
}

#[test]
fn downcast_ref() {
    let mut report = create_report();
    assert!(report.contains::<RootError>());

    assert!(!report.contains::<AttachmentA>());
    report = report.attach(AttachmentA(10));
    assert!(report.contains::<AttachmentA>());

    let attachment = report
        .downcast_ref::<AttachmentA>()
        .expect("Attachment not found");
    assert_eq!(attachment.0, 10);
}

#[test]
fn downcast_iter() {
    let report = create_report()
        .change_context(ContextA(42))
        .attach(ContextA(50))
        .attach(ContextA(60))
        .attach(ContextB(1))
        .change_context(ContextA(100))
        .attach(ContextB(2))
        .change_context(ContextB(3))
        .change_context(ContextA(300));

    let ctxes_a = report.downcast_iter::<ContextA>().collect::<Vec<_>>();
    assert_eq!(ctxes_a.len(), 5);
    assert_eq!(
        ctxes_a,
        vec![
            &ContextA(300),
            &ContextA(100),
            &ContextA(60),
            &ContextA(50),
            &ContextA(42)
        ]
    );

    let ctxes_b = report.downcast_iter::<ContextB>().collect::<Vec<_>>();
    assert_eq!(ctxes_b.len(), 3);
    assert_eq!(ctxes_b, vec![&ContextB(3), &ContextB(2), &ContextB(1)]);
}

#[test]
fn downcast_mut() {
    let mut report = create_report();
    assert!(report.contains::<RootError>());

    assert!(!report.contains::<AttachmentA>());
    report = report.attach(AttachmentA(10));
    assert!(report.contains::<AttachmentA>());

    let attachment = report
        .downcast_mut::<AttachmentA>()
        .expect("Attachment not found");
    attachment.0 += 10;

    let attachment = report
        .downcast_ref::<AttachmentA>()
        .expect("Attachment not found");
    assert_eq!(attachment.0, 20);
}

#[test]
fn downcast_iter_mut() {
    let mut report = create_report()
        .change_context(ContextA(42))
        .attach(ContextA(50))
        .attach(ContextA(60))
        .attach(ContextB(1))
        .change_context(ContextA(100))
        .attach(ContextB(2))
        .change_context(ContextB(3))
        .change_context(ContextA(300));

    let ctxes_a = report.downcast_iter_mut::<ContextA>().collect::<Vec<_>>();
    assert_eq!(ctxes_a.len(), 5);
    assert_eq!(
        ctxes_a,
        vec![
            &ContextA(300),
            &ContextA(100),
            &ContextA(60),
            &ContextA(50),
            &ContextA(42)
        ]
    );

    let ctxes_b = report.downcast_iter_mut::<ContextB>().collect::<Vec<_>>();
    assert_eq!(ctxes_b.len(), 3);
    assert_eq!(ctxes_b, vec![&ContextB(3), &ContextB(2), &ContextB(1)]);
}