use std::error::Error;
use std::num::NonZeroUsize;
use super::{
FIELD, TestResult, code, companion, create, declare, head, made, page, position, put, records,
revision, upto,
};
use crate::serve::protocol::Version;
use crate::serve::storage::embed_job::{Made, Page, Reach};
use crate::serve::storage::embed_pending::Waiting;
use crate::serve::storage::embedded::{self, Position};
use crate::serve::storage::{Storage, reads};
fn passed_two(storage: &mut Storage) -> Result<Version, Box<dyn Error>> {
for id in ["n-1", "n-2", "n-3", "n-4", "n-5"] {
put(storage, id, "text")?;
}
declare(storage)?;
let through = head(storage)?;
let mut vectors = Vec::new();
for id in ["n-1", "n-3", "n-5"] {
vectors.push(made(id, revision(storage, id)?, &[1.0, 0.0]));
}
storage.embed_commit("main", &page(vectors, &[], through), records()?)?;
Ok(through)
}
fn marked(storage: &Storage) -> Result<bool, Box<dyn Error>> {
let at = companion(storage).ok_or("no companion")?;
let key = embedded::rewalk_key("notes", FIELD);
Ok(reads::get_bytes(&storage.reader, &at, &key)?.is_some())
}
#[test]
fn rewalk_lists_only_longer_texts_a_page_at_a_time() -> TestResult {
let (_directory, mut storage) = create()?;
let through = passed_two(&mut storage)?;
assert_eq!(
storage.embed_rewalk_longer("main", "notes", FIELD)?,
through
);
assert!(marked(&storage)?);
let two = NonZeroUsize::new(2).ok_or("two is not zero")?;
let bytes = NonZeroUsize::new(1024).ok_or("1024 is not zero")?;
let mut listed = Vec::new();
let mut ended = false;
for _page in 0..5 {
let pending = storage
.embed_pending("main", "notes", FIELD, two, bytes)?
.ok_or("the rewalk ended before its last page")?;
assert!(pending.waiting.len() <= 2, "{pending:?}");
assert_eq!(pending.toward, through);
let mut made_now: Vec<Made> = Vec::new();
for waiting in &pending.waiting {
let Waiting::Text { id, made_from, .. } = waiting else {
return Err("a rewalk lists no removal".into());
};
listed.push(id.clone());
made_now.push(made(id, *made_from, &[0.0, 1.0]));
}
let next = Page {
reach: pending.reach.clone(),
..page(made_now, &[], through)
};
storage.embed_commit("main", &next, records()?)?;
if pending.reach == Reach::End {
ended = true;
break;
}
}
assert!(ended, "the rewalk did not end");
assert_eq!(listed, ["n-2", "n-4"]);
assert!(!marked(&storage)?, "the last page removes the marker");
let expected = Position {
branch: "main".to_owned(),
through: Some(through),
toward: None,
};
assert_eq!(position(&storage)?, Some(expected));
let again = storage.embed_pending("main", "notes", FIELD, two, bytes)?;
assert_eq!(again, None, "the field is at the head again");
Ok(())
}
#[test]
fn a_rewalk_needs_a_finished_walk_of_its_own() -> TestResult {
let (_directory, mut storage) = create()?;
put(&mut storage, "n-1", "text")?;
declare(&mut storage)?;
let refused = storage.embed_rewalk_longer("main", "notes", FIELD);
assert_eq!(code(refused)?, "embed_rewalk_not_ready");
put(&mut storage, "n-2", "text")?;
let toward = head(&storage)?;
let first = made("n-1", revision(&storage, "n-1")?, &[1.0, 0.0]);
storage.embed_commit("main", &upto(vec![first], toward, "n-1"), records()?)?;
let refused = storage.embed_rewalk_longer("main", "notes", FIELD);
assert_eq!(code(refused)?, "embed_walk_open");
assert!(!marked(&storage)?);
Ok(())
}
#[test]
fn a_rewalk_is_opened_once() -> TestResult {
let (_directory, mut storage) = create()?;
passed_two(&mut storage)?;
storage.embed_rewalk_longer("main", "notes", FIELD)?;
let refused = storage.embed_rewalk_longer("main", "notes", FIELD);
assert_eq!(code(refused)?, "embed_walk_open");
Ok(())
}