@@ -5,14 +5,108 @@ test_that("basic DAG operations", {
55 dag <- RDAG $ new()
66 dag $ add_node(" A" , FALSE )
77 dag $ add_node(" B" , FALSE )
8- dag $ add_edge(" A" , " B" , NULL )
8+ dag $ add_edge(" A" , " B" , 20 )
9+
910 expect_setequal(dag $ nodes(), c(" A" , " B" ))
10- expect_equal(dag $ node_count(), 2 )
11- expect_equal(dag $ edge_count(), 1 )
11+ expect_equal(dag $ node_count(), 2L )
12+ expect_equal(dag $ edge_count(), 1L )
13+
1214 expect_equal(dag $ get_parents(" B" ), " A" )
1315 expect_equal(dag $ get_children(" A" ), " B" )
16+
17+ e <- dag $ edges()
18+ expect_true(is.list(e ) && all(c(" from" , " to" ) %in% names(e )))
19+ expect_equal(length(e $ from ), 1L )
20+ expect_equal(paste0(e $ from , " ->" , e $ to ), " A->B" )
21+ })
22+
23+ test_that(" add_nodes_from with and without latent mask" , {
24+ # With latent mask
25+ dag1 <- RDAG $ new()
26+ dag1 $ add_nodes_from(c(" X" , " Y" , " Z" ), c(TRUE , FALSE , TRUE ))
27+ expect_setequal(dag1 $ nodes(), c(" X" , " Y" , " Z" ))
28+ expect_setequal(dag1 $ latents(), c(" X" , " Z" ))
29+
30+ # Without latent mask (all observed). Pass NULL explicitly.
31+ dag2 <- RDAG $ new()
32+ dag2 $ add_nodes_from(c(" A" , " B" , " C" ), NULL )
33+ expect_setequal(dag2 $ nodes(), c(" A" , " B" , " C" ))
34+ expect_length(dag2 $ latents(), 0L )
35+ })
36+
37+ test_that(" add_node defaults latent=FALSE and duplicate adds are no-ops" , {
38+ dag <- RDAG $ new()
39+ dag $ add_node(" L" , FALSE )
40+ dag $ add_node(" L" , TRUE )
41+ expect_setequal(dag $ nodes(), " L" )
42+ expect_length(dag $ latents(), 0L )
43+ expect_equal(dag $ node_count(), 1L )
44+ })
45+
46+ test_that(" add_edge auto-adds missing nodes; optional weight works" , {
47+ dag <- RDAG $ new()
48+
49+ dag $ add_edge(" S" , " T" , NULL )
50+ expect_setequal(dag $ nodes(), c(" S" , " T" ))
51+ expect_equal(dag $ node_count(), 2L )
52+ expect_equal(dag $ edge_count(), 1L )
53+ expect_equal(dag $ get_parents(" T" ), " S" )
54+ expect_equal(dag $ get_children(" S" ), " T" )
55+
56+ # another edge with an explicit weight
57+ dag $ add_edge(" T" , " U" , 0.5 )
58+ expect_equal(dag $ edge_count(), 2L )
59+
60+ # edge list is order-insensitive for assertions
61+ e <- dag $ edges()
62+ got <- paste0(e $ from , " ->" , e $ to )
63+ expect_setequal(got , c(" S->T" , " T->U" ))
1464})
1565
66+ test_that(" get_parents / get_children errors on unknown node" , {
67+ dag <- RDAG $ new()
68+ dag $ add_nodes_from(c(" A" ," B" ), NULL )
69+ dag $ add_edge(" A" ," B" , NULL )
70+
71+ expect_error(dag $ get_parents(" Z" ))
72+ expect_error(dag $ get_children(" Z" ))
73+ })
74+
75+ test_that(" get_ancestors_of returns nodes plus all their ancestors" , {
76+ dag <- RDAG $ new()
77+ dag $ add_nodes_from(c(" A" ," B" ," C" ," D" ), NULL )
78+ dag $ add_edge(" A" ," B" , NULL )
79+ dag $ add_edge(" B" ," C" , NULL )
80+ dag $ add_edge(" D" ," C" , NULL )
81+
82+ # ancestors(C) = {A, B, D, C} (includes the node itself per implementation)
83+ anc_C <- dag $ get_ancestors_of(c(" C" ))
84+ expect_setequal(anc_C , c(" A" ," B" ," C" ," D" ))
85+
86+ # ancestors(B, D) = {A, B, D}
87+ anc_BD <- dag $ get_ancestors_of(c(" B" ," D" ))
88+ expect_setequal(anc_BD , c(" A" ," B" ," D" ))
89+
90+ # Unknown node should error
91+ expect_error(dag $ get_ancestors_of(c(" C" ," Z" )))
92+ })
93+
94+ test_that(" nodes(), edges(), node_count(), edge_count(), latents() remain consistent" , {
95+ dag <- RDAG $ new()
96+ dag $ add_nodes_from(c(" L1" ," O1" ," O2" ), c(TRUE , FALSE , FALSE ))
97+ dag $ add_edge(" O1" ," O2" , NULL )
98+ dag $ add_edge(" L1" ," O2" , NULL )
99+
100+ expect_equal(dag $ node_count(), 3L )
101+ expect_equal(dag $ edge_count(), 2L )
102+ expect_setequal(dag $ latents(), " L1" )
103+ expect_setequal(dag $ nodes(), c(" L1" ," O1" ," O2" ))
104+
105+ e <- dag $ edges()
106+ expect_setequal(paste0(e $ from , " ->" , e $ to ), c(" O1->O2" ," L1->O2" ))
107+ })
108+
109+
16110test_that(" add_edges_from adds multiple edges correctly" , {
17111 dag <- RDAG $ new()
18112 dag $ add_nodes_from(c(" A" , " B" , " C" , " D" ), NULL )
0 commit comments