Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Group Messages Table/Impl/Tests #310

Merged
merged 13 commits into from
Nov 7, 2023
1 change: 0 additions & 1 deletion xmtp/src/storage/encrypted_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
//! if there are any outstanding database migrations and perform them as needed. When updating the
//! table definitions `schema.rs` must also be updated. To generate the correct schemas you can run
//! `diesel print-schema` or use `cargo run update-schema` which will update the files for you.
//!

pub mod models;
pub mod schema;
Expand Down
2 changes: 1 addition & 1 deletion xmtp_mls/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ where
provider: &XmtpOpenMlsProvider,
) -> Result<Identity, ClientBuilderError> {
let identity_option: Option<Identity> =
store.conn()?.fetch(())?.map(|i: StoredIdentity| i.into());
store.conn()?.fetch(&())?.map(|i: StoredIdentity| i.into());
debug!("Existing identity in store: {:?}", identity_option);
match self {
IdentityStrategy::CachedOnly => {
Expand Down
52 changes: 51 additions & 1 deletion xmtp_mls/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub trait Store<StorageConnection> {

pub trait Fetch<Model> {
type Key;
fn fetch(&mut self, key: Self::Key) -> Result<Option<Model>, StorageError>;
fn fetch(&mut self, key: &Self::Key) -> Result<Option<Model>, StorageError>;
}

pub trait Delete<Model> {
Expand All @@ -47,4 +47,54 @@ mod tests {
tracing_subscriber::fmt::init();
})
}

/// wrapper over assert!(matches!()) for Errors
/// assert_err!(fun(), StorageError::Explosion)
///
/// or the message variant,
/// assert_err!(fun(), StorageError::Explosion, "the storage did not explode");
#[macro_export]
macro_rules! assert_err {
( $x:expr , $y:pat $(,)? ) => {
assert!(matches!($x, Err($y)));
};

( $x:expr, $y:pat $(,)?, $($msg:tt)+) => {{
assert!(matches!($x, Err($y)), $($msg)+)
}}
}

/// wrapper over assert! macros for Ok's
///
/// Make sure something is Ok(_) without caring about return value.
/// assert_ok!(fun());
///
/// Against an expected value, e.g Ok(true)
/// assert_ok!(fun(), true);
///
/// or the message variant,
/// assert_ok!(fun(), Ok(_), "the storage is not ok");
insipx marked this conversation as resolved.
Show resolved Hide resolved
#[macro_export]
macro_rules! assert_ok {

( $e:expr ) => {
assert_ok!($e,)
};

( $e:expr, ) => {{
use std::result::Result::*;
match $e {
Ok(v) => v,
Err(e) => panic!("assertion failed: Err({:?})", e),
}
}};

( $x:expr , $y:expr $(,)? ) => {
assert_eq!($x, Ok($y.into()));
};

( $x:expr, $y:expr $(,)?, $($msg:tt)+) => {{
assert_eq!($x, Ok($y.into()), $($msg)+);
}}
}
}
68 changes: 49 additions & 19 deletions xmtp_mls/src/storage/encrypted_store/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ use diesel::{
sqlite::Sqlite,
};

use super::schema::groups;
use crate::impl_fetch;
use crate::impl_store;
use super::{schema::groups, DbConnection, EncryptedMessageStore};
use crate::{impl_fetch, impl_store, StorageError};

/// The Group ID type.
pub type ID = Vec<u8>;
Expand Down Expand Up @@ -43,6 +42,24 @@ impl StoredGroup {
}
}

impl EncryptedMessageStore {
/// Updates group membership state
pub fn update_group_membership<GroupId: AsRef<[u8]>>(
&self,
conn: &mut DbConnection,
id: GroupId,
state: GroupMembershipState,
) -> Result<(), StorageError> {
use super::schema::groups::dsl;

diesel::update(dsl::groups.find(id.as_ref()))
.set(dsl::membership_state.eq(state))
.execute(conn)?;

Ok(())
}
}

#[repr(i32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, AsExpression, FromSqlRow)]
#[diesel(sql_type = Integer)]
Expand Down Expand Up @@ -81,18 +98,30 @@ where
}

#[cfg(test)]
mod tests {
pub(crate) mod tests {
use super::*;
use crate::{
storage::encrypted_store::{schema::groups::dsl::groups, tests::with_store},
assert_ok,
storage::encrypted_store::{
schema::groups::dsl::groups,
tests::{rand_time, rand_vec, with_store},
},
Fetch, Store,
};

/// Generate a test group
pub fn generate_group(state: Option<GroupMembershipState>) -> StoredGroup {
StoredGroup {
id: rand_vec(),
created_at_ns: rand_time(),
membership_state: state.unwrap_or(GroupMembershipState::Allowed),
}
}

#[test]
fn it_stores_group() {
with_store(|store| {
let mut conn = store.conn().unwrap();
let test_group = StoredGroup::new(vec![0x0], 100, GroupMembershipState::Allowed);
with_store(|_, mut conn| {
let test_group = generate_group(None);

test_group.store(&mut conn).unwrap();
assert_eq!(groups.first::<StoredGroup>(&mut conn).unwrap(), test_group);
Expand All @@ -101,29 +130,30 @@ mod tests {

#[test]
fn it_fetches_group() {
with_store(|store| {
let mut conn = store.conn().unwrap();
let test_group = StoredGroup::new(vec![0x0], 100, GroupMembershipState::Allowed);
with_store(|_, mut conn| {
let test_group = generate_group(None);

diesel::insert_into(groups)
.values(test_group.clone())
.execute(&mut conn)
.unwrap();
let fetched_group = conn.fetch(vec![0x0]).ok().flatten().unwrap();
assert_eq!(test_group, fetched_group);

let fetched_group = Fetch::<StoredGroup>::fetch(&mut conn, &test_group.id);
assert_ok!(fetched_group, Some(test_group));
})
}

#[test]
fn it_updates_group_membership_state() {
with_store(|store| {
let id = vec![0x0];
let mut conn = store.conn().unwrap();
let test_group = StoredGroup::new(id.clone(), 100, GroupMembershipState::Pending);
with_store(|store, mut conn| {
let test_group = generate_group(Some(GroupMembershipState::Pending));

test_group.store(&mut conn).unwrap();
let updated_group = store
.update_group_membership(&mut conn, id, GroupMembershipState::Rejected)
store
.update_group_membership(&mut conn, &test_group.id, GroupMembershipState::Rejected)
.unwrap();

let updated_group: StoredGroup = conn.fetch(&test_group.id).ok().flatten().unwrap();
assert_eq!(
updated_group,
StoredGroup {
Expand Down
Loading
Loading