summaryrefslogtreecommitdiff
path: root/rust/tests/websocket.rs
diff options
context:
space:
mode:
authorRubens Brandao <git@rubens.io>2024-06-26 17:24:33 -0300
committerMason Reed <mason@vector35.com>2025-02-07 15:52:59 -0500
commita039d392b54170d236d9d993024e9eca38f701ce (patch)
treeac5900027386c9b4a1197689008c646eb59e0b80 /rust/tests/websocket.rs
parent3f0a217d7d097c0502af81e78a01ed3bf9f38761 (diff)
Implement Rust WebsocketProvider
Diffstat (limited to 'rust/tests/websocket.rs')
-rw-r--r--rust/tests/websocket.rs124
1 files changed, 124 insertions, 0 deletions
diff --git a/rust/tests/websocket.rs b/rust/tests/websocket.rs
new file mode 100644
index 00000000..9feb9381
--- /dev/null
+++ b/rust/tests/websocket.rs
@@ -0,0 +1,124 @@
+use binaryninja::headless::Session;
+use binaryninja::rc::Ref;
+use binaryninja::string::BnStrCompatible;
+use binaryninja::websocket::{
+ register_websocket_provider, CoreWebsocketClient, CoreWebsocketProvider, WebsocketClient,
+ WebsocketClientCallback, WebsocketProvider,
+};
+use rstest::*;
+
+#[fixture]
+#[once]
+fn session() -> Session {
+ Session::new().expect("Failed to initialize session")
+}
+
+struct MyWebsocketProvider {
+ core: CoreWebsocketProvider,
+}
+
+impl WebsocketProvider for MyWebsocketProvider {
+ type Client = MyWebsocketClient;
+
+ fn handle(&self) -> CoreWebsocketProvider {
+ self.core
+ }
+
+ fn from_core(core: CoreWebsocketProvider) -> Self {
+ MyWebsocketProvider { core }
+ }
+}
+
+struct MyWebsocketClient {
+ core: Ref<CoreWebsocketClient>,
+}
+
+impl WebsocketClient for MyWebsocketClient {
+ fn from_core(core: Ref<CoreWebsocketClient>) -> Self {
+ Self { core }
+ }
+
+ fn connect<I, K, V>(&self, host: &str, _headers: I) -> bool
+ where
+ I: IntoIterator<Item = (K, V)>,
+ K: BnStrCompatible,
+ V: BnStrCompatible,
+ {
+ assert_eq!(host, "url");
+ true
+ }
+
+ fn write(&self, data: &[u8]) -> bool {
+ if !self.core.notify_read("sent: ".as_bytes()) {
+ return false;
+ }
+ if !self.core.notify_read(data) {
+ return false;
+ }
+ self.core.notify_read("\n".as_bytes())
+ }
+
+ fn disconnect(&self) -> bool {
+ true
+ }
+}
+
+#[derive(Default)]
+struct MyClientCallbacks {
+ data_read: Vec<u8>,
+ did_disconnect: bool,
+ did_error: bool,
+}
+
+impl WebsocketClientCallback for MyClientCallbacks {
+ fn connected(&mut self) -> bool {
+ true
+ }
+
+ fn disconnected(&mut self) {
+ self.did_disconnect = true;
+ }
+
+ fn error(&mut self, msg: &str) {
+ assert_eq!(msg, "error");
+ self.did_error = true;
+ }
+
+ fn read(&mut self, data: &[u8]) -> bool {
+ self.data_read.extend_from_slice(data);
+ true
+ }
+}
+
+#[rstest]
+fn reg_websocket_provider(_session: &Session) {
+ let provider = register_websocket_provider::<MyWebsocketProvider>("RustWebsocketProvider");
+ let client = provider.create_client().unwrap();
+ let mut callback = MyClientCallbacks::default();
+ let success = client.initialize_connection("url", [("header", "value")], &mut callback);
+ assert!(success, "Failed to initialize connection!");
+}
+
+#[rstest]
+fn listen_websocket_provider(_session: &Session) {
+ let provider = register_websocket_provider::<MyWebsocketProvider>("RustWebsocketProvider2");
+
+ let client = provider.create_client().unwrap();
+ let mut callback = MyClientCallbacks::default();
+ client.initialize_connection("url", [("header", "value")], &mut callback);
+
+ assert!(client.write("test1".as_bytes()));
+ assert!(client.write("test2".as_bytes()));
+
+ client.notify_error("error");
+ client.disconnect();
+ drop(client);
+
+ assert_eq!(
+ &callback.data_read[..],
+ "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);
+}