⎇ d3649bfd1a80153652c2a028315369bb4b184024
crates/modules/semantic_dht/minga-p2p/tests/kad_providers.rs
Historia
Quién tocó qué
crudo
chore: monorepo inicial con arje + minga + yahweh absorbidos
1//! Tests de Provider Records vía Kademlia DHT.
2//!
3//! Discovery a nivel de **contenido**: en lugar de "¿quién está
4//! cerca?", la pregunta es "¿quién tiene el hash X?". Cuando un peer
5//! ingresa contenido, se anuncia como provider; otros peers consultan
6//! el DHT para encontrar a quién dial directamente.
7
8use std::time::Duration;
9
10use minga_core::{parse, AttestationStore, ContentHash, Keypair, MemStore, Mst};
11use minga_p2p::{LibP2pNode, MingaPeer};
12
13fn kp(seed: u8) -> Keypair {
14 Keypair::from_seed(&[seed; 32])
15}
16
17#[tokio::test]
18async fn provider_announce_and_lookup_two_nodes() {
19 let a = LibP2pNode::new().unwrap();
20 let b = LibP2pNode::new().unwrap();
21
22 let addr_b = b.listen("/ip4/127.0.0.1/tcp/0".parse().unwrap()).await;
23
24 // A conoce a B y dializa para establecer conexión Kad.
25 a.add_dht_peer(b.peer_id, addr_b.clone());
26 a.dial(addr_b);
27
28 tokio::time::sleep(Duration::from_millis(300)).await;
29
30 // A anuncia que tiene `content`.
31 let content = ContentHash([0x42; 32]);
32 a.start_providing(&content.0);
33
34 // Margen para que el ADD_PROVIDER se replique a B.
35 tokio::time::sleep(Duration::from_millis(500)).await;
36
37 // B consulta — debe encontrar A.
38 let providers = b.find_providers(&content.0).await;
39 assert!(
40 providers.iter().any(|p| *p == a.peer_id),
41 "B debe descubrir a A como provider, obtuvo: {:?}",
42 providers
43 );
44}
45
46#[tokio::test]
47async fn provider_lookup_returns_empty_for_unknown_content() {
48 let a = LibP2pNode::new().unwrap();
49 let b = LibP2pNode::new().unwrap();
50
51 let addr_b = b.listen("/ip4/127.0.0.1/tcp/0".parse().unwrap()).await;
52 a.add_dht_peer(b.peer_id, addr_b.clone());
53 a.dial(addr_b);
54 tokio::time::sleep(Duration::from_millis(300)).await;
55
56 // Nadie ha anunciado este hash.
57 let unknown = ContentHash([0xFF; 32]);
58 let providers = b.find_providers(&unknown.0).await;
59 assert!(providers.is_empty());
60}
61
62#[tokio::test]
63async fn minga_peer_ingest_auto_announces_provider() {
64 // El test de integración del flujo "fase de salida al mundo real":
65 // un peer hace ingest de un archivo y, sin acción adicional, otro
66 // peer puede descubrirlo vía DHT como provider.
67
68 let a_kp = kp(1);
69 let b_kp = kp(2);
70
71 let a = MingaPeer::new(a_kp, Mst::new(), MemStore::new(), AttestationStore::new()).unwrap();
72 let b = MingaPeer::new(b_kp, Mst::new(), MemStore::new(), AttestationStore::new()).unwrap();
73
74 let addr_a = a.listen("/ip4/127.0.0.1/tcp/0".parse().unwrap()).await;
75 let _addr_b = b.listen("/ip4/127.0.0.1/tcp/0".parse().unwrap()).await;
76
77 // Conectar B a A vía Kad (rendezvous bidireccional).
78 a.add_dht_peer(b.peer_id(), _addr_b);
79 b.add_dht_peer(a.peer_id(), addr_a.clone());
80 b.dial(addr_a);
81
82 tokio::time::sleep(Duration::from_millis(300)).await;
83
84 // A ingresa una función. Esto debe anunciarla automáticamente.
85 let n = parse::rust("fn discover_me() -> i32 { 7 }").unwrap();
86 let h = a.ingest(&n).await;
87
88 // Margen para la replicación del provider record.
89 tokio::time::sleep(Duration::from_millis(500)).await;
90
91 // B busca quién tiene `h` y debe encontrar A.
92 let providers = b.find_providers(h).await;
93 assert!(
94 providers.iter().any(|p| *p == a.peer_id()),
95 "B debe descubrir a A como provider del contenido recién ingerido. Obtuvo: {:?}",
96 providers,
97 );
98}