Federated blogging application, thanks to ActivityPub https://joinplu.me
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

253 lines
8.3 KiB

  1. mod query;
  2. mod searcher;
  3. mod tokenizer;
  4. pub use self::query::PlumeQuery as Query;
  5. pub use self::searcher::*;
  6. pub use self::tokenizer::TokenizerKind;
  7. #[cfg(test)]
  8. pub(crate) mod tests {
  9. use super::{Query, Searcher};
  10. use diesel::Connection;
  11. use plume_common::utils::random_hex;
  12. use std::env::temp_dir;
  13. use std::str::FromStr;
  14. use crate::{
  15. blogs::tests::fill_database,
  16. config::SearchTokenizerConfig,
  17. post_authors::*,
  18. posts::{NewPost, Post},
  19. safe_string::SafeString,
  20. tests::db,
  21. tests::pool,
  22. CONFIG,
  23. };
  24. pub(crate) fn get_searcher(tokenizers: &SearchTokenizerConfig) -> Searcher {
  25. let dir = temp_dir().join(&format!("plume-test-{}", random_hex()));
  26. if dir.exists() {
  27. Searcher::open(&dir, pool(), tokenizers)
  28. } else {
  29. Searcher::create(&dir, pool(), tokenizers)
  30. }
  31. .unwrap()
  32. }
  33. #[test]
  34. fn get_first_token() {
  35. let vector = vec![
  36. ("+\"my token\" other", ("+\"my token\"", " other")),
  37. ("-\"my token\" other", ("-\"my token\"", " other")),
  38. (" \"my token\" other", ("\"my token\"", " other")),
  39. ("\"my token\" other", ("\"my token\"", " other")),
  40. ("+my token other", ("+my", " token other")),
  41. ("-my token other", ("-my", " token other")),
  42. (" my token other", ("my", " token other")),
  43. ("my token other", ("my", " token other")),
  44. ("+\"my token other", ("+\"my token other", "")),
  45. ("-\"my token other", ("-\"my token other", "")),
  46. (" \"my token other", ("\"my token other", "")),
  47. ("\"my token other", ("\"my token other", "")),
  48. ];
  49. for (source, res) in vector {
  50. assert_eq!(Query::get_first_token(source), res);
  51. }
  52. }
  53. #[test]
  54. fn from_str() {
  55. let vector = vec![
  56. ("", ""),
  57. ("a query", "a query"),
  58. ("\"a query\"", "\"a query\""),
  59. ("+a -\"query\"", "+a -query"),
  60. ("title:\"something\" a query", "a query title:something"),
  61. ("-title:\"something\" a query", "a query -title:something"),
  62. ("author:user@domain", "author:user@domain"),
  63. ("-author:@user@domain", "-author:user@domain"),
  64. ("before:2017-11-05 before:2018-01-01", "before:2017-11-05"),
  65. ("after:2017-11-05 after:2018-01-01", "after:2018-01-01"),
  66. ];
  67. for (source, res) in vector {
  68. assert_eq!(&Query::from_str(source).unwrap().to_string(), res);
  69. assert_eq!(Query::new().parse_query(source).to_string(), res);
  70. }
  71. }
  72. #[test]
  73. fn setters() {
  74. let vector = vec![
  75. ("something", "title:something"),
  76. ("+something", "+title:something"),
  77. ("-something", "-title:something"),
  78. ("+\"something\"", "+title:something"),
  79. ("+some thing", "+title:\"some thing\""),
  80. ];
  81. for (source, res) in vector {
  82. assert_eq!(&Query::new().title(source, None).to_string(), res);
  83. }
  84. let vector = vec![
  85. ("something", "author:something"),
  86. ("+something", "+author:something"),
  87. ("-something", "-author:something"),
  88. ("+\"something\"", "+author:something"),
  89. ("+@someone@somewhere", "+author:someone@somewhere"),
  90. ];
  91. for (source, res) in vector {
  92. assert_eq!(&Query::new().author(source, None).to_string(), res);
  93. }
  94. }
  95. #[test]
  96. fn open() {
  97. let dir = temp_dir().join(format!("plume-test-{}", random_hex()));
  98. {
  99. Searcher::create(&dir, pool(), &CONFIG.search_tokenizers).unwrap();
  100. }
  101. Searcher::open(&dir, pool(), &CONFIG.search_tokenizers).unwrap();
  102. }
  103. #[test]
  104. fn create() {
  105. let dir = temp_dir().join(format!("plume-test-{}", random_hex()));
  106. assert!(Searcher::open(&dir, pool(), &CONFIG.search_tokenizers).is_err());
  107. {
  108. Searcher::create(&dir, pool(), &CONFIG.search_tokenizers).unwrap();
  109. }
  110. Searcher::open(&dir, pool(), &CONFIG.search_tokenizers).unwrap(); //verify it's well created
  111. }
  112. #[test]
  113. fn search() {
  114. let conn = &db();
  115. conn.test_transaction::<_, (), _>(|| {
  116. let searcher = get_searcher(&CONFIG.search_tokenizers);
  117. let blog = &fill_database(conn).1[0];
  118. let author = &blog.list_authors(conn).unwrap()[0];
  119. let title = random_hex()[..8].to_owned();
  120. let mut post = Post::insert(
  121. conn,
  122. NewPost {
  123. blog_id: blog.id,
  124. slug: title.clone(),
  125. title: title.clone(),
  126. content: SafeString::new(""),
  127. published: true,
  128. license: "CC-BY-SA".to_owned(),
  129. ap_url: "".to_owned(),
  130. creation_date: None,
  131. subtitle: "".to_owned(),
  132. source: "".to_owned(),
  133. cover_id: None,
  134. },
  135. &searcher,
  136. )
  137. .unwrap();
  138. PostAuthor::insert(
  139. conn,
  140. NewPostAuthor {
  141. post_id: post.id,
  142. author_id: author.id,
  143. },
  144. )
  145. .unwrap();
  146. searcher.commit();
  147. assert_eq!(
  148. searcher.search_document(Query::from_str(&title).unwrap(), (0, 1))[0].id,
  149. post.id
  150. );
  151. let newtitle = random_hex()[..8].to_owned();
  152. post.title = newtitle.clone();
  153. post.update(conn).unwrap();
  154. searcher.commit();
  155. assert_eq!(
  156. searcher.search_document(Query::from_str(&newtitle).unwrap(), (0, 1))[0].id,
  157. post.id
  158. );
  159. assert!(searcher
  160. .search_document(Query::from_str(&title).unwrap(), (0, 1))
  161. .is_empty());
  162. post.delete(conn, &searcher).unwrap();
  163. searcher.commit();
  164. assert!(searcher
  165. .search_document(Query::from_str(&newtitle).unwrap(), (0, 1))
  166. .is_empty());
  167. Ok(())
  168. });
  169. }
  170. #[cfg(feature = "search-lindera")]
  171. #[test]
  172. fn search_japanese() {
  173. let conn = &db();
  174. conn.test_transaction::<_, (), _>(|| {
  175. let tokenizers = SearchTokenizerConfig {
  176. tag_tokenizer: TokenizerKind::Lindera,
  177. content_tokenizer: TokenizerKind::Lindera,
  178. property_tokenizer: TokenizerKind::Ngram,
  179. };
  180. let searcher = get_searcher(&tokenizers);
  181. let blog = &fill_database(conn).1[0];
  182. let title = random_hex()[..8].to_owned();
  183. let post = Post::insert(
  184. conn,
  185. NewPost {
  186. blog_id: blog.id,
  187. slug: title.clone(),
  188. title: title.clone(),
  189. content: SafeString::new("ブログエンジンPlumeです。"),
  190. published: true,
  191. license: "CC-BY-SA".to_owned(),
  192. ap_url: "".to_owned(),
  193. creation_date: None,
  194. subtitle: "".to_owned(),
  195. source: "".to_owned(),
  196. cover_id: None,
  197. },
  198. &searcher,
  199. )
  200. .unwrap();
  201. searcher.commit();
  202. assert_eq!(
  203. searcher.search_document(conn, Query::from_str("ブログエンジン").unwrap(), (0, 1))
  204. [0]
  205. .id,
  206. post.id
  207. );
  208. assert_eq!(
  209. searcher.search_document(conn, Query::from_str("Plume").unwrap(), (0, 1))[0].id,
  210. post.id
  211. );
  212. assert_eq!(
  213. searcher.search_document(conn, Query::from_str("です").unwrap(), (0, 1))[0].id,
  214. post.id
  215. );
  216. assert_eq!(
  217. searcher.search_document(conn, Query::from_str("。").unwrap(), (0, 1))[0].id,
  218. post.id
  219. );
  220. Ok(())
  221. });
  222. }
  223. #[test]
  224. fn drop_writer() {
  225. let searcher = get_searcher(&CONFIG.search_tokenizers);
  226. searcher.drop_writer();
  227. get_searcher(&CONFIG.search_tokenizers);
  228. }
  229. }