matrix-sdk: Support compiling to wasm32-unknown-unknown
parent
b6c0d4e3bb
commit
ef6104bc53
22
.travis.yml
22
.travis.yml
|
@ -20,6 +20,28 @@ jobs:
|
||||||
after_success:
|
after_success:
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
name: wasm32-unknown-unknown
|
||||||
|
before_script:
|
||||||
|
- |
|
||||||
|
cargo install wasm-bindgen-cli
|
||||||
|
rustup target add wasm32-unknown-unknown
|
||||||
|
wget https://github.com/emscripten-core/emsdk/archive/master.zip
|
||||||
|
unzip master.zip
|
||||||
|
./emsdk-master/emsdk install latest
|
||||||
|
./emsdk-master/emsdk activate latest
|
||||||
|
script:
|
||||||
|
- |
|
||||||
|
source emsdk-master/emsdk_env.sh
|
||||||
|
cd matrix_sdk/examples/wasm_send_message
|
||||||
|
cargo build --target wasm32-unknown-unknown
|
||||||
|
cd -
|
||||||
|
|
||||||
|
cd matrix_sdk_base
|
||||||
|
cargo test --target wasm32-unknown-unknown --no-default-features --features encryption
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- rustup component add rustfmt
|
- rustup component add rustfmt
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,10 @@ members = [
|
||||||
"matrix_sdk",
|
"matrix_sdk",
|
||||||
"matrix_sdk_base",
|
"matrix_sdk_base",
|
||||||
"matrix_sdk_test",
|
"matrix_sdk_test",
|
||||||
|
"matrix_sdk_test_macros",
|
||||||
"matrix_sdk_crypto",
|
"matrix_sdk_crypto",
|
||||||
"matrix_sdk_common",
|
"matrix_sdk_common",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
olm-sys = { git = "https://gitlab.gnome.org/stoically/olm-sys", branch = "wasm-target" }
|
||||||
|
|
|
@ -17,14 +17,14 @@ encryption = ["matrix-sdk-base/encryption"]
|
||||||
sqlite-cryptostore = ["matrix-sdk-base/sqlite-cryptostore"]
|
sqlite-cryptostore = ["matrix-sdk-base/sqlite-cryptostore"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures = "0.3.4"
|
|
||||||
http = "0.2.1"
|
http = "0.2.1"
|
||||||
reqwest = "0.10.4"
|
reqwest = "0.10.4"
|
||||||
serde_json = "1.0.52"
|
serde_json = "1.0.52"
|
||||||
thiserror = "1.0.16"
|
thiserror = "1.0.16"
|
||||||
tracing = "0.1.13"
|
tracing = "0.1.13"
|
||||||
url = "2.1.1"
|
url = "2.1.1"
|
||||||
uuid = { version = "0.8.1", features = ["v4"] }
|
futures-timer = "3.0.2"
|
||||||
|
|
||||||
|
|
||||||
matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" }
|
matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" }
|
||||||
|
|
||||||
|
@ -38,11 +38,6 @@ version = "0.2.4"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["std", "std-future"]
|
features = ["std", "std-future"]
|
||||||
|
|
||||||
[dependencies.tokio]
|
|
||||||
version = "0.2.20"
|
|
||||||
default-features = false
|
|
||||||
features = ["time"]
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
async-trait = "0.1.30"
|
async-trait = "0.1.30"
|
||||||
dirs = "2.0.2"
|
dirs = "2.0.2"
|
||||||
|
@ -54,3 +49,4 @@ tracing-subscriber = "0.2.5"
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
mockito = "0.25.1"
|
mockito = "0.25.1"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
futures = "0.3.4"
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
node_modules
|
||||||
|
pkg
|
||||||
|
target
|
||||||
|
Cargo.lock
|
||||||
|
*.swp
|
||||||
|
dist
|
||||||
|
package-lock.json
|
|
@ -0,0 +1,21 @@
|
||||||
|
[package]
|
||||||
|
name = "wasm"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["stoically <stoically@protonmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# Config mostly pulled from: https://github.com/rustwasm/wasm-bindgen/blob/master/examples/fetch/Cargo.toml
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
matrix-sdk = { path = "../..", default-features = false, features = ["encryption"] }
|
||||||
|
url = "2.1.1"
|
||||||
|
wasm-bindgen = { version = "0.2.62", features = ["serde-serialize"] }
|
||||||
|
wasm-bindgen-futures = "0.4.12"
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
olm-sys = { git = "https://gitlab.gnome.org/stoically/olm-sys", branch = "wasm-target" }
|
|
@ -0,0 +1,13 @@
|
||||||
|
## Example usage of matrix-rust-sdk from WASM
|
||||||
|
|
||||||
|
This requires [emscripten](https://github.com/emscripten-core/emscripten) to be installed and in PATH to compile successfully.
|
||||||
|
|
||||||
|
You can build the example locally with:
|
||||||
|
|
||||||
|
npm install
|
||||||
|
npm run serve
|
||||||
|
|
||||||
|
and then visiting http://localhost:8080 in a browser should run the example!
|
||||||
|
|
||||||
|
|
||||||
|
This example is loosely based off of [this example](https://github.com/seanmonstar/reqwest/tree/master/examples/wasm_github_fetch), an example usage of `fetch` from `wasm-bindgen`.
|
|
@ -0,0 +1,7 @@
|
||||||
|
const rust = import('./pkg');
|
||||||
|
|
||||||
|
rust
|
||||||
|
.then(m => {
|
||||||
|
return m.run()
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"build": "webpack",
|
||||||
|
"serve": "webpack-dev-server"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@wasm-tool/wasm-pack-plugin": "1.0.1",
|
||||||
|
"text-encoding": "^0.7.0",
|
||||||
|
"html-webpack-plugin": "^3.2.0",
|
||||||
|
"webpack": "^4.29.4",
|
||||||
|
"webpack-cli": "^3.1.1",
|
||||||
|
"webpack-dev-server": "^3.1.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
use matrix_sdk::{
|
||||||
|
events::room::message::{MessageEventContent, TextMessageEventContent},
|
||||||
|
identifiers::RoomId,
|
||||||
|
Client, ClientConfig,
|
||||||
|
};
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use url::Url;
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub async fn run() -> Result<JsValue, JsValue> {
|
||||||
|
let homeserver_url = "http://localhost:8008";
|
||||||
|
let username = "user";
|
||||||
|
let password = "password";
|
||||||
|
|
||||||
|
let client_config = ClientConfig::new();
|
||||||
|
let homeserver_url = Url::parse(&homeserver_url).unwrap();
|
||||||
|
let client = Client::new_with_config(homeserver_url, None, client_config).unwrap();
|
||||||
|
|
||||||
|
client
|
||||||
|
.login(username, password, None, Some("rust-sdk"))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let room_id = RoomId::try_from("!KpLWMcXcHKDMfEYNqA:localhost").unwrap();
|
||||||
|
|
||||||
|
let content = MessageEventContent::Text(TextMessageEventContent {
|
||||||
|
body: "hello from wasm".to_string(),
|
||||||
|
format: None,
|
||||||
|
formatted_body: None,
|
||||||
|
relates_to: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
client.room_send(&room_id, content, None).await.unwrap();
|
||||||
|
|
||||||
|
Ok(JsValue::NULL)
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
const path = require('path');
|
||||||
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: './index.js',
|
||||||
|
output: {
|
||||||
|
path: path.resolve(__dirname, 'dist'),
|
||||||
|
filename: 'index.js',
|
||||||
|
},
|
||||||
|
devtool: 'source-map',
|
||||||
|
plugins: [
|
||||||
|
new HtmlWebpackPlugin(),
|
||||||
|
new WasmPackPlugin({
|
||||||
|
crateDirectory: path.resolve(__dirname, ".")
|
||||||
|
}),
|
||||||
|
// Have this example work in Edge which doesn't ship `TextEncoder` or
|
||||||
|
// `TextDecoder` at this time.
|
||||||
|
new webpack.ProvidePlugin({
|
||||||
|
TextDecoder: ['text-encoding', 'TextDecoder'],
|
||||||
|
TextEncoder: ['text-encoding', 'TextEncoder']
|
||||||
|
})
|
||||||
|
],
|
||||||
|
mode: 'development'
|
||||||
|
};
|
|
@ -21,18 +21,18 @@ use std::result::Result as StdResult;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use uuid::Uuid;
|
use matrix_sdk_common::locks::RwLock;
|
||||||
|
use matrix_sdk_common::uuid::Uuid;
|
||||||
|
|
||||||
use futures::future::Future;
|
use futures_timer::Delay as sleep;
|
||||||
use tokio::sync::RwLock;
|
use std::future::Future;
|
||||||
use tokio::time::delay_for as sleep;
|
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
use tracing::{debug, warn};
|
use tracing::{debug, warn};
|
||||||
use tracing::{info, instrument, trace};
|
use tracing::{info, instrument, trace};
|
||||||
|
|
||||||
use http::Method as HttpMethod;
|
use http::Method as HttpMethod;
|
||||||
use http::Response as HttpResponse;
|
use http::Response as HttpResponse;
|
||||||
use reqwest::header::{HeaderValue, InvalidHeaderValue};
|
use reqwest::header::{HeaderValue, InvalidHeaderValue, AUTHORIZATION};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::events::room::message::MessageEventContent;
|
use crate::events::room::message::MessageEventContent;
|
||||||
|
@ -98,6 +98,7 @@ impl std::fmt::Debug for Client {
|
||||||
/// .state_store(Box::new(store));
|
/// .state_store(Box::new(store));
|
||||||
/// ```
|
/// ```
|
||||||
pub struct ClientConfig {
|
pub struct ClientConfig {
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
proxy: Option<reqwest::Proxy>,
|
proxy: Option<reqwest::Proxy>,
|
||||||
user_agent: Option<HeaderValue>,
|
user_agent: Option<HeaderValue>,
|
||||||
disable_ssl_verification: bool,
|
disable_ssl_verification: bool,
|
||||||
|
@ -106,9 +107,12 @@ pub struct ClientConfig {
|
||||||
|
|
||||||
impl std::fmt::Debug for ClientConfig {
|
impl std::fmt::Debug for ClientConfig {
|
||||||
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> StdResult<(), std::fmt::Error> {
|
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> StdResult<(), std::fmt::Error> {
|
||||||
fmt.debug_struct("ClientConfig")
|
let mut res = fmt.debug_struct("ClientConfig");
|
||||||
.field("proxy", &self.proxy)
|
|
||||||
.field("user_agent", &self.user_agent)
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
let res = res.field("proxy", &self.proxy);
|
||||||
|
|
||||||
|
res.field("user_agent", &self.user_agent)
|
||||||
.field("disable_ssl_verification", &self.disable_ssl_verification)
|
.field("disable_ssl_verification", &self.disable_ssl_verification)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
|
@ -137,6 +141,7 @@ impl ClientConfig {
|
||||||
/// .proxy("http://localhost:8080")
|
/// .proxy("http://localhost:8080")
|
||||||
/// .unwrap();
|
/// .unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub fn proxy(mut self, proxy: &str) -> Result<Self> {
|
pub fn proxy(mut self, proxy: &str) -> Result<Self> {
|
||||||
self.proxy = Some(reqwest::Proxy::all(proxy)?);
|
self.proxy = Some(reqwest::Proxy::all(proxy)?);
|
||||||
Ok(self)
|
Ok(self)
|
||||||
|
@ -262,27 +267,32 @@ impl Client {
|
||||||
|
|
||||||
let http_client = reqwest::Client::builder();
|
let http_client = reqwest::Client::builder();
|
||||||
|
|
||||||
let http_client = if config.disable_ssl_verification {
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
http_client.danger_accept_invalid_certs(true)
|
let http_client = {
|
||||||
} else {
|
let http_client = if config.disable_ssl_verification {
|
||||||
http_client
|
http_client.danger_accept_invalid_certs(true)
|
||||||
|
} else {
|
||||||
|
http_client
|
||||||
|
};
|
||||||
|
|
||||||
|
let http_client = match config.proxy {
|
||||||
|
Some(p) => http_client.proxy(p),
|
||||||
|
None => http_client,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut headers = reqwest::header::HeaderMap::new();
|
||||||
|
|
||||||
|
let user_agent = match config.user_agent {
|
||||||
|
Some(a) => a,
|
||||||
|
None => HeaderValue::from_str(&format!("matrix-rust-sdk {}", VERSION)).unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
|
headers.insert(reqwest::header::USER_AGENT, user_agent);
|
||||||
|
|
||||||
|
http_client.default_headers(headers)
|
||||||
};
|
};
|
||||||
|
|
||||||
let http_client = match config.proxy {
|
let http_client = http_client.build()?;
|
||||||
Some(p) => http_client.proxy(p),
|
|
||||||
None => http_client,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut headers = reqwest::header::HeaderMap::new();
|
|
||||||
|
|
||||||
let user_agent = match config.user_agent {
|
|
||||||
Some(a) => a,
|
|
||||||
None => HeaderValue::from_str(&format!("matrix-rust-sdk {}", VERSION)).unwrap(),
|
|
||||||
};
|
|
||||||
|
|
||||||
headers.insert(reqwest::header::USER_AGENT, user_agent);
|
|
||||||
|
|
||||||
let http_client = http_client.default_headers(headers).build()?;
|
|
||||||
|
|
||||||
let base_client = if let Some(store) = config.state_store {
|
let base_client = if let Some(store) = config.state_store {
|
||||||
BaseClient::new_with_state_store(session, store)?
|
BaseClient::new_with_state_store(session, store)?
|
||||||
|
@ -317,21 +327,21 @@ impl Client {
|
||||||
/// Returns the joined rooms this client knows about.
|
/// Returns the joined rooms this client knows about.
|
||||||
///
|
///
|
||||||
/// A `HashMap` of room id to `matrix::models::Room`
|
/// A `HashMap` of room id to `matrix::models::Room`
|
||||||
pub fn joined_rooms(&self) -> Arc<RwLock<HashMap<RoomId, Arc<tokio::sync::RwLock<Room>>>>> {
|
pub fn joined_rooms(&self) -> Arc<RwLock<HashMap<RoomId, Arc<RwLock<Room>>>>> {
|
||||||
self.base_client.joined_rooms()
|
self.base_client.joined_rooms()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the invited rooms this client knows about.
|
/// Returns the invited rooms this client knows about.
|
||||||
///
|
///
|
||||||
/// A `HashMap` of room id to `matrix::models::Room`
|
/// A `HashMap` of room id to `matrix::models::Room`
|
||||||
pub fn invited_rooms(&self) -> Arc<RwLock<HashMap<RoomId, Arc<tokio::sync::RwLock<Room>>>>> {
|
pub fn invited_rooms(&self) -> Arc<RwLock<HashMap<RoomId, Arc<RwLock<Room>>>>> {
|
||||||
self.base_client.invited_rooms()
|
self.base_client.invited_rooms()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the left rooms this client knows about.
|
/// Returns the left rooms this client knows about.
|
||||||
///
|
///
|
||||||
/// A `HashMap` of room id to `matrix::models::Room`
|
/// A `HashMap` of room id to `matrix::models::Room`
|
||||||
pub fn left_rooms(&self) -> Arc<RwLock<HashMap<RoomId, Arc<tokio::sync::RwLock<Room>>>>> {
|
pub fn left_rooms(&self) -> Arc<RwLock<HashMap<RoomId, Arc<RwLock<Room>>>>> {
|
||||||
self.base_client.left_rooms()
|
self.base_client.left_rooms()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -837,7 +847,7 @@ impl Client {
|
||||||
let response = if let Ok(r) = response {
|
let response = if let Ok(r) = response {
|
||||||
r
|
r
|
||||||
} else {
|
} else {
|
||||||
sleep(Duration::from_secs(1)).await;
|
sleep::new(Duration::from_secs(1)).await;
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -871,7 +881,7 @@ impl Client {
|
||||||
// the sync timeout.
|
// the sync timeout.
|
||||||
if let Some(t) = last_sync_time {
|
if let Some(t) = last_sync_time {
|
||||||
if now - t <= Duration::from_secs(1) {
|
if now - t <= Duration::from_secs(1) {
|
||||||
sleep(Duration::from_secs(1)).await;
|
sleep::new(Duration::from_secs(1)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,7 +933,8 @@ impl Client {
|
||||||
let session = self.base_client.session().read().await;
|
let session = self.base_client.session().read().await;
|
||||||
|
|
||||||
if let Some(session) = session.as_ref() {
|
if let Some(session) = session.as_ref() {
|
||||||
request_builder.bearer_auth(&session.access_token)
|
let header_value = format!("Bearer {}", &session.access_token);
|
||||||
|
request_builder.header(AUTHORIZATION, header_value)
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::AuthenticationRequired);
|
return Err(Error::AuthenticationRequired);
|
||||||
}
|
}
|
||||||
|
@ -980,7 +991,7 @@ impl Client {
|
||||||
/// # let homeserver = Url::parse("http://localhost:8080").unwrap();
|
/// # let homeserver = Url::parse("http://localhost:8080").unwrap();
|
||||||
/// # let mut client = Client::new(homeserver, None).unwrap();
|
/// # let mut client = Client::new(homeserver, None).unwrap();
|
||||||
/// # let room_id = RoomId::try_from("!test:localhost").unwrap();
|
/// # let room_id = RoomId::try_from("!test:localhost").unwrap();
|
||||||
/// use uuid::Uuid;
|
/// use matrix_sdk_common::uuid::Uuid;
|
||||||
///
|
///
|
||||||
/// let content = MessageEventContent::Text(TextMessageEventContent {
|
/// let content = MessageEventContent::Text(TextMessageEventContent {
|
||||||
/// body: "Hello world".to_owned(),
|
/// body: "Hello world".to_owned(),
|
||||||
|
@ -1203,7 +1214,7 @@ mod test {
|
||||||
use crate::identifiers::{EventId, RoomId, UserId};
|
use crate::identifiers::{EventId, RoomId, UserId};
|
||||||
|
|
||||||
use matrix_sdk_base::JsonStore;
|
use matrix_sdk_base::JsonStore;
|
||||||
use matrix_sdk_test::EventBuilder;
|
use matrix_sdk_test::{EventBuilder, EventsFile};
|
||||||
|
|
||||||
use mockito::{mock, Matcher};
|
use mockito::{mock, Matcher};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
@ -1250,11 +1261,8 @@ mod test {
|
||||||
let client = Client::new(homeserver, Some(session)).unwrap();
|
let client = Client::new(homeserver, Some(session)).unwrap();
|
||||||
|
|
||||||
let mut response = EventBuilder::default()
|
let mut response = EventBuilder::default()
|
||||||
.add_room_event_from_file("../test_data/events/member.json", RoomEvent::RoomMember)
|
.add_room_event(EventsFile::Member, RoomEvent::RoomMember)
|
||||||
.add_room_event_from_file(
|
.add_room_event(EventsFile::PowerLevels, RoomEvent::RoomPowerLevels)
|
||||||
"../test_data/events/power_levels.json",
|
|
||||||
RoomEvent::RoomPowerLevels,
|
|
||||||
)
|
|
||||||
.build_sync_response();
|
.build_sync_response();
|
||||||
|
|
||||||
client
|
client
|
||||||
|
@ -1651,7 +1659,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn room_message_send() {
|
async fn room_message_send() {
|
||||||
use uuid::Uuid;
|
use matrix_sdk_common::uuid::Uuid;
|
||||||
|
|
||||||
let homeserver = Url::from_str(&mockito::server_url()).unwrap();
|
let homeserver = Url::from_str(&mockito::server_url()).unwrap();
|
||||||
let user = UserId::try_from("@example:localhost").unwrap();
|
let user = UserId::try_from("@example:localhost").unwrap();
|
||||||
|
|
|
@ -26,8 +26,10 @@
|
||||||
//! destroyed.
|
//! destroyed.
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub use matrix_sdk_base::JsonStore;
|
||||||
pub use matrix_sdk_base::{EventEmitter, Room, Session};
|
pub use matrix_sdk_base::{EventEmitter, Room, Session};
|
||||||
pub use matrix_sdk_base::{JsonStore, RoomState, StateStore};
|
pub use matrix_sdk_base::{RoomState, StateStore};
|
||||||
pub use matrix_sdk_common::*;
|
pub use matrix_sdk_common::*;
|
||||||
pub use reqwest::header::InvalidHeaderValue;
|
pub use reqwest::header::InvalidHeaderValue;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
# required because of https://github.com/rustwasm/wasm-pack/issues/698
|
||||||
|
[target.wasm32-unknown-unknown]
|
||||||
|
runner = 'wasm-bindgen-test-runner'
|
|
@ -17,7 +17,6 @@ encryption = ["matrix-sdk-crypto"]
|
||||||
sqlite-cryptostore = ["matrix-sdk-crypto/sqlite-cryptostore"]
|
sqlite-cryptostore = ["matrix-sdk-crypto/sqlite-cryptostore"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures = "0.3.4"
|
|
||||||
async-trait = "0.1.30"
|
async-trait = "0.1.30"
|
||||||
serde = "1.0.106"
|
serde = "1.0.106"
|
||||||
serde_json = "1.0.52"
|
serde_json = "1.0.52"
|
||||||
|
@ -28,15 +27,20 @@ matrix-sdk-crypto = { version = "0.1.0", path = "../matrix_sdk_crypto", optional
|
||||||
# Misc dependencies
|
# Misc dependencies
|
||||||
thiserror = "1.0.16"
|
thiserror = "1.0.16"
|
||||||
|
|
||||||
[dependencies.tokio]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies.tokio]
|
||||||
version = "0.2.20"
|
version = "0.2.20"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["sync", "fs"]
|
features = ["sync", "fs"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
matrix-sdk-test = { version = "0.1.0", path = "../matrix_sdk_test" }
|
matrix-sdk-test = { version = "0.1.0", path = "../matrix_sdk_test" }
|
||||||
tokio = { version = "0.2.20", features = ["rt-threaded", "macros"] }
|
|
||||||
http = "0.2.1"
|
http = "0.2.1"
|
||||||
dirs = "2.0.2"
|
dirs = "2.0.2"
|
||||||
tracing-subscriber = "0.2.5"
|
tracing-subscriber = "0.2.5"
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
|
|
||||||
|
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
|
||||||
|
tokio = { version = "0.2.20", features = ["rt-threaded", "macros"] }
|
||||||
|
|
||||||
|
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
|
||||||
|
wasm-bindgen-test = "0.3.12"
|
|
@ -39,10 +39,10 @@ use crate::session::Session;
|
||||||
use crate::state::{ClientState, StateStore};
|
use crate::state::{ClientState, StateStore};
|
||||||
use crate::EventEmitter;
|
use crate::EventEmitter;
|
||||||
|
|
||||||
use std::ops::Deref;
|
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
use tokio::sync::Mutex;
|
use matrix_sdk_common::locks::Mutex;
|
||||||
use tokio::sync::RwLock;
|
use matrix_sdk_common::locks::RwLock;
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
use crate::api::r0::keys::{
|
use crate::api::r0::keys::{
|
||||||
|
@ -297,7 +297,7 @@ impl BaseClient {
|
||||||
/// Returns the joined rooms this client knows about.
|
/// Returns the joined rooms this client knows about.
|
||||||
///
|
///
|
||||||
/// A `HashMap` of room id to `matrix::models::Room`
|
/// A `HashMap` of room id to `matrix::models::Room`
|
||||||
pub fn joined_rooms(&self) -> Arc<RwLock<HashMap<RoomId, Arc<tokio::sync::RwLock<Room>>>>> {
|
pub fn joined_rooms(&self) -> Arc<RwLock<HashMap<RoomId, Arc<RwLock<Room>>>>> {
|
||||||
self.joined_rooms.clone()
|
self.joined_rooms.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ impl BaseClient {
|
||||||
/// Returns the invited rooms this client knows about.
|
/// Returns the invited rooms this client knows about.
|
||||||
///
|
///
|
||||||
/// A `HashMap` of room id to `matrix::models::Room`
|
/// A `HashMap` of room id to `matrix::models::Room`
|
||||||
pub fn invited_rooms(&self) -> Arc<RwLock<HashMap<RoomId, Arc<tokio::sync::RwLock<Room>>>>> {
|
pub fn invited_rooms(&self) -> Arc<RwLock<HashMap<RoomId, Arc<RwLock<Room>>>>> {
|
||||||
self.invited_rooms.clone()
|
self.invited_rooms.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,7 +365,7 @@ impl BaseClient {
|
||||||
/// Returns the left rooms this client knows about.
|
/// Returns the left rooms this client knows about.
|
||||||
///
|
///
|
||||||
/// A `HashMap` of room id to `matrix::models::Room`
|
/// A `HashMap` of room id to `matrix::models::Room`
|
||||||
pub fn left_rooms(&self) -> Arc<RwLock<HashMap<RoomId, Arc<tokio::sync::RwLock<Room>>>>> {
|
pub fn left_rooms(&self) -> Arc<RwLock<HashMap<RoomId, Arc<RwLock<Room>>>>> {
|
||||||
self.left_rooms.clone()
|
self.left_rooms.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -168,8 +168,13 @@ pub trait EventEmitter: Send + Sync {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use matrix_sdk_common::locks::Mutex;
|
||||||
|
use matrix_sdk_test::{async_test, sync_response, SyncResponseFile};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::Mutex;
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
pub use wasm_bindgen_test::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct EvEmitterTest(Arc<Mutex<Vec<String>>>);
|
pub struct EvEmitterTest(Arc<Mutex<Vec<String>>>);
|
||||||
|
|
||||||
|
@ -283,22 +288,10 @@ mod test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::api::r0::sync::sync_events::Response as SyncResponse;
|
|
||||||
use crate::identifiers::UserId;
|
use crate::identifiers::UserId;
|
||||||
use crate::{BaseClient, Session};
|
use crate::{BaseClient, Session};
|
||||||
|
|
||||||
use http::Response;
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
fn sync_response(file: &str) -> SyncResponse {
|
|
||||||
let mut file = File::open(file).unwrap();
|
|
||||||
let mut data = vec![];
|
|
||||||
file.read_to_end(&mut data).unwrap();
|
|
||||||
let response = Response::builder().body(data).unwrap();
|
|
||||||
SyncResponse::try_from(response).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_client() -> BaseClient {
|
fn get_client() -> BaseClient {
|
||||||
let session = Session {
|
let session = Session {
|
||||||
|
@ -309,7 +302,7 @@ mod test {
|
||||||
BaseClient::new(Some(session)).unwrap()
|
BaseClient::new(Some(session)).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[async_test]
|
||||||
async fn event_emitter_joined() {
|
async fn event_emitter_joined() {
|
||||||
let vec = Arc::new(Mutex::new(Vec::new()));
|
let vec = Arc::new(Mutex::new(Vec::new()));
|
||||||
let test_vec = Arc::clone(&vec);
|
let test_vec = Arc::clone(&vec);
|
||||||
|
@ -318,7 +311,7 @@ mod test {
|
||||||
let client = get_client();
|
let client = get_client();
|
||||||
client.add_event_emitter(emitter).await;
|
client.add_event_emitter(emitter).await;
|
||||||
|
|
||||||
let mut response = sync_response("../test_data/sync.json");
|
let mut response = sync_response(SyncResponseFile::Default);
|
||||||
client.receive_sync_response(&mut response).await.unwrap();
|
client.receive_sync_response(&mut response).await.unwrap();
|
||||||
|
|
||||||
let v = test_vec.lock().await;
|
let v = test_vec.lock().await;
|
||||||
|
@ -340,7 +333,7 @@ mod test {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[async_test]
|
||||||
async fn event_emitter_invite() {
|
async fn event_emitter_invite() {
|
||||||
let vec = Arc::new(Mutex::new(Vec::new()));
|
let vec = Arc::new(Mutex::new(Vec::new()));
|
||||||
let test_vec = Arc::clone(&vec);
|
let test_vec = Arc::clone(&vec);
|
||||||
|
@ -349,7 +342,7 @@ mod test {
|
||||||
let client = get_client();
|
let client = get_client();
|
||||||
client.add_event_emitter(emitter).await;
|
client.add_event_emitter(emitter).await;
|
||||||
|
|
||||||
let mut response = sync_response("../test_data/invite_sync.json");
|
let mut response = sync_response(SyncResponseFile::Invite);
|
||||||
client.receive_sync_response(&mut response).await.unwrap();
|
client.receive_sync_response(&mut response).await.unwrap();
|
||||||
|
|
||||||
let v = test_vec.lock().await;
|
let v = test_vec.lock().await;
|
||||||
|
@ -359,7 +352,7 @@ mod test {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[async_test]
|
||||||
async fn event_emitter_leave() {
|
async fn event_emitter_leave() {
|
||||||
let vec = Arc::new(Mutex::new(Vec::new()));
|
let vec = Arc::new(Mutex::new(Vec::new()));
|
||||||
let test_vec = Arc::clone(&vec);
|
let test_vec = Arc::clone(&vec);
|
||||||
|
@ -368,7 +361,7 @@ mod test {
|
||||||
let client = get_client();
|
let client = get_client();
|
||||||
client.add_event_emitter(emitter).await;
|
client.add_event_emitter(emitter).await;
|
||||||
|
|
||||||
let mut response = sync_response("../test_data/leave_sync.json");
|
let mut response = sync_response(SyncResponseFile::Leave);
|
||||||
client.receive_sync_response(&mut response).await.unwrap();
|
client.receive_sync_response(&mut response).await.unwrap();
|
||||||
|
|
||||||
let v = test_vec.lock().await;
|
let v = test_vec.lock().await;
|
||||||
|
|
|
@ -41,4 +41,6 @@ pub use event_emitter::EventEmitter;
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
pub use matrix_sdk_crypto::{Device, TrustState};
|
pub use matrix_sdk_crypto::{Device, TrustState};
|
||||||
pub use models::Room;
|
pub use models::Room;
|
||||||
pub use state::{JsonStore, StateStore};
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub use state::JsonStore;
|
||||||
|
pub use state::StateStore;
|
||||||
|
|
|
@ -143,6 +143,9 @@ mod test {
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
use wasm_bindgen_test::*;
|
||||||
|
|
||||||
use crate::events::{collections::all::RoomEvent, EventJson};
|
use crate::events::{collections::all::RoomEvent, EventJson};
|
||||||
use crate::identifiers::{RoomId, UserId};
|
use crate::identifiers::{RoomId, UserId};
|
||||||
use crate::Room;
|
use crate::Room;
|
||||||
|
|
|
@ -521,27 +521,17 @@ impl Room {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::api::r0::sync::sync_events::Response as SyncResponse;
|
|
||||||
use crate::events::room::member::MembershipState;
|
use crate::events::room::member::MembershipState;
|
||||||
use crate::identifiers::UserId;
|
use crate::identifiers::UserId;
|
||||||
use crate::{BaseClient, Session};
|
use crate::{BaseClient, Session};
|
||||||
use matrix_sdk_test::EventBuilder;
|
use matrix_sdk_test::{async_test, sync_response, EventBuilder, EventsFile, SyncResponseFile};
|
||||||
|
|
||||||
use http::Response;
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
use wasm_bindgen_test::*;
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Read;
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
fn sync_response(file: &str) -> SyncResponse {
|
|
||||||
let mut file = File::open(file).unwrap();
|
|
||||||
let mut data = vec![];
|
|
||||||
file.read_to_end(&mut data).unwrap();
|
|
||||||
let response = Response::builder().body(data).unwrap();
|
|
||||||
SyncResponse::try_from(response).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_client() -> BaseClient {
|
fn get_client() -> BaseClient {
|
||||||
let session = Session {
|
let session = Session {
|
||||||
access_token: "1234".to_owned(),
|
access_token: "1234".to_owned(),
|
||||||
|
@ -555,11 +545,11 @@ mod test {
|
||||||
RoomId::try_from("!SVkFJHzfwvuaIEawgC:localhost").unwrap()
|
RoomId::try_from("!SVkFJHzfwvuaIEawgC:localhost").unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[async_test]
|
||||||
async fn user_presence() {
|
async fn user_presence() {
|
||||||
let client = get_client();
|
let client = get_client();
|
||||||
|
|
||||||
let mut response = sync_response("../test_data/sync.json");
|
let mut response = sync_response(SyncResponseFile::Default);
|
||||||
|
|
||||||
client.receive_sync_response(&mut response).await.unwrap();
|
client.receive_sync_response(&mut response).await.unwrap();
|
||||||
|
|
||||||
|
@ -579,18 +569,15 @@ mod test {
|
||||||
assert!(room.deref().power_levels.is_some())
|
assert!(room.deref().power_levels.is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[async_test]
|
||||||
async fn room_events() {
|
async fn room_events() {
|
||||||
let client = get_client();
|
let client = get_client();
|
||||||
let room_id = get_room_id();
|
let room_id = get_room_id();
|
||||||
let user_id = UserId::try_from("@example:localhost").unwrap();
|
let user_id = UserId::try_from("@example:localhost").unwrap();
|
||||||
|
|
||||||
let mut response = EventBuilder::default()
|
let mut response = EventBuilder::default()
|
||||||
.add_room_event_from_file("../test_data/events/member.json", RoomEvent::RoomMember)
|
.add_room_event(EventsFile::Member, RoomEvent::RoomMember)
|
||||||
.add_room_event_from_file(
|
.add_room_event(EventsFile::PowerLevels, RoomEvent::RoomPowerLevels)
|
||||||
"../test_data/events/power_levels.json",
|
|
||||||
RoomEvent::RoomPowerLevels,
|
|
||||||
)
|
|
||||||
.build_sync_response();
|
.build_sync_response();
|
||||||
|
|
||||||
client.receive_sync_response(&mut response).await.unwrap();
|
client.receive_sync_response(&mut response).await.unwrap();
|
||||||
|
@ -611,14 +598,14 @@ mod test {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[async_test]
|
||||||
async fn calculate_aliases() {
|
async fn calculate_aliases() {
|
||||||
let client = get_client();
|
let client = get_client();
|
||||||
|
|
||||||
let room_id = get_room_id();
|
let room_id = get_room_id();
|
||||||
|
|
||||||
let mut response = EventBuilder::default()
|
let mut response = EventBuilder::default()
|
||||||
.add_state_event_from_file("../test_data/events/aliases.json", StateEvent::RoomAliases)
|
.add_state_event(EventsFile::Aliases, StateEvent::RoomAliases)
|
||||||
.build_sync_response();
|
.build_sync_response();
|
||||||
|
|
||||||
client.receive_sync_response(&mut response).await.unwrap();
|
client.receive_sync_response(&mut response).await.unwrap();
|
||||||
|
@ -629,17 +616,14 @@ mod test {
|
||||||
assert_eq!("tutorial", room.display_name());
|
assert_eq!("tutorial", room.display_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[async_test]
|
||||||
async fn calculate_alias() {
|
async fn calculate_alias() {
|
||||||
let client = get_client();
|
let client = get_client();
|
||||||
|
|
||||||
let room_id = get_room_id();
|
let room_id = get_room_id();
|
||||||
|
|
||||||
let mut response = EventBuilder::default()
|
let mut response = EventBuilder::default()
|
||||||
.add_state_event_from_file(
|
.add_state_event(EventsFile::Alias, StateEvent::RoomCanonicalAlias)
|
||||||
"../test_data/events/alias.json",
|
|
||||||
StateEvent::RoomCanonicalAlias,
|
|
||||||
)
|
|
||||||
.build_sync_response();
|
.build_sync_response();
|
||||||
|
|
||||||
client.receive_sync_response(&mut response).await.unwrap();
|
client.receive_sync_response(&mut response).await.unwrap();
|
||||||
|
@ -650,14 +634,14 @@ mod test {
|
||||||
assert_eq!("tutorial", room.display_name());
|
assert_eq!("tutorial", room.display_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[async_test]
|
||||||
async fn calculate_name() {
|
async fn calculate_name() {
|
||||||
let client = get_client();
|
let client = get_client();
|
||||||
|
|
||||||
let room_id = get_room_id();
|
let room_id = get_room_id();
|
||||||
|
|
||||||
let mut response = EventBuilder::default()
|
let mut response = EventBuilder::default()
|
||||||
.add_state_event_from_file("../test_data/events/name.json", StateEvent::RoomName)
|
.add_state_event(EventsFile::Name, StateEvent::RoomName)
|
||||||
.build_sync_response();
|
.build_sync_response();
|
||||||
|
|
||||||
client.receive_sync_response(&mut response).await.unwrap();
|
client.receive_sync_response(&mut response).await.unwrap();
|
||||||
|
@ -668,9 +652,9 @@ mod test {
|
||||||
assert_eq!("room name", room.display_name());
|
assert_eq!("room name", room.display_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[async_test]
|
||||||
async fn calculate_room_names_from_summary() {
|
async fn calculate_room_names_from_summary() {
|
||||||
let mut response = sync_response("../test_data/sync_with_summary.json");
|
let mut response = sync_response(SyncResponseFile::DefaultWithSummary);
|
||||||
|
|
||||||
let session = Session {
|
let session = Session {
|
||||||
access_token: "1234".to_owned(),
|
access_token: "1234".to_owned(),
|
||||||
|
|
|
@ -199,7 +199,7 @@ impl RoomMember {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use matrix_sdk_test::EventBuilder;
|
use matrix_sdk_test::{async_test, EventBuilder, EventsFile};
|
||||||
|
|
||||||
use crate::events::collections::all::RoomEvent;
|
use crate::events::collections::all::RoomEvent;
|
||||||
use crate::events::room::member::MembershipState;
|
use crate::events::room::member::MembershipState;
|
||||||
|
@ -208,6 +208,9 @@ mod test {
|
||||||
|
|
||||||
use crate::js_int::Int;
|
use crate::js_int::Int;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
use wasm_bindgen_test::*;
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
fn get_client() -> BaseClient {
|
fn get_client() -> BaseClient {
|
||||||
|
@ -223,18 +226,15 @@ mod test {
|
||||||
RoomId::try_from("!SVkFJHzfwvuaIEawgC:localhost").unwrap()
|
RoomId::try_from("!SVkFJHzfwvuaIEawgC:localhost").unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[async_test]
|
||||||
async fn room_member_events() {
|
async fn room_member_events() {
|
||||||
let client = get_client();
|
let client = get_client();
|
||||||
|
|
||||||
let room_id = get_room_id();
|
let room_id = get_room_id();
|
||||||
|
|
||||||
let mut response = EventBuilder::default()
|
let mut response = EventBuilder::default()
|
||||||
.add_room_event_from_file("../test_data/events/member.json", RoomEvent::RoomMember)
|
.add_room_event(EventsFile::Member, RoomEvent::RoomMember)
|
||||||
.add_room_event_from_file(
|
.add_room_event(EventsFile::PowerLevels, RoomEvent::RoomPowerLevels)
|
||||||
"../test_data/events/power_levels.json",
|
|
||||||
RoomEvent::RoomPowerLevels,
|
|
||||||
)
|
|
||||||
.build_sync_response();
|
.build_sync_response();
|
||||||
|
|
||||||
client.receive_sync_response(&mut response).await.unwrap();
|
client.receive_sync_response(&mut response).await.unwrap();
|
||||||
|
@ -250,19 +250,16 @@ mod test {
|
||||||
assert_eq!(member.power_level, Int::new(100));
|
assert_eq!(member.power_level, Int::new(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[async_test]
|
||||||
async fn member_presence_events() {
|
async fn member_presence_events() {
|
||||||
let client = get_client();
|
let client = get_client();
|
||||||
|
|
||||||
let room_id = get_room_id();
|
let room_id = get_room_id();
|
||||||
|
|
||||||
let mut response = EventBuilder::default()
|
let mut response = EventBuilder::default()
|
||||||
.add_room_event_from_file("../test_data/events/member.json", RoomEvent::RoomMember)
|
.add_room_event(EventsFile::Member, RoomEvent::RoomMember)
|
||||||
.add_room_event_from_file(
|
.add_room_event(EventsFile::PowerLevels, RoomEvent::RoomPowerLevels)
|
||||||
"../test_data/events/power_levels.json",
|
.add_presence_event(EventsFile::Presence)
|
||||||
RoomEvent::RoomPowerLevels,
|
|
||||||
)
|
|
||||||
.add_presence_event_from_file("../test_data/events/presence.json")
|
|
||||||
.build_sync_response();
|
.build_sync_response();
|
||||||
|
|
||||||
client.receive_sync_response(&mut response).await.unwrap();
|
client.receive_sync_response(&mut response).await.unwrap();
|
||||||
|
|
|
@ -16,7 +16,9 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub mod state_store;
|
pub mod state_store;
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub use state_store::JsonStore;
|
pub use state_store::JsonStore;
|
||||||
|
|
||||||
use crate::client::{BaseClient, Token};
|
use crate::client::{BaseClient, Token};
|
||||||
|
|
|
@ -6,9 +6,9 @@ use std::sync::{
|
||||||
Arc,
|
Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use matrix_sdk_common::locks::RwLock;
|
||||||
use tokio::fs as async_fs;
|
use tokio::fs as async_fs;
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::AsyncWriteExt;
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
use super::{ClientState, StateStore};
|
use super::{ClientState, StateStore};
|
||||||
use crate::identifiers::RoomId;
|
use crate::identifiers::RoomId;
|
||||||
|
|
|
@ -16,3 +16,15 @@ ruma-api = "0.16.0"
|
||||||
ruma-client-api = "0.8.0"
|
ruma-client-api = "0.8.0"
|
||||||
ruma-events = "0.21.0"
|
ruma-events = "0.21.0"
|
||||||
ruma-identifiers = "0.16.1"
|
ruma-identifiers = "0.16.1"
|
||||||
|
|
||||||
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
|
uuid = { version = "0.8.1", features = ["v4"] }
|
||||||
|
|
||||||
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies.tokio]
|
||||||
|
version = "0.2.20"
|
||||||
|
default-features = false
|
||||||
|
features = ["sync", "time", "fs"]
|
||||||
|
|
||||||
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
|
futures-locks = { git = "https://github.com/asomers/futures-locks", default-features = false }
|
||||||
|
uuid = { version = "0.8.1", features = ["v4", "wasm-bindgen"] }
|
|
@ -6,3 +6,7 @@ pub use ruma_api::{
|
||||||
pub use ruma_client_api as api;
|
pub use ruma_client_api as api;
|
||||||
pub use ruma_events as events;
|
pub use ruma_events as events;
|
||||||
pub use ruma_identifiers as identifiers;
|
pub use ruma_identifiers as identifiers;
|
||||||
|
|
||||||
|
pub use uuid;
|
||||||
|
|
||||||
|
pub mod locks;
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
// could switch to futures-lock completely at some point, blocker:
|
||||||
|
// https://github.com/asomers/futures-locks/issues/34
|
||||||
|
// https://www.reddit.com/r/rust/comments/f4zldz/i_audited_3_different_implementation_of_async/
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
pub use futures_locks::Mutex;
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
pub use futures_locks::RwLock;
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub use tokio::sync::Mutex;
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub use tokio::sync::RwLock;
|
|
@ -15,7 +15,6 @@ default = []
|
||||||
sqlite-cryptostore = ["sqlx"]
|
sqlite-cryptostore = ["sqlx"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures = "0.3.4"
|
|
||||||
async-trait = "0.1.30"
|
async-trait = "0.1.30"
|
||||||
|
|
||||||
matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" }
|
matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" }
|
||||||
|
@ -23,9 +22,8 @@ matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" }
|
||||||
olm-rs = { version = "0.5.0", features = ["serde"] }
|
olm-rs = { version = "0.5.0", features = ["serde"] }
|
||||||
serde = { version = "1.0.106", features = ["derive"] }
|
serde = { version = "1.0.106", features = ["derive"] }
|
||||||
serde_json = "1.0.52"
|
serde_json = "1.0.52"
|
||||||
cjson = "0.1.0"
|
cjson = { git = "https://github.com/stoically/cjson", rev = "24a82d94e339e27a62434493869f3dce62c60e0d" }
|
||||||
zeroize = { version = "1.1.0", features = ["zeroize_derive"] }
|
zeroize = { version = "1.1.0", features = ["zeroize_derive"] }
|
||||||
uuid = { version = "0.8.1", features = ["v4"] }
|
|
||||||
url = "2.1.1"
|
url = "2.1.1"
|
||||||
|
|
||||||
# Misc dependencies
|
# Misc dependencies
|
||||||
|
@ -39,12 +37,7 @@ version = "0.2.4"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["std", "std-future"]
|
features = ["std", "std-future"]
|
||||||
|
|
||||||
[dependencies.tokio]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies.sqlx]
|
||||||
version = "0.2.20"
|
|
||||||
default-features = false
|
|
||||||
features = ["sync", "time"]
|
|
||||||
|
|
||||||
[dependencies.sqlx]
|
|
||||||
version = "0.3.5"
|
version = "0.3.5"
|
||||||
optional = true
|
optional = true
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
|
@ -19,7 +19,6 @@ use std::mem;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::result::Result as StdResult;
|
use std::result::Result as StdResult;
|
||||||
use std::sync::atomic::{AtomicU64, Ordering};
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
use super::error::{EventError, MegolmError, MegolmResult, OlmError, OlmResult, SignatureError};
|
use super::error::{EventError, MegolmError, MegolmResult, OlmError, OlmResult, SignatureError};
|
||||||
use super::olm::{
|
use super::olm::{
|
||||||
|
@ -46,6 +45,7 @@ use matrix_sdk_common::events::{
|
||||||
Algorithm, EventJson, EventType,
|
Algorithm, EventJson, EventType,
|
||||||
};
|
};
|
||||||
use matrix_sdk_common::identifiers::{DeviceId, RoomId, UserId};
|
use matrix_sdk_common::identifiers::{DeviceId, RoomId, UserId};
|
||||||
|
use matrix_sdk_common::uuid::Uuid;
|
||||||
|
|
||||||
use api::r0::keys;
|
use api::r0::keys;
|
||||||
use api::r0::{
|
use api::r0::{
|
||||||
|
|
|
@ -16,7 +16,7 @@ use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use dashmap::{DashMap, ReadOnlyView};
|
use dashmap::{DashMap, ReadOnlyView};
|
||||||
use tokio::sync::Mutex;
|
use matrix_sdk_common::locks::Mutex;
|
||||||
|
|
||||||
use super::device::Device;
|
use super::device::Device;
|
||||||
use super::olm::{InboundGroupSession, Session};
|
use super::olm::{InboundGroupSession, Session};
|
||||||
|
|
|
@ -18,8 +18,8 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use matrix_sdk_common::locks::Mutex;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tokio::sync::Mutex;
|
|
||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
pub use olm_rs::account::IdentityKeys;
|
pub use olm_rs::account::IdentityKeys;
|
||||||
|
|
|
@ -16,7 +16,7 @@ use std::collections::HashSet;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use tokio::sync::Mutex;
|
use matrix_sdk_common::locks::Mutex;
|
||||||
|
|
||||||
use super::{Account, CryptoStore, InboundGroupSession, Result, Session};
|
use super::{Account, CryptoStore, InboundGroupSession, Result, Session};
|
||||||
use crate::device::Device;
|
use crate::device::Device;
|
||||||
|
|
|
@ -19,9 +19,9 @@ use std::sync::Arc;
|
||||||
use url::ParseError;
|
use url::ParseError;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use matrix_sdk_common::locks::Mutex;
|
||||||
use serde_json::Error as SerdeError;
|
use serde_json::Error as SerdeError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::sync::Mutex;
|
|
||||||
|
|
||||||
use super::device::Device;
|
use super::device::Device;
|
||||||
use super::memory_stores::UserDevices;
|
use super::memory_stores::UserDevices;
|
||||||
|
|
|
@ -22,9 +22,9 @@ use std::time::{Duration, Instant};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use matrix_sdk_common::locks::Mutex;
|
||||||
use olm_rs::PicklingMode;
|
use olm_rs::PicklingMode;
|
||||||
use sqlx::{query, query_as, sqlite::SqliteQueryAs, Connect, Executor, SqliteConnection};
|
use sqlx::{query, query_as, sqlite::SqliteQueryAs, Connect, Executor, SqliteConnection};
|
||||||
use tokio::sync::Mutex;
|
|
||||||
use zeroize::Zeroizing;
|
use zeroize::Zeroizing;
|
||||||
|
|
||||||
use super::{Account, CryptoStore, CryptoStoreError, InboundGroupSession, Result, Session};
|
use super::{Account, CryptoStore, CryptoStoreError, InboundGroupSession, Result, Session};
|
||||||
|
|
|
@ -14,3 +14,4 @@ version = "0.1.0"
|
||||||
serde_json = "1.0.52"
|
serde_json = "1.0.52"
|
||||||
http = "0.2.1"
|
http = "0.2.1"
|
||||||
matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" }
|
matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" }
|
||||||
|
matrix-sdk-test-macros = { path = "../matrix_sdk_test_macros" }
|
|
@ -1,7 +1,5 @@
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fs;
|
|
||||||
use std::panic;
|
use std::panic;
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use http::Response;
|
use http::Response;
|
||||||
|
|
||||||
|
@ -15,6 +13,34 @@ use matrix_sdk_common::events::{
|
||||||
EventJson, TryFromRaw,
|
EventJson, TryFromRaw,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub use matrix_sdk_test_macros::async_test;
|
||||||
|
|
||||||
|
/// Embedded event files
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum EventsFile {
|
||||||
|
Alias,
|
||||||
|
Aliases,
|
||||||
|
Create,
|
||||||
|
FullyRead,
|
||||||
|
HistoryVisibility,
|
||||||
|
JoinRules,
|
||||||
|
Member,
|
||||||
|
MessageEmote,
|
||||||
|
MessageNotice,
|
||||||
|
MessageText,
|
||||||
|
Name,
|
||||||
|
PowerLevels,
|
||||||
|
Presence,
|
||||||
|
RedactedInvalid,
|
||||||
|
RedactedState,
|
||||||
|
Redacted,
|
||||||
|
Redaction,
|
||||||
|
RoomAvatar,
|
||||||
|
Tag,
|
||||||
|
Topic,
|
||||||
|
Typing,
|
||||||
|
}
|
||||||
|
|
||||||
/// Easily create events to stream into either a Client or a `Room` for testing.
|
/// Easily create events to stream into either a Client or a `Room` for testing.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct EventBuilder {
|
pub struct EventBuilder {
|
||||||
|
@ -32,13 +58,16 @@ pub struct EventBuilder {
|
||||||
|
|
||||||
impl EventBuilder {
|
impl EventBuilder {
|
||||||
/// Add an event to the room events `Vec`.
|
/// Add an event to the room events `Vec`.
|
||||||
pub fn add_ephemeral_from_file<Ev: TryFromRaw, P: AsRef<Path>>(
|
pub fn add_ephemeral<Ev: TryFromRaw>(
|
||||||
mut self,
|
mut self,
|
||||||
path: P,
|
file: EventsFile,
|
||||||
variant: fn(Ev) -> Event,
|
variant: fn(Ev) -> Event,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let val = fs::read_to_string(path.as_ref())
|
let val: &str = match file {
|
||||||
.unwrap_or_else(|_| panic!("file not found {:?}", path.as_ref()));
|
EventsFile::Typing => include_str!("../../test_data/events/typing.json"),
|
||||||
|
_ => panic!("unknown ephemeral event file {:?}", file),
|
||||||
|
};
|
||||||
|
|
||||||
let event = serde_json::from_str::<EventJson<Ev>>(&val)
|
let event = serde_json::from_str::<EventJson<Ev>>(&val)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.deserialize()
|
.deserialize()
|
||||||
|
@ -48,13 +77,16 @@ impl EventBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add an event to the room events `Vec`.
|
/// Add an event to the room events `Vec`.
|
||||||
pub fn add_account_from_file<Ev: TryFromRaw, P: AsRef<Path>>(
|
#[allow(clippy::match_single_binding, unused)]
|
||||||
|
pub fn add_account<Ev: TryFromRaw>(
|
||||||
mut self,
|
mut self,
|
||||||
path: P,
|
file: EventsFile,
|
||||||
variant: fn(Ev) -> Event,
|
variant: fn(Ev) -> Event,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let val = fs::read_to_string(path.as_ref())
|
let val: &str = match file {
|
||||||
.unwrap_or_else(|_| panic!("file not found {:?}", path.as_ref()));
|
_ => panic!("unknown account event file {:?}", file),
|
||||||
|
};
|
||||||
|
|
||||||
let event = serde_json::from_str::<EventJson<Ev>>(&val)
|
let event = serde_json::from_str::<EventJson<Ev>>(&val)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.deserialize()
|
.deserialize()
|
||||||
|
@ -64,13 +96,17 @@ impl EventBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add an event to the room events `Vec`.
|
/// Add an event to the room events `Vec`.
|
||||||
pub fn add_room_event_from_file<Ev: TryFromRaw, P: AsRef<Path>>(
|
pub fn add_room_event<Ev: TryFromRaw>(
|
||||||
mut self,
|
mut self,
|
||||||
path: P,
|
file: EventsFile,
|
||||||
variant: fn(Ev) -> RoomEvent,
|
variant: fn(Ev) -> RoomEvent,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let val = fs::read_to_string(path.as_ref())
|
let val = match file {
|
||||||
.unwrap_or_else(|_| panic!("file not found {:?}", path.as_ref()));
|
EventsFile::Member => include_str!("../../test_data/events/member.json"),
|
||||||
|
EventsFile::PowerLevels => include_str!("../../test_data/events/power_levels.json"),
|
||||||
|
_ => panic!("unknown room event file {:?}", file),
|
||||||
|
};
|
||||||
|
|
||||||
let event = serde_json::from_str::<EventJson<Ev>>(&val)
|
let event = serde_json::from_str::<EventJson<Ev>>(&val)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.deserialize()
|
.deserialize()
|
||||||
|
@ -80,13 +116,18 @@ impl EventBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a state event to the state events `Vec`.
|
/// Add a state event to the state events `Vec`.
|
||||||
pub fn add_state_event_from_file<Ev: TryFromRaw, P: AsRef<Path>>(
|
pub fn add_state_event<Ev: TryFromRaw>(
|
||||||
mut self,
|
mut self,
|
||||||
path: P,
|
file: EventsFile,
|
||||||
variant: fn(Ev) -> StateEvent,
|
variant: fn(Ev) -> StateEvent,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let val = fs::read_to_string(path.as_ref())
|
let val = match file {
|
||||||
.unwrap_or_else(|_| panic!("file not found {:?}", path.as_ref()));
|
EventsFile::Alias => include_str!("../../test_data/events/alias.json"),
|
||||||
|
EventsFile::Aliases => include_str!("../../test_data/events/aliases.json"),
|
||||||
|
EventsFile::Name => include_str!("../../test_data/events/name.json"),
|
||||||
|
_ => panic!("unknown state event file {:?}", file),
|
||||||
|
};
|
||||||
|
|
||||||
let event = serde_json::from_str::<EventJson<Ev>>(&val)
|
let event = serde_json::from_str::<EventJson<Ev>>(&val)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.deserialize()
|
.deserialize()
|
||||||
|
@ -95,10 +136,13 @@ impl EventBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a presence event to the presence events `Vec`.
|
/// Add an presence event to the presence events `Vec`.
|
||||||
pub fn add_presence_event_from_file<P: AsRef<Path>>(mut self, path: P) -> Self {
|
pub fn add_presence_event(mut self, file: EventsFile) -> Self {
|
||||||
let val = fs::read_to_string(path.as_ref())
|
let val = match file {
|
||||||
.unwrap_or_else(|_| panic!("file not found {:?}", path.as_ref()));
|
EventsFile::Presence => include_str!("../../test_data/events/presence.json"),
|
||||||
|
_ => panic!("unknown presence event file {:?}", file),
|
||||||
|
};
|
||||||
|
|
||||||
let event = serde_json::from_str::<EventJson<PresenceEvent>>(&val)
|
let event = serde_json::from_str::<EventJson<PresenceEvent>>(&val)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.deserialize()
|
.deserialize()
|
||||||
|
@ -158,3 +202,26 @@ impl EventBuilder {
|
||||||
SyncResponse::try_from(response).unwrap()
|
SyncResponse::try_from(response).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Embedded sync reponse files
|
||||||
|
pub enum SyncResponseFile {
|
||||||
|
Default,
|
||||||
|
DefaultWithSummary,
|
||||||
|
Invite,
|
||||||
|
Leave,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get specific API responses for testing
|
||||||
|
pub fn sync_response(kind: SyncResponseFile) -> SyncResponse {
|
||||||
|
let data = match kind {
|
||||||
|
SyncResponseFile::Default => include_bytes!("../../test_data/sync.json").to_vec(),
|
||||||
|
SyncResponseFile::DefaultWithSummary => {
|
||||||
|
include_bytes!("../../test_data/sync_with_summary.json").to_vec()
|
||||||
|
}
|
||||||
|
SyncResponseFile::Invite => include_bytes!("../../test_data/invite_sync.json").to_vec(),
|
||||||
|
SyncResponseFile::Leave => include_bytes!("../../test_data/leave_sync.json").to_vec(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = Response::builder().body(data.to_vec()).unwrap();
|
||||||
|
SyncResponse::try_from(response).unwrap()
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
authors = ["stoically <stoically@protonmail.com>"]
|
||||||
|
description = "Helper macros to write tests for the Matrix SDK"
|
||||||
|
edition = "2018"
|
||||||
|
homepage = "https://github.com/matrix-org/matrix-rust-sdk"
|
||||||
|
keywords = ["matrix", "chat", "messaging", "ruma"]
|
||||||
|
license = "Apache-2.0"
|
||||||
|
name = "matrix-sdk-test-macros"
|
||||||
|
readme = "README.md"
|
||||||
|
repository = "https://github.com/matrix-org/matrix-rust-sdk"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
|
@ -0,0 +1,14 @@
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
|
||||||
|
/// Attribute to use `wasm_bindgen_test` for wasm32 targets and `tokio::test` for everything else
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn async_test(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
let attrs = r#"
|
||||||
|
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
|
||||||
|
#[cfg_attr(not(target_arch = "wasm32"), tokio::test)]
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let mut out: TokenStream = attrs.parse().unwrap();
|
||||||
|
out.extend(item);
|
||||||
|
out
|
||||||
|
}
|
Loading…
Reference in New Issue