@@ -5,8 +5,8 @@ use stellar_event_assertion::EventAssertion;
55
66use crate :: access_control:: {
77 accept_admin_transfer, add_to_role_enumeration, ensure_if_admin_or_admin_role, get_admin,
8- get_role_admin, get_role_member, get_role_member_count, grant_role, grant_role_no_auth ,
9- has_role, remove_from_role_enumeration, remove_role_accounts_count_no_auth,
8+ get_existing_roles , get_role_admin, get_role_member, get_role_member_count, grant_role,
9+ grant_role_no_auth , has_role, remove_from_role_enumeration, remove_role_accounts_count_no_auth,
1010 remove_role_admin_no_auth, renounce_admin, renounce_role, revoke_role, set_admin,
1111 set_role_admin, set_role_admin_no_auth, transfer_admin_role,
1212} ;
@@ -685,3 +685,205 @@ fn renounce_admin_fails_when_transfer_in_progress() {
685685 renounce_admin ( & e) ;
686686 } ) ;
687687}
688+
689+ #[ test]
690+ fn get_existing_roles_returns_empty_when_no_roles_exist ( ) {
691+ let e = Env :: default ( ) ;
692+ e. mock_all_auths ( ) ;
693+ let address = e. register ( MockContract , ( ) ) ;
694+
695+ e. as_contract ( & address, || {
696+ let roles = get_existing_roles ( & e) ;
697+ assert_eq ! ( roles. len( ) , 0 ) ;
698+ } ) ;
699+ }
700+
701+ #[ test]
702+ fn get_existing_roles_returns_roles_after_granting ( ) {
703+ let e = Env :: default ( ) ;
704+ e. mock_all_auths ( ) ;
705+ let address = e. register ( MockContract , ( ) ) ;
706+ let admin = Address :: generate ( & e) ;
707+ let user = Address :: generate ( & e) ;
708+
709+ e. as_contract ( & address, || {
710+ set_admin ( & e, & admin) ;
711+
712+ // Grant first role
713+ grant_role ( & e, & user, & USER_ROLE , & admin) ;
714+
715+ let roles = get_existing_roles ( & e) ;
716+ assert_eq ! ( roles. len( ) , 1 ) ;
717+ assert_eq ! ( roles. get( 0 ) . unwrap( ) , USER_ROLE ) ;
718+ } ) ;
719+ }
720+
721+ #[ test]
722+ fn get_existing_roles_removes_role_when_last_account_removed ( ) {
723+ let e = Env :: default ( ) ;
724+ e. mock_all_auths ( ) ;
725+ let address = e. register ( MockContract , ( ) ) ;
726+ let admin = Address :: generate ( & e) ;
727+ let user = Address :: generate ( & e) ;
728+
729+ e. as_contract ( & address, || {
730+ set_admin ( & e, & admin) ;
731+
732+ // Grant role
733+ grant_role ( & e, & user, & USER_ROLE , & admin) ;
734+
735+ // Verify role exists
736+ let roles_before = get_existing_roles ( & e) ;
737+ assert_eq ! ( roles_before. len( ) , 1 ) ;
738+ } ) ;
739+
740+ e. as_contract ( & address, || {
741+ // Revoke role from last (and only) user
742+ revoke_role ( & e, & user, & USER_ROLE , & admin) ;
743+
744+ // Verify role is removed from existing roles
745+ let roles_after = get_existing_roles ( & e) ;
746+ assert_eq ! ( roles_after. len( ) , 0 ) ;
747+ } ) ;
748+ }
749+
750+ #[ test]
751+ fn get_existing_roles_keeps_role_when_some_accounts_remain ( ) {
752+ let e = Env :: default ( ) ;
753+ e. mock_all_auths ( ) ;
754+ let address = e. register ( MockContract , ( ) ) ;
755+ let admin = Address :: generate ( & e) ;
756+ let user1 = Address :: generate ( & e) ;
757+ let user2 = Address :: generate ( & e) ;
758+
759+ e. as_contract ( & address, || {
760+ set_admin ( & e, & admin) ;
761+
762+ // Grant role to two users
763+ grant_role ( & e, & user1, & USER_ROLE , & admin) ;
764+ } ) ;
765+
766+ e. as_contract ( & address, || {
767+ grant_role ( & e, & user2, & USER_ROLE , & admin) ;
768+
769+ // Verify role exists
770+ let roles_before = get_existing_roles ( & e) ;
771+ assert_eq ! ( roles_before. len( ) , 1 ) ;
772+ } ) ;
773+
774+ e. as_contract ( & address, || {
775+ // Revoke role from one user (but another still has it)
776+ revoke_role ( & e, & user1, & USER_ROLE , & admin) ;
777+
778+ // Verify role still exists
779+ let roles_after = get_existing_roles ( & e) ;
780+ assert_eq ! ( roles_after. len( ) , 1 ) ;
781+ assert_eq ! ( roles_after. get( 0 ) . unwrap( ) , USER_ROLE ) ;
782+ } ) ;
783+ }
784+
785+ #[ test]
786+ fn get_existing_roles_does_not_create_duplicates ( ) {
787+ let e = Env :: default ( ) ;
788+ e. mock_all_auths ( ) ;
789+ let address = e. register ( MockContract , ( ) ) ;
790+ let admin = Address :: generate ( & e) ;
791+ let user1 = Address :: generate ( & e) ;
792+ let user2 = Address :: generate ( & e) ;
793+
794+ e. as_contract ( & address, || {
795+ set_admin ( & e, & admin) ;
796+
797+ // Grant same role to multiple users
798+ grant_role ( & e, & user1, & USER_ROLE , & admin) ;
799+ } ) ;
800+
801+ e. as_contract ( & address, || {
802+ grant_role ( & e, & user2, & USER_ROLE , & admin) ;
803+
804+ // Should still only have one role in the list
805+ let roles = get_existing_roles ( & e) ;
806+ assert_eq ! ( roles. len( ) , 1 ) ;
807+ assert_eq ! ( roles. get( 0 ) . unwrap( ) , USER_ROLE ) ;
808+ } ) ;
809+ }
810+
811+ #[ test]
812+ #[ should_panic( expected = "Error(Contract, #2010)" ) ]
813+ fn grant_role_fails_when_max_roles_exceeded ( ) {
814+ use crate :: access_control:: MAX_ROLES ;
815+
816+ let e = Env :: default ( ) ;
817+ e. mock_all_auths ( ) ;
818+ let address = e. register ( MockContract , ( ) ) ;
819+ let admin = Address :: generate ( & e) ;
820+ let user = Address :: generate ( & e) ;
821+
822+ e. as_contract ( & address, || {
823+ set_admin ( & e, & admin) ;
824+ } ) ;
825+
826+ // Create MAX_ROLES roles
827+ for i in 0 ..MAX_ROLES {
828+ e. as_contract ( & address, || {
829+ let role = Symbol :: new ( & e, & std:: format!( "role_{}" , i) ) ;
830+ grant_role ( & e, & user, & role, & admin) ;
831+ } ) ;
832+ }
833+
834+ e. as_contract ( & address, || {
835+ // Verify we have MAX_ROLES
836+ let roles = get_existing_roles ( & e) ;
837+ assert_eq ! ( roles. len( ) , MAX_ROLES ) ;
838+
839+ // Try to create one more role - should panic
840+ let overflow_role = Symbol :: new ( & e, "overflow_role" ) ;
841+ grant_role ( & e, & user, & overflow_role, & admin) ;
842+ } ) ;
843+ }
844+
845+ #[ test]
846+ fn can_reuse_role_slot_after_removal ( ) {
847+ use crate :: access_control:: MAX_ROLES ;
848+
849+ let e = Env :: default ( ) ;
850+ e. mock_all_auths ( ) ;
851+ let address = e. register ( MockContract , ( ) ) ;
852+ let admin = Address :: generate ( & e) ;
853+ let user = Address :: generate ( & e) ;
854+
855+ e. as_contract ( & address, || {
856+ set_admin ( & e, & admin) ;
857+ } ) ;
858+
859+ // Create MAX_ROLES roles
860+ for i in 0 ..MAX_ROLES {
861+ e. as_contract ( & address, || {
862+ let role = Symbol :: new ( & e, & std:: format!( "role_{}" , i) ) ;
863+ grant_role ( & e, & user, & role, & admin) ;
864+ } ) ;
865+ }
866+ e. as_contract ( & address, || {
867+ // Verify we have MAX_ROLES
868+ let roles_before = get_existing_roles ( & e) ;
869+ assert_eq ! ( roles_before. len( ) , MAX_ROLES ) ;
870+
871+ // Remove one role
872+ let first_role = Symbol :: new ( & e, "role_0" ) ;
873+ revoke_role ( & e, & user, & first_role, & admin) ;
874+
875+ // Verify we now have MAX_ROLES - 1
876+ let roles_after_removal = get_existing_roles ( & e) ;
877+ assert_eq ! ( roles_after_removal. len( ) , MAX_ROLES - 1 ) ;
878+ } ) ;
879+
880+ e. as_contract ( & address, || {
881+ // Now we should be able to add a new role
882+ let new_role = Symbol :: new ( & e, "new_role" ) ;
883+ grant_role ( & e, & user, & new_role, & admin) ;
884+
885+ // Verify we're back to MAX_ROLES
886+ let roles_final = get_existing_roles ( & e) ;
887+ assert_eq ! ( roles_final. len( ) , MAX_ROLES ) ;
888+ } ) ;
889+ }
0 commit comments