@@ -11,7 +11,7 @@ use libc::{id_t, setpriority};
1111#[ cfg( target_os = "linux" ) ]
1212use linux_taskstats:: Client ;
1313
14- use std:: cmp:: Ordering :: { self , Equal } ;
14+ use std:: cmp:: Ordering :: { self } ;
1515use std:: time:: { Duration , SystemTime , UNIX_EPOCH } ;
1616use sysinfo:: Process ;
1717use sysinfo:: ProcessExt ;
@@ -436,3 +436,243 @@ impl ProcessStatusExt for ProcessStatus {
436436 }
437437 }
438438}
439+
440+ #[ cfg( test) ]
441+ mod tests {
442+ use super :: * ;
443+ use std:: time:: Duration ;
444+
445+ fn create_test_process ( ) -> ZProcess {
446+ ZProcess {
447+ pid : 1234 ,
448+ uid : 1000 ,
449+ user_name : "testuser" . to_string ( ) ,
450+ memory : 1024 * 1024 ,
451+ cpu_usage : 50.0 ,
452+ cum_cpu_usage : 100.0 ,
453+ command : vec ! [ "test" . to_string( ) , "--arg" . to_string( ) ] ,
454+ exe : "/usr/bin/test" . to_string ( ) ,
455+ status : ProcessStatus :: Run ,
456+ name : "test_process" . to_string ( ) ,
457+ priority : 20 ,
458+ nice : 0 ,
459+ virtual_memory : 2 * 1024 * 1024 ,
460+ threads_total : 4 ,
461+ read_bytes : 1000 ,
462+ write_bytes : 500 ,
463+ prev_read_bytes : 500 ,
464+ prev_write_bytes : 250 ,
465+ last_updated : SystemTime :: now ( ) ,
466+ end_time : None ,
467+ start_time : SystemTime :: now ( )
468+ . duration_since ( UNIX_EPOCH )
469+ . unwrap ( )
470+ . as_secs ( )
471+ - 3600 , // Started 1 hour ago
472+ gpu_usage : 0 ,
473+ fb_utilization : 0 ,
474+ enc_utilization : 0 ,
475+ dec_utilization : 0 ,
476+ sm_utilization : 0 ,
477+ io_delay : Duration :: from_nanos ( 0 ) ,
478+ swap_delay : Duration :: from_nanos ( 0 ) ,
479+ prev_io_delay : Duration :: from_nanos ( 0 ) ,
480+ prev_swap_delay : Duration :: from_nanos ( 0 ) ,
481+ }
482+ }
483+
484+ #[ test]
485+ fn test_get_read_bytes_sec ( ) {
486+ let process = create_test_process ( ) ;
487+ let tick_rate = Duration :: from_secs ( 1 ) ;
488+
489+ // read_bytes: 1000, prev_read_bytes: 500
490+ // (1000 - 500) / 1.0 = 500.0
491+ let read_rate = process. get_read_bytes_sec ( & tick_rate) ;
492+ assert ! ( ( read_rate - 500.0 ) . abs( ) < 0.01 ) ;
493+ }
494+
495+ #[ test]
496+ fn test_get_read_bytes_sec_with_different_tick ( ) {
497+ let process = create_test_process ( ) ;
498+ let tick_rate = Duration :: from_secs ( 2 ) ;
499+
500+ // (1000 - 500) / 2.0 = 250.0
501+ let read_rate = process. get_read_bytes_sec ( & tick_rate) ;
502+ assert ! ( ( read_rate - 250.0 ) . abs( ) < 0.01 ) ;
503+ }
504+
505+ #[ test]
506+ fn test_get_write_bytes_sec ( ) {
507+ let process = create_test_process ( ) ;
508+ let tick_rate = Duration :: from_secs ( 1 ) ;
509+
510+ // write_bytes: 500, prev_write_bytes: 250
511+ // (500 - 250) / 1.0 = 250.0
512+ let write_rate = process. get_write_bytes_sec ( & tick_rate) ;
513+ assert ! ( ( write_rate - 250.0 ) . abs( ) < 0.01 ) ;
514+ }
515+
516+ #[ test]
517+ fn test_get_write_bytes_sec_with_different_tick ( ) {
518+ let process = create_test_process ( ) ;
519+ let tick_rate = Duration :: from_millis ( 500 ) ;
520+
521+ // (500 - 250) / 0.5 = 500.0
522+ let write_rate = process. get_write_bytes_sec ( & tick_rate) ;
523+ assert ! ( ( write_rate - 500.0 ) . abs( ) < 0.01 ) ;
524+ }
525+
526+ #[ test]
527+ fn test_get_run_duration_alive_process ( ) {
528+ let process = create_test_process ( ) ;
529+ let duration = process. get_run_duration ( ) ;
530+
531+ // Process started 1 hour ago
532+ assert ! ( duration. num_minutes( ) >= 59 ) ;
533+ assert ! ( duration. num_minutes( ) <= 61 ) ;
534+ }
535+
536+ #[ test]
537+ fn test_get_run_duration_dead_process ( ) {
538+ let mut process = create_test_process ( ) ;
539+ // Process ended 30 minutes after start
540+ process. end_time = Some ( process. start_time + 1800 ) ;
541+
542+ let duration = process. get_run_duration ( ) ;
543+ assert_eq ! ( duration. num_minutes( ) , 30 ) ;
544+ }
545+
546+ #[ test]
547+ fn test_set_end_time ( ) {
548+ let mut process = create_test_process ( ) ;
549+ assert ! ( process. end_time. is_none( ) ) ;
550+
551+ process. set_end_time ( ) ;
552+ assert ! ( process. end_time. is_some( ) ) ;
553+
554+ // Calling again should not change the end time
555+ let first_end_time = process. end_time ;
556+ process. set_end_time ( ) ;
557+ assert_eq ! ( process. end_time, first_end_time) ;
558+ }
559+
560+ #[ test]
561+ fn test_field_comparator_cpu ( ) {
562+ let mut p1 = create_test_process ( ) ;
563+ let mut p2 = create_test_process ( ) ;
564+ p1. cpu_usage = 10.0 ;
565+ p2. cpu_usage = 20.0 ;
566+
567+ let tick = Duration :: from_secs ( 1 ) ;
568+ let comparator = ZProcess :: field_comparator ( ProcessTableSortBy :: Cpu ) ;
569+
570+ assert_eq ! ( comparator( & p1, & p2, & tick) , Ordering :: Less ) ;
571+ assert_eq ! ( comparator( & p2, & p1, & tick) , Ordering :: Greater ) ;
572+ assert_eq ! ( comparator( & p1, & p1, & tick) , Ordering :: Equal ) ;
573+ }
574+
575+ #[ test]
576+ fn test_field_comparator_memory ( ) {
577+ let mut p1 = create_test_process ( ) ;
578+ let mut p2 = create_test_process ( ) ;
579+ p1. memory = 1000 ;
580+ p2. memory = 2000 ;
581+
582+ let tick = Duration :: from_secs ( 1 ) ;
583+ let comparator = ZProcess :: field_comparator ( ProcessTableSortBy :: Mem ) ;
584+
585+ assert_eq ! ( comparator( & p1, & p2, & tick) , Ordering :: Less ) ;
586+ assert_eq ! ( comparator( & p2, & p1, & tick) , Ordering :: Greater ) ;
587+ }
588+
589+ #[ test]
590+ fn test_field_comparator_pid ( ) {
591+ let mut p1 = create_test_process ( ) ;
592+ let mut p2 = create_test_process ( ) ;
593+ p1. pid = 100 ;
594+ p2. pid = 200 ;
595+
596+ let tick = Duration :: from_secs ( 1 ) ;
597+ let comparator = ZProcess :: field_comparator ( ProcessTableSortBy :: Pid ) ;
598+
599+ assert_eq ! ( comparator( & p1, & p2, & tick) , Ordering :: Less ) ;
600+ }
601+
602+ #[ test]
603+ fn test_field_comparator_user ( ) {
604+ let mut p1 = create_test_process ( ) ;
605+ let mut p2 = create_test_process ( ) ;
606+ p1. user_name = "alice" . to_string ( ) ;
607+ p2. user_name = "bob" . to_string ( ) ;
608+
609+ let tick = Duration :: from_secs ( 1 ) ;
610+ let comparator = ZProcess :: field_comparator ( ProcessTableSortBy :: User ) ;
611+
612+ assert_eq ! ( comparator( & p1, & p2, & tick) , Ordering :: Less ) ;
613+ }
614+
615+ #[ test]
616+ fn test_field_comparator_disk_read ( ) {
617+ let mut p1 = create_test_process ( ) ;
618+ let mut p2 = create_test_process ( ) ;
619+ p1. read_bytes = 1000 ;
620+ p1. prev_read_bytes = 0 ;
621+ p2. read_bytes = 2000 ;
622+ p2. prev_read_bytes = 0 ;
623+
624+ let tick = Duration :: from_secs ( 1 ) ;
625+ let comparator = ZProcess :: field_comparator ( ProcessTableSortBy :: DiskRead ) ;
626+
627+ assert_eq ! ( comparator( & p1, & p2, & tick) , Ordering :: Less ) ;
628+ }
629+
630+ #[ test]
631+ fn test_field_comparator_cmd ( ) {
632+ let mut p1 = create_test_process ( ) ;
633+ let mut p2 = create_test_process ( ) ;
634+ p1. name = "aaa" . to_string ( ) ;
635+ p2. name = "zzz" . to_string ( ) ;
636+
637+ let tick = Duration :: from_secs ( 1 ) ;
638+ let comparator = ZProcess :: field_comparator ( ProcessTableSortBy :: Cmd ) ;
639+
640+ assert_eq ! ( comparator( & p1, & p2, & tick) , Ordering :: Less ) ;
641+ }
642+
643+ #[ test]
644+ fn test_process_status_to_single_char ( ) {
645+ assert_eq ! ( ProcessStatus :: Run . to_single_char( ) , "R" ) ;
646+ assert_eq ! ( ProcessStatus :: Sleep . to_single_char( ) , "S" ) ;
647+ assert_eq ! ( ProcessStatus :: Stop . to_single_char( ) , "T" ) ;
648+ assert_eq ! ( ProcessStatus :: Zombie . to_single_char( ) , "Z" ) ;
649+ assert_eq ! ( ProcessStatus :: Idle . to_single_char( ) , "I" ) ;
650+ }
651+
652+ #[ test]
653+ fn test_zero_io_rates ( ) {
654+ let mut process = create_test_process ( ) ;
655+ process. read_bytes = 0 ;
656+ process. prev_read_bytes = 0 ;
657+ process. write_bytes = 0 ;
658+ process. prev_write_bytes = 0 ;
659+
660+ let tick_rate = Duration :: from_secs ( 1 ) ;
661+
662+ assert_eq ! ( process. get_read_bytes_sec( & tick_rate) , 0.0 ) ;
663+ assert_eq ! ( process. get_write_bytes_sec( & tick_rate) , 0.0 ) ;
664+ }
665+
666+ #[ test]
667+ fn test_large_io_rates ( ) {
668+ let mut process = create_test_process ( ) ;
669+ process. read_bytes = 1_000_000_000 ; // 1GB
670+ process. prev_read_bytes = 0 ;
671+
672+ let tick_rate = Duration :: from_secs ( 1 ) ;
673+ let rate = process. get_read_bytes_sec ( & tick_rate) ;
674+
675+ assert ! ( ( rate - 1_000_000_000.0 ) . abs( ) < 1.0 ) ;
676+ }
677+ }
678+
0 commit comments