diff options
author | Jamie Murphy <hello@itsjamie.dev> | 2023-02-12 23:32:40 -0800 |
---|---|---|
committer | Jamie Murphy <hello@itsjamie.dev> | 2023-02-12 23:32:40 -0800 |
commit | e1e21365233c8801164ed1c68da36f3235932ae0 (patch) | |
tree | c0570f2cfebbc859e51de9f9b472cc85187d5498 | |
parent | 93685e72796e468eed66b9c1f148a6a713d18a5f (diff) | |
download | gnome-todo-e1e21365233c8801164ed1c68da36f3235932ae0.tar.gz |
local_provider: Switch to VFuncs
Currently, the tests *must* be ran sequentially
-rw-r--r-- | src/engine/providers/local.rs | 124 | ||||
-rw-r--r-- | src/engine/utils.rs | 21 |
2 files changed, 92 insertions, 53 deletions
diff --git a/src/engine/providers/local.rs b/src/engine/providers/local.rs index 22bbab07..c663ad46 100644 --- a/src/engine/providers/local.rs +++ b/src/engine/providers/local.rs @@ -47,8 +47,7 @@ where } mod imp { - use async_trait::async_trait; - use gtk::gio::ThemedIcon; + use gtk::gio::{GioFuture, ThemedIcon}; use super::*; use crate::{schema, task::Task, utils::Iso8601}; @@ -83,58 +82,64 @@ mod imp { } } - #[async_trait] impl ProviderImpl for LocalProvider { - async fn create_task(&self, title: &str) -> anyhow::Result<Task> { - let task = Task::default(); - task.set_title(title); - - let mut connection = self.pool().get().expect("Expected a Connection"); - let fields = vec![( - schema::tasks::dsl::id.eq(task.id()), - schema::tasks::dsl::title.eq(task.title()), - schema::tasks::dsl::description.eq(task.description()), - schema::tasks::dsl::due_date.eq(task.due_date()), - schema::tasks::dsl::completed.eq(task.completed()), - schema::tasks::dsl::priority.eq(task.priority()), - schema::tasks::dsl::created.eq(task.created()), - schema::tasks::dsl::last_modified.eq(task.last_modified()), - schema::tasks::dsl::modification_count.eq(task.modification_count()), - )]; - - diesel::insert_into(schema::tasks::dsl::tasks) - .values(fields) - .execute(&mut connection) - .unwrap(); - - drop(connection); - - Ok(task) - } - - async fn update_task(&self, task: &Task) -> anyhow::Result<bool> { - let current_time = chrono::Utc::now().naive_utc().to_iso8601(); - let mut connection = self.pool().get().expect("Expected a Connection"); + fn create_task(&self, obj: &Provider, title: &str) -> PinnedFuture<Task> { + let _self = self.obj().clone(); + let _title = title.to_string(); - task.set_last_modified(current_time); - task.set_modification_count(task.modification_count() + 1); + Box::pin(GioFuture::new(obj, move |_, _, send| { + let task = Task::default(); + task.set_title(_title); - // TODO: Search for the properties that actually need to be updated - diesel::update(schema::tasks::dsl::tasks) - .filter(schema::tasks::dsl::id.eq(task.id())) - .set(( + let mut connection = _self.imp().pool().get().expect("Expected a Connection"); + let fields = vec![( + schema::tasks::dsl::id.eq(task.id()), schema::tasks::dsl::title.eq(task.title()), schema::tasks::dsl::description.eq(task.description()), schema::tasks::dsl::due_date.eq(task.due_date()), schema::tasks::dsl::completed.eq(task.completed()), schema::tasks::dsl::priority.eq(task.priority()), + schema::tasks::dsl::created.eq(task.created()), schema::tasks::dsl::last_modified.eq(task.last_modified()), schema::tasks::dsl::modification_count.eq(task.modification_count()), - )) - .execute(&mut connection) - .unwrap(); + )]; + + diesel::insert_into(schema::tasks::dsl::tasks) + .values(fields) + .execute(&mut connection) + .unwrap(); + + send.resolve(Ok(task)) + })) + } - Ok(true) + fn update_task(&self, obj: &Provider, task: &Task) -> PinnedFuture<()> { + let _self = self.obj().clone(); + let _task = task.clone(); + Box::pin(GioFuture::new(obj, move |_, _, send| { + let current_time = chrono::Utc::now().naive_utc().to_iso8601(); + let mut connection = _self.imp().pool().get().expect("Expected a Connection"); + + _task.set_last_modified(current_time); + _task.set_modification_count(_task.modification_count() + 1); + + // TODO: Search for the properties that actually need to be updated + diesel::update(schema::tasks::dsl::tasks) + .filter(schema::tasks::dsl::id.eq(_task.id())) + .set(( + schema::tasks::dsl::title.eq(_task.title()), + schema::tasks::dsl::description.eq(_task.description()), + schema::tasks::dsl::due_date.eq(_task.due_date()), + schema::tasks::dsl::completed.eq(_task.completed()), + schema::tasks::dsl::priority.eq(_task.priority()), + schema::tasks::dsl::last_modified.eq(_task.last_modified()), + schema::tasks::dsl::modification_count.eq(_task.modification_count()), + )) + .execute(&mut connection) + .unwrap(); + + send.resolve(Ok(())) + })) } } @@ -160,25 +165,38 @@ impl Default for LocalProvider { mod tests { use std::{thread, time}; - use futures::executor::block_on; - use super::*; + use crate::utils::tests::run_in_main_loop; #[test] fn test_save_task() { let provider = LocalProvider::default(); - block_on(provider.imp().create_task("Test Task")).unwrap(); + run_in_main_loop(move |main_loop| { + provider + .upcast::<Provider>() + .create_task_async("Test Task", None, move |_, _| main_loop.quit()); + }); } #[test] fn test_update_task() { let provider = LocalProvider::default(); - let task = block_on(provider.imp().create_task("Test Task")).unwrap(); - task.set_description("Test Description"); - - thread::sleep(time::Duration::from_secs(5)); - - block_on(provider.imp().update_task(&task)).unwrap(); - assert_eq!(task.modification_count(), 1); + run_in_main_loop(move |main_loop| { + provider.upcast::<Provider>().create_task_async( + "Test Task", + None, + move |task, provider| { + task.set_description("Test Description"); + + thread::sleep(time::Duration::from_secs(5)); + + let _task = task.clone(); + provider.update_task_async(&task, None, move |_, _| { + main_loop.quit(); + assert_eq!(_task.modification_count(), 1); + }); + }, + ); + }); } } diff --git a/src/engine/utils.rs b/src/engine/utils.rs index f907db07..3271f835 100644 --- a/src/engine/utils.rs +++ b/src/engine/utils.rs @@ -56,3 +56,24 @@ impl Iso8601 for DateTime<Local> { } } } + +pub mod tests { + use gtk::glib::{MainContext, MainLoop}; + use once_cell::sync::Lazy; + + static MAINLOOP: Lazy<MainLoop> = + Lazy::new(|| MainLoop::new(Some(&MainContext::default()), false)); + + /// Runs a function inside the MainLoop. + /// Use `main_loop.quit()` to exit the MainLoop + pub fn run_in_main_loop<F>(func: F) -> MainLoop + where + F: FnOnce(MainLoop) + 'static, + { + let ctx = MainContext::default(); + let cloned_loop = MAINLOOP.clone(); + ctx.invoke_local(move || func(cloned_loop)); + MAINLOOP.run(); + MAINLOOP.clone() + } +} |