upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/test_utils/src
diff options
context:
space:
mode:
Diffstat (limited to 'test_utils/src')
-rw-r--r--test_utils/src/lib.rs39
-rw-r--r--test_utils/src/relay.rs196
2 files changed, 233 insertions, 2 deletions
diff --git a/test_utils/src/lib.rs b/test_utils/src/lib.rs
index 0f870f6..a9d818c 100644
--- a/test_utils/src/lib.rs
+++ b/test_utils/src/lib.rs
@@ -9,6 +9,7 @@ use rexpect::session::{Options, PtySession};
9use strip_ansi_escapes::strip_str; 9use strip_ansi_escapes::strip_str;
10 10
11pub mod git; 11pub mod git;
12pub mod relay;
12 13
13pub static TEST_KEY_1_NSEC: &str = 14pub static TEST_KEY_1_NSEC: &str =
14 "nsec1ppsg5sm2aexq06juxmu9evtutr6jkwkhp98exxxvwamhru9lyx9s3rwseq"; 15 "nsec1ppsg5sm2aexq06juxmu9evtutr6jkwkhp98exxxvwamhru9lyx9s3rwseq";
@@ -353,7 +354,12 @@ impl CliTester {
353 } 354 }
354 355
355 /// returns what came before expected message 356 /// returns what came before expected message
356 pub fn expect_eventually(&mut self, message: &str) -> Result<String> { 357 pub fn expect_eventually<S>(&mut self, message: S) -> Result<String>
358 where
359 S: Into<String>,
360 {
361 let message_string = message.into();
362 let message = message_string.as_str();
357 let before = self 363 let before = self
358 .rexpect_session 364 .rexpect_session
359 .exp_string(message) 365 .exp_string(message)
@@ -361,8 +367,27 @@ impl CliTester {
361 Ok(before) 367 Ok(before)
362 } 368 }
363 369
364 pub fn expect(&mut self, message: &str) -> Result<&mut Self> { 370 pub fn expect_after_whitespace<S>(&mut self, message: S) -> Result<&mut Self>
371 where
372 S: Into<String>,
373 {
374 assert_eq!("", self.expect_eventually(message)?.trim());
375 Ok(self)
376 }
377
378 pub fn expect<S>(&mut self, message: S) -> Result<&mut Self>
379 where
380 S: Into<String>,
381 {
382 let message_string = message.into();
383 let message = message_string.as_str();
365 let before = self.expect_eventually(message)?; 384 let before = self.expect_eventually(message)?;
385 if !before.is_empty() {
386 std::fs::write("aaaaaaaaaaaa.txt", before.clone())?;
387
388 // let mut output = std::fs::File::create("aaaaaaaaaaa.txt")?;
389 // write!(output, "{}", *before);
390 }
366 ensure!( 391 ensure!(
367 before.is_empty(), 392 before.is_empty(),
368 format!( 393 format!(
@@ -397,6 +422,16 @@ impl CliTester {
397 assert_eq!(before, message); 422 assert_eq!(before, message);
398 Ok(()) 423 Ok(())
399 } 424 }
425
426 pub fn expect_end_with_whitespace(&mut self) -> Result<()> {
427 let before = self
428 .rexpect_session
429 .exp_eof()
430 .context("expected immediate end but got timed out")?;
431 assert_eq!(before.trim(), "");
432 Ok(())
433 }
434
400 pub fn expect_end_eventually(&mut self) -> Result<String> { 435 pub fn expect_end_eventually(&mut self) -> Result<String> {
401 self.rexpect_session 436 self.rexpect_session
402 .exp_eof() 437 .exp_eof()
diff --git a/test_utils/src/relay.rs b/test_utils/src/relay.rs
new file mode 100644
index 0000000..6de3618
--- /dev/null
+++ b/test_utils/src/relay.rs
@@ -0,0 +1,196 @@
1use std::collections::HashMap;
2
3use anyhow::{bail, Result};
4use nostr::{ClientMessage, RelayMessage};
5
6use crate::CliTester;
7
8type ListenerFunc<'a> = &'a dyn Fn(&mut Relay, u64, nostr::Event) -> Result<()>;
9
10pub struct Relay<'a> {
11 port: u16,
12 event_hub: simple_websockets::EventHub,
13 clients: HashMap<u64, simple_websockets::Responder>,
14 pub events: Vec<nostr::Event>,
15 event_listener: Option<ListenerFunc<'a>>,
16}
17
18impl<'a> Relay<'a> {
19 pub fn new(port: u16, event_listener: Option<ListenerFunc<'a>>) -> Self {
20 let event_hub = simple_websockets::launch(port)
21 .unwrap_or_else(|_| panic!("failed to listen on port {port}"));
22 Self {
23 port,
24 events: vec![],
25 event_hub,
26 clients: HashMap::new(),
27 event_listener,
28 }
29 }
30 pub fn respond_ok(
31 &self,
32 client_id: u64,
33 event: nostr::Event,
34 error: Option<&str>,
35 ) -> Result<bool> {
36 let responder = self.clients.get(&client_id).unwrap();
37
38 let ok_json = RelayMessage::Ok {
39 event_id: event.id,
40 status: error.is_none(),
41 message: error.unwrap_or("").to_string(),
42 }
43 .as_json();
44 // bail!(format!("{}", &ok_json));
45 Ok(responder.send(simple_websockets::Message::Text(ok_json)))
46 }
47 /// listen, collect events and responds with event_listener to events or
48 /// Ok(eventid) if event_listner is None
49 pub async fn listen_until_close(&mut self) -> Result<()> {
50 loop {
51 println!("polling");
52 match self.event_hub.poll_async().await {
53 simple_websockets::Event::Connect(client_id, responder) => {
54 // add their Responder to our `clients` map:
55 self.clients.insert(client_id, responder);
56 }
57 simple_websockets::Event::Disconnect(client_id) => {
58 // remove the disconnected client from the clients map:
59 println!("{} disconnected", self.port);
60 self.clients.remove(&client_id);
61 break;
62 }
63 simple_websockets::Event::Message(client_id, message) => {
64 println!(
65 "Received a message from client #{}: {:?}",
66 client_id, message
67 );
68
69 if let Ok(event) = get_nevent(message) {
70 self.events.push(event.clone());
71 if let Some(listner) = self.event_listener {
72 listner(self, client_id, event)?;
73 } else {
74 self.respond_ok(client_id, event, None)?;
75 }
76 }
77 }
78 }
79 }
80 println!("stop polling");
81 println!("we may not be polling but the tcplistner is still listening");
82 Ok(())
83 }
84}
85
86fn get_nevent(message: simple_websockets::Message) -> Result<nostr::Event> {
87 if let simple_websockets::Message::Text(s) = message.clone() {
88 let cm_result = ClientMessage::from_json(s);
89 if let Ok(ClientMessage::Event(event)) = cm_result {
90 let e = *event;
91 return Ok(e.clone());
92 }
93 }
94 bail!("not nostr event")
95}
96
97pub enum Message {
98 Event,
99 // Request,
100}
101
102/// leaves trailing whitespace and only compatible with --no-cli-spinners flag
103/// relays tuple: (title,successful,message)
104pub fn expect_send_with_progress(
105 p: &mut CliTester,
106 relays: Vec<(&str, bool, &str)>,
107 event_count: u16,
108) -> Result<()> {
109 p.expect(format!(
110 " - {} -------------------- 0/{event_count}",
111 &relays[0].0
112 ))?;
113 for relay in &relays {
114 // if successful
115 if relay.1 {
116 p.expect_eventually(format!(" y {}", relay.0))?;
117 } else {
118 p.expect_eventually(format!(" x {} {}", relay.0, relay.2))?;
119 }
120 // could check that before only contains titles:
121 // - # y x n/n and whitespace
122 // let before = p.expect_eventually(format!(" â {title}"))?;
123 // assert_eq!("", before.trim());
124 }
125 Ok(())
126}
127
128pub fn expect_send_with_progress_exact_interaction(
129 p: &mut CliTester,
130 titles: Vec<&str>,
131 count: u16,
132) -> Result<()> {
133 let whitespace_mid = " \r\n";
134 let whitespace_end = " \r\r\r";
135
136 p.expect(format!(
137 " - {} -------------------- 0/{count} \r",
138 titles[0]
139 ))?;
140 p.expect(format!(
141 " - {} -------------------- 0/{count}{whitespace_mid}",
142 titles[0]
143 ))?;
144 p.expect(format!(
145 " - {} -------------------- 0/{count} \r\r",
146 titles[1]
147 ))?;
148
149 let generate_text = |title: &str, num: u16, confirmed_complete: bool| -> String {
150 let symbol = if confirmed_complete && num.eq(&count) {
151 "â"
152 } else {
153 "-"
154 };
155 let bar = match (num, count) {
156 (0, _) => "--------------------",
157 (1, 2) => "###########---------",
158 (x, y) => {
159 if x.eq(&y) {
160 "####################"
161 } else {
162 "--unknown--"
163 }
164 }
165 };
166 format!(
167 " {symbol} {title} {bar} {num}/{count}{}",
168 if (&title).eq(titles.last().unwrap()) {
169 whitespace_end
170 } else {
171 whitespace_mid
172 }
173 )
174 };
175 let mut nums: HashMap<&str, u16> = HashMap::new();
176 for title in &titles {
177 nums.insert(title, 0);
178 p.expect(generate_text(title, 0, false))?;
179 }
180 loop {
181 for selected_title in &titles {
182 for title in &titles {
183 if title.eq(selected_title) {
184 let new_num = nums.get(title).unwrap() + 1;
185 if new_num.gt(&count) {
186 return Ok(());
187 }
188 nums.insert(title, new_num);
189 p.expect(generate_text(title, *nums.get(title).unwrap(), false))?;
190 } else {
191 p.expect(generate_text(title, *nums.get(title).unwrap(), true))?;
192 }
193 }
194 }
195 }
196}