1#![feature(async_closure)]
2
3use lazy_static::lazy_static;
4use nustify::Builder;
5use std::env;
6
7use tokio::task;
8use tokio::task::spawn_blocking;
9
10lazy_static! {
11 static ref KEY: String = env::var("IFTTT_TEST_WEBHOOK_KEY").unwrap();
12}
13
14pub struct TestNotifier {
15 message: Option<String>,
16}
17
18impl TestNotifier {
19 pub fn new() -> TestNotifier {
20 TestNotifier { message: None }
21 }
22 pub fn set_message(&mut self, message: String) {
23 self.message = Some(message);
24 }
25 pub fn new_with_message(message: String) -> TestNotifier {
26 TestNotifier {
27 message: Some(message),
28 }
29 }
30}
31
32impl Default for TestNotifier {
33 fn default() -> Self {
34 Self::new()
35 }
36}
37
38async fn do_notify(test_name: String, extra_message: Option<String>) {
39 println!("test_name: {test_name}");
40 println!("message: {:?}", extra_message.clone());
41 let extra_message = extra_message.unwrap_or_else(|| "no extra message".to_string());
42 let output = format!(
43 "test {} is done. also, my caller says: {}",
44 test_name,
45 extra_message.clone()
46 );
47 let notification = Builder::new(output.clone())
48 .title("Hello from Rust test notifier".to_owned())
49 .build();
50 nustify::send(¬ification, "nustify", &KEY).await.unwrap();
51}
52
53impl Drop for TestNotifier {
54 fn drop(&mut self) {
55 let mut found_my_drop = false; let mut printed_my_message = false; backtrace::trace(|frame| {
58 backtrace::resolve_frame(frame, |symbol| {
59 if !printed_my_message {
60 let sn = symbol
61 .name()
62 .map_or_else(|| "unknown".to_string(), |sn| format!("{sn:?}"));
63 if sn.contains("core::ptr::drop_in_place<test_notifier::TestNotifier>") {
65 found_my_drop = true;
66 } else if found_my_drop {
67 let msg = self.message.clone();
68 let rt = tokio::runtime::Runtime::new().unwrap();
69 let local = task::LocalSet::new();
70 local.block_on(&rt, async {
71 let join = task::spawn_local(async move {
72 spawn_blocking(move || do_notify(sn, msg))
73 .await
74 .unwrap()
75 .await;
76 });
77 join.await.unwrap();
78 });
79 printed_my_message = true;
80 }
81 }
82 });
83 true
84 });
85 }
86}
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn test_failing() {
93 let mut tn = TestNotifier::new();
94 tn.set_message("about to fail".to_string());
95 assert!(false);
96 }
97
98 #[test]
99 fn test_passing() {
100 let mut tn = TestNotifier::new();
101 tn.set_message("about to pass".to_string());
102 assert!(true);
103 }
104}