use super::*;
use crate::memory_core::analytics::RecallLog;
use crate::memory_core::palace::{Drawer, DrawerType, Palace, PalaceId, RoomType};
use crate::memory_core::store::{kg::KnowledgeGraph, vector::UsearchStore, vector::VectorStore};
use std::collections::HashMap;
use std::sync::Arc;
use tempfile::tempdir;
use uuid::Uuid;
use super::layers::{L1_NO_SIMILARITY_PENALTY, uuid_prefix_eq};
fn init_embedder() {
seed_shared_embedder_with_mock();
}
fn make_handle(dir: &std::path::Path) -> PalaceHandle {
let vs = UsearchStore::new(dir.join("idx.usearch"), 384).unwrap();
let kg = KnowledgeGraph::open(&dir.join("kg.db")).unwrap();
PalaceHandle::new(PalaceId::new("test"), "Test palace".to_string(), vs, kg)
}
#[test]
fn l0_l1_always_present() {
let dir = tempdir().unwrap();
let mut handle = make_handle(dir.path());
let room_id = uuid::Uuid::new_v4();
let mut d = Drawer::new(room_id, "important fact");
d.importance = 0.9;
handle.add_drawer(d);
handle.refresh_l1();
let results = retrieve_l0_l1(&handle);
assert!(results.iter().any(|r| r.layer == 0), "L0 identity missing");
assert!(results.iter().any(|r| r.layer == 1), "L1 drawer missing");
}
#[tokio::test]
async fn l2_returns_relevant_drawer() {
init_embedder();
let dir = tempdir().unwrap();
let handle = make_handle(dir.path());
let embedder = shared_embedder().await.unwrap();
let room_id = uuid::Uuid::new_v4();
let drawer = Drawer::new(room_id, "Rust is a systems programming language");
let drawer_id = drawer.id;
let vecs = embedder
.embed_batch(std::slice::from_ref(&drawer.content))
.await
.unwrap();
handle
.vector_store
.upsert(drawer_id, vecs[0].clone())
.await
.unwrap();
handle.add_drawer(drawer);
let results = retrieve_l2(
&handle,
embedder.as_ref(),
"systems programming Rust",
None,
5,
)
.await
.unwrap();
assert!(!results.is_empty(), "L2 should return results");
assert!(
uuid_prefix_eq(results[0].drawer.id, drawer_id),
"Top L2 result should match the upserted drawer (got {:?}, want {:?})",
results[0].drawer.id,
drawer_id
);
assert_eq!(results[0].layer, 2);
}
#[tokio::test]
async fn cli_remember_and_recall() {
init_embedder();
let dir = tempdir().unwrap();
let palace = Palace {
id: PalaceId::new("test"),
name: "Test".into(),
description: None,
created_at: chrono::Utc::now(),
data_dir: dir.path().join("test"),
};
std::fs::create_dir_all(&palace.data_dir).unwrap();
let handle = PalaceHandle::open(&palace).unwrap();
let _id = handle
.remember(
"Rust async runtime is tokio".into(),
RoomType::Backend,
vec!["rust".into()],
0.7,
)
.await
.unwrap();
handle
.remember(
"React uses a virtual DOM".into(),
RoomType::Frontend,
vec![],
0.5,
)
.await
.unwrap();
let results = recall_with_default_embedder(&handle, "tokio rust async", 5)
.await
.unwrap();
assert!(
results.iter().any(|r| r.drawer.content.contains("tokio")),
"expected to recall the tokio drawer; got {results:?}"
);
}
#[tokio::test]
async fn cli_forget_removes_drawer() {
init_embedder();
let dir = tempdir().unwrap();
let palace = Palace {
id: PalaceId::new("forget-test"),
name: "Forget".into(),
description: None,
created_at: chrono::Utc::now(),
data_dir: dir.path().join("forget-test"),
};
std::fs::create_dir_all(&palace.data_dir).unwrap();
let handle = PalaceHandle::open(&palace).unwrap();
let id = handle
.remember(
"ephemeral fact about Quokkas".into(),
RoomType::General,
vec![],
0.5,
)
.await
.unwrap();
handle.forget(id).await.unwrap();
let results = recall_with_default_embedder(&handle, "Quokkas ephemeral", 5)
.await
.unwrap();
assert!(
!results.iter().any(|r| r.drawer.id == id),
"forgotten drawer should not appear in recall results"
);
}
#[tokio::test]
async fn remember_concurrent_does_not_lose_writes() {
init_embedder();
let dir = tempdir().unwrap();
let palace = Palace {
id: PalaceId::new("concurrent-test"),
name: "Concurrent".into(),
description: None,
created_at: chrono::Utc::now(),
data_dir: dir.path().join("concurrent-test"),
};
std::fs::create_dir_all(&palace.data_dir).unwrap();
let handle = PalaceHandle::open(&palace).unwrap();
let mut tasks = Vec::with_capacity(32);
for i in 0..32u32 {
let h = handle.clone();
tasks.push(tokio::spawn(async move {
h.remember(
format!(
"concurrent write test payload number {i} with enough \
tokens to satisfy the default token filter check"
),
RoomType::General,
vec!["concurrent".into(), format!("idx-{i}")],
0.5,
)
.await
}));
}
let mut ok = 0usize;
let mut errs = Vec::new();
for t in tasks {
match t.await.expect("task panicked") {
Ok(_id) => ok += 1,
Err(e) => errs.push(format!("{e:#}")),
}
}
assert_eq!(
ok, 32,
"expected all 32 concurrent remembers to succeed; failures: {errs:?}"
);
let drawer_count = handle.drawers.read().len();
assert_eq!(
drawer_count, 32,
"expected 32 drawers after concurrent burst, got {drawer_count}"
);
let leaked: Vec<_> = std::fs::read_dir(&palace.data_dir)
.unwrap()
.filter_map(|e| e.ok())
.map(|e| e.file_name().to_string_lossy().into_owned())
.filter(|n| n.starts_with("l1_cache.json") && n.contains(".tmp."))
.collect();
assert!(
leaked.is_empty(),
"expected no .tmp.* orphans after concurrent saves; found {leaked:?}"
);
}
#[tokio::test]
async fn cli_list_filters_by_room() {
init_embedder();
let dir = tempdir().unwrap();
let palace = Palace {
id: PalaceId::new("list-test"),
name: "List".into(),
description: None,
created_at: chrono::Utc::now(),
data_dir: dir.path().join("list-test"),
};
std::fs::create_dir_all(&palace.data_dir).unwrap();
let handle = PalaceHandle::open(&palace).unwrap();
handle
.remember(
"backend fact about the test fixture".into(),
RoomType::Backend,
vec![],
0.5,
)
.await
.unwrap();
handle
.remember(
"frontend fact about the test fixture".into(),
RoomType::Frontend,
vec![],
0.5,
)
.await
.unwrap();
handle
.remember(
"docs fact about the test fixture".into(),
RoomType::Documentation,
vec![],
0.5,
)
.await
.unwrap();
let backend_only = handle.list_drawers(Some(RoomType::Backend), None, 10);
assert_eq!(
backend_only.len(),
1,
"expected exactly 1 backend drawer, got {backend_only:?}"
);
assert!(backend_only[0].content.contains("backend"));
}
#[tokio::test]
async fn recall_logs_events_when_log_present() {
init_embedder();
let dir = tempdir().unwrap();
let log = Arc::new(RecallLog::open(&dir.path().join("recall.db")).unwrap());
let mut handle = make_handle(dir.path()).with_recall_log(log.clone());
let embedder = shared_embedder().await.unwrap();
let room_id = uuid::Uuid::new_v4();
let drawer = Drawer::new(room_id, "Rust is a systems programming language");
let drawer_id = drawer.id;
let vecs = embedder
.embed_batch(std::slice::from_ref(&drawer.content))
.await
.unwrap();
handle
.vector_store
.upsert(drawer_id, vecs[0].clone())
.await
.unwrap();
handle.add_drawer(drawer);
handle.refresh_l1();
let _ = recall(&handle, embedder.as_ref(), "systems programming Rust", 5)
.await
.unwrap();
let mut hits = 0u64;
for _ in 0..20 {
hits = log.hit_count(drawer_id).await.unwrap();
if hits >= 1 {
break;
}
tokio::time::sleep(std::time::Duration::from_millis(25)).await;
}
assert!(hits >= 1, "expected at least one logged hit, got {hits}");
}
#[tokio::test]
async fn open_attaches_recall_log_automatically() {
init_embedder();
let dir = tempdir().unwrap();
let palace = Palace {
id: PalaceId::new("analytics-auto"),
name: "AnalyticsAuto".into(),
description: None,
created_at: chrono::Utc::now(),
data_dir: dir.path().join("analytics-auto"),
};
std::fs::create_dir_all(&palace.data_dir).unwrap();
let handle = PalaceHandle::open(&palace).unwrap();
assert!(
handle.recall_log.is_some(),
"PalaceHandle::open must auto-attach a RecallLog (issue #53)"
);
assert!(
palace.data_dir.join("recall.redb").exists(),
"recall.redb must exist on disk after open"
);
let drawer_id = handle
.remember(
"the platypus is a monotreme native to eastern Australia".into(),
RoomType::Research,
vec!["wildlife".into()],
0.7,
)
.await
.unwrap();
let embedder = shared_embedder().await.unwrap();
let _ = recall(&handle, embedder.as_ref(), "platypus monotreme", 5)
.await
.unwrap();
let log = handle.recall_log.as_ref().unwrap().clone();
let mut hits = 0u64;
for _ in 0..20 {
hits = log.hit_count(drawer_id).await.unwrap();
if hits >= 1 {
break;
}
tokio::time::sleep(std::time::Duration::from_millis(25)).await;
}
assert!(
hits >= 1,
"auto-attached recall log must record events; got {hits}"
);
}
#[tokio::test]
async fn closet_updated_after_remember() {
init_embedder();
let dir = tempdir().unwrap();
let palace = Palace {
id: PalaceId::new("closet-test"),
name: "Closet".into(),
description: None,
created_at: chrono::Utc::now(),
data_dir: dir.path().join("closet-test"),
};
std::fs::create_dir_all(&palace.data_dir).unwrap();
let handle = PalaceHandle::open(&palace).unwrap();
let id = handle
.remember(
"Quokkas are happy marsupials".into(),
RoomType::General,
vec![],
0.5,
)
.await
.unwrap();
let closets = handle.closets.read();
let entry = closets
.get("quokkas")
.expect("expected `quokkas` keyword in closet index");
assert!(
entry.contains(&id),
"closet entry for `quokkas` should contain the new drawer id"
);
}
#[test]
fn expand_query_adds_synonyms() {
let out = expand_query("how fast is vector search?");
assert!(out.contains("HNSW"), "expected HNSW synonym, got: {out}");
assert!(
out.contains("latency"),
"expected latency synonym, got: {out}"
);
}
#[test]
fn expand_query_noop_for_unmatched() {
let out = expand_query("what is a borrow checker?");
assert!(
out.contains("borrow checker"),
"expected original query preserved, got: {out}"
);
assert!(
out.contains("ownership") || out.contains("lifetime"),
"expected ownership/lifetime synonyms, got: {out}"
);
let untouched = expand_query("what colour is the sky on Tuesday");
assert_eq!(
untouched, "what colour is the sky on Tuesday",
"queries with no triggers must pass through unchanged"
);
}
#[ignore = "requires real ONNX embedder (issue #850)"]
#[tokio::test]
async fn cold_restart_recalls_beyond_l1_snapshot() {
init_embedder();
let dir = tempdir().unwrap();
let palace = Palace {
id: PalaceId::new("cold-restart"),
name: "Cold".into(),
description: None,
created_at: chrono::Utc::now(),
data_dir: dir.path().join("cold-restart"),
};
std::fs::create_dir_all(&palace.data_dir).unwrap();
let needle_id = {
let handle = PalaceHandle::open(&palace).unwrap();
for i in 0..19 {
handle
.remember(
format!("filler drawer number {i} about generic topics"),
RoomType::General,
vec![],
0.9,
)
.await
.unwrap();
}
handle
.remember(
"the pangolin is a scaly nocturnal mammal".into(),
RoomType::Research,
vec![],
0.1,
)
.await
.unwrap()
};
let handle2 = PalaceHandle::open(&palace).unwrap();
let count = handle2.drawers.read().len();
assert!(
count >= 20,
"expected >=20 drawers after cold reopen, got {count}"
);
let results = recall_with_default_embedder(&handle2, "pangolin scaly mammal", 10)
.await
.unwrap();
assert!(
results.iter().any(|r| r.drawer.id == needle_id),
"low-importance drawer beyond L1 must still be recallable after cold restart; got {results:?}"
);
}
#[tokio::test]
async fn shared_embedder_is_singleton() {
init_embedder();
let a = shared_embedder().await.unwrap();
let b = shared_embedder().await.unwrap();
assert!(
Arc::ptr_eq(&a, &b),
"shared_embedder must return the same Arc on every call"
);
}
#[tokio::test]
async fn retrieve_l2_tag_boost_raises_rank() {
init_embedder();
let dir = tempdir().unwrap();
let palace = Palace {
id: PalaceId::new("boost-test"),
name: "Boost".into(),
description: None,
created_at: chrono::Utc::now(),
data_dir: dir.path().join("boost-test"),
};
std::fs::create_dir_all(&palace.data_dir).unwrap();
let handle = PalaceHandle::open(&palace).unwrap();
let id_tagged = handle
.remember(
"Vector search performance benchmarks show low latency".into(),
RoomType::Backend,
vec!["vector-search".into()],
0.5,
)
.await
.unwrap();
let _id_other = handle
.remember(
"React components render through a virtual DOM".into(),
RoomType::Frontend,
vec![],
0.5,
)
.await
.unwrap();
let embedder = shared_embedder().await.unwrap();
let results = retrieve_l2(
&handle,
embedder.as_ref(),
"vector search performance",
None,
5,
)
.await
.unwrap();
assert!(!results.is_empty(), "L2 should return results");
assert!(
uuid_prefix_eq(results[0].drawer.id, id_tagged),
"tagged drawer should rank first; got {:?}",
results[0].drawer.content
);
}
#[tokio::test]
async fn recall_across_palaces_merges_results() {
init_embedder();
let dir = tempdir().unwrap();
let palace_a = Palace {
id: PalaceId::new("alpha"),
name: "Alpha".into(),
description: None,
created_at: chrono::Utc::now(),
data_dir: dir.path().join("alpha"),
};
std::fs::create_dir_all(&palace_a.data_dir).unwrap();
let handle_a = PalaceHandle::open(&palace_a).unwrap();
handle_a
.remember(
"the pangolin is a scaly nocturnal mammal".into(),
RoomType::Research,
vec![],
0.6,
)
.await
.unwrap();
let palace_b = Palace {
id: PalaceId::new("beta"),
name: "Beta".into(),
description: None,
created_at: chrono::Utc::now(),
data_dir: dir.path().join("beta"),
};
std::fs::create_dir_all(&palace_b.data_dir).unwrap();
let handle_b = PalaceHandle::open(&palace_b).unwrap();
handle_b
.remember(
"the platypus is a venomous monotreme".into(),
RoomType::Research,
vec![],
0.6,
)
.await
.unwrap();
let handles = vec![handle_a, handle_b];
let results = recall_across_palaces_with_default_embedder(
&handles,
"pangolin platypus mammal",
10,
false,
)
.await
.unwrap();
assert!(!results.is_empty(), "expected merged results, got none");
assert!(
results.iter().any(|r| r.palace_id == "alpha"),
"expected at least one alpha result; got {:?}",
results.iter().map(|r| &r.palace_id).collect::<Vec<_>>()
);
assert!(
results.iter().any(|r| r.palace_id == "beta"),
"expected at least one beta result; got {:?}",
results.iter().map(|r| &r.palace_id).collect::<Vec<_>>()
);
for w in results.windows(2) {
assert!(
w[0].result.score >= w[1].result.score,
"results not sorted: {} < {}",
w[0].result.score,
w[1].result.score
);
}
}
#[tokio::test]
async fn remember_rejects_short_content() {
let dir = tempdir().unwrap();
let handle = make_handle(dir.path());
let err = handle
.remember("too short".to_string(), RoomType::General, vec![], 0.5)
.await
.expect_err("should reject");
let msg = format!("{err:#}");
assert!(
msg.to_lowercase().contains("too short")
|| msg.contains("memory_note")
|| msg.contains("tokens"),
"expected actionable error, got: {msg}"
);
}
#[tokio::test]
async fn remember_rejects_known_noise_patterns() {
let dir = tempdir().unwrap();
let handle = make_handle(dir.path());
let cases = [
"Tool use: search_files with query parameter very_long_string_here",
"feat(memory): add filter for noise patterns to reduce drawer clutter",
"Running cargo test --workspace --all-features for the entire monorepo...",
];
for c in cases {
let err = handle
.remember(c.to_string(), RoomType::General, vec![], 0.5)
.await
.expect_err("should reject");
assert!(
format!("{err:#}").to_lowercase().contains("noise")
|| format!("{err:#}").to_lowercase().contains("low-signal"),
"expected noise-pattern reject for: {c}",
);
}
}
#[tokio::test]
async fn remember_force_bypasses_filter() {
init_embedder();
let dir = tempdir().unwrap();
let handle = make_handle(dir.path());
let id = handle
.remember_with_options(
"x".to_string(),
RoomType::General,
vec![],
0.5,
RememberOptions::forced(),
)
.await
.expect("force should bypass filter");
assert_ne!(id, uuid::Uuid::nil());
}
#[tokio::test]
async fn note_options_skip_token_check_but_keep_noise_filter() {
init_embedder();
let dir = tempdir().unwrap();
let handle = make_handle(dir.path());
let id = handle
.remember_with_options(
"User prefers snake_case".to_string(),
RoomType::General,
vec![],
1.0,
RememberOptions::note(),
)
.await
.expect("note should accept short curated fact");
let stored_type = {
let drawers = handle.drawers.read();
let stored = drawers.iter().find(|d| d.id == id).expect("present");
stored.drawer_type
};
assert_eq!(stored_type, DrawerType::UserFact);
let err = handle
.remember_with_options(
"Tool use: x".to_string(),
RoomType::General,
vec![],
1.0,
RememberOptions::note(),
)
.await
.expect_err("note must still reject noise patterns");
assert!(format!("{err:#}").to_lowercase().contains("noise"));
}
#[tokio::test]
async fn remember_classifies_commit_messages() {
init_embedder();
let dir = tempdir().unwrap();
let handle = make_handle(dir.path());
let id = handle
.remember_with_options(
"feat(scope): non-empty long enough message body here please".to_string(),
RoomType::General,
vec![],
0.5,
RememberOptions::forced(),
)
.await
.expect("forced commit message");
let drawers = handle.drawers.read();
let stored = drawers.iter().find(|d| d.id == id).expect("present");
assert_eq!(stored.drawer_type, DrawerType::Commit);
}
#[tokio::test]
async fn purge_expired_drops_only_past_ttl() {
let dir = tempdir().unwrap();
let handle = make_handle(dir.path());
let room_id = uuid::Uuid::new_v4();
let mut expired = Drawer::new(room_id, "expired");
expired.expires_at = Some(chrono::Utc::now() - chrono::Duration::days(1));
let expired_id = expired.id;
let mut future = Drawer::new(room_id, "future");
future.expires_at = Some(chrono::Utc::now() + chrono::Duration::days(7));
let future_id = future.id;
let permanent = Drawer::new(room_id, "permanent");
let permanent_id = permanent.id;
handle.add_drawer(expired);
handle.add_drawer(future);
handle.add_drawer(permanent);
let pruned = handle.purge_expired().await.expect("purge");
assert_eq!(pruned, 1, "exactly one drawer should be pruned");
let remaining: Vec<uuid::Uuid> = handle.drawers.read().iter().map(|d| d.id).collect();
assert!(!remaining.contains(&expired_id));
assert!(remaining.contains(&future_id));
assert!(remaining.contains(&permanent_id));
}
#[ignore = "requires real ONNX embedder (issue #850)"]
#[tokio::test]
async fn recall_ranks_by_similarity_over_importance() {
init_embedder();
let dir = tempdir().unwrap();
let palace = Palace {
id: PalaceId::new("similarity-ranking-test"),
name: "SimilarityRank".into(),
description: None,
created_at: chrono::Utc::now(),
data_dir: dir.path().join("similarity-ranking-test"),
};
std::fs::create_dir_all(&palace.data_dir).unwrap();
let handle = PalaceHandle::open(&palace).unwrap();
let _high_imp_id = handle
.remember(
"concurrent write regression test fixture number one payload here".into(),
RoomType::General,
vec![],
1.0,
)
.await
.unwrap();
let on_topic_id = handle
.remember(
"the pangolin is a scaly nocturnal mammal with protective keratin scales".into(),
RoomType::Research,
vec![],
0.1,
)
.await
.unwrap();
let embedder = shared_embedder().await.unwrap();
let results = recall(
&handle,
embedder.as_ref(),
"pangolin scaly nocturnal mammal",
10,
)
.await
.unwrap();
assert!(
!results.is_empty(),
"recall must return at least one result"
);
let on_topic_rank = results
.iter()
.enumerate()
.find(|(_, r)| r.drawer.id == on_topic_id)
.map(|(i, _)| i);
assert!(
on_topic_rank.is_some(),
"on-topic drawer must appear in recall results"
);
let rank = on_topic_rank.unwrap();
assert!(
rank <= 2,
"on-topic drawer (importance=0.1) should rank in top-3 for a semantically \
matching query, but ranked at position {rank}. \
Results: {:?}",
results
.iter()
.map(|r| format!(
"[layer={} imp={:.2} score={:.3}] {}",
r.layer,
r.drawer.importance,
r.score,
&r.drawer.content[..r.drawer.content.len().min(40)]
))
.collect::<Vec<_>>()
);
for w in results.windows(2) {
assert!(
w[0].score >= w[1].score,
"results must be sorted by score descending: {} >= {} failed",
w[0].score,
w[1].score
);
}
}
#[test]
fn rescore_l1_by_similarity_patches_scores() {
let room_id = uuid::Uuid::new_v4();
let identity_drawer = Drawer {
id: Uuid::nil(),
room_id: Uuid::nil(),
content: "identity".into(),
importance: 1.0,
source_file: None,
created_at: chrono::Utc::now(),
tags: Vec::new(),
last_accessed_at: None,
access_count: 0,
drawer_type: crate::memory_core::palace::DrawerType::UserFact,
expires_at: None,
completed_at: None,
};
let mut matched = Drawer::new(room_id, "matched drawer");
matched.importance = 0.9;
let matched_id = matched.id;
let mut unmatched = Drawer::new(room_id, "unmatched drawer");
unmatched.importance = 1.0;
let mut results = vec![
RecallResult {
drawer: identity_drawer,
score: 1.0,
layer: 0,
},
RecallResult {
drawer: matched.clone(),
score: matched.importance, layer: 1,
},
RecallResult {
drawer: unmatched.clone(),
score: unmatched.importance, layer: 1,
},
];
let mut sim_scores = HashMap::new();
sim_scores.insert(matched_id, 0.75_f32);
rescore_l1_by_similarity(&mut results, &sim_scores);
assert!(
(results[0].score - 1.0).abs() < 1e-6,
"L0 identity score must not change"
);
assert!(
(results[1].score - 0.75).abs() < 1e-6,
"matched L1 entry must get similarity score 0.75, got {}",
results[1].score
);
let expected_penalty = 1.0_f32 * L1_NO_SIMILARITY_PENALTY;
assert!(
(results[2].score - expected_penalty).abs() < 1e-6,
"unmatched L1 entry must get importance * L1_NO_SIMILARITY_PENALTY = {expected_penalty}, got {}",
results[2].score
);
}
#[tokio::test]
async fn recall_top_k_caps_result_count() {
init_embedder();
let dir = tempdir().unwrap();
let palace = Palace {
id: PalaceId::new("topk-cap-test"),
name: "TopKCap".into(),
description: None,
created_at: chrono::Utc::now(),
data_dir: dir.path().join("topk-cap-test"),
};
std::fs::create_dir_all(&palace.data_dir).unwrap();
let handle = PalaceHandle::open(&palace).unwrap();
for i in 0..20u32 {
handle
.remember(
format!(
"test fact number {i} about the recall top-k cap regression \
with enough tokens to pass the default filter check"
),
RoomType::General,
vec![],
(i as f32) * 0.04 + 0.1,
)
.await
.unwrap();
}
let embedder = shared_embedder().await.unwrap();
let top_k = 5_usize;
let shallow = recall(&handle, embedder.as_ref(), "test fact recall", top_k)
.await
.unwrap();
assert!(
shallow.len() <= top_k,
"shallow recall: expected at most {top_k} results, got {}",
shallow.len()
);
let deep = recall_deep(&handle, embedder.as_ref(), "test fact recall", top_k)
.await
.unwrap();
assert!(
deep.len() <= top_k,
"deep recall: expected at most {top_k} results, got {}",
deep.len()
);
}