summaryrefslogtreecommitdiff
path: root/rust/tests
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2026-02-19 20:25:30 -0800
committerMason Reed <35282038+emesare@users.noreply.github.com>2026-02-23 00:09:44 -0800
commitdbd54d67a6d523f64615f653d82d8224cd09870a (patch)
tree7aecf160c624e415a47fd6dc6e9a2921963c9e23 /rust/tests
parentbfbb878c05220e1697aa550a23ad59911e546c17 (diff)
[Rust] Ensure proper lifetime management of `WebsocketClientCallback` objects
Diffstat (limited to 'rust/tests')
-rw-r--r--rust/tests/websocket.rs102
1 files changed, 77 insertions, 25 deletions
diff --git a/rust/tests/websocket.rs b/rust/tests/websocket.rs
index 2c25a810..19aacf4c 100644
--- a/rust/tests/websocket.rs
+++ b/rust/tests/websocket.rs
@@ -4,6 +4,8 @@ use binaryninja::websocket::{
register_websocket_provider, CoreWebsocketClient, CoreWebsocketProvider, WebsocketClient,
WebsocketClientCallback, WebsocketProvider,
};
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::RwLock;
struct MyWebsocketProvider {
core: CoreWebsocketProvider,
@@ -55,27 +57,50 @@ impl WebsocketClient for MyWebsocketClient {
#[derive(Default)]
struct MyClientCallbacks {
- data_read: Vec<u8>,
- did_disconnect: bool,
- did_error: bool,
+ data_read: RwLock<Vec<u8>>,
+ did_disconnect: AtomicBool,
+ did_error: AtomicBool,
}
impl WebsocketClientCallback for MyClientCallbacks {
- fn connected(&mut self) -> bool {
+ fn connected(&self) -> bool {
true
}
- fn disconnected(&mut self) {
- self.did_disconnect = true;
+ fn disconnected(&self) {
+ self.did_disconnect.store(true, Ordering::Relaxed);
}
- fn error(&mut self, msg: &str) {
+ fn error(&self, msg: &str) {
assert_eq!(msg, "error");
- self.did_error = true;
+ self.did_error.store(true, Ordering::Relaxed);
}
- fn read(&mut self, data: &[u8]) -> bool {
- self.data_read.extend_from_slice(data);
+ fn read(&self, data: &[u8]) -> bool {
+ self.data_read.write().unwrap().extend_from_slice(data);
+ true
+ }
+}
+
+#[derive(Default)]
+struct LifetimeCallbacks {
+ data: RwLock<Vec<u8>>,
+}
+
+impl WebsocketClientCallback for LifetimeCallbacks {
+ fn connected(&self) -> bool {
+ true
+ }
+
+ fn disconnected(&self) {}
+
+ fn error(&self, _msg: &str) {}
+
+ fn read(&self, data: &[u8]) -> bool {
+ if data == "sent: ".as_bytes() || data == "\n".as_bytes() {
+ return true;
+ }
+ assert_eq!(data, &self.data.read().unwrap()[..]);
true
}
}
@@ -86,12 +111,12 @@ fn reg_websocket_provider() {
let provider = register_websocket_provider::<MyWebsocketProvider>("RustWebsocketProvider");
let client = provider.create_client().unwrap();
let mut callback = MyClientCallbacks::default();
- let success = client.initialize_connection(
+ let connection = client.connect(
"url",
[("header".to_string(), "value".to_string())],
&mut callback,
);
- assert!(success, "Failed to initialize connection!");
+ assert!(connection.is_some(), "Failed to initialize connection!");
}
#[test]
@@ -101,24 +126,51 @@ fn listen_websocket_provider() {
let client = provider.create_client().unwrap();
let mut callback = MyClientCallbacks::default();
- client.initialize_connection(
- "url",
- [("header".to_string(), "value".to_string())],
- &mut callback,
- );
+ let connection = client
+ .connect(
+ "url",
+ [("header".to_string(), "value".to_string())],
+ &callback,
+ )
+ .expect("Failed to initialize connection!");
- assert!(client.write("test1".as_bytes()));
- assert!(client.write("test2".as_bytes()));
+ assert!(connection.write("test1".as_bytes()));
+ assert!(connection.write("test2".as_bytes()));
- client.notify_error("error");
- client.disconnect();
- drop(client);
+ connection.notify_error("error");
+ connection.disconnect();
assert_eq!(
- &callback.data_read[..],
+ &callback.data_read.read().unwrap()[..],
"sent: test1\nsent: test2\n".as_bytes()
);
// If we disconnected that means the error callback was not notified.
- assert!(!callback.did_disconnect);
- assert!(callback.did_error);
+ assert!(!callback.did_disconnect.load(Ordering::Relaxed));
+ assert!(callback.did_error.load(Ordering::Relaxed));
+}
+
+#[test]
+fn correct_websocket_client_lifetime() {
+ let _session = Session::new().expect("Failed to initialize session");
+ let provider = register_websocket_provider::<MyWebsocketProvider>("RustWebsocketProvider2");
+
+ let client = provider.create_client().unwrap();
+ let callback = LifetimeCallbacks::default();
+ let connection = client
+ .connect(
+ "url",
+ [("header".to_string(), "value".to_string())],
+ &callback,
+ )
+ .expect("Failed to initialize connection!");
+
+ println!("{:?}", callback.data);
+ callback
+ .data
+ .write()
+ .unwrap()
+ .extend(vec![0x55, 0x55, 0x55, 0x55, 0x55]);
+
+ assert!(connection.write(&[0x55, 0x55, 0x55, 0x55, 0x55]));
+ assert!(connection.write(&[0x55, 0x55, 0x55, 0x55, 0x55]));
}