@@ -18,7 +18,6 @@ use kitsune2_transport_tx5::Tx5TransportFactory;
18
18
/// - `op_store` - The default op store is [MemOpStoreFactory].
19
19
/// Note: you will likely want to implement your own op store.
20
20
/// - `peer_meta_store` - The default peer meta store is [factories::MemPeerMetaStoreFactory].
21
- /// Note: you will likely want to implement your own peer meta store.
22
21
/// - `gossip` - The default gossip module is [K2GossipFactory].
23
22
/// - `local_agent_store` - The default local agent store is [factories::CoreLocalAgentStoreFactory].
24
23
pub fn default_builder ( ) -> Builder {
@@ -37,3 +36,215 @@ pub fn default_builder() -> Builder {
37
36
local_agent_store : factories:: CoreLocalAgentStoreFactory :: create ( ) ,
38
37
}
39
38
}
39
+
40
+ #[ cfg( test) ]
41
+ mod test {
42
+ use crate :: default_builder;
43
+ use bytes:: Bytes ;
44
+ use kitsune2_api:: {
45
+ BoxFut , DhtArc , DynSpace , DynSpaceHandler , K2Result , KitsuneHandler ,
46
+ LocalAgent , OpId , SpaceHandler , SpaceId , Timestamp ,
47
+ } ;
48
+ use kitsune2_core:: {
49
+ factories:: {
50
+ config:: { CoreBootstrapConfig , CoreBootstrapModConfig } ,
51
+ MemOpStoreFactory , MemoryOp ,
52
+ } ,
53
+ Ed25519LocalAgent ,
54
+ } ;
55
+ use kitsune2_gossip:: { K2GossipConfig , K2GossipModConfig } ;
56
+ use kitsune2_test_utils:: {
57
+ bootstrap:: TestBootstrapSrv , enable_tracing, iter_check, random_bytes,
58
+ space:: TEST_SPACE_ID ,
59
+ } ;
60
+ use kitsune2_transport_tx5:: config:: {
61
+ Tx5TransportConfig , Tx5TransportModConfig ,
62
+ } ;
63
+ use sbd_server:: SbdServer ;
64
+ use std:: sync:: Arc ;
65
+
66
+ fn create_op_list ( num_ops : u16 ) -> ( Vec < Bytes > , Vec < OpId > ) {
67
+ let mut ops = Vec :: new ( ) ;
68
+ let mut op_ids = Vec :: new ( ) ;
69
+ for _ in 0 ..num_ops {
70
+ let op =
71
+ MemoryOp :: new ( Timestamp :: from_micros ( 0 ) , random_bytes ( 256 ) ) ;
72
+ let op_id = op. compute_op_id ( ) ;
73
+ ops. push ( op. into ( ) ) ;
74
+ op_ids. push ( op_id) ;
75
+ }
76
+ ( ops, op_ids)
77
+ }
78
+
79
+ #[ derive( Debug ) ]
80
+ struct HolochainKitsuneHandler ;
81
+ impl KitsuneHandler for HolochainKitsuneHandler {
82
+ fn create_space (
83
+ & self ,
84
+ _space_id : SpaceId ,
85
+ ) -> BoxFut < ' _ , K2Result < DynSpaceHandler > > {
86
+ Box :: pin ( async {
87
+ let space_handler: DynSpaceHandler =
88
+ Arc :: new ( HolochainSpaceHandler ) ;
89
+ Ok ( space_handler)
90
+ } )
91
+ }
92
+ }
93
+
94
+ #[ derive( Debug ) ]
95
+ struct HolochainSpaceHandler ;
96
+ impl SpaceHandler for HolochainSpaceHandler { }
97
+
98
+ async fn make_kitsune_space (
99
+ signal_server_url : & str ,
100
+ bootstrap_server_url : & str ,
101
+ ) -> DynSpace {
102
+ let mut kitsune_builder =
103
+ default_builder ( ) . with_default_config ( ) . unwrap ( ) ;
104
+ kitsune_builder
105
+ . config
106
+ . set_module_config ( & CoreBootstrapModConfig {
107
+ core_bootstrap : CoreBootstrapConfig {
108
+ server_url : bootstrap_server_url. to_owned ( ) ,
109
+ backoff_max_ms : 1000 ,
110
+ ..Default :: default ( )
111
+ } ,
112
+ } )
113
+ . unwrap ( ) ;
114
+ kitsune_builder. op_store = MemOpStoreFactory :: create ( ) ;
115
+ kitsune_builder
116
+ . config
117
+ . set_module_config ( & Tx5TransportModConfig {
118
+ tx5_transport : Tx5TransportConfig {
119
+ server_url : signal_server_url. to_owned ( ) ,
120
+ signal_allow_plain_text : true ,
121
+ } ,
122
+ } )
123
+ . unwrap ( ) ;
124
+ kitsune_builder
125
+ . config
126
+ . set_module_config ( & K2GossipModConfig {
127
+ k2_gossip : K2GossipConfig {
128
+ initiate_interval_ms : 100 ,
129
+ min_initiate_interval_ms : 75 ,
130
+ round_timeout_ms : 10000 ,
131
+ ..Default :: default ( )
132
+ } ,
133
+ } )
134
+ . unwrap ( ) ;
135
+
136
+ let kitsune_handler = Arc :: new ( HolochainKitsuneHandler ) ;
137
+ let kitsune = kitsune_builder
138
+ . build ( kitsune_handler. clone ( ) )
139
+ . await
140
+ . unwrap ( ) ;
141
+ kitsune. space ( TEST_SPACE_ID ) . await . unwrap ( )
142
+ }
143
+
144
+ #[ tokio:: test]
145
+ async fn two_node_gossip ( ) {
146
+ enable_tracing ( ) ;
147
+ let signal_server = SbdServer :: new ( Arc :: new ( sbd_server:: Config {
148
+ bind : vec ! [ "127.0.0.1:0" . to_string( ) ] ,
149
+ ..Default :: default ( )
150
+ } ) )
151
+ . await
152
+ . unwrap ( ) ;
153
+ let signal_server_url =
154
+ format ! ( "ws://{}" , signal_server. bind_addrs( ) [ 0 ] ) ;
155
+
156
+ let bootstrap_server = TestBootstrapSrv :: new ( false ) . await ;
157
+ let bootstrap_server_url = bootstrap_server. addr ( ) . to_string ( ) ;
158
+
159
+ // Create 2 Kitsune instances and 1 space each.
160
+ let space_1 =
161
+ make_kitsune_space ( & signal_server_url, & bootstrap_server_url) . await ;
162
+ let space_2 =
163
+ make_kitsune_space ( & signal_server_url, & bootstrap_server_url) . await ;
164
+
165
+ // Insert ops into both spaces' op stores.
166
+ let ( ops_1, op_ids_1) = create_op_list ( 100 ) ;
167
+ space_1
168
+ . op_store ( )
169
+ . process_incoming_ops ( ops_1. clone ( ) )
170
+ . await
171
+ . unwrap ( ) ;
172
+ let ( ops_2, op_ids_2) = create_op_list ( 100 ) ;
173
+ space_2
174
+ . op_store ( )
175
+ . process_incoming_ops ( ops_2. clone ( ) )
176
+ . await
177
+ . unwrap ( ) ;
178
+
179
+ // Create 2 agents.
180
+ let local_agent_1 = Arc :: new ( Ed25519LocalAgent :: default ( ) ) ;
181
+ let local_agent_2 = Arc :: new ( Ed25519LocalAgent :: default ( ) ) ;
182
+ local_agent_1. set_tgt_storage_arc_hint ( DhtArc :: FULL ) ;
183
+ local_agent_2. set_tgt_storage_arc_hint ( DhtArc :: FULL ) ;
184
+
185
+ // Join agent 1 to local space.
186
+ space_1
187
+ . local_agent_join ( local_agent_1. clone ( ) )
188
+ . await
189
+ . unwrap ( ) ;
190
+
191
+ // Wait for agent_1 to publish their info to the bootstrap & peer store.
192
+ iter_check ! ( 5000 , 100 , {
193
+ let space_1_agents = space_1. peer_store( ) . get_all( ) . await . unwrap( ) ;
194
+ if space_1_agents
195
+ . iter( )
196
+ . any( |agent| agent. agent == * local_agent_1. agent( ) )
197
+ {
198
+ break ;
199
+ }
200
+ } ) ;
201
+
202
+ // Join agent 2 to local space.
203
+ space_2
204
+ . local_agent_join ( local_agent_2. clone ( ) )
205
+ . await
206
+ . unwrap ( ) ;
207
+
208
+ // Wait for agent 2 to publish their info and agent 1 to be polled from
209
+ // bootstrap.
210
+ iter_check ! ( 5000 , 100 , {
211
+ let space_2_agents = space_2. peer_store( ) . get_all( ) . await . unwrap( ) ;
212
+ if space_2_agents. len( ) == 2 {
213
+ break ;
214
+ }
215
+ } ) ;
216
+
217
+ // Wait for peer connection setup to complete.
218
+ tokio:: time:: sleep ( std:: time:: Duration :: from_secs ( 1 ) ) . await ;
219
+
220
+ // Wait for gossip to exchange all ops.
221
+ iter_check ! ( 5000 , 500 , {
222
+ let actual_ops_1 = space_1
223
+ . op_store( )
224
+ . retrieve_ops( op_ids_2. clone( ) )
225
+ . await
226
+ . unwrap( ) ;
227
+ let actual_ops_2 = space_2
228
+ . op_store( )
229
+ . retrieve_ops( op_ids_1. clone( ) )
230
+ . await
231
+ . unwrap( ) ;
232
+ if actual_ops_1. len( ) == ops_2. len( )
233
+ && actual_ops_2. len( ) == ops_1. len( )
234
+ {
235
+ break ;
236
+ } else {
237
+ println!(
238
+ "space 1 actual ops {}/expected {}" ,
239
+ actual_ops_1. len( ) ,
240
+ ops_2. len( )
241
+ ) ;
242
+ println!(
243
+ "space 2 actual ops {}/expected {}" ,
244
+ actual_ops_2. len( ) ,
245
+ ops_1. len( )
246
+ ) ;
247
+ }
248
+ } ) ;
249
+ }
250
+ }
0 commit comments