summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJamie Murphy <hello@itsjamie.dev>2023-02-12 23:32:40 -0800
committerJamie Murphy <hello@itsjamie.dev>2023-02-12 23:32:40 -0800
commite1e21365233c8801164ed1c68da36f3235932ae0 (patch)
treec0570f2cfebbc859e51de9f9b472cc85187d5498
parent93685e72796e468eed66b9c1f148a6a713d18a5f (diff)
downloadgnome-todo-e1e21365233c8801164ed1c68da36f3235932ae0.tar.gz
local_provider: Switch to VFuncs
Currently, the tests *must* be ran sequentially
-rw-r--r--src/engine/providers/local.rs124
-rw-r--r--src/engine/utils.rs21
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()
+ }
+}