MeiliSearch/meilisearch/tests/search/errors.rs

815 lines
28 KiB
Rust
Raw Normal View History

use meili_snap::*;
2021-07-06 11:54:37 +02:00
use serde_json::json;
2021-10-21 14:42:01 +02:00
use super::DOCUMENTS;
2022-10-20 18:00:07 +02:00
use crate::common::Server;
2021-10-21 14:42:01 +02:00
2021-07-06 11:54:37 +02:00
#[actix_rt::test]
async fn search_unexisting_index() {
let server = Server::new().await;
let index = server.index("test");
2021-10-26 19:36:48 +02:00
let expected_response = json!({
"message": "Index `test` not found.",
"code": "index_not_found",
"type": "invalid_request",
2023-01-19 16:10:05 +01:00
"link": "https://docs.meilisearch.com/errors#index_not_found"
2021-10-26 19:36:48 +02:00
});
2021-07-06 11:54:37 +02:00
index
.search(json!({"q": "hello"}), |response, code| {
2021-10-26 19:36:48 +02:00
assert_eq!(code, 404);
assert_eq!(response, expected_response);
2021-07-06 11:54:37 +02:00
})
.await;
}
#[actix_rt::test]
async fn search_unexisting_parameter() {
let server = Server::new().await;
let index = server.index("test");
index
.search(json!({"marin": "hello"}), |response, code| {
assert_eq!(code, 400, "{}", response);
2021-10-26 19:36:48 +02:00
assert_eq!(response["code"], "bad_request");
2021-07-06 11:54:37 +02:00
})
.await;
}
2021-10-21 14:42:01 +02:00
#[actix_rt::test]
async fn search_bad_q() {
let server = Server::new().await;
let index = server.index("test");
let (response, code) = index.search_post(json!({"q": ["doggo"]})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value type at `.q`: expected a string, but found an array: `[\"doggo\"]`",
"code": "invalid_search_q",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_q"
}
"###);
// Can't make the `q` fail with a get search since it'll accept anything as a string.
}
#[actix_rt::test]
async fn search_bad_offset() {
let server = Server::new().await;
let index = server.index("test");
let (response, code) = index.search_post(json!({"offset": "doggo"})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value type at `.offset`: expected a positive integer, but found a string: `\"doggo\"`",
"code": "invalid_search_offset",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_offset"
}
"###);
let (response, code) = index.search_get("offset=doggo").await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value in parameter `offset`: could not parse `doggo` as a positive integer",
"code": "invalid_search_offset",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_offset"
}
"###);
}
#[actix_rt::test]
async fn search_bad_limit() {
let server = Server::new().await;
let index = server.index("test");
let (response, code) = index.search_post(json!({"limit": "doggo"})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value type at `.limit`: expected a positive integer, but found a string: `\"doggo\"`",
"code": "invalid_search_limit",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_limit"
}
"###);
let (response, code) = index.search_get("limit=doggo").await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value in parameter `limit`: could not parse `doggo` as a positive integer",
"code": "invalid_search_limit",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_limit"
}
"###);
}
#[actix_rt::test]
async fn search_bad_page() {
let server = Server::new().await;
let index = server.index("test");
let (response, code) = index.search_post(json!({"page": "doggo"})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value type at `.page`: expected a positive integer, but found a string: `\"doggo\"`",
"code": "invalid_search_page",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_page"
}
"###);
let (response, code) = index.search_get("page=doggo").await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value in parameter `page`: could not parse `doggo` as a positive integer",
"code": "invalid_search_page",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_page"
}
"###);
}
#[actix_rt::test]
async fn search_bad_hits_per_page() {
let server = Server::new().await;
let index = server.index("test");
let (response, code) = index.search_post(json!({"hitsPerPage": "doggo"})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value type at `.hitsPerPage`: expected a positive integer, but found a string: `\"doggo\"`",
"code": "invalid_search_hits_per_page",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_hits_per_page"
}
"###);
let (response, code) = index.search_get("hitsPerPage=doggo").await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value in parameter `hitsPerPage`: could not parse `doggo` as a positive integer",
"code": "invalid_search_hits_per_page",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_hits_per_page"
}
"###);
}
#[actix_rt::test]
async fn search_bad_attributes_to_crop() {
let server = Server::new().await;
let index = server.index("test");
let (response, code) = index.search_post(json!({"attributesToCrop": "doggo"})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value type at `.attributesToCrop`: expected an array, but found a string: `\"doggo\"`",
"code": "invalid_search_attributes_to_crop",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_attributes_to_crop"
}
"###);
// Can't make the `attributes_to_crop` fail with a get search since it'll accept anything as an array of strings.
}
#[actix_rt::test]
async fn search_bad_crop_length() {
let server = Server::new().await;
let index = server.index("test");
let (response, code) = index.search_post(json!({"cropLength": "doggo"})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value type at `.cropLength`: expected a positive integer, but found a string: `\"doggo\"`",
"code": "invalid_search_crop_length",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_crop_length"
}
"###);
let (response, code) = index.search_get("cropLength=doggo").await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value in parameter `cropLength`: could not parse `doggo` as a positive integer",
"code": "invalid_search_crop_length",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_crop_length"
}
"###);
}
#[actix_rt::test]
async fn search_bad_attributes_to_highlight() {
let server = Server::new().await;
let index = server.index("test");
let (response, code) = index.search_post(json!({"attributesToHighlight": "doggo"})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value type at `.attributesToHighlight`: expected an array, but found a string: `\"doggo\"`",
"code": "invalid_search_attributes_to_highlight",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_attributes_to_highlight"
}
"###);
// Can't make the `attributes_to_highlight` fail with a get search since it'll accept anything as an array of strings.
}
#[actix_rt::test]
async fn search_bad_filter() {
2023-01-11 11:37:12 +01:00
// Since a filter is deserialized as a json Value it will never fail to deserialize.
// Thus the error message is not generated by deserr but written by us.
let server = Server::new().await;
let index = server.index("test");
2023-01-11 11:37:12 +01:00
// Also, to trigger the error message we need to effectively create the index or else it'll throw an
// index does not exists error.
let (_, code) = index.create(None).await;
2023-01-11 14:54:29 +01:00
server.wait_task(0).await;
2023-01-11 11:37:12 +01:00
snapshot!(code, @"202 Accepted");
let (response, code) = index.search_post(json!({ "filter": true })).await;
2023-01-11 11:37:12 +01:00
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
2023-01-11 11:37:12 +01:00
"message": "Invalid syntax for the filter parameter: `expected String, Array, found: true`.",
"code": "invalid_search_filter",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_filter"
}
"###);
2023-01-11 11:37:12 +01:00
// Can't make the `filter` fail with a get search since it'll accept anything as a strings.
}
#[actix_rt::test]
async fn search_bad_sort() {
let server = Server::new().await;
let index = server.index("test");
let (response, code) = index.search_post(json!({"sort": "doggo"})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value type at `.sort`: expected an array, but found a string: `\"doggo\"`",
"code": "invalid_search_sort",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_sort"
}
"###);
// Can't make the `sort` fail with a get search since it'll accept anything as a strings.
}
#[actix_rt::test]
async fn search_bad_show_matches_position() {
let server = Server::new().await;
let index = server.index("test");
let (response, code) = index.search_post(json!({"showMatchesPosition": "doggo"})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value type at `.showMatchesPosition`: expected a boolean, but found a string: `\"doggo\"`",
"code": "invalid_search_show_matches_position",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_show_matches_position"
}
"###);
let (response, code) = index.search_get("showMatchesPosition=doggo").await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value in parameter `showMatchesPosition`: could not parse `doggo` as a boolean, expected either `true` or `false`",
"code": "invalid_search_show_matches_position",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_show_matches_position"
}
"###);
}
#[actix_rt::test]
async fn search_bad_facets() {
let server = Server::new().await;
let index = server.index("test");
let (response, code) = index.search_post(json!({"facets": "doggo"})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value type at `.facets`: expected an array, but found a string: `\"doggo\"`",
"code": "invalid_search_facets",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_facets"
}
"###);
// Can't make the `attributes_to_highlight` fail with a get search since it'll accept anything as an array of strings.
}
#[actix_rt::test]
async fn search_non_filterable_facets() {
let server = Server::new().await;
let index = server.index("test");
index.update_settings(json!({"filterableAttributes": ["title"]})).await;
// Wait for the settings update to complete
index.wait_task(0).await;
let (response, code) = index.search_post(json!({"facets": ["doggo"]})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid facet distribution, the fields `doggo` are not set as filterable.",
"code": "invalid_search_facets",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_facets"
}
"###);
let (response, code) = index.search_get("facets=doggo").await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid facet distribution, the fields `doggo` are not set as filterable.",
"code": "invalid_search_facets",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_facets"
}
"###);
}
#[actix_rt::test]
async fn search_bad_highlight_pre_tag() {
let server = Server::new().await;
let index = server.index("test");
let (response, code) = index.search_post(json!({"highlightPreTag": ["doggo"]})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value type at `.highlightPreTag`: expected a string, but found an array: `[\"doggo\"]`",
"code": "invalid_search_highlight_pre_tag",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_highlight_pre_tag"
}
"###);
// Can't make the `highlight_pre_tag` fail with a get search since it'll accept anything as a strings.
}
#[actix_rt::test]
async fn search_bad_highlight_post_tag() {
let server = Server::new().await;
let index = server.index("test");
let (response, code) = index.search_post(json!({"highlightPostTag": ["doggo"]})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value type at `.highlightPostTag`: expected a string, but found an array: `[\"doggo\"]`",
"code": "invalid_search_highlight_post_tag",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_highlight_post_tag"
}
"###);
// Can't make the `highlight_post_tag` fail with a get search since it'll accept anything as a strings.
}
#[actix_rt::test]
async fn search_bad_crop_marker() {
let server = Server::new().await;
let index = server.index("test");
let (response, code) = index.search_post(json!({"cropMarker": ["doggo"]})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Invalid value type at `.cropMarker`: expected a string, but found an array: `[\"doggo\"]`",
"code": "invalid_search_crop_marker",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_crop_marker"
}
"###);
// Can't make the `crop_marker` fail with a get search since it'll accept anything as a strings.
}
#[actix_rt::test]
async fn search_bad_matching_strategy() {
let server = Server::new().await;
let index = server.index("test");
let (response, code) = index.search_post(json!({"matchingStrategy": "doggo"})).await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Unknown value `doggo` at `.matchingStrategy`: expected one of `last`, `all`",
"code": "invalid_search_matching_strategy",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_matching_strategy"
}
"###);
let (response, code) = index.search_get("matchingStrategy=doggo").await;
snapshot!(code, @"400 Bad Request");
snapshot!(json_string!(response), @r###"
{
"message": "Unknown value `doggo` for parameter `matchingStrategy`: expected one of `last`, `all`",
"code": "invalid_search_matching_strategy",
"type": "invalid_request",
2023-01-19 15:48:20 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_matching_strategy"
}
"###);
}
2021-10-21 14:42:01 +02:00
#[actix_rt::test]
async fn filter_invalid_syntax_object() {
let server = Server::new().await;
let index = server.index("test");
2022-10-20 18:00:07 +02:00
index.update_settings(json!({"filterableAttributes": ["title"]})).await;
2021-10-21 14:42:01 +02:00
let documents = DOCUMENTS.clone();
index.add_documents(documents, None).await;
index.wait_task(1).await;
2021-10-21 14:42:01 +02:00
let expected_response = json!({
Bring back `release-v0.30.0` into `release-v0.30.0-temp` (final: into `main`) (#3145) * Fix error code of the "duplicate index found" error * Use the content of the ProcessingTasks in the tasks cancelation system * Change the missing_filters error code into missing_task_filters * WIP Introduce the invalid_task_uid error code * Use more precise error codes/message for the task routes + Allow star operator in delete/cancel tasks + rename originalQuery to originalFilters + Display error/canceled_by in task view even when they are = null + Rename task filter fields by using their plural forms + Prepare an error code for canceledBy filter + Only return global tasks if the API key action `index.*` is there * Add canceledBy task filter * Update tests following task API changes * Rename original_query to original_filters everywhere * Update more insta-snap tests * Make clippy happy They're a happy clip now. * Make rustfmt happy >:-( * Fix Index name parsing error message to fit the specification * Bump milli version to 0.35.1 * Fix the new error messages * fix the error messages and add tests * rename the error codes for the sake of consistency * refactor the way we send the cli informations + add the analytics for the config file and ssl usage * Apply suggestions from code review Co-authored-by: Clément Renault <clement@meilisearch.com> * add a comment over the new infos structure * reformat, sorry @kero * Store analytics for the documents deletions * Add analytics on all the settings * Spawn threads with names * Spawn rayon threads with names * update the distinct attributes to the spec update * update the analytics on the search route * implements the analytics on the health and version routes * Fix task details serialization * Add the question mark to the task deletion query filter * Add the question mark to the task cancelation query filter * Fix tests * add analytics on the task route * Add all the missing fields of the new task query type * Create a new analytics for the task deletion * Create a new analytics for the task creation * batch the tasks seen events * Update the finite pagination analytics * add the analytics of the swap-indexes route * Stop removing the DB when failing to read it * Rename originalFilters into originalFilters * Rename matchedDocuments into providedIds * Add `workflow_dispatch` to flaky.yml * Bump grenad to 0.4.4 * Bump milli to version v0.37.0 * Don't multiply total memory returned by sysinfo anymore sysinfo now returns bytes rather than KB * Add a dispatch to the publish binaries workflow * Fix publish release CI * Don't use gold but the default linker * Always display details for the indexDeletion task * Fix the insta tests * refactorize the whole test suite 1. Make a call to assert_internally_consistent automatically when snapshoting the scheduler. There is no point in snapshoting something broken and expect the dumb humans to notice. 2. Replace every possible call to assert_internally_consistent by a snapshot of the scheduler. It takes as many lines and ensure we never change something without noticing in any tests ever. 3. Name every snapshots: it's easier to debug when something goes wrong and easier to review in general. 4. Stop skipping breakpoints, it's too easy to miss something. Now you must explicitely show which path is the scheduler supposed to use. 5. Add a timeout on the channel.recv, it eases the process of writing tests, now when something file you get a failure instead of a deadlock. * rebase on release-v0.30 * makes clippy happy * update the snapshots after a rebase * try to remove the flakyness of the failing test * Add more analytics on the ranking rules positions * Update the dump test to check for the dumpUid dumpCreation task details * send the ranking rules as a string because amplitude is too dumb to process an array as a single value * Display a null dumpUid until we computed the dump itself on disk * Update tests * Check if the master key is missing before returning an error Co-authored-by: Loïc Lecrenier <loic.lecrenier@me.com> Co-authored-by: bors[bot] <26634292+bors[bot]@users.noreply.github.com> Co-authored-by: Kerollmops <clement@meilisearch.com> Co-authored-by: ManyTheFish <many@meilisearch.com> Co-authored-by: Tamo <tamo@meilisearch.com> Co-authored-by: Louis Dureuil <louis@meilisearch.com>
2022-11-28 16:27:41 +01:00
"message": "Was expecting an operation `=`, `!=`, `>=`, `>`, `<=`, `<`, `IN`, `NOT IN`, `TO`, `EXISTS`, `NOT EXISTS`, or `_geoRadius` at `title & Glass`.\n1:14 title & Glass",
"code": "invalid_search_filter",
2021-10-21 14:42:01 +02:00
"type": "invalid_request",
2023-01-19 16:10:05 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_filter"
2021-10-21 14:42:01 +02:00
});
index
2021-10-26 19:36:48 +02:00
.search(json!({"filter": "title & Glass"}), |response, code| {
2021-10-21 14:42:01 +02:00
assert_eq!(response, expected_response);
assert_eq!(code, 400);
})
.await;
}
#[actix_rt::test]
async fn filter_invalid_syntax_array() {
let server = Server::new().await;
let index = server.index("test");
2022-10-20 18:00:07 +02:00
index.update_settings(json!({"filterableAttributes": ["title"]})).await;
2021-10-21 14:42:01 +02:00
let documents = DOCUMENTS.clone();
index.add_documents(documents, None).await;
index.wait_task(1).await;
2021-10-21 14:42:01 +02:00
let expected_response = json!({
Bring back `release-v0.30.0` into `release-v0.30.0-temp` (final: into `main`) (#3145) * Fix error code of the "duplicate index found" error * Use the content of the ProcessingTasks in the tasks cancelation system * Change the missing_filters error code into missing_task_filters * WIP Introduce the invalid_task_uid error code * Use more precise error codes/message for the task routes + Allow star operator in delete/cancel tasks + rename originalQuery to originalFilters + Display error/canceled_by in task view even when they are = null + Rename task filter fields by using their plural forms + Prepare an error code for canceledBy filter + Only return global tasks if the API key action `index.*` is there * Add canceledBy task filter * Update tests following task API changes * Rename original_query to original_filters everywhere * Update more insta-snap tests * Make clippy happy They're a happy clip now. * Make rustfmt happy >:-( * Fix Index name parsing error message to fit the specification * Bump milli version to 0.35.1 * Fix the new error messages * fix the error messages and add tests * rename the error codes for the sake of consistency * refactor the way we send the cli informations + add the analytics for the config file and ssl usage * Apply suggestions from code review Co-authored-by: Clément Renault <clement@meilisearch.com> * add a comment over the new infos structure * reformat, sorry @kero * Store analytics for the documents deletions * Add analytics on all the settings * Spawn threads with names * Spawn rayon threads with names * update the distinct attributes to the spec update * update the analytics on the search route * implements the analytics on the health and version routes * Fix task details serialization * Add the question mark to the task deletion query filter * Add the question mark to the task cancelation query filter * Fix tests * add analytics on the task route * Add all the missing fields of the new task query type * Create a new analytics for the task deletion * Create a new analytics for the task creation * batch the tasks seen events * Update the finite pagination analytics * add the analytics of the swap-indexes route * Stop removing the DB when failing to read it * Rename originalFilters into originalFilters * Rename matchedDocuments into providedIds * Add `workflow_dispatch` to flaky.yml * Bump grenad to 0.4.4 * Bump milli to version v0.37.0 * Don't multiply total memory returned by sysinfo anymore sysinfo now returns bytes rather than KB * Add a dispatch to the publish binaries workflow * Fix publish release CI * Don't use gold but the default linker * Always display details for the indexDeletion task * Fix the insta tests * refactorize the whole test suite 1. Make a call to assert_internally_consistent automatically when snapshoting the scheduler. There is no point in snapshoting something broken and expect the dumb humans to notice. 2. Replace every possible call to assert_internally_consistent by a snapshot of the scheduler. It takes as many lines and ensure we never change something without noticing in any tests ever. 3. Name every snapshots: it's easier to debug when something goes wrong and easier to review in general. 4. Stop skipping breakpoints, it's too easy to miss something. Now you must explicitely show which path is the scheduler supposed to use. 5. Add a timeout on the channel.recv, it eases the process of writing tests, now when something file you get a failure instead of a deadlock. * rebase on release-v0.30 * makes clippy happy * update the snapshots after a rebase * try to remove the flakyness of the failing test * Add more analytics on the ranking rules positions * Update the dump test to check for the dumpUid dumpCreation task details * send the ranking rules as a string because amplitude is too dumb to process an array as a single value * Display a null dumpUid until we computed the dump itself on disk * Update tests * Check if the master key is missing before returning an error Co-authored-by: Loïc Lecrenier <loic.lecrenier@me.com> Co-authored-by: bors[bot] <26634292+bors[bot]@users.noreply.github.com> Co-authored-by: Kerollmops <clement@meilisearch.com> Co-authored-by: ManyTheFish <many@meilisearch.com> Co-authored-by: Tamo <tamo@meilisearch.com> Co-authored-by: Louis Dureuil <louis@meilisearch.com>
2022-11-28 16:27:41 +01:00
"message": "Was expecting an operation `=`, `!=`, `>=`, `>`, `<=`, `<`, `IN`, `NOT IN`, `TO`, `EXISTS`, `NOT EXISTS`, or `_geoRadius` at `title & Glass`.\n1:14 title & Glass",
"code": "invalid_search_filter",
2021-10-21 14:42:01 +02:00
"type": "invalid_request",
2023-01-19 16:10:05 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_filter"
2021-10-21 14:42:01 +02:00
});
index
2022-06-28 13:01:18 +02:00
.search(json!({"filter": ["title & Glass"]}), |response, code| {
2021-10-26 19:36:48 +02:00
assert_eq!(response, expected_response);
assert_eq!(code, 400);
})
2021-10-21 14:42:01 +02:00
.await;
}
#[actix_rt::test]
async fn filter_invalid_syntax_string() {
let server = Server::new().await;
let index = server.index("test");
2022-10-20 18:00:07 +02:00
index.update_settings(json!({"filterableAttributes": ["title"]})).await;
2021-10-21 14:42:01 +02:00
let documents = DOCUMENTS.clone();
index.add_documents(documents, None).await;
index.wait_task(1).await;
2021-10-21 14:42:01 +02:00
let expected_response = json!({
"message": "Found unexpected characters at the end of the filter: `XOR title = Glass`. You probably forgot an `OR` or an `AND` rule.\n15:32 title = Glass XOR title = Glass",
"code": "invalid_search_filter",
2021-10-21 14:42:01 +02:00
"type": "invalid_request",
2023-01-19 16:10:05 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_filter"
2021-10-21 14:42:01 +02:00
});
index
2022-10-20 18:00:07 +02:00
.search(json!({"filter": "title = Glass XOR title = Glass"}), |response, code| {
assert_eq!(response, expected_response);
assert_eq!(code, 400);
})
2021-10-21 14:42:01 +02:00
.await;
}
#[actix_rt::test]
async fn filter_invalid_attribute_array() {
let server = Server::new().await;
let index = server.index("test");
2022-10-20 18:00:07 +02:00
index.update_settings(json!({"filterableAttributes": ["title"]})).await;
2021-10-21 14:42:01 +02:00
let documents = DOCUMENTS.clone();
index.add_documents(documents, None).await;
index.wait_task(1).await;
2021-10-21 14:42:01 +02:00
let expected_response = json!({
"message": "Attribute `many` is not filterable. Available filterable attributes are: `title`.\n1:5 many = Glass",
"code": "invalid_search_filter",
2021-10-21 14:42:01 +02:00
"type": "invalid_request",
2023-01-19 16:10:05 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_filter"
2021-10-21 14:42:01 +02:00
});
index
2022-06-28 13:01:18 +02:00
.search(json!({"filter": ["many = Glass"]}), |response, code| {
2021-10-21 14:42:01 +02:00
assert_eq!(response, expected_response);
assert_eq!(code, 400);
})
.await;
}
#[actix_rt::test]
async fn filter_invalid_attribute_string() {
let server = Server::new().await;
let index = server.index("test");
2022-10-20 18:00:07 +02:00
index.update_settings(json!({"filterableAttributes": ["title"]})).await;
2021-10-21 14:42:01 +02:00
let documents = DOCUMENTS.clone();
index.add_documents(documents, None).await;
index.wait_task(1).await;
2021-10-21 14:42:01 +02:00
let expected_response = json!({
"message": "Attribute `many` is not filterable. Available filterable attributes are: `title`.\n1:5 many = Glass",
"code": "invalid_search_filter",
2021-10-21 14:42:01 +02:00
"type": "invalid_request",
2023-01-19 16:10:05 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_filter"
2021-10-21 14:42:01 +02:00
});
index
.search(json!({"filter": "many = Glass"}), |response, code| {
assert_eq!(response, expected_response);
assert_eq!(code, 400);
})
.await;
}
#[actix_rt::test]
async fn filter_reserved_geo_attribute_array() {
let server = Server::new().await;
let index = server.index("test");
2022-10-20 18:00:07 +02:00
index.update_settings(json!({"filterableAttributes": ["title"]})).await;
2021-10-21 14:42:01 +02:00
let documents = DOCUMENTS.clone();
index.add_documents(documents, None).await;
index.wait_task(1).await;
2021-10-21 14:42:01 +02:00
let expected_response = json!({
"message": "`_geo` is a reserved keyword and thus can't be used as a filter expression. Use the _geoRadius(latitude, longitude, distance) built-in rule to filter on _geo field coordinates.\n1:5 _geo = Glass",
"code": "invalid_search_filter",
2021-10-21 14:42:01 +02:00
"type": "invalid_request",
2023-01-19 16:10:05 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_filter"
2021-10-21 14:42:01 +02:00
});
index
2022-06-28 13:01:18 +02:00
.search(json!({"filter": ["_geo = Glass"]}), |response, code| {
2021-10-21 14:42:01 +02:00
assert_eq!(response, expected_response);
assert_eq!(code, 400);
})
.await;
}
#[actix_rt::test]
async fn filter_reserved_geo_attribute_string() {
let server = Server::new().await;
let index = server.index("test");
2022-10-20 18:00:07 +02:00
index.update_settings(json!({"filterableAttributes": ["title"]})).await;
2021-10-21 14:42:01 +02:00
let documents = DOCUMENTS.clone();
index.add_documents(documents, None).await;
index.wait_task(1).await;
2021-10-21 14:42:01 +02:00
let expected_response = json!({
"message": "`_geo` is a reserved keyword and thus can't be used as a filter expression. Use the _geoRadius(latitude, longitude, distance) built-in rule to filter on _geo field coordinates.\n1:5 _geo = Glass",
"code": "invalid_search_filter",
2021-10-21 14:42:01 +02:00
"type": "invalid_request",
2023-01-19 16:10:05 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_filter"
2021-10-21 14:42:01 +02:00
});
index
.search(json!({"filter": "_geo = Glass"}), |response, code| {
assert_eq!(response, expected_response);
assert_eq!(code, 400);
})
.await;
}
#[actix_rt::test]
async fn filter_reserved_attribute_array() {
let server = Server::new().await;
let index = server.index("test");
2022-10-20 18:00:07 +02:00
index.update_settings(json!({"filterableAttributes": ["title"]})).await;
2021-10-21 14:42:01 +02:00
let documents = DOCUMENTS.clone();
index.add_documents(documents, None).await;
index.wait_task(1).await;
2021-10-21 14:42:01 +02:00
let expected_response = json!({
"message": "`_geoDistance` is a reserved keyword and thus can't be used as a filter expression.\n1:13 _geoDistance = Glass",
"code": "invalid_search_filter",
2021-10-21 14:42:01 +02:00
"type": "invalid_request",
2023-01-19 16:10:05 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_filter"
2021-10-21 14:42:01 +02:00
});
index
2022-10-20 18:00:07 +02:00
.search(json!({"filter": ["_geoDistance = Glass"]}), |response, code| {
assert_eq!(response, expected_response);
assert_eq!(code, 400);
})
2021-10-21 14:42:01 +02:00
.await;
}
#[actix_rt::test]
async fn filter_reserved_attribute_string() {
let server = Server::new().await;
let index = server.index("test");
2022-10-20 18:00:07 +02:00
index.update_settings(json!({"filterableAttributes": ["title"]})).await;
2021-10-21 14:42:01 +02:00
let documents = DOCUMENTS.clone();
index.add_documents(documents, None).await;
index.wait_task(1).await;
2021-10-21 14:42:01 +02:00
let expected_response = json!({
"message": "`_geoDistance` is a reserved keyword and thus can't be used as a filter expression.\n1:13 _geoDistance = Glass",
"code": "invalid_search_filter",
2021-10-21 14:42:01 +02:00
"type": "invalid_request",
2023-01-19 16:10:05 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_filter"
2021-10-21 14:42:01 +02:00
});
index
2022-10-20 18:00:07 +02:00
.search(json!({"filter": "_geoDistance = Glass"}), |response, code| {
assert_eq!(response, expected_response);
assert_eq!(code, 400);
})
2021-10-21 14:42:01 +02:00
.await;
}
#[actix_rt::test]
async fn sort_geo_reserved_attribute() {
let server = Server::new().await;
let index = server.index("test");
2022-10-20 18:00:07 +02:00
index.update_settings(json!({"sortableAttributes": ["id"]})).await;
2021-10-21 14:42:01 +02:00
let documents = DOCUMENTS.clone();
index.add_documents(documents, None).await;
index.wait_task(1).await;
2021-10-21 14:42:01 +02:00
let expected_response = json!({
2021-10-26 19:36:48 +02:00
"message": "`_geo` is a reserved keyword and thus can't be used as a sort expression. Use the _geoPoint(latitude, longitude) built-in rule to sort on _geo field coordinates.",
"code": "invalid_search_sort",
2021-10-21 14:42:01 +02:00
"type": "invalid_request",
2023-01-19 16:10:05 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_sort"
2021-10-21 14:42:01 +02:00
});
index
.search(
json!({
"sort": ["_geo:asc"]
}),
|response, code| {
assert_eq!(response, expected_response);
assert_eq!(code, 400);
},
)
.await;
}
#[actix_rt::test]
async fn sort_reserved_attribute() {
let server = Server::new().await;
let index = server.index("test");
2022-10-20 18:00:07 +02:00
index.update_settings(json!({"sortableAttributes": ["id"]})).await;
2021-10-21 14:42:01 +02:00
let documents = DOCUMENTS.clone();
index.add_documents(documents, None).await;
index.wait_task(1).await;
2021-10-21 14:42:01 +02:00
let expected_response = json!({
2021-10-26 19:36:48 +02:00
"message": "`_geoDistance` is a reserved keyword and thus can't be used as a sort expression.",
"code": "invalid_search_sort",
2021-10-21 14:42:01 +02:00
"type": "invalid_request",
2023-01-19 16:10:05 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_sort"
2021-10-21 14:42:01 +02:00
});
index
.search(
json!({
"sort": ["_geoDistance:asc"]
}),
|response, code| {
assert_eq!(response, expected_response);
assert_eq!(code, 400);
},
)
.await;
}
#[actix_rt::test]
async fn sort_unsortable_attribute() {
let server = Server::new().await;
let index = server.index("test");
2022-10-20 18:00:07 +02:00
index.update_settings(json!({"sortableAttributes": ["id"]})).await;
2021-10-21 14:42:01 +02:00
let documents = DOCUMENTS.clone();
index.add_documents(documents, None).await;
index.wait_task(1).await;
2021-10-21 14:42:01 +02:00
let expected_response = json!({
2021-10-26 19:36:48 +02:00
"message": "Attribute `title` is not sortable. Available sortable attributes are: `id`.",
"code": "invalid_search_sort",
2021-10-21 14:42:01 +02:00
"type": "invalid_request",
2023-01-19 16:10:05 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_sort"
2021-10-21 14:42:01 +02:00
});
index
.search(
json!({
"sort": ["title:asc"]
}),
|response, code| {
assert_eq!(response, expected_response);
assert_eq!(code, 400);
},
)
.await;
}
#[actix_rt::test]
async fn sort_invalid_syntax() {
let server = Server::new().await;
let index = server.index("test");
2022-10-20 18:00:07 +02:00
index.update_settings(json!({"sortableAttributes": ["id"]})).await;
2021-10-21 14:42:01 +02:00
let documents = DOCUMENTS.clone();
index.add_documents(documents, None).await;
index.wait_task(1).await;
2021-10-21 14:42:01 +02:00
let expected_response = json!({
2021-10-26 19:36:48 +02:00
"message": "Invalid syntax for the sort parameter: expected expression ending by `:asc` or `:desc`, found `title`.",
"code": "invalid_search_sort",
2021-10-21 14:42:01 +02:00
"type": "invalid_request",
2023-01-19 16:10:05 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_sort"
2021-10-21 14:42:01 +02:00
});
index
.search(
json!({
"sort": ["title"]
}),
|response, code| {
assert_eq!(response, expected_response);
assert_eq!(code, 400);
},
)
.await;
}
#[actix_rt::test]
async fn sort_unset_ranking_rule() {
let server = Server::new().await;
let index = server.index("test");
index
.update_settings(
2021-10-26 19:36:48 +02:00
json!({"sortableAttributes": ["title"], "rankingRules": ["proximity", "exactness"]}),
2021-10-21 14:42:01 +02:00
)
.await;
let documents = DOCUMENTS.clone();
index.add_documents(documents, None).await;
index.wait_task(1).await;
2021-10-21 14:42:01 +02:00
let expected_response = json!({
"message": "The sort ranking rule must be specified in the ranking rules settings to use the sort parameter at search time.",
"code": "invalid_search_sort",
2021-10-21 14:42:01 +02:00
"type": "invalid_request",
2023-01-19 16:10:05 +01:00
"link": "https://docs.meilisearch.com/errors#invalid_search_sort"
2021-10-21 14:42:01 +02:00
});
index
.search(
json!({
2021-10-26 19:36:48 +02:00
"sort": ["title:asc"]
2021-10-21 14:42:01 +02:00
}),
|response, code| {
assert_eq!(response, expected_response);
assert_eq!(code, 400);
},
)
.await;
}