mirror of
https://github.com/hanzoai/index.git
synced 2026-11-03 00:48:16 +00:00
337 lines
11 KiB
Rust
337 lines
11 KiB
Rust
use meilisearch::Opt;
|
|
use tempfile::TempDir;
|
|
|
|
use crate::common::{default_settings, Server};
|
|
use crate::json;
|
|
|
|
/// Feature name to test against.
|
|
/// This will have to be changed by a different one when that feature is stabilized.
|
|
/// All tests that need to set a feature can make use of this constant.
|
|
const FEATURE_NAME: &str = "metrics";
|
|
|
|
#[actix_rt::test]
|
|
async fn experimental_features() {
|
|
let server = Server::new().await;
|
|
|
|
let (response, code) = server.get_features().await;
|
|
|
|
meili_snap::snapshot!(code, @"200 OK");
|
|
meili_snap::snapshot!(meili_snap::json_string!(response), @r###"
|
|
{
|
|
"metrics": false,
|
|
"logsRoute": false,
|
|
"editDocumentsByFunction": false,
|
|
"containsFilter": false,
|
|
"dynamicSearchRules": false,
|
|
"network": false,
|
|
"getTaskDocumentsRoute": false,
|
|
"taskQueueCompactionRoute": false,
|
|
"compositeEmbedders": false,
|
|
"chatCompletions": false,
|
|
"multimodal": false,
|
|
"foreignKeys": false
|
|
}
|
|
"###);
|
|
|
|
let (response, code) = server.set_features(json!({FEATURE_NAME: true})).await;
|
|
|
|
meili_snap::snapshot!(code, @"200 OK");
|
|
meili_snap::snapshot!(meili_snap::json_string!(response), @r###"
|
|
{
|
|
"metrics": true,
|
|
"logsRoute": false,
|
|
"editDocumentsByFunction": false,
|
|
"containsFilter": false,
|
|
"dynamicSearchRules": false,
|
|
"network": false,
|
|
"getTaskDocumentsRoute": false,
|
|
"taskQueueCompactionRoute": false,
|
|
"compositeEmbedders": false,
|
|
"chatCompletions": false,
|
|
"multimodal": false,
|
|
"foreignKeys": false
|
|
}
|
|
"###);
|
|
|
|
let (response, code) = server.get_features().await;
|
|
|
|
meili_snap::snapshot!(code, @"200 OK");
|
|
meili_snap::snapshot!(meili_snap::json_string!(response), @r###"
|
|
{
|
|
"metrics": true,
|
|
"logsRoute": false,
|
|
"editDocumentsByFunction": false,
|
|
"containsFilter": false,
|
|
"dynamicSearchRules": false,
|
|
"network": false,
|
|
"getTaskDocumentsRoute": false,
|
|
"taskQueueCompactionRoute": false,
|
|
"compositeEmbedders": false,
|
|
"chatCompletions": false,
|
|
"multimodal": false,
|
|
"foreignKeys": false
|
|
}
|
|
"###);
|
|
|
|
// sending null does not change the value
|
|
let (response, code) = server.set_features(json!({FEATURE_NAME: null})).await;
|
|
|
|
meili_snap::snapshot!(code, @"200 OK");
|
|
meili_snap::snapshot!(meili_snap::json_string!(response), @r###"
|
|
{
|
|
"metrics": true,
|
|
"logsRoute": false,
|
|
"editDocumentsByFunction": false,
|
|
"containsFilter": false,
|
|
"dynamicSearchRules": false,
|
|
"network": false,
|
|
"getTaskDocumentsRoute": false,
|
|
"taskQueueCompactionRoute": false,
|
|
"compositeEmbedders": false,
|
|
"chatCompletions": false,
|
|
"multimodal": false,
|
|
"foreignKeys": false
|
|
}
|
|
"###);
|
|
|
|
// not sending the field does not change the value
|
|
let (response, code) = server.set_features(json!({})).await;
|
|
|
|
meili_snap::snapshot!(code, @"200 OK");
|
|
meili_snap::snapshot!(meili_snap::json_string!(response), @r###"
|
|
{
|
|
"metrics": true,
|
|
"logsRoute": false,
|
|
"editDocumentsByFunction": false,
|
|
"containsFilter": false,
|
|
"dynamicSearchRules": false,
|
|
"network": false,
|
|
"getTaskDocumentsRoute": false,
|
|
"taskQueueCompactionRoute": false,
|
|
"compositeEmbedders": false,
|
|
"chatCompletions": false,
|
|
"multimodal": false,
|
|
"foreignKeys": false
|
|
}
|
|
"###);
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn experimental_feature_metrics() {
|
|
// instance flag for metrics enables metrics at startup
|
|
let dir = TempDir::new().unwrap();
|
|
let enable_metrics = Opt { experimental_enable_metrics: true, ..default_settings(dir.path()) };
|
|
let server = Server::new_with_options(enable_metrics).await.unwrap();
|
|
|
|
let (response, code) = server.get_features().await;
|
|
|
|
meili_snap::snapshot!(code, @"200 OK");
|
|
meili_snap::snapshot!(meili_snap::json_string!(response), @r###"
|
|
{
|
|
"metrics": true,
|
|
"logsRoute": false,
|
|
"editDocumentsByFunction": false,
|
|
"containsFilter": false,
|
|
"dynamicSearchRules": false,
|
|
"network": false,
|
|
"getTaskDocumentsRoute": false,
|
|
"taskQueueCompactionRoute": false,
|
|
"compositeEmbedders": false,
|
|
"chatCompletions": false,
|
|
"multimodal": false,
|
|
"foreignKeys": false
|
|
}
|
|
"###);
|
|
|
|
let (response, code) = server.get_metrics().await;
|
|
meili_snap::snapshot!(code, @"200 OK");
|
|
|
|
// metrics are not returned in json format
|
|
// so the test server will return null
|
|
meili_snap::snapshot!(response, @"null");
|
|
|
|
// disabling metrics results in invalid request
|
|
let (response, code) = server.set_features(json!({"metrics": false})).await;
|
|
meili_snap::snapshot!(code, @"200 OK");
|
|
meili_snap::snapshot!(response["metrics"], @"false");
|
|
|
|
let (response, code) = server.get_metrics().await;
|
|
meili_snap::snapshot!(code, @"400 Bad Request");
|
|
meili_snap::snapshot!(meili_snap::json_string!(response), @r###"
|
|
{
|
|
"message": "Getting metrics requires enabling the `metrics` experimental feature. See https://github.com/meilisearch/product/discussions/625",
|
|
"code": "feature_not_enabled",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#feature_not_enabled"
|
|
}
|
|
"###);
|
|
|
|
// enabling metrics via HTTP results in valid request
|
|
let (response, code) = server.set_features(json!({"metrics": true})).await;
|
|
meili_snap::snapshot!(code, @"200 OK");
|
|
meili_snap::snapshot!(response["metrics"], @"true");
|
|
|
|
let (response, code) = server.get_metrics().await;
|
|
meili_snap::snapshot!(code, @"200 OK");
|
|
meili_snap::snapshot!(response, @"null");
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn errors() {
|
|
let server = Server::new().await;
|
|
|
|
// Sending a feature not in the list is an error
|
|
let (response, code) = server.set_features(json!({"NotAFeature": true})).await;
|
|
|
|
meili_snap::snapshot!(code, @"400 Bad Request");
|
|
meili_snap::snapshot!(meili_snap::json_string!(response), @r#"
|
|
{
|
|
"message": "Unknown field `NotAFeature`: expected one of `metrics`, `logsRoute`, `editDocumentsByFunction`, `containsFilter`, `dynamicSearchRules`, `network`, `getTaskDocumentsRoute`, `taskQueueCompactionRoute`, `compositeEmbedders`, `chatCompletions`, `multimodal`, `foreignKeys`",
|
|
"code": "bad_request",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#bad_request"
|
|
}
|
|
"#);
|
|
|
|
// The type must be a bool, not a number
|
|
let (response, code) = server.set_features(json!({FEATURE_NAME: 42})).await;
|
|
|
|
meili_snap::snapshot!(code, @"400 Bad Request");
|
|
meili_snap::snapshot!(meili_snap::json_string!(response), @r###"
|
|
{
|
|
"message": "Invalid value type at `.metrics`: expected a boolean, but found a positive integer: `42`",
|
|
"code": "bad_request",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#bad_request"
|
|
}
|
|
"###);
|
|
|
|
// The type must be a bool, not a string
|
|
let (response, code) = server.set_features(json!({FEATURE_NAME: "true"})).await;
|
|
|
|
meili_snap::snapshot!(code, @"400 Bad Request");
|
|
meili_snap::snapshot!(meili_snap::json_string!(response), @r###"
|
|
{
|
|
"message": "Invalid value type at `.metrics`: expected a boolean, but found a string: `\"true\"`",
|
|
"code": "bad_request",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#bad_request"
|
|
}
|
|
"###);
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn search_with_personalization_without_enabling_the_feature() {
|
|
let server = Server::new().await;
|
|
let index = server.unique_index();
|
|
|
|
// Create the index and add some documents
|
|
let (task, _code) = index.create(None).await;
|
|
server.wait_task(task.uid()).await.succeeded();
|
|
|
|
let (task, _code) = index
|
|
.add_documents(
|
|
json!([
|
|
{"id": 1, "title": "The Dark Knight", "genre": "Action"},
|
|
{"id": 2, "title": "Inception", "genre": "Sci-Fi"},
|
|
{"id": 3, "title": "The Matrix", "genre": "Sci-Fi"}
|
|
]),
|
|
None,
|
|
)
|
|
.await;
|
|
server.wait_task(task.uid()).await.succeeded();
|
|
|
|
// Try to search with personalization - should return feature_not_enabled error
|
|
let (response, code) = index
|
|
.search_post(json!({
|
|
"q": "movie",
|
|
"personalize": {
|
|
"userContext": "I love science fiction movies"
|
|
}
|
|
}))
|
|
.await;
|
|
|
|
meili_snap::snapshot!(code, @"400 Bad Request");
|
|
meili_snap::snapshot!(meili_snap::json_string!(response), @r###"
|
|
{
|
|
"message": "reranking search results requires enabling the `personalization` experimental feature. See https://github.com/orgs/meilisearch/discussions/866",
|
|
"code": "feature_not_enabled",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#feature_not_enabled"
|
|
}
|
|
"###);
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn multi_search_with_personalization_without_enabling_the_feature() {
|
|
let server = Server::new().await;
|
|
let index = server.unique_index();
|
|
|
|
// Create the index and add some documents
|
|
let (task, _code) = index.create(None).await;
|
|
server.wait_task(task.uid()).await.succeeded();
|
|
|
|
let (task, _code) = index
|
|
.add_documents(
|
|
json!([
|
|
{"id": 1, "title": "The Dark Knight", "genre": "Action"},
|
|
{"id": 2, "title": "Inception", "genre": "Sci-Fi"},
|
|
{"id": 3, "title": "The Matrix", "genre": "Sci-Fi"}
|
|
]),
|
|
None,
|
|
)
|
|
.await;
|
|
server.wait_task(task.uid()).await.succeeded();
|
|
|
|
// Try to multi-search with personalization - should return feature_not_enabled error
|
|
let (response, code) = server
|
|
.multi_search(json!({
|
|
"queries": [
|
|
{
|
|
"indexUid": index.uid,
|
|
"q": "movie",
|
|
"personalize": {
|
|
"userContext": "I love science fiction movies"
|
|
}
|
|
}
|
|
]
|
|
}))
|
|
.await;
|
|
|
|
meili_snap::snapshot!(code, @"400 Bad Request");
|
|
meili_snap::snapshot!(meili_snap::json_string!(response), @r###"
|
|
{
|
|
"message": "Inside `.queries[0]`: reranking search results requires enabling the `personalization` experimental feature. See https://github.com/orgs/meilisearch/discussions/866",
|
|
"code": "feature_not_enabled",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#feature_not_enabled"
|
|
}
|
|
"###);
|
|
|
|
// Try to federated search with personalization - should return feature_not_enabled error
|
|
let (response, code) = server
|
|
.multi_search(json!({
|
|
"federation": {},
|
|
"queries": [
|
|
{
|
|
"indexUid": index.uid,
|
|
"q": "movie",
|
|
"personalize": {
|
|
"userContext": "I love science fiction movies"
|
|
}
|
|
}
|
|
]
|
|
}))
|
|
.await;
|
|
|
|
meili_snap::snapshot!(code, @"400 Bad Request");
|
|
meili_snap::snapshot!(meili_snap::json_string!(response), @r###"
|
|
{
|
|
"message": "Inside `.queries[0]`: Using `.personalize` is not allowed in federated queries.\n - Hint: remove `personalize` from query #0 or remove `federation` from the request",
|
|
"code": "invalid_multi_search_query_personalization",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#invalid_multi_search_query_personalization"
|
|
}
|
|
"###);
|
|
}
|