@@ -44,3 +44,106 @@ impl TransformPath {
4444 Self { steps, total_cost, total_quality }
4545 }
4646}
47+
48+ #[ cfg( test) ]
49+ mod tests {
50+ use super :: * ;
51+ use crate :: graph:: { Format , TransformEdge } ;
52+
53+ fn edge ( from : Format , to : Format , cost : f32 , quality : f32 ) -> TransformEdge {
54+ TransformEdge :: new ( from, to, cost, quality)
55+ }
56+
57+ // ── single-step paths ─────────────────────────────────────────────────────
58+
59+ #[ test]
60+ fn test_single_step_quality_preserved ( ) {
61+ let steps = vec ! [ edge( Format :: Markdown , Format :: Html , 1.0 , 0.9 ) ] ;
62+ let path = TransformPath :: from_steps ( steps) ;
63+ assert ! ( ( path. total_quality - 0.9 ) . abs( ) < 1e-5 ,
64+ "single-step quality must equal the edge quality" ) ;
65+ }
66+
67+ #[ test]
68+ fn test_single_step_cost_preserved ( ) {
69+ let steps = vec ! [ edge( Format :: Markdown , Format :: Html , 2.5 , 1.0 ) ] ;
70+ let path = TransformPath :: from_steps ( steps) ;
71+ assert ! ( ( path. total_cost - 2.5 ) . abs( ) < 1e-5 ) ;
72+ }
73+
74+ // ── multi-step quality is multiplicative ──────────────────────────────────
75+
76+ #[ test]
77+ fn test_two_step_quality_is_product ( ) {
78+ // 0.9 * 0.8 = 0.72
79+ let steps = vec ! [
80+ edge( Format :: Markdown , Format :: Html , 1.0 , 0.9 ) ,
81+ edge( Format :: Html , Format :: Pdf , 1.0 , 0.8 ) ,
82+ ] ;
83+ let path = TransformPath :: from_steps ( steps) ;
84+ assert ! ( ( path. total_quality - 0.72 ) . abs( ) < 1e-5 ,
85+ "two-step quality must be the product of both edge qualities" ) ;
86+ }
87+
88+ #[ test]
89+ fn test_two_step_cost_is_sum ( ) {
90+ let steps = vec ! [
91+ edge( Format :: Markdown , Format :: Html , 0.5 , 1.0 ) ,
92+ edge( Format :: Html , Format :: Pdf , 0.8 , 0.85 ) ,
93+ ] ;
94+ let path = TransformPath :: from_steps ( steps) ;
95+ assert ! ( ( path. total_cost - 1.3 ) . abs( ) < 1e-5 ) ;
96+ }
97+
98+ #[ test]
99+ fn test_three_step_quality_propagates_multiplicatively ( ) {
100+ // 0.9 * 0.8 * 0.7 = 0.504
101+ let steps = vec ! [
102+ edge( Format :: Markdown , Format :: Html , 1.0 , 0.9 ) ,
103+ edge( Format :: Html , Format :: Rst , 1.0 , 0.8 ) ,
104+ edge( Format :: Rst , Format :: Pdf , 1.0 , 0.7 ) ,
105+ ] ;
106+ let path = TransformPath :: from_steps ( steps) ;
107+ assert ! ( ( path. total_quality - 0.504_f32 ) . abs( ) < 1e-5 ,
108+ "three-step quality must be the product of all three edge qualities" ) ;
109+ }
110+
111+ // ── perfect quality path ──────────────────────────────────────────────────
112+
113+ #[ test]
114+ fn test_all_quality_one_yields_product_one ( ) {
115+ let steps = vec ! [
116+ edge( Format :: Markdown , Format :: Html , 1.0 , 1.0 ) ,
117+ edge( Format :: Html , Format :: Pdf , 1.0 , 1.0 ) ,
118+ ] ;
119+ let path = TransformPath :: from_steps ( steps) ;
120+ assert ! ( ( path. total_quality - 1.0 ) . abs( ) < 1e-5 ,
121+ "product of 1.0 values must equal 1.0" ) ;
122+ }
123+
124+ // ── zero quality collapses path quality ───────────────────────────────────
125+
126+ #[ test]
127+ fn test_zero_quality_edge_collapses_path_quality ( ) {
128+ let steps = vec ! [
129+ edge( Format :: Markdown , Format :: Html , 1.0 , 0.9 ) ,
130+ edge( Format :: Html , Format :: Pdf , 1.0 , 0.0 ) ,
131+ ] ;
132+ let path = TransformPath :: from_steps ( steps) ;
133+ assert ! ( ( path. total_quality - 0.0 ) . abs( ) < 1e-5 ,
134+ "a zero-quality edge must bring total path quality to 0.0" ) ;
135+ }
136+
137+ // ── step count ────────────────────────────────────────────────────────────
138+
139+ #[ test]
140+ fn test_steps_count_matches_input ( ) {
141+ let steps = vec ! [
142+ edge( Format :: Markdown , Format :: Html , 1.0 , 1.0 ) ,
143+ edge( Format :: Html , Format :: Pdf , 1.0 , 1.0 ) ,
144+ edge( Format :: Pdf , Format :: Epub , 1.0 , 1.0 ) ,
145+ ] ;
146+ let path = TransformPath :: from_steps ( steps) ;
147+ assert_eq ! ( path. steps. len( ) , 3 ) ;
148+ }
149+ }
0 commit comments