@@ -156,10 +156,9 @@ impl Network {
156156 }
157157
158158
159- /// BFS to find path to destination
159+ /// Finds a path from `start` to ` destination` where intermediate nodes must be drones.
160160 #[ must_use]
161- pub ( crate ) fn find_path ( & self , destination : NodeId ) -> Option < Vec < NodeId > > {
162- let start = self . nodes [ 0 ] . id ;
161+ pub ( crate ) fn find_path ( & self , start : NodeId , destination : NodeId ) -> Option < Vec < NodeId > > {
163162 let mut visited = HashSet :: new ( ) ;
164163 let mut queue = VecDeque :: new ( ) ;
165164 let mut parent_map = HashMap :: new ( ) ;
@@ -169,22 +168,30 @@ impl Network {
169168
170169 while let Some ( current) = queue. pop_front ( ) {
171170 if current == destination {
171+ // reconstruct path
172172 let mut path = vec ! [ destination] ;
173- let mut current = destination;
174- while let Some ( & parent) = parent_map. get ( & current ) {
173+ let mut cur = destination;
174+ while let Some ( & parent) = parent_map. get ( & cur ) {
175175 path. push ( parent) ;
176- current = parent;
176+ cur = parent;
177177 }
178178 path. reverse ( ) ;
179179 return Some ( path) ;
180180 }
181181
182182 if let Some ( node) = self . nodes . iter ( ) . find ( |n| n. id == current) {
183183 for neighbor in node. get_adjacents ( ) {
184- if !visited. contains ( neighbor) {
185- visited. insert ( * neighbor) ;
186- parent_map. insert ( neighbor, current) ;
187- queue. push_back ( * neighbor) ;
184+ if visited. contains ( neighbor) {
185+ continue ;
186+ }
187+
188+ if let Some ( neigh_node) = self . nodes . iter ( ) . find ( |n| n. id == * neighbor) {
189+ // Only allow stepping into the destination or into a drone
190+ if * neighbor == destination || neigh_node. get_node_type ( ) == NodeType :: Drone {
191+ visited. insert ( * neighbor) ;
192+ parent_map. insert ( neighbor, current) ;
193+ queue. push_back ( * neighbor) ;
194+ }
188195 }
189196 }
190197 }
@@ -289,115 +296,67 @@ mod tests {
289296 }
290297
291298 #[ test]
292- /// Tests the `find_path` method
293- fn test_find_path ( ) {
294- let root = Node :: new ( 1 , NodeType :: Client , vec ! [ 2 , 3 ] ) ;
295- let mut network = Network :: new ( root) ;
296-
297- let node2 = Node :: new ( 2 , NodeType :: Client , vec ! [ 1 , 4 ] ) ;
298- let node3 = Node :: new ( 3 , NodeType :: Client , vec ! [ 1 ] ) ;
299- let node4 = Node :: new ( 4 , NodeType :: Client , vec ! [ 2 ] ) ;
300-
301- network. add_node ( node2) ;
302- network. add_node ( node3) ;
303- network. add_node ( node4) ;
304-
305- let path = network. find_path ( 4 ) . unwrap ( ) ;
306-
307- assert_eq ! ( path, vec![ 1 , 2 , 4 ] ) ;
308- }
309-
310- #[ test]
311- /// Tests the `find_path` method with non-existing path
312- fn test_find_path_not_found ( ) {
313- let root = Node :: new ( 1 , NodeType :: Client , vec ! [ 2 ] ) ;
314- let mut network = Network :: new ( root) ;
315-
316- let node2 = Node :: new ( 2 , NodeType :: Client , vec ! [ 1 ] ) ;
317- network. add_node ( node2) ;
318-
319- let result = network. find_path ( 3 ) ;
320-
321- assert ! ( result. is_none( ) ) ;
322- }
323-
324- #[ test]
325- /// Tests `find_path` method in a complex network
326- fn test_complex_network_topology ( ) {
327- let root = Node :: new ( 1 , NodeType :: Client , vec ! [ 2 , 3 ] ) ;
328- let mut network = Network :: new ( root) ;
329-
330- network. add_node ( Node :: new ( 2 , NodeType :: Drone , vec ! [ 1 , 4 , 5 ] ) ) ;
331- network. add_node ( Node :: new ( 3 , NodeType :: Drone , vec ! [ 1 , 6 ] ) ) ;
332- network. add_node ( Node :: new ( 4 , NodeType :: Drone , vec ! [ 2 , 7 ] ) ) ;
333- network. add_node ( Node :: new ( 5 , NodeType :: Server , vec ! [ 2 ] ) ) ;
334- network. add_node ( Node :: new ( 6 , NodeType :: Server , vec ! [ 3 ] ) ) ;
335- network. add_node ( Node :: new ( 7 , NodeType :: Client , vec ! [ 4 ] ) ) ;
336-
337- let path_to_server5 = network. find_path ( 5 ) ;
338- assert ! ( path_to_server5. is_some( ) ) ;
339- let path = path_to_server5. unwrap ( ) ;
340- assert_eq ! ( path[ 0 ] , 1 ) ;
341- assert_eq ! ( path[ path. len( ) - 1 ] , 5 ) ;
342- let path_to_client7 = network. find_path ( 7 ) ;
343- assert ! ( path_to_client7. is_some( ) ) ;
299+ fn test_direct_client_to_server ( ) {
300+ let nodes = vec ! [
301+ Node { id: 1 , kind: NodeType :: Client , adjacents: vec![ 2 ] } ,
302+ Node { id: 2 , kind: NodeType :: Server , adjacents: vec![ 1 ] } ,
303+ ] ;
304+
305+
306+ let mut graph = Network :: default ( ) ;
307+ for node in nodes {
308+ graph. add_node ( node) ;
309+ }
310+ let path = graph. find_path ( 1 , 2 ) ;
311+ assert_eq ! ( path, Some ( vec![ 1 , 2 ] ) ) ;
344312 }
345313
346314 #[ test]
347- /// Tests `find_path` method in a partitioned network
348- fn test_network_partition_handling ( ) {
349- let root = Node :: new ( 1 , NodeType :: Client , vec ! [ 2 ] ) ;
350- let mut network = Network :: new ( root) ;
351-
352- network. add_node ( Node :: new ( 2 , NodeType :: Drone , vec ! [ 1 ] ) ) ;
353- network. add_node ( Node :: new ( 3 , NodeType :: Server , vec ! [ 4 ] ) ) ; // Isolated
354- network. add_node ( Node :: new ( 4 , NodeType :: Drone , vec ! [ 3 ] ) ) ; // Isolated
355-
356- let path_to_2 = network. find_path ( 2 ) ;
357- assert ! ( path_to_2. is_some( ) ) ;
358-
359- let path_to_3 = network. find_path ( 3 ) ;
360- assert ! ( path_to_3. is_none( ) ) ;
315+ fn test_path_with_drone ( ) {
316+ let nodes = vec ! [
317+ Node { id: 1 , kind: NodeType :: Client , adjacents: vec![ 2 ] } ,
318+ Node { id: 2 , kind: NodeType :: Drone , adjacents: vec![ 1 , 3 ] } ,
319+ Node { id: 3 , kind: NodeType :: Server , adjacents: vec![ 2 ] } ,
320+ ] ;
321+
322+ let mut graph = Network :: default ( ) ;
323+ for node in nodes {
324+ graph. add_node ( node) ;
325+ } let path = graph. find_path ( 1 , 3 ) ;
326+ assert_eq ! ( path, Some ( vec![ 1 , 2 , 3 ] ) ) ;
361327 }
362328
363329 #[ test]
364- /// Tests `get_servers` and `get_clients` method in a network
365- fn test_node_type_filtering ( ) {
366- let root = Node :: new ( 1 , NodeType :: Client , vec ! [ ] ) ;
367- let mut network = Network :: new ( root) ;
368-
369- network. add_node ( Node :: new ( 2 , NodeType :: Server , vec ! [ ] ) ) ;
370- network. add_node ( Node :: new ( 3 , NodeType :: Server , vec ! [ ] ) ) ;
371- network. add_node ( Node :: new ( 4 , NodeType :: Client , vec ! [ ] ) ) ;
372- network. add_node ( Node :: new ( 5 , NodeType :: Drone , vec ! [ ] ) ) ;
373-
374- let servers = network. get_servers ( ) . unwrap ( ) ;
375- assert_eq ! ( servers. len( ) , 2 ) ;
376- assert ! ( servers. contains( & 2 ) ) ;
377- assert ! ( servers. contains( & 3 ) ) ;
378-
379- let clients = network. get_clients ( ) . unwrap ( ) ;
380- assert_eq ! ( clients. len( ) , 2 ) ;
381- assert ! ( clients. contains( & 1 ) ) ;
382- assert ! ( clients. contains( & 4 ) ) ;
330+ fn test_disallow_non_drone_intermediate ( ) {
331+ let nodes = vec ! [
332+ Node { id: 1 , kind: NodeType :: Client , adjacents: vec![ 2 ] } ,
333+ Node { id: 2 , kind: NodeType :: Client , adjacents: vec![ 1 , 3 ] } , // not a drone
334+ Node { id: 3 , kind: NodeType :: Server , adjacents: vec![ 2 ] } ,
335+ ] ;
336+
337+ let mut graph = Network :: default ( ) ;
338+ for node in nodes {
339+ graph. add_node ( node) ;
340+ }
341+ let path = graph. find_path ( 1 , 3 ) ;
342+ assert_eq ! ( path, None ) ; // should fail because node 2 is not a drone
383343 }
384344
385345 #[ test]
386- fn test_dynamic_network_updates ( ) {
387- let root = Node :: new ( 1 , NodeType :: Client , vec ! [ 2 ] ) ;
388- let mut network = Network :: new ( root) ;
389-
390- network. add_node ( Node :: new ( 2 , NodeType :: Drone , vec ! [ 1 , 3 ] ) ) ;
391- network. add_node ( Node :: new ( 3 , NodeType :: Server , vec ! [ 2 ] ) ) ;
392-
393- network. update_node ( 1 , vec ! [ 4 ] ) . unwrap ( ) ;
394- network. add_node ( Node :: new ( 4 , NodeType :: Drone , vec ! [ 1 ] ) ) ;
395-
396- let path = network. find_path ( 3 ) ;
397- assert ! ( path. is_some( ) ) ;
398-
399- network. remove_node ( 2 ) ;
400- let path_after_removal = network. find_path ( 3 ) ;
401- assert ! ( path_after_removal. is_none( ) ) ;
346+ fn test_multiple_paths_choose_valid ( ) {
347+ let nodes = vec ! [
348+ Node { id: 1 , kind: NodeType :: Client , adjacents: vec![ 2 , 4 ] } ,
349+ Node { id: 2 , kind: NodeType :: Client , adjacents: vec![ 1 , 3 ] } , // not a drone
350+ Node { id: 3 , kind: NodeType :: Server , adjacents: vec![ 2 , 5 ] } ,
351+ Node { id: 4 , kind: NodeType :: Drone , adjacents: vec![ 1 , 5 ] } ,
352+ Node { id: 5 , kind: NodeType :: Server , adjacents: vec![ 3 , 4 ] } ,
353+ ] ;
354+
355+ let mut graph = Network :: default ( ) ;
356+ for node in nodes {
357+ graph. add_node ( node) ;
358+ }
359+ let path = graph. find_path ( 1 , 5 ) ;
360+ assert_eq ! ( path, Some ( vec![ 1 , 4 , 5 ] ) ) ; // must avoid node 2 because it's not a drone
402361 }
403362}
0 commit comments