Skip to content

Commit

Permalink
Group Messages Table/Impl/Tests (#310)
Browse files Browse the repository at this point in the history
* needs tests

* fmt

* fmt

* tests

* tests

* rand_bytes -> rand_vec

* use less data in unit tests

* use AsRef<[u8]>

* fmt

* 3 -> 2

* remove return value from group membership update statement

* AsRef<ID> -> AsRef<[u8]>
  • Loading branch information
insipx authored Nov 7, 2023
1 parent 129e3c4 commit e4a4fba
Show file tree
Hide file tree
Showing 9 changed files with 451 additions and 94 deletions.
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");
#[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

0 comments on commit e4a4fba

Please sign in to comment.