summaryrefslogtreecommitdiffstats
path: root/atuin-client/src/database.rs
diff options
context:
space:
mode:
Diffstat (limited to 'atuin-client/src/database.rs')
-rw-r--r--atuin-client/src/database.rs88
1 files changed, 88 insertions, 0 deletions
diff --git a/atuin-client/src/database.rs b/atuin-client/src/database.rs
index 160c6054..6a70ae33 100644
--- a/atuin-client/src/database.rs
+++ b/atuin-client/src/database.rs
@@ -6,6 +6,7 @@ use chrono::prelude::*;
use chrono::Utc;
use eyre::Result;
+use itertools::Itertools;
use sqlx::sqlite::{
SqliteConnectOptions, SqliteJournalMode, SqlitePool, SqlitePoolOptions, SqliteRow,
@@ -286,6 +287,7 @@ impl Database for Sqlite {
let query = match search_mode {
SearchMode::Prefix => query,
SearchMode::FullText => format!("%{}", query),
+ SearchMode::Fuzzy => query.split("").join("%"),
};
let res = sqlx::query(
@@ -318,3 +320,89 @@ impl Database for Sqlite {
Ok(res)
}
}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ async fn new_history_item(db: &mut impl Database, cmd: &str) -> Result<()> {
+ let history = History::new(
+ chrono::Utc::now(),
+ cmd.to_string(),
+ "/home/ellie".to_string(),
+ 0,
+ 1,
+ Some("beep boop".to_string()),
+ Some("booop".to_string()),
+ );
+ return db.save(&history).await;
+ }
+
+ #[tokio::test(flavor = "multi_thread")]
+ async fn test_search_prefix() {
+ let mut db = Sqlite::new("sqlite::memory:").await.unwrap();
+ new_history_item(&mut db, "ls /home/ellie").await.unwrap();
+
+ let mut results = db.search(None, SearchMode::Prefix, "ls").await.unwrap();
+ assert_eq!(results.len(), 1);
+
+ results = db.search(None, SearchMode::Prefix, "/home").await.unwrap();
+ assert_eq!(results.len(), 0);
+
+ results = db.search(None, SearchMode::Prefix, "ls ").await.unwrap();
+ assert_eq!(results.len(), 0);
+ }
+
+ #[tokio::test(flavor = "multi_thread")]
+ async fn test_search_fulltext() {
+ let mut db = Sqlite::new("sqlite::memory:").await.unwrap();
+ new_history_item(&mut db, "ls /home/ellie").await.unwrap();
+
+ let mut results = db.search(None, SearchMode::FullText, "ls").await.unwrap();
+ assert_eq!(results.len(), 1);
+
+ results = db
+ .search(None, SearchMode::FullText, "/home")
+ .await
+ .unwrap();
+ assert_eq!(results.len(), 1);
+
+ results = db.search(None, SearchMode::FullText, "ls ").await.unwrap();
+ assert_eq!(results.len(), 0);
+ }
+
+ #[tokio::test(flavor = "multi_thread")]
+ async fn test_search_fuzzy() {
+ let mut db = Sqlite::new("sqlite::memory:").await.unwrap();
+ new_history_item(&mut db, "ls /home/ellie").await.unwrap();
+ new_history_item(&mut db, "ls /home/frank").await.unwrap();
+ new_history_item(&mut db, "cd /home/ellie").await.unwrap();
+ new_history_item(&mut db, "/home/ellie/.bin/rustup")
+ .await
+ .unwrap();
+
+ let mut results = db.search(None, SearchMode::Fuzzy, "ls /").await.unwrap();
+ assert_eq!(results.len(), 2);
+
+ results = db.search(None, SearchMode::Fuzzy, "l/h/").await.unwrap();
+ assert_eq!(results.len(), 2);
+
+ results = db.search(None, SearchMode::Fuzzy, "/h/e").await.unwrap();
+ assert_eq!(results.len(), 3);
+
+ results = db.search(None, SearchMode::Fuzzy, "/hmoe/").await.unwrap();
+ assert_eq!(results.len(), 0);
+
+ results = db
+ .search(None, SearchMode::Fuzzy, "ellie/home")
+ .await
+ .unwrap();
+ assert_eq!(results.len(), 0);
+
+ results = db.search(None, SearchMode::Fuzzy, "lsellie").await.unwrap();
+ assert_eq!(results.len(), 1);
+
+ results = db.search(None, SearchMode::Fuzzy, " ").await.unwrap();
+ assert_eq!(results.len(), 3);
+ }
+}