@@ -13,6 +13,8 @@ namespace TestProject.RuntimeTests
13
13
public class SceneEventProgressTests : NetcodeIntegrationTest
14
14
{
15
15
private const string k_SceneUsedToGetAsyncOperation = "EmptyScene" ;
16
+ private const string k_SceneUsedToGetClientAsyncOperation = "UnitTestBaseScene" ;
17
+
16
18
protected override int NumberOfClients => 4 ;
17
19
18
20
private bool m_SceneEventProgressCompleted ;
@@ -51,6 +53,7 @@ private void StartNewSceneEventProgress()
51
53
m_CurrentSceneEventProgress . SetAsyncOperation ( SceneManager . LoadSceneAsync ( k_SceneUsedToGetAsyncOperation , LoadSceneMode . Additive ) ) ;
52
54
}
53
55
56
+
54
57
private void MockServerLoadedSene ( Scene scene , LoadSceneMode loadSceneMode )
55
58
{
56
59
if ( scene . name == k_SceneUsedToGetAsyncOperation )
@@ -155,6 +158,31 @@ public IEnumerator ClientsDisconnectDuring()
155
158
VerifyClientsThatCompleted ( ) ;
156
159
}
157
160
161
+ [ UnityTest ]
162
+ public IEnumerator ClientsShutdownDuring ( )
163
+ {
164
+ StartNewSceneEventProgress ( ) ;
165
+
166
+ for ( int i = 0 ; i < NumberOfClients ; i ++ )
167
+ {
168
+ var currentClientNetworkManager = m_ClientNetworkManagers [ i ] ;
169
+ // Two clients will shutdown
170
+ var clientFinished = i % 2 == 0 ;
171
+ SetClientFinished ( currentClientNetworkManager . LocalClientId , clientFinished ) ;
172
+
173
+ if ( ! clientFinished )
174
+ {
175
+ currentClientNetworkManager . Shutdown ( ) ;
176
+ }
177
+ // wait anywhere from 100-500ms until processing next client
178
+ var randomWaitPeriod = Random . Range ( 0.1f , 0.5f ) ;
179
+ yield return new WaitForSeconds ( randomWaitPeriod ) ;
180
+ }
181
+ yield return WaitForConditionOrTimeOut ( ( ) => m_SceneEventProgressCompleted ) ;
182
+ AssertOnTimeout ( $ "Timed out waiting for SceneEventProgress to time out!") ;
183
+ VerifyClientsThatCompleted ( ) ;
184
+ }
185
+
158
186
/// <summary>
159
187
/// This verifies that SceneEventProgress will still complete
160
188
/// even when clients late join.
@@ -163,16 +191,13 @@ public IEnumerator ClientsDisconnectDuring()
163
191
public IEnumerator ClientsLateJoinDuring ( )
164
192
{
165
193
StartNewSceneEventProgress ( ) ;
166
-
167
194
for ( int i = 0 ; i < NumberOfClients ; i ++ )
168
195
{
169
196
// Two clients will connect during a SceneEventProgress
170
197
var shouldNewClientJoin = i % 2 == 0 ;
171
198
var currentClientNetworkManager = m_ClientNetworkManagers [ i ] ;
172
-
173
199
// All connected clients will finish their SceneEventProgress
174
200
SetClientFinished ( currentClientNetworkManager . LocalClientId , true ) ;
175
-
176
201
if ( shouldNewClientJoin )
177
202
{
178
203
yield return CreateAndStartNewClient ( ) ;
@@ -181,11 +206,84 @@ public IEnumerator ClientsLateJoinDuring()
181
206
var randomWaitPeriod = Random . Range ( 0.1f , 0.5f ) ;
182
207
yield return new WaitForSeconds ( randomWaitPeriod ) ;
183
208
}
184
-
185
209
yield return WaitForConditionOrTimeOut ( ( ) => m_SceneEventProgressCompleted ) ;
186
210
AssertOnTimeout ( $ "Timed out waiting for SceneEventProgress to finish!") ;
211
+ VerifyClientsThatCompleted ( ) ;
212
+ }
213
+
214
+ private List < ulong > m_ClientsThatTimedOutAndFinished = new List < ulong > ( ) ;
215
+
216
+ private SceneEventProgress StartClientSceneEventProgress ( NetworkManager networkManager )
217
+ {
218
+ var sceneEventProgress = new SceneEventProgress ( networkManager , SceneEventProgressStatus . Started ) ;
187
219
220
+ // Mock Scene Loading Event for mocking timed out client
221
+ m_CurrentSceneEventProgress . SceneEventId = ( uint ) networkManager . LocalClientId ;
222
+ var asyncOperation = SceneManager . LoadSceneAsync ( k_SceneUsedToGetClientAsyncOperation , LoadSceneMode . Additive ) ;
223
+ asyncOperation . completed += new System . Action < AsyncOperation > ( asyncOp2 =>
224
+ {
225
+ m_ClientsThatTimedOutAndFinished . Add ( networkManager . LocalClientId ) ;
226
+ } ) ;
227
+
228
+ m_CurrentSceneEventProgress . SetAsyncOperation ( asyncOperation ) ;
229
+ return sceneEventProgress ;
230
+ }
231
+
232
+ private Dictionary < NetworkManager , SceneEventProgress > m_ClientsToFinishAfterDisconnecting = new Dictionary < NetworkManager , SceneEventProgress > ( ) ;
233
+ private bool TimedOutClientsFinishedSceneEventProgress ( )
234
+ {
235
+ // Now, verify all "mock timed out" clients still finished their SceneEventProgress
236
+ foreach ( var entry in m_ClientsToFinishAfterDisconnecting )
237
+ {
238
+ if ( ! m_ClientsThatTimedOutAndFinished . Contains ( entry . Key . LocalClientId ) )
239
+ {
240
+ return false ;
241
+ }
242
+ }
243
+ return true ;
244
+ }
245
+
246
+ /// <summary>
247
+ /// This mocks a client timing out during a SceneEventProgress
248
+ /// </summary>
249
+ [ UnityTest ]
250
+ public IEnumerator ClientsMockTimeOutDuring ( )
251
+ {
252
+ m_ClientsThatTimedOutAndFinished . Clear ( ) ;
253
+ m_ClientsToFinishAfterDisconnecting . Clear ( ) ;
254
+ StartNewSceneEventProgress ( ) ;
255
+
256
+ for ( int i = 0 ; i < NumberOfClients ; i ++ )
257
+ {
258
+ // Two clients will mock timing out during a SceneEventProgress
259
+ var shouldClientFinish = i % 2 == 0 ;
260
+ var currentClientNetworkManager = m_ClientNetworkManagers [ i ] ;
261
+
262
+ // Set whether the client should or should not have finished
263
+ SetClientFinished ( currentClientNetworkManager . LocalClientId , shouldClientFinish ) ;
264
+ if ( ! shouldClientFinish )
265
+ {
266
+ var sceneEventProgress = StartClientSceneEventProgress ( currentClientNetworkManager ) ;
267
+ m_ClientsToFinishAfterDisconnecting . Add ( currentClientNetworkManager , sceneEventProgress ) ;
268
+ currentClientNetworkManager . Shutdown ( ) ;
269
+ }
270
+ }
271
+
272
+ yield return WaitForConditionOrTimeOut ( ( ) => m_SceneEventProgressCompleted ) ;
273
+ AssertOnTimeout ( $ "Timed out waiting for SceneEventProgress to finish!") ;
188
274
VerifyClientsThatCompleted ( ) ;
275
+
276
+ yield return WaitForConditionOrTimeOut ( TimedOutClientsFinishedSceneEventProgress ) ;
277
+ if ( s_GlobalTimeoutHelper . TimedOut )
278
+ {
279
+ foreach ( var entry in m_ClientsToFinishAfterDisconnecting )
280
+ {
281
+ Assert . IsTrue ( m_ClientsThatTimedOutAndFinished . Contains ( entry . Key . LocalClientId ) , $ "Client-{ entry . Key . LocalClientId } did not complete its { nameof ( SceneEventProgress ) } !") ;
282
+ // Now, as a final check we try to finish the "mock" timed out client's scene event progress
283
+ entry . Value . TryFinishingSceneEventProgress ( ) ;
284
+ }
285
+ }
286
+ m_ClientsToFinishAfterDisconnecting . Clear ( ) ;
189
287
}
190
288
}
191
289
}
0 commit comments