mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-11-05 12:38:55 +01:00
Merge #2466
2466: index resolver tests r=MarinPostma a=MarinPostma add more index resolver tests depends on #2455 followup #2453 Co-authored-by: ad hoc <postma.marin@protonmail.com>
This commit is contained in:
commit
4fc73195e6
@ -386,8 +386,14 @@ mod real {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::index::IndexStats;
|
||||
|
||||
use super::index_store::MockIndexStore;
|
||||
use super::meta_store::MockIndexMetaStore;
|
||||
use super::*;
|
||||
|
||||
use futures::future::ok;
|
||||
use milli::FieldDistribution;
|
||||
use nelson::Mocker;
|
||||
|
||||
pub enum MockIndexResolver<U, I> {
|
||||
@ -493,174 +499,178 @@ mod test {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: ignoring this test, it has become too complex to maintain, and rather implement
|
||||
// handler logic test.
|
||||
// proptest! {
|
||||
// #[test]
|
||||
// #[ignore]
|
||||
// fn test_process_task(
|
||||
// task in any::<Task>().prop_filter("IndexUid should be Some", |s| s.index_uid.is_some()),
|
||||
// index_exists in any::<bool>(),
|
||||
// index_op_fails in any::<bool>(),
|
||||
// any_int in any::<u64>(),
|
||||
// ) {
|
||||
// actix_rt::System::new().block_on(async move {
|
||||
// let uuid = Uuid::new_v4();
|
||||
// let mut index_store = MockIndexStore::new();
|
||||
//
|
||||
// let mocker = Mocker::default();
|
||||
//
|
||||
// // Return arbitrary data from index call.
|
||||
// match &task.content {
|
||||
// TaskContent::DocumentAddition{primary_key, ..} => {
|
||||
// let result = move || if !index_op_fails {
|
||||
// Ok(DocumentAdditionResult { indexed_documents: any_int, number_of_documents: any_int })
|
||||
// } else {
|
||||
// // return this error because it's easy to generate...
|
||||
// Err(IndexError::DocumentNotFound("a doc".into()))
|
||||
// };
|
||||
// if primary_key.is_some() {
|
||||
// mocker.when::<String, IndexResult<IndexMeta>>("update_primary_key")
|
||||
// .then(move |_| Ok(IndexMeta{ created_at: OffsetDateTime::now_utc(), updated_at: OffsetDateTime::now_utc(), primary_key: None }));
|
||||
// }
|
||||
// mocker.when::<(IndexDocumentsMethod, Option<String>, UpdateFileStore, IntoIter<Uuid>), IndexResult<DocumentAdditionResult>>("update_documents")
|
||||
// .then(move |(_, _, _, _)| result());
|
||||
// }
|
||||
// TaskContent::SettingsUpdate{..} => {
|
||||
// let result = move || if !index_op_fails {
|
||||
// Ok(())
|
||||
// } else {
|
||||
// // return this error because it's easy to generate...
|
||||
// Err(IndexError::DocumentNotFound("a doc".into()))
|
||||
// };
|
||||
// mocker.when::<&Settings<Checked>, IndexResult<()>>("update_settings")
|
||||
// .then(move |_| result());
|
||||
// }
|
||||
// TaskContent::DocumentDeletion(DocumentDeletion::Ids(_ids)) => {
|
||||
// let result = move || if !index_op_fails {
|
||||
// Ok(DocumentDeletionResult { deleted_documents: any_int as u64, remaining_documents: any_int as u64 })
|
||||
// } else {
|
||||
// // return this error because it's easy to generate...
|
||||
// Err(IndexError::DocumentNotFound("a doc".into()))
|
||||
// };
|
||||
//
|
||||
// mocker.when::<&[String], IndexResult<DocumentDeletionResult>>("delete_documents")
|
||||
// .then(move |_| result());
|
||||
// },
|
||||
// TaskContent::DocumentDeletion(DocumentDeletion::Clear) => {
|
||||
// let result = move || if !index_op_fails {
|
||||
// Ok(())
|
||||
// } else {
|
||||
// // return this error because it's easy to generate...
|
||||
// Err(IndexError::DocumentNotFound("a doc".into()))
|
||||
// };
|
||||
// mocker.when::<(), IndexResult<()>>("clear_documents")
|
||||
// .then(move |_| result());
|
||||
// },
|
||||
// TaskContent::IndexDeletion => {
|
||||
// mocker.when::<(), ()>("close")
|
||||
// .times(index_exists as usize)
|
||||
// .then(move |_| ());
|
||||
// }
|
||||
// TaskContent::IndexUpdate { primary_key }
|
||||
// | TaskContent::IndexCreation { primary_key } => {
|
||||
// if primary_key.is_some() {
|
||||
// let result = move || if !index_op_fails {
|
||||
// Ok(IndexMeta{ created_at: OffsetDateTime::now_utc(), updated_at: OffsetDateTime::now_utc(), primary_key: None })
|
||||
// } else {
|
||||
// // return this error because it's easy to generate...
|
||||
// Err(IndexError::DocumentNotFound("a doc".into()))
|
||||
// };
|
||||
// mocker.when::<String, IndexResult<IndexMeta>>("update_primary_key")
|
||||
// .then(move |_| result());
|
||||
// }
|
||||
// }
|
||||
// TaskContent::Dump { .. } => { }
|
||||
// }
|
||||
//
|
||||
// mocker.when::<(), IndexResult<IndexStats>>("stats")
|
||||
// .then(|()| Ok(IndexStats { size: 0, number_of_documents: 0, is_indexing: Some(false), field_distribution: BTreeMap::new() }));
|
||||
//
|
||||
// let index = Index::mock(mocker);
|
||||
//
|
||||
// match &task.content {
|
||||
// // an unexisting index should trigger an index creation in the folllowing cases:
|
||||
// TaskContent::DocumentAddition { allow_index_creation: true, .. }
|
||||
// | TaskContent::SettingsUpdate { allow_index_creation: true, is_deletion: false, .. }
|
||||
// | TaskContent::IndexCreation { .. } if !index_exists => {
|
||||
// index_store
|
||||
// .expect_create()
|
||||
// .once()
|
||||
// .withf(move |&found| !index_exists || found == uuid)
|
||||
// .returning(move |_| Box::pin(ok(index.clone())));
|
||||
// },
|
||||
// TaskContent::IndexDeletion => {
|
||||
// index_store
|
||||
// .expect_delete()
|
||||
// // this is called only if the index.exists
|
||||
// .times(index_exists as usize)
|
||||
// .withf(move |&found| !index_exists || found == uuid)
|
||||
// .returning(move |_| Box::pin(ok(Some(index.clone()))));
|
||||
// }
|
||||
// // if index already exists, create index will return an error
|
||||
// TaskContent::IndexCreation { .. } if index_exists => (),
|
||||
// TaskContent::Dump { .. } => (),
|
||||
// // The index exists and get should be called
|
||||
// _ if index_exists => {
|
||||
// index_store
|
||||
// .expect_get()
|
||||
// .once()
|
||||
// .withf(move |&found| found == uuid)
|
||||
// .returning(move |_| Box::pin(ok(Some(index.clone()))));
|
||||
// },
|
||||
// // the index doesn't exist and shouldn't be created, the uuidstore will return an error, and get_index will never be called.
|
||||
// _ => (),
|
||||
// }
|
||||
//
|
||||
// let mut uuid_store = MockIndexMetaStore::new();
|
||||
// uuid_store
|
||||
// .expect_get()
|
||||
// .returning(move |uid| {
|
||||
// Box::pin(ok((uid, index_exists.then(|| crate::index_resolver::meta_store::IndexMeta {uuid, creation_task_id: 0 }))))
|
||||
// });
|
||||
//
|
||||
// // we sould only be creating an index if the index doesn't alredy exist
|
||||
// uuid_store
|
||||
// .expect_insert()
|
||||
// .withf(move |_, _| !index_exists)
|
||||
// .returning(|_, _| Box::pin(ok(())));
|
||||
//
|
||||
// uuid_store
|
||||
// .expect_delete()
|
||||
// .times(matches!(task.content, TaskContent::IndexDeletion) as usize)
|
||||
// .returning(move |_| Box::pin(ok(index_exists.then(|| crate::index_resolver::meta_store::IndexMeta { uuid, creation_task_id: 0}))));
|
||||
//
|
||||
// let mocker = Mocker::default();
|
||||
// let update_file_store = UpdateFileStore::mock(mocker);
|
||||
// let index_resolver = IndexResolver::new(uuid_store, index_store, update_file_store);
|
||||
//
|
||||
// let batch = Batch { id: Some(1), created_at: OffsetDateTime::now_utc(), content: crate::tasks::batch::BatchContent::IndexUpdate(task.clone()) };
|
||||
// if index_resolver.accept(&batch) {
|
||||
// let result = index_resolver.process_batch(batch).await;
|
||||
//
|
||||
// // Test for some expected output scenarios:
|
||||
// // Index creation and deletion cannot fail because of a failed index op, since they
|
||||
// // don't perform index ops.
|
||||
// if index_op_fails && !matches!(task.content, TaskContent::IndexDeletion | TaskContent::IndexCreation { primary_key: None } | TaskContent::IndexUpdate { primary_key: None } | TaskContent::Dump { .. })
|
||||
// || (index_exists && matches!(task.content, TaskContent::IndexCreation { .. }))
|
||||
// || (!index_exists && matches!(task.content, TaskContent::IndexDeletion
|
||||
// | TaskContent::DocumentDeletion(_)
|
||||
// | TaskContent::SettingsUpdate { is_deletion: true, ..}
|
||||
// | TaskContent::SettingsUpdate { allow_index_creation: false, ..}
|
||||
// | TaskContent::DocumentAddition { allow_index_creation: false, ..}
|
||||
// | TaskContent::IndexUpdate { .. } ))
|
||||
// {
|
||||
// assert!(matches!(result.content.first().unwrap().events.last().unwrap(), TaskEvent::Failed { .. }), "{:?}", result);
|
||||
// } else {
|
||||
// assert!(matches!(result.content.first().unwrap().events.last().unwrap(), TaskEvent::Succeeded { .. }), "{:?}", result);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
#[actix_rt::test]
|
||||
async fn test_remove_unknown_index() {
|
||||
let mut meta_store = MockIndexMetaStore::new();
|
||||
meta_store
|
||||
.expect_delete()
|
||||
.once()
|
||||
.returning(|_| Box::pin(ok(None)));
|
||||
|
||||
let index_store = MockIndexStore::new();
|
||||
|
||||
let mocker = Mocker::default();
|
||||
let file_store = UpdateFileStore::mock(mocker);
|
||||
|
||||
let index_resolver = IndexResolver::new(meta_store, index_store, file_store);
|
||||
|
||||
let mut task = Task {
|
||||
id: 1,
|
||||
content: TaskContent::IndexDeletion {
|
||||
index_uid: IndexUid::new_unchecked("test"),
|
||||
},
|
||||
events: Vec::new(),
|
||||
};
|
||||
|
||||
index_resolver.process_task(&mut task).await;
|
||||
|
||||
assert!(matches!(task.events[0], TaskEvent::Failed { .. }));
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_remove_index() {
|
||||
let mut meta_store = MockIndexMetaStore::new();
|
||||
meta_store.expect_delete().once().returning(|_| {
|
||||
Box::pin(ok(Some(IndexMeta {
|
||||
uuid: Uuid::new_v4(),
|
||||
creation_task_id: 1,
|
||||
})))
|
||||
});
|
||||
|
||||
let mut index_store = MockIndexStore::new();
|
||||
index_store.expect_delete().once().returning(|_| {
|
||||
let mocker = Mocker::default();
|
||||
mocker.when::<(), ()>("close").then(|_| ());
|
||||
mocker
|
||||
.when::<(), IndexResult<IndexStats>>("stats")
|
||||
.then(|_| {
|
||||
Ok(IndexStats {
|
||||
size: 10,
|
||||
number_of_documents: 10,
|
||||
is_indexing: None,
|
||||
field_distribution: FieldDistribution::default(),
|
||||
})
|
||||
});
|
||||
Box::pin(ok(Some(Index::mock(mocker))))
|
||||
});
|
||||
|
||||
let mocker = Mocker::default();
|
||||
let file_store = UpdateFileStore::mock(mocker);
|
||||
|
||||
let index_resolver = IndexResolver::new(meta_store, index_store, file_store);
|
||||
|
||||
let mut task = Task {
|
||||
id: 1,
|
||||
content: TaskContent::IndexDeletion {
|
||||
index_uid: IndexUid::new_unchecked("test"),
|
||||
},
|
||||
events: Vec::new(),
|
||||
};
|
||||
|
||||
index_resolver.process_task(&mut task).await;
|
||||
|
||||
assert!(matches!(task.events[0], TaskEvent::Succeeded { .. }));
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_delete_documents() {
|
||||
let mut meta_store = MockIndexMetaStore::new();
|
||||
meta_store.expect_get().once().returning(|_| {
|
||||
Box::pin(ok((
|
||||
"test".to_string(),
|
||||
Some(IndexMeta {
|
||||
uuid: Uuid::new_v4(),
|
||||
creation_task_id: 1,
|
||||
}),
|
||||
)))
|
||||
});
|
||||
|
||||
let mut index_store = MockIndexStore::new();
|
||||
index_store.expect_get().once().returning(|_| {
|
||||
let mocker = Mocker::default();
|
||||
mocker
|
||||
.when::<(), IndexResult<()>>("clear_documents")
|
||||
.once()
|
||||
.then(|_| Ok(()));
|
||||
mocker
|
||||
.when::<(), IndexResult<IndexStats>>("stats")
|
||||
.once()
|
||||
.then(|_| {
|
||||
Ok(IndexStats {
|
||||
size: 10,
|
||||
number_of_documents: 10,
|
||||
is_indexing: None,
|
||||
field_distribution: FieldDistribution::default(),
|
||||
})
|
||||
});
|
||||
Box::pin(ok(Some(Index::mock(mocker))))
|
||||
});
|
||||
|
||||
let mocker = Mocker::default();
|
||||
let file_store = UpdateFileStore::mock(mocker);
|
||||
|
||||
let index_resolver = IndexResolver::new(meta_store, index_store, file_store);
|
||||
|
||||
let mut task = Task {
|
||||
id: 1,
|
||||
content: TaskContent::DocumentDeletion {
|
||||
deletion: DocumentDeletion::Clear,
|
||||
index_uid: IndexUid::new_unchecked("test"),
|
||||
},
|
||||
events: Vec::new(),
|
||||
};
|
||||
|
||||
index_resolver.process_task(&mut task).await;
|
||||
|
||||
assert!(matches!(task.events[0], TaskEvent::Succeeded { .. }));
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_index_update() {
|
||||
let mut meta_store = MockIndexMetaStore::new();
|
||||
meta_store.expect_get().once().returning(|_| {
|
||||
Box::pin(ok((
|
||||
"test".to_string(),
|
||||
Some(IndexMeta {
|
||||
uuid: Uuid::new_v4(),
|
||||
creation_task_id: 1,
|
||||
}),
|
||||
)))
|
||||
});
|
||||
|
||||
let mut index_store = MockIndexStore::new();
|
||||
index_store.expect_get().once().returning(|_| {
|
||||
let mocker = Mocker::default();
|
||||
|
||||
mocker
|
||||
.when::<String, IndexResult<crate::index::IndexMeta>>("update_primary_key")
|
||||
.once()
|
||||
.then(|_| {
|
||||
Ok(crate::index::IndexMeta {
|
||||
created_at: OffsetDateTime::now_utc(),
|
||||
updated_at: OffsetDateTime::now_utc(),
|
||||
primary_key: Some("key".to_string()),
|
||||
})
|
||||
});
|
||||
Box::pin(ok(Some(Index::mock(mocker))))
|
||||
});
|
||||
|
||||
let mocker = Mocker::default();
|
||||
let file_store = UpdateFileStore::mock(mocker);
|
||||
|
||||
let index_resolver = IndexResolver::new(meta_store, index_store, file_store);
|
||||
|
||||
let mut task = Task {
|
||||
id: 1,
|
||||
content: TaskContent::IndexUpdate {
|
||||
primary_key: Some("key".to_string()),
|
||||
index_uid: IndexUid::new_unchecked("test"),
|
||||
},
|
||||
events: Vec::new(),
|
||||
};
|
||||
|
||||
index_resolver.process_task(&mut task).await;
|
||||
|
||||
assert!(matches!(task.events[0], TaskEvent::Succeeded { .. }));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user