@@ -50,3 +50,92 @@ pub fn update_grid(grid: &mut Grid, balls: &[Metaball]) {
5050 }
5151 }
5252}
53+
54+ #[ cfg( test) ]
55+ mod tests {
56+ use super :: * ;
57+
58+ fn make_ball ( x : f32 , y : f32 , vx : f32 , vy : f32 , radius : f32 ) -> Metaball {
59+ Metaball { x, y, vx, vy, radius }
60+ }
61+
62+ // clamp_and_bounce tests (tested via update_balls)
63+
64+ #[ test]
65+ fn ball_moves_by_velocity ( ) {
66+ let mut balls = vec ! [ make_ball( 10.0 , 10.0 , 2.0 , -3.0 , 1.0 ) ] ;
67+ update_balls ( & mut balls, 100.0 , 100.0 ) ;
68+ assert_eq ! ( balls[ 0 ] . x, 12.0 ) ;
69+ assert_eq ! ( balls[ 0 ] . y, 7.0 ) ;
70+ }
71+
72+ #[ test]
73+ fn ball_bounces_off_right_wall ( ) {
74+ // Place ball near right wall with positive vx so it would exceed max
75+ let mut balls = vec ! [ make_ball( 98.0 , 50.0 , 5.0 , 0.0 , 2.0 ) ] ;
76+ update_balls ( & mut balls, 100.0 , 100.0 ) ;
77+ // After update: x = 103 > 98 (100 - radius), so clamp to 98 and reverse vx
78+ assert_eq ! ( balls[ 0 ] . x, 98.0 ) ;
79+ assert ! ( balls[ 0 ] . vx < 0.0 ) ;
80+ }
81+
82+ #[ test]
83+ fn ball_bounces_off_left_wall ( ) {
84+ let mut balls = vec ! [ make_ball( 3.0 , 50.0 , -5.0 , 0.0 , 4.0 ) ] ;
85+ update_balls ( & mut balls, 100.0 , 100.0 ) ;
86+ // After update: x = -2 < 4 (radius), clamp to 4 and flip vx positive
87+ assert_eq ! ( balls[ 0 ] . x, 4.0 ) ;
88+ assert ! ( balls[ 0 ] . vx > 0.0 ) ;
89+ }
90+
91+ #[ test]
92+ fn ball_bounces_off_bottom_wall ( ) {
93+ let mut balls = vec ! [ make_ball( 50.0 , 97.0 , 0.0 , 5.0 , 3.0 ) ] ;
94+ update_balls ( & mut balls, 100.0 , 100.0 ) ;
95+ assert_eq ! ( balls[ 0 ] . y, 97.0 ) ;
96+ assert ! ( balls[ 0 ] . vy < 0.0 ) ;
97+ }
98+
99+ #[ test]
100+ fn ball_bounces_off_top_wall ( ) {
101+ let mut balls = vec ! [ make_ball( 50.0 , 2.0 , 0.0 , -5.0 , 3.0 ) ] ;
102+ update_balls ( & mut balls, 100.0 , 100.0 ) ;
103+ assert_eq ! ( balls[ 0 ] . y, 3.0 ) ;
104+ assert ! ( balls[ 0 ] . vy > 0.0 ) ;
105+ }
106+
107+ #[ test]
108+ fn field_value_is_higher_near_ball_center ( ) {
109+ let balls = vec ! [ make_ball( 5.0 , 5.0 , 0.0 , 0.0 , 10.0 ) ] ;
110+ // Cell directly on ball center should have high field value
111+ let near = field_value ( 5.0 , 5.0 , & balls) ;
112+ // Cell far from ball
113+ let far = field_value ( 50.0 , 50.0 , & balls) ;
114+ assert ! ( near > far) ;
115+ }
116+
117+ #[ test]
118+ fn field_value_no_balls_returns_negative_threshold ( ) {
119+ let value = field_value ( 0.0 , 0.0 , & [ ] ) ;
120+ assert_eq ! ( value, -0.8 ) ;
121+ }
122+
123+ #[ test]
124+ fn update_grid_populates_all_cells ( ) {
125+ let mut grid = Grid :: new ( 5 , 5 ) ;
126+ let balls = vec ! [ make_ball( 2.0 , 2.0 , 0.0 , 0.0 , 5.0 ) ] ;
127+ update_grid ( & mut grid, & balls) ;
128+ // At least some cells should be non-zero
129+ assert ! ( grid. cells. iter( ) . any( |& v| v != 0.0 ) ) ;
130+ }
131+
132+ #[ test]
133+ fn update_grid_center_cell_higher_than_edge ( ) {
134+ let mut grid = Grid :: new ( 10 , 10 ) ;
135+ let balls = vec ! [ make_ball( 5.0 , 5.0 , 0.0 , 0.0 , 10.0 ) ] ;
136+ update_grid ( & mut grid, & balls) ;
137+ let center = grid. get ( 5 , 5 ) ;
138+ let edge = grid. get ( 0 , 0 ) ;
139+ assert ! ( center > edge) ;
140+ }
141+ }
0 commit comments