77import math
88
99import pytest
10- from hypothesis import given , settings
10+ from hypothesis import assume , given , settings
1111from hypothesis import strategies as st
1212
1313from physbound .engines .link_budget import free_space_path_loss_db , max_aperture_gain_dbi
@@ -49,6 +49,7 @@ def test_db_to_linear_roundtrip(self, x):
4949 @given (x = positive_linear , y = positive_linear )
5050 def test_db_preserves_ordering (self , x , y ):
5151 """dB conversion preserves ordering: if x > y then dB(x) > dB(y)."""
52+ assume (x > y * 1.001 or y > x * 1.001 ) # require meaningful separation
5253 if x > y :
5354 assert linear_to_db (x ) > linear_to_db (y )
5455 elif x < y :
@@ -67,18 +68,20 @@ class TestFSPLProperties:
6768 @given (f = positive_freq , d1 = positive_dist , d2 = positive_dist )
6869 def test_fspl_increases_with_distance (self , f , d1 , d2 ):
6970 """FSPL is monotonically increasing with distance at fixed frequency."""
70- if d1 < d2 :
71- assert free_space_path_loss_db (f , d1 ) < free_space_path_loss_db (f , d2 )
71+ assume ( d2 > d1 * 1.001 )
72+ assert free_space_path_loss_db (f , d1 ) < free_space_path_loss_db (f , d2 )
7273
7374 @given (d = positive_dist , f1 = positive_freq , f2 = positive_freq )
7475 def test_fspl_increases_with_frequency (self , d , f1 , f2 ):
7576 """FSPL is monotonically increasing with frequency at fixed distance."""
76- if f1 < f2 :
77- assert free_space_path_loss_db (f1 , d ) < free_space_path_loss_db (f2 , d )
77+ assume ( f2 > f1 * 1.001 )
78+ assert free_space_path_loss_db (f1 , d ) < free_space_path_loss_db (f2 , d )
7879
7980 @given (f = positive_freq , d = positive_dist )
80- def test_fspl_always_positive (self , f , d ):
81- """FSPL is always a positive loss (in dB)."""
81+ def test_fspl_positive_in_far_field (self , f , d ):
82+ """FSPL is positive when the link is in the far field (d > wavelength)."""
83+ wavelength = 299_792_458 / f
84+ assume (d > wavelength )
8285 assert free_space_path_loss_db (f , d ) > 0
8386
8487 @given (f = positive_freq , d = positive_dist )
@@ -97,14 +100,14 @@ class TestShannonProperties:
97100 @given (bw = positive_bw , snr1 = positive_snr , snr2 = positive_snr )
98101 def test_capacity_increases_with_snr (self , bw , snr1 , snr2 ):
99102 """Shannon capacity increases with SNR at fixed bandwidth."""
100- if snr1 < snr2 :
101- assert channel_capacity_bps (bw , snr1 ) < channel_capacity_bps (bw , snr2 )
103+ assume ( snr2 > snr1 * 1.001 )
104+ assert channel_capacity_bps (bw , snr1 ) < channel_capacity_bps (bw , snr2 )
102105
103106 @given (snr = positive_snr , bw1 = positive_bw , bw2 = positive_bw )
104107 def test_capacity_increases_with_bandwidth (self , snr , bw1 , bw2 ):
105108 """Shannon capacity increases with bandwidth at fixed SNR."""
106- if bw1 < bw2 :
107- assert channel_capacity_bps (bw1 , snr ) < channel_capacity_bps (bw2 , snr )
109+ assume ( bw2 > bw1 * 1.001 )
110+ assert channel_capacity_bps (bw1 , snr ) < channel_capacity_bps (bw2 , snr )
108111
109112 @given (bw = positive_bw , snr = positive_snr )
110113 def test_capacity_always_positive (self , bw , snr ):
@@ -134,14 +137,14 @@ class TestNoiseProperties:
134137 @given (t = positive_temp , bw1 = positive_bw , bw2 = positive_bw )
135138 def test_noise_increases_with_bandwidth (self , t , bw1 , bw2 ):
136139 """Thermal noise increases with bandwidth."""
137- if bw1 < bw2 :
138- assert thermal_noise_power_dbm (bw1 , t ) < thermal_noise_power_dbm (bw2 , t )
140+ assume ( bw2 > bw1 * 1.001 )
141+ assert thermal_noise_power_dbm (bw1 , t ) < thermal_noise_power_dbm (bw2 , t )
139142
140143 @given (bw = positive_bw , t1 = positive_temp , t2 = positive_temp )
141144 def test_noise_increases_with_temperature (self , bw , t1 , t2 ):
142145 """Thermal noise increases with temperature."""
143- if t1 < t2 :
144- assert thermal_noise_power_dbm (bw , t1 ) < thermal_noise_power_dbm (bw , t2 )
146+ assume ( t2 > t1 * 1.001 )
147+ assert thermal_noise_power_dbm (bw , t1 ) < thermal_noise_power_dbm (bw , t2 )
145148
146149 @given (bw = positive_bw )
147150 def test_noise_at_290k_anchored (self , bw ):
@@ -158,14 +161,14 @@ class TestApertureProperties:
158161 @given (d = diameter , f1 = positive_freq , f2 = positive_freq )
159162 def test_gain_increases_with_frequency (self , d , f1 , f2 ):
160163 """Aperture gain increases with frequency (shorter wavelength)."""
161- if f1 < f2 :
162- assert max_aperture_gain_dbi (d , f1 ) < max_aperture_gain_dbi (d , f2 )
164+ assume ( f2 > f1 * 1.001 ) # require meaningful separation
165+ assert max_aperture_gain_dbi (d , f1 ) < max_aperture_gain_dbi (d , f2 )
163166
164167 @given (f = positive_freq , d1 = diameter , d2 = diameter )
165168 def test_gain_increases_with_diameter (self , f , d1 , d2 ):
166169 """Aperture gain increases with antenna diameter."""
167- if d1 < d2 :
168- assert max_aperture_gain_dbi (d1 , f ) < max_aperture_gain_dbi (d2 , f )
170+ assume ( d2 > d1 * 1.001 ) # require meaningful separation to avoid FP equality
171+ assert max_aperture_gain_dbi (d1 , f ) < max_aperture_gain_dbi (d2 , f )
169172
170173 @given (d = diameter , f = positive_freq )
171174 def test_doubling_diameter_adds_6db (self , d , f ):
0 commit comments