From 5db62d4d0896436210009f894abb90f062116d7b Mon Sep 17 00:00:00 2001 From: CodeSteak Date: Tue, 7 May 2019 21:18:05 +0200 Subject: [PATCH] test search by using examples in doc. --- .../src/persistency/search/mod.rs | 115 ++++++++++++++++-- 1 file changed, 106 insertions(+), 9 deletions(-) diff --git a/server/texture-sync-server/src/persistency/search/mod.rs b/server/texture-sync-server/src/persistency/search/mod.rs index 70f03ed..c133618 100644 --- a/server/texture-sync-server/src/persistency/search/mod.rs +++ b/server/texture-sync-server/src/persistency/search/mod.rs @@ -10,26 +10,26 @@ pub struct Query { impl Query { pub fn search(&self, input: &mut Iterator) -> Vec { - let mut results: Vec<(u64, &Texture)> = Vec::new(); + let mut results: Vec<(i64, &Texture)> = Vec::new(); // We use pseudo decimal fixed point numbers here. // 1.000_000 = 1_000_000; // This is done, since algorithms like quicksort can fail on floats. - let required_score = self.required_score() * 1_000_000u64; + let required_score = self.required_score() * 1_000_000i64; - for texture in input { - let mut score = 0u64; + 'texture_loop: for texture in input { + let mut score = 0i64; for (pos, filter) in self.filters.iter().enumerate() { match filter.score(texture) { Score::RequiredMatch(true) => (), Score::RequiredMatch(false) => { // skip this texture - continue; + continue 'texture_loop; } Score::Match(true) => { - score += 1_000_000u64 * (1 + (0.1 / f64::sqrt(pos as f64 + 1.0)) as u64); + score += 1_000_000i64 + ((100_000.0 / f64::sqrt(pos as f64 + 1.0)) as i64); } Score::Match(false) => (), } @@ -40,7 +40,7 @@ impl Query { } } - results.sort_by_key(|(score, _)| *score); + results.sort_by_key(|(score, _)| score * -1); results .iter() @@ -48,8 +48,8 @@ impl Query { .collect::>() } - fn required_score(&self) -> u64 { - let non_special = self.filters.iter().filter(|f| !f.is_special()).count() as u64; + fn required_score(&self) -> i64 { + let non_special = self.filters.iter().filter(|f| !f.is_special()).count() as i64; // ceil(non_special / 2) (non_special + 1) / 2 @@ -66,3 +66,100 @@ impl Query { Ok(result) } } + +#[cfg(test)] +/// These tests check against the example section in the search design document. +mod test { + use super::*; + use std::str::FromStr; + + /// just a shorthand + fn tex(id: i32, name: &str, tags: &str, added_on: &str, resolution: u64) -> Texture { + Texture { + id: format!("{}", id), // Id should actaly be a uuid, but for testing this is fine. + name: name.to_string(), + tags: tags.split(",").map(|s| s.trim().to_string()).collect(), + added_on: Date::from_str(added_on).unwrap(), + resolution: (resolution, resolution), + format: TextureFormat::JPEG, + texture_hash: Sha256::from_data(b"Some Hash"), + } + } + + // data of example section of search document. + fn test_data() -> Vec { + vec![ + tex( + 1, + "wood_185841", + "Holz, Dunkel, Rot, Edel", + "2019-05-15", + 4 * 1024, + ), + tex(2, "wood_84846", "Holz, Hell", "2019-05-13", 2 * 1024), + tex(3, "silk_large", "Stoff, Rot, Edel", "2018-01-01", 8 * 1024), + tex(4, "cotton_xxx", "Stoff, Rot, Rau", "2018-02-01", 2048), + tex(5, "green_frabric", "GrĂ¼n, Stoff", "2018-03-01", 1024), + tex(6, "tin54_45", "Metall, Hell", "2018-03-01", 4 * 1024), + tex(7, "copper4_1k", "Rot, Metall", "2016-03-01", 1024), + tex( + 8, + "rusty_metall", + "Rot, Metall, Rost, Dunkel", + "2015-03-01", + 8 * 1024, + ), + ] + } + + fn assert_query(query: &str, expected: Vec) { + let q = Query::parse( + &query + .split_whitespace() + .map(|s| s.to_string()) + .collect::>(), + ) + .unwrap(); + + let data = test_data(); + + let result = q.search(&mut data.iter()); + + let only_ids = result + .into_iter() + .map(|tex| tex.id.parse::().unwrap()) + .collect::>(); + + assert_eq!(only_ids, expected) + } + + #[test] + fn test_examples_from_doc_1() { + assert_query("Holz Dunkel", vec![1, 2, 8]); + } + + #[test] + fn test_examples_from_doc_2() { + assert_query("n:wood_", vec![1, 2]); + } + + #[test] + fn test_examples_from_doc_3() { + assert_query("before:2019-05-31 after:2019-04-30", vec![1, 2]); + } + + #[test] + fn test_examples_from_doc_4() { + assert_query("Stoff Rot Edel", vec![3, 4, 1]); + } + + #[test] + fn test_examples_from_doc_5() { + assert_query("Stoff Rot !Edel", vec![4, 3, 5, 7, 8]); + } + + #[test] + fn test_examples_from_doc_6() { + assert_query("Metall Dunkel res:4k", vec![8, 6, 1]); + } +}