@@ -173,3 +173,192 @@ pub async fn get_disk_io_metrics(disks: &mut HashMap<String, ZDisk>) {
173173 }
174174 }
175175}
176+
177+ #[ cfg( test) ]
178+ mod tests {
179+ use super :: * ;
180+ use std:: time:: Duration ;
181+
182+ #[ test]
183+ fn test_zdisk_get_perc_free_space_zero_size ( ) {
184+ let disk = ZDisk :: new_total ( ) ;
185+ assert_eq ! ( disk. get_perc_free_space( ) , 0.0 ) ;
186+ }
187+
188+ #[ test]
189+ fn test_zdisk_get_perc_free_space_normal ( ) {
190+ let mut disk = ZDisk :: new_total ( ) ;
191+ disk. size_bytes = 1000 ;
192+ disk. available_bytes = 500 ;
193+
194+ assert_eq ! ( disk. get_perc_free_space( ) , 50.0 ) ;
195+ }
196+
197+ #[ test]
198+ fn test_zdisk_get_perc_free_space_full ( ) {
199+ let mut disk = ZDisk :: new_total ( ) ;
200+ disk. size_bytes = 1000 ;
201+ disk. available_bytes = 0 ;
202+
203+ assert_eq ! ( disk. get_perc_free_space( ) , 0.0 ) ;
204+ }
205+
206+ #[ test]
207+ fn test_zdisk_get_perc_free_space_empty ( ) {
208+ let mut disk = ZDisk :: new_total ( ) ;
209+ disk. size_bytes = 1000 ;
210+ disk. available_bytes = 1000 ;
211+
212+ assert_eq ! ( disk. get_perc_free_space( ) , 100.0 ) ;
213+ }
214+
215+ #[ test]
216+ fn test_zdisk_get_used_bytes ( ) {
217+ let mut disk = ZDisk :: new_total ( ) ;
218+ disk. size_bytes = 1000 ;
219+ disk. available_bytes = 300 ;
220+
221+ assert_eq ! ( disk. get_used_bytes( ) , 700 ) ;
222+ }
223+
224+ #[ test]
225+ fn test_zdisk_get_used_bytes_underflow ( ) {
226+ let mut disk = ZDisk :: new_total ( ) ;
227+ disk. size_bytes = 100 ;
228+ disk. available_bytes = 200 ; // More available than size (edge case)
229+
230+ // saturating_sub should return 0
231+ assert_eq ! ( disk. get_used_bytes( ) , 0 ) ;
232+ }
233+
234+ #[ test]
235+ fn test_zdisk_get_perc_used_space_zero_size ( ) {
236+ let disk = ZDisk :: new_total ( ) ;
237+ assert_eq ! ( disk. get_perc_used_space( ) , 0.0 ) ;
238+ }
239+
240+ #[ test]
241+ fn test_zdisk_get_perc_used_space_normal ( ) {
242+ let mut disk = ZDisk :: new_total ( ) ;
243+ disk. size_bytes = 1000 ;
244+ disk. available_bytes = 300 ;
245+
246+ // used = 700, 700/1000 * 100 = 70%
247+ assert ! ( ( disk. get_perc_used_space( ) - 70.0 ) . abs( ) < 0.01 ) ;
248+ }
249+
250+ #[ test]
251+ fn test_zdisk_get_read_bytes_sec ( ) {
252+ let mut disk = ZDisk :: new_total ( ) ;
253+ disk. previous_io = IoMetrics {
254+ read_bytes : 100 ,
255+ write_bytes : 50 ,
256+ } ;
257+ disk. current_io = IoMetrics {
258+ read_bytes : 600 ,
259+ write_bytes : 150 ,
260+ } ;
261+
262+ let tick = Duration :: from_secs ( 1 ) ;
263+ assert_eq ! ( disk. get_read_bytes_sec( & tick) , 500.0 ) ;
264+ }
265+
266+ #[ test]
267+ fn test_zdisk_get_read_bytes_sec_different_tick ( ) {
268+ let mut disk = ZDisk :: new_total ( ) ;
269+ disk. previous_io = IoMetrics {
270+ read_bytes : 100 ,
271+ write_bytes : 50 ,
272+ } ;
273+ disk. current_io = IoMetrics {
274+ read_bytes : 600 ,
275+ write_bytes : 150 ,
276+ } ;
277+
278+ let tick = Duration :: from_secs ( 2 ) ;
279+ assert_eq ! ( disk. get_read_bytes_sec( & tick) , 250.0 ) ;
280+ }
281+
282+ #[ test]
283+ fn test_zdisk_get_write_bytes_sec ( ) {
284+ let mut disk = ZDisk :: new_total ( ) ;
285+ disk. previous_io = IoMetrics {
286+ read_bytes : 100 ,
287+ write_bytes : 50 ,
288+ } ;
289+ disk. current_io = IoMetrics {
290+ read_bytes : 600 ,
291+ write_bytes : 150 ,
292+ } ;
293+
294+ let tick = Duration :: from_secs ( 1 ) ;
295+ assert_eq ! ( disk. get_write_bytes_sec( & tick) , 100.0 ) ;
296+ }
297+
298+ #[ test]
299+ fn test_zdisk_get_write_bytes_sec_different_tick ( ) {
300+ let mut disk = ZDisk :: new_total ( ) ;
301+ disk. previous_io = IoMetrics {
302+ read_bytes : 100 ,
303+ write_bytes : 100 ,
304+ } ;
305+ disk. current_io = IoMetrics {
306+ read_bytes : 600 ,
307+ write_bytes : 500 ,
308+ } ;
309+
310+ let tick = Duration :: from_millis ( 500 ) ;
311+ // (500 - 100) / 0.5 = 800
312+ assert_eq ! ( disk. get_write_bytes_sec( & tick) , 800.0 ) ;
313+ }
314+
315+ // Tests for get_device_name
316+ #[ test]
317+ fn test_get_device_name_simple ( ) {
318+ use std:: ffi:: OsStr ;
319+ let name = get_device_name ( OsStr :: new ( "/dev/sda1" ) ) ;
320+ // Since /dev/sda1 is not a symlink in test environment, it returns as-is
321+ assert ! ( name. contains( "sda1" ) || name. contains( "/dev/" ) ) ;
322+ }
323+
324+ #[ test]
325+ fn test_get_device_name_non_existent ( ) {
326+ use std:: ffi:: OsStr ;
327+ let name = get_device_name ( OsStr :: new ( "/nonexistent/path/device" ) ) ;
328+ assert_eq ! ( name, "/nonexistent/path/device" ) ;
329+ }
330+
331+ #[ test]
332+ fn test_get_device_name_empty ( ) {
333+ use std:: ffi:: OsStr ;
334+ let name = get_device_name ( OsStr :: new ( "" ) ) ;
335+ assert_eq ! ( name, "" ) ;
336+ }
337+
338+ // Tests for ZDisk io operations
339+ #[ test]
340+ fn test_zdisk_io_metrics_zero ( ) {
341+ let disk = ZDisk :: new_total ( ) ;
342+ let tick = Duration :: from_secs ( 1 ) ;
343+
344+ assert_eq ! ( disk. get_read_bytes_sec( & tick) , 0.0 ) ;
345+ assert_eq ! ( disk. get_write_bytes_sec( & tick) , 0.0 ) ;
346+ }
347+
348+ #[ test]
349+ fn test_zdisk_large_io_values ( ) {
350+ let mut disk = ZDisk :: new_total ( ) ;
351+ disk. previous_io = IoMetrics {
352+ read_bytes : 0 ,
353+ write_bytes : 0 ,
354+ } ;
355+ disk. current_io = IoMetrics {
356+ read_bytes : 1_000_000_000 , // 1 GB
357+ write_bytes : 500_000_000 , // 500 MB
358+ } ;
359+
360+ let tick = Duration :: from_secs ( 1 ) ;
361+ assert_eq ! ( disk. get_read_bytes_sec( & tick) , 1_000_000_000.0 ) ;
362+ assert_eq ! ( disk. get_write_bytes_sec( & tick) , 500_000_000.0 ) ;
363+ }
364+ }
0 commit comments