11using System . Collections ;
2+ using System . Collections . Generic ;
3+ using System . Linq ;
4+ using System . Text ;
25using NUnit . Framework ;
36using Unity . Netcode . TestHelpers . Runtime ;
47using UnityEngine ;
58using UnityEngine . TestTools ;
69
710namespace Unity . Netcode . RuntimeTests
811{
9- [ TestFixture ( HostOrServer . DAHost , true ) ]
10- [ TestFixture ( HostOrServer . DAHost , false ) ]
12+ internal enum SceneManagementSetting
13+ {
14+ EnableSceneManagement ,
15+ DisableSceneManagement
16+ }
17+
18+ [ TestFixture ( SceneManagementSetting . EnableSceneManagement ) ]
19+ [ TestFixture ( SceneManagementSetting . DisableSceneManagement ) ]
1120 internal class ExtendedNetworkShowAndHideTests : NetcodeIntegrationTest
1221 {
1322 protected override int NumberOfClients => 3 ;
14- private bool m_EnableSceneManagement ;
23+ private readonly bool m_EnableSceneManagement ;
1524 private GameObject m_ObjectToSpawn ;
16- private NetworkObject m_SpawnedObject ;
17- private NetworkManager m_ClientToHideFrom ;
18- private NetworkManager m_LateJoinClient ;
19- private NetworkManager m_SpawnOwner ;
20-
21- // TODO: [CmbServiceTests] Adapt to run with the service (can't control who becomes the session owner, needs a logic rework)
22- /// <inheritdoc/>
23- protected override bool UseCMBService ( )
24- {
25- return false ;
26- }
25+ private List < NetworkObject > m_SpawnedObjects = new ( ) ;
26+ private Dictionary < NetworkManager , NetworkObject > m_ObjectHiddenFromClient = new ( ) ;
2727
28- public ExtendedNetworkShowAndHideTests ( HostOrServer hostOrServer , bool enableSceneManagement ) : base ( hostOrServer )
28+ public ExtendedNetworkShowAndHideTests ( SceneManagementSetting sceneManagement ) : base ( HostOrServer . DAHost )
2929 {
30- m_EnableSceneManagement = enableSceneManagement ;
30+ m_EnableSceneManagement = sceneManagement == SceneManagementSetting . EnableSceneManagement ;
3131 }
3232
3333 protected override void OnServerAndClientsCreated ( )
@@ -38,48 +38,93 @@ protected override void OnServerAndClientsCreated()
3838 }
3939
4040 m_ObjectToSpawn = CreateNetworkObjectPrefab ( "TestObject" ) ;
41+ m_ObjectToSpawn . AddComponent < EmptyBehaviour > ( ) ;
4142 m_ObjectToSpawn . SetActive ( false ) ;
4243
4344 base . OnServerAndClientsCreated ( ) ;
4445 }
4546
46- private bool AllClientsSpawnedObject ( )
47+ private bool AllObjectsHiddenFromTheirClient ( StringBuilder errorLog )
4748 {
48- foreach ( var client in m_NetworkManagers )
49+ var allHidden = true ;
50+ foreach ( var ( clientToHideFrom , objectToHide ) in m_ObjectHiddenFromClient )
4951 {
50- if ( ! s_GlobalNetworkObjects . ContainsKey ( client . LocalClientId ) )
52+ if ( clientToHideFrom . SpawnManager . SpawnedObjects . ContainsKey ( objectToHide . NetworkObjectId ) )
5153 {
52- return false ;
53- }
54- if ( ! s_GlobalNetworkObjects [ client . LocalClientId ] . ContainsKey ( m_SpawnedObject . NetworkObjectId ) )
55- {
56- return false ;
54+ errorLog . AppendLine ( $ "Object-{ objectToHide . NetworkObjectId } is still visible to Client-{ clientToHideFrom . LocalClientId } ") ;
55+ allHidden = false ;
5756 }
5857 }
59- return true ;
58+
59+ return allHidden ;
6060 }
6161
62- private bool IsClientPromotedToSessionOwner ( )
62+ private bool IsClientPromotedToSessionOwner ( StringBuilder errorLog )
6363 {
64+ var valid = true ;
65+ var currentSessionOwner = GetAuthorityNetworkManager ( ) ;
6466 foreach ( var client in m_NetworkManagers )
6567 {
66- if ( ! client . IsConnectedClient )
68+ if ( currentSessionOwner == client )
6769 {
68- continue ;
70+ if ( ! client . LocalClient . IsSessionOwner )
71+ {
72+ errorLog . AppendLine ( $ "Session owner is Client-{ client . LocalClientId } but they are not marked as session owner.") ;
73+ valid = false ;
74+ }
6975 }
70- if ( client . CurrentSessionOwner != m_ClientToHideFrom . LocalClientId )
76+ else if ( client . LocalClient . IsSessionOwner )
7177 {
72- return false ;
78+ errorLog . AppendLine ( $ "Client-{ client . LocalClientId } is incorrectly marked as Session Owner.") ;
79+ valid = false ;
80+ }
81+
82+ if ( client . CurrentSessionOwner != currentSessionOwner . LocalClientId )
83+ {
84+ errorLog . AppendLine ( $ "Client-{ client . LocalClientId } has the incorrect session owner id (Has: { client . CurrentSessionOwner } , expected: { currentSessionOwner . LocalClientId } ).") ;
85+ valid = false ;
7386 }
7487 }
75- return true ;
88+ return valid ;
7689 }
7790
78- protected override void OnNewClientCreated ( NetworkManager networkManager )
91+ private bool AllObjectsSpawnedExceptForHidden ( StringBuilder errorLog )
7992 {
80- m_LateJoinClient = networkManager ;
81- networkManager . NetworkConfig . EnableSceneManagement = m_EnableSceneManagement ;
82- base . OnNewClientCreated ( networkManager ) ;
93+ var valid = true ;
94+ foreach ( var client in m_NetworkManagers )
95+ {
96+ foreach ( var spawnedObject in m_SpawnedObjects )
97+ {
98+ var isVisible = client . SpawnManager . SpawnedObjects . ContainsKey ( spawnedObject . NetworkObjectId ) ;
99+
100+ if ( m_ObjectHiddenFromClient . TryGetValue ( client , out var hiddenObject ) && hiddenObject == spawnedObject )
101+ {
102+ if ( isVisible )
103+ {
104+ errorLog . AppendLine ( $ "Client-{ client . LocalClientId } can see object-{ spawnedObject . NetworkObjectId } that should be hidden.") ;
105+ valid = false ;
106+ continue ;
107+ }
108+ }
109+ else if ( ! isVisible )
110+ {
111+ errorLog . AppendLine ( $ "Client-{ client . LocalClientId } hasn't spawned object-{ spawnedObject . NetworkObjectId } ") ;
112+ valid = false ;
113+ }
114+
115+ if ( isVisible )
116+ {
117+ var clientObject = client . SpawnManager . SpawnedObjects [ spawnedObject . NetworkObjectId ] ;
118+ var behaviour = clientObject . GetComponent < EmptyBehaviour > ( ) ;
119+ if ( behaviour . IsSessionOwner != client . LocalClient . IsSessionOwner )
120+ {
121+ errorLog . AppendLine ( $ "Client-{ client . LocalClientId } network behaviour has incorrect session owner value. Should be { client . LocalClient . IsSessionOwner } , is { behaviour . IsSessionOwner } ") ;
122+ valid = false ;
123+ }
124+ }
125+ }
126+ }
127+ return valid ;
83128 }
84129
85130 /// <summary>
@@ -95,41 +140,89 @@ public IEnumerator HiddenObjectPromotedSessionOwnerNewClientSynchronizes()
95140 {
96141 // Get the test relative session owner
97142 var sessionOwner = GetAuthorityNetworkManager ( ) ;
98- m_SpawnOwner = m_UseCmbService ? m_ClientNetworkManagers [ 1 ] : m_ClientNetworkManagers [ 0 ] ;
99- m_ClientToHideFrom = m_UseCmbService ? m_ClientNetworkManagers [ NumberOfClients - 1 ] : m_ClientNetworkManagers [ 1 ] ;
143+
144+ // Spawn objects for the non-session owner clients
100145 m_ObjectToSpawn . SetActive ( true ) ;
146+ foreach ( var client in m_NetworkManagers )
147+ {
148+ if ( client == sessionOwner )
149+ {
150+ Assert . IsTrue ( client . LocalClient . IsSessionOwner ) ;
151+ continue ;
152+ }
153+
154+ var instance = SpawnObject ( m_ObjectToSpawn , client ) . GetComponent < NetworkObject > ( ) ;
155+ m_SpawnedObjects . Add ( instance ) ;
156+ }
157+
158+ yield return WaitForSpawnedOnAllOrTimeOut ( m_SpawnedObjects ) ;
159+ AssertOnTimeout ( "[InitialSpawn] Not all clients spawned all objects" ) ;
160+
161+ // Hide one spawned object from each client
162+ var setOfInstances = m_SpawnedObjects . ToHashSet ( ) ;
163+ foreach ( var clientToHideFrom in m_NetworkManagers )
164+ {
165+ // Session owner doesn't need to have an object hidden from them
166+ if ( clientToHideFrom == sessionOwner )
167+ {
168+ continue ;
169+ }
170+
171+ // Find an object that this client doesn't own that isn't already hidden from another client
172+ var toHide = setOfInstances . Last ( obj => obj . OwnerClientId != clientToHideFrom . LocalClientId ) ;
173+ toHide . NetworkHide ( clientToHideFrom . LocalClientId ) ;
174+ setOfInstances . Remove ( toHide ) ;
175+ m_ObjectHiddenFromClient . Add ( clientToHideFrom , toHide ) ;
101176
102- // Spawn the object with a non-session owner client
103- m_SpawnedObject = SpawnObject ( m_ObjectToSpawn , m_SpawnOwner ) . GetComponent < NetworkObject > ( ) ;
104- yield return WaitForConditionOrTimeOut ( AllClientsSpawnedObject ) ;
105- AssertOnTimeout ( $ "Not all clients spawned and instance of { m_SpawnedObject . name } ") ;
177+ Assert . IsFalse ( toHide . GetComponent < EmptyBehaviour > ( ) . IsSessionOwner , "No object should have been spawned owned by the session owner" ) ;
178+ }
106179
107- // Hide the spawned object from the to be promoted session owner
108- m_SpawnedObject . NetworkHide ( m_ClientToHideFrom . LocalClientId ) ;
180+ Assert . That ( m_ObjectHiddenFromClient . Count , Is . EqualTo ( NumberOfClients ) , "Test should hide one object per non-authority client" ) ;
181+ Assert . That ( setOfInstances , Is . Empty , "Not all objects have been hidden frm someone." ) ;
109182
110- yield return WaitForConditionOrTimeOut ( ( ) => ! m_ClientToHideFrom . SpawnManager . SpawnedObjects . ContainsKey ( m_SpawnedObject . NetworkObjectId ) ) ;
111- AssertOnTimeout ( $ " { m_SpawnedObject . name } was not hidden from Client- { m_ClientToHideFrom . LocalClientId } !") ;
183+ yield return WaitForConditionOrTimeOut ( AllObjectsHiddenFromTheirClient ) ;
184+ AssertOnTimeout ( "Not all objects have been hidden from someone !") ;
112185
113186 // Promoted a new session owner (DAHost promotes while CMB Session we disconnect the current session owner)
114187 if ( ! m_UseCmbService )
115188 {
116- m_ServerNetworkManager . PromoteSessionOwner ( m_ClientToHideFrom . LocalClientId ) ;
189+ var nonAuthority = GetNonAuthorityNetworkManager ( ) ;
190+ m_ServerNetworkManager . PromoteSessionOwner ( nonAuthority . LocalClientId ) ;
191+ yield return s_DefaultWaitForTick ;
117192 }
118193 else
119194 {
120- sessionOwner . Shutdown ( ) ;
195+ yield return StopOneClient ( sessionOwner ) ;
121196 }
122197
123198 // Wait for the new session owner to be promoted and for all clients to acknowledge the promotion
124199 yield return WaitForConditionOrTimeOut ( IsClientPromotedToSessionOwner ) ;
125- AssertOnTimeout ( $ "Client-{ m_ClientToHideFrom . LocalClientId } was not promoted as session owner on all client instances!") ;
200+ AssertOnTimeout ( $ "No client was promoted as session owner on all client instances!") ;
201+
202+ var newSessionOwner = GetAuthorityNetworkManager ( ) ;
203+ VerboseDebug ( $ "Client-{ newSessionOwner . LocalClientId } was promoted as session owner on all client instances!") ;
204+ Assert . That ( newSessionOwner , Is . Not . EqualTo ( sessionOwner ) , "The current session owner be different from the original session owner." ) ;
205+ Assert . That ( m_ObjectHiddenFromClient , Does . ContainKey ( newSessionOwner ) , "An object should be hidden from the newly promoted session owner" ) ;
126206
127207 // Connect a new client instance
128- yield return CreateAndStartNewClient ( ) ;
208+ var newClient = CreateNewClient ( ) ;
209+ newClient . NetworkConfig . EnableSceneManagement = m_EnableSceneManagement ;
210+ yield return StartClient ( newClient ) ;
129211
130212 // Assure the newly connected client is synchronized with the NetworkObject hidden from the newly promoted session owner
131- yield return WaitForConditionOrTimeOut ( ( ) => m_LateJoinClient . SpawnManager . SpawnedObjects . ContainsKey ( m_SpawnedObject . NetworkObjectId ) ) ;
132- AssertOnTimeout ( $ "Client-{ m_LateJoinClient . LocalClientId } never spawned { nameof ( NetworkObject ) } { m_SpawnedObject . name } !") ;
213+ yield return WaitForConditionOrTimeOut ( AllObjectsSpawnedExceptForHidden ) ;
214+ AssertOnTimeout ( "[LateJoinClient] Not all objects spawned correctly" ) ;
215+ }
216+
217+ protected override IEnumerator OnTearDown ( )
218+ {
219+ m_SpawnedObjects . Clear ( ) ;
220+ m_ObjectHiddenFromClient . Clear ( ) ;
221+ return base . OnTearDown ( ) ;
222+ }
223+
224+ private class EmptyBehaviour : NetworkBehaviour
225+ {
133226 }
134227 }
135228}
0 commit comments