@@ -599,6 +599,95 @@ mod tests {
599
599
assert ! ( c4. is_ok( ) ) ;
600
600
}
601
601
602
+ #[ tokio:: test]
603
+ async fn test_global_limits_with_multiple_ips ( ) {
604
+ let user_1 = IpAddr :: from_str ( "127.0.0.1" ) . unwrap ( ) ;
605
+ let user_2 = IpAddr :: from_str ( "127.0.0.2" ) . unwrap ( ) ;
606
+ let user_3 = IpAddr :: from_str ( "127.0.0.3" ) . unwrap ( ) ;
607
+
608
+ let rate_limiter = Arc :: new ( InMemoryRateLimit :: new ( 4 , 3 ) ) ;
609
+
610
+ let ticket_1_1 = rate_limiter. clone ( ) . try_acquire ( user_1) . unwrap ( ) ;
611
+ let ticket_1_2 = rate_limiter. clone ( ) . try_acquire ( user_1) . unwrap ( ) ;
612
+
613
+ let ticket_2_1 = rate_limiter. clone ( ) . try_acquire ( user_2) . unwrap ( ) ;
614
+ let ticket_2_2 = rate_limiter. clone ( ) . try_acquire ( user_2) . unwrap ( ) ;
615
+
616
+ assert_eq ! (
617
+ rate_limiter. inner. lock( ) . unwrap( ) . semaphore. available_permits( ) ,
618
+ 0
619
+ ) ;
620
+
621
+ // Try user_3 - should fail due to global limit
622
+ let result = rate_limiter. clone ( ) . try_acquire ( user_3) ;
623
+ assert ! ( result. is_err( ) ) ;
624
+ assert_eq ! (
625
+ result. err( ) . unwrap( ) . to_string( ) ,
626
+ "Rate Limit Reached: Global limit"
627
+ ) ;
628
+
629
+ drop ( ticket_1_1) ;
630
+
631
+ let ticket_3_1 = rate_limiter. clone ( ) . try_acquire ( user_3) . unwrap ( ) ;
632
+
633
+ drop ( ticket_1_2) ;
634
+ drop ( ticket_2_1) ;
635
+ drop ( ticket_2_2) ;
636
+ drop ( ticket_3_1) ;
637
+
638
+ assert_eq ! (
639
+ rate_limiter. inner. lock( ) . unwrap( ) . semaphore. available_permits( ) ,
640
+ 4
641
+ ) ;
642
+ assert_eq ! (
643
+ rate_limiter. inner. lock( ) . unwrap( ) . active_connections. len( ) ,
644
+ 0
645
+ ) ;
646
+ }
647
+
648
+ #[ tokio:: test]
649
+ async fn test_per_ip_limits_remain_enforced ( ) {
650
+ let user_1 = IpAddr :: from_str ( "127.0.0.1" ) . unwrap ( ) ;
651
+ let user_2 = IpAddr :: from_str ( "127.0.0.2" ) . unwrap ( ) ;
652
+
653
+ let rate_limiter = Arc :: new ( InMemoryRateLimit :: new ( 5 , 2 ) ) ;
654
+
655
+ let ticket_1_1 = rate_limiter. clone ( ) . try_acquire ( user_1) . unwrap ( ) ;
656
+ let ticket_1_2 = rate_limiter. clone ( ) . try_acquire ( user_1) . unwrap ( ) ;
657
+
658
+ let result = rate_limiter. clone ( ) . try_acquire ( user_1) ;
659
+ assert ! ( result. is_err( ) ) ;
660
+ assert_eq ! (
661
+ result. err( ) . unwrap( ) . to_string( ) ,
662
+ "Rate Limit Reached: IP limit exceeded"
663
+ ) ;
664
+
665
+ let ticket_2_1 = rate_limiter. clone ( ) . try_acquire ( user_2) . unwrap ( ) ;
666
+ drop ( ticket_1_1) ;
667
+
668
+ let ticket_1_3 = rate_limiter. clone ( ) . try_acquire ( user_1) . unwrap ( ) ;
669
+
670
+ let result = rate_limiter. clone ( ) . try_acquire ( user_1) ;
671
+ assert ! ( result. is_err( ) ) ;
672
+ assert_eq ! (
673
+ result. err( ) . unwrap( ) . to_string( ) ,
674
+ "Rate Limit Reached: IP limit exceeded"
675
+ ) ;
676
+
677
+ drop ( ticket_1_2) ;
678
+ drop ( ticket_1_3) ;
679
+ drop ( ticket_2_1) ;
680
+
681
+ assert_eq ! (
682
+ rate_limiter. inner. lock( ) . unwrap( ) . semaphore. available_permits( ) ,
683
+ 5
684
+ ) ;
685
+ assert_eq ! (
686
+ rate_limiter. inner. lock( ) . unwrap( ) . active_connections. len( ) ,
687
+ 0
688
+ ) ;
689
+ }
690
+
602
691
#[ tokio:: test]
603
692
#[ cfg( all( feature = "integration" , test) ) ]
604
693
async fn test_instance_tracking_and_cleanup ( ) {
0 commit comments