@@ -27,6 +27,12 @@ public NetworkListTests(HostOrServer host) : base(host) { }
2727
2828 private ulong m_TestObjectId ;
2929
30+ protected override IEnumerator OnSetup ( )
31+ {
32+ IsOwnerWriteTest = false ;
33+ return base . OnSetup ( ) ;
34+ }
35+
3036 protected override void OnServerAndClientsCreated ( )
3137 {
3238 m_ListObjectPrefab = CreateNetworkObjectPrefab ( "ListObject" ) ;
@@ -285,13 +291,144 @@ private int[] Shuffle(List<int> list)
285291 // This will do a shuffle of the list
286292 return list . OrderBy ( _ => rng . Next ( ) ) . ToArray ( ) ;
287293 }
294+
295+ private List < NetworkObject > m_SpawnedObjects = new List < NetworkObject > ( ) ;
296+ internal const int SpawnCount = 10 ;
297+ internal bool IsOwnerWriteTest ;
298+ internal NetworkManager LateJoinedClient ;
299+
300+ protected override void OnNewClientCreated ( NetworkManager networkManager )
301+ {
302+ if ( IsOwnerWriteTest )
303+ {
304+ LateJoinedClient = networkManager ;
305+ }
306+ else
307+ {
308+ LateJoinedClient = null ;
309+ }
310+ base . OnNewClientCreated ( networkManager ) ;
311+ }
312+
313+ [ UnityTest ]
314+ public IEnumerator OwnerWriteTests ( )
315+ {
316+ IsOwnerWriteTest = true ;
317+ var authorityBetworkManager = GetAuthorityNetworkManager ( ) ;
318+ m_SpawnedObjects . Clear ( ) ;
319+ m_ExpectedValues . Clear ( ) ;
320+ // Set our initial expected values as 0 - 9
321+ for ( int i = 0 ; i < SpawnCount ; i ++ )
322+ {
323+ m_ExpectedValues . Add ( i ) ;
324+ }
325+
326+ // Each spawned instance will be owned by each NetworkManager instance in order
327+ // to validate owner write NetworkLists.
328+ foreach ( var networkManager in m_NetworkManagers )
329+ {
330+ m_SpawnedObjects . Add ( SpawnObject ( m_ListObjectPrefab , networkManager ) . GetComponent < NetworkObject > ( ) ) ;
331+ }
332+
333+ // Verify all NetworkManager instances spawned the objects
334+ yield return WaitForSpawnedOnAllOrTimeOut ( m_SpawnedObjects ) ;
335+ AssertOnTimeout ( "Not all instances were spawned on all clients!" ) ;
336+
337+ // Verify all spawned object instances have the expected owner write NetworkList values
338+ yield return WaitForConditionOrTimeOut ( OnVerifyOwnerWriteData ) ;
339+ AssertOnTimeout ( "Detected invalid count or value on one of the spawned instances!" ) ;
340+
341+ // Late join a client
342+ yield return CreateAndStartNewClient ( ) ;
343+
344+ // Spawn an instance with the new client being the owner
345+ m_SpawnedObjects . Add ( SpawnObject ( m_ListObjectPrefab , LateJoinedClient ) . GetComponent < NetworkObject > ( ) ) ;
346+
347+ // Verify all NetworkManager instances spawned the objects
348+ yield return WaitForSpawnedOnAllOrTimeOut ( m_SpawnedObjects ) ;
349+ AssertOnTimeout ( "Not all instances were spawned on all clients!" ) ;
350+
351+ // Verify all spawned object instances have the expected owner write NetworkList values
352+ yield return WaitForConditionOrTimeOut ( OnVerifyOwnerWriteData ) ;
353+ AssertOnTimeout ( "Detected invalid count or value on one of the spawned instances!" ) ;
354+
355+ // Now have all of the clients update their list values to randomly assigned values
356+ // in order to verify changes to owner write NetworkLists are synchronized properly.
357+ m_ExpectedValues . Clear ( ) ;
358+ for ( int i = 0 ; i < SpawnCount ; i ++ )
359+ {
360+ m_ExpectedValues . Add ( Random . Range ( 10 , 100 ) ) ;
361+ }
362+ UpdateOwnerWriteValues ( ) ;
363+
364+ // Verify all spawned object instances have the expected owner write NetworkList values
365+ yield return WaitForConditionOrTimeOut ( OnVerifyOwnerWriteData ) ;
366+ AssertOnTimeout ( "Detected invalid count or value on one of the spawned instances!" ) ;
367+ }
368+
369+ private void UpdateOwnerWriteValues ( )
370+ {
371+ foreach ( var spawnedObject in m_SpawnedObjects )
372+ {
373+ var owningNetworkManager = m_NetworkManagers . Where ( ( c ) => c . LocalClientId == spawnedObject . OwnerClientId ) . First ( ) ;
374+ var networkObjectId = spawnedObject . NetworkObjectId ;
375+ var listComponent = owningNetworkManager . SpawnManager . SpawnedObjects [ networkObjectId ] . GetComponent < NetworkListTest > ( ) ;
376+ for ( int i = 0 ; i < SpawnCount ; i ++ )
377+ {
378+ listComponent . OwnerWriteList [ i ] = m_ExpectedValues [ i ] ;
379+ }
380+ }
381+ }
382+
383+ private bool OnVerifyOwnerWriteData ( StringBuilder errorLog )
384+ {
385+ foreach ( var spawnedObject in m_SpawnedObjects )
386+ {
387+ var networkObjectId = spawnedObject . NetworkObjectId ;
388+ foreach ( var networkManager in m_NetworkManagers )
389+ {
390+ if ( ! networkManager . SpawnManager . SpawnedObjects . ContainsKey ( networkObjectId ) )
391+ {
392+ errorLog . Append ( $ "[Client-{ networkManager . LocalClientId } ] Does not have an instance of spawned object NetworkObjectId: { networkObjectId } ") ;
393+ return false ;
394+ }
395+ var listComponent = networkManager . SpawnManager . SpawnedObjects [ networkObjectId ] . GetComponent < NetworkListTest > ( ) ;
396+
397+ if ( listComponent == null )
398+ {
399+ errorLog . Append ( $ "[Client-{ networkManager . LocalClientId } ] List component was not found") ;
400+ return false ;
401+ }
402+
403+ if ( listComponent . OwnerWriteList . Count != SpawnCount )
404+ {
405+ errorLog . Append ( $ "[Client-{ networkManager . LocalClientId } ] List component has the incorrect number of items. Expected: { SpawnCount } , Have: { listComponent . TheList . Count } ") ;
406+ return false ;
407+ }
408+
409+ for ( int i = 0 ; i < SpawnCount ; i ++ )
410+ {
411+ var actual = listComponent . OwnerWriteList [ i ] ;
412+ var expected = m_ExpectedValues [ i ] ;
413+ if ( expected != actual )
414+ {
415+ errorLog . Append ( $ "[Client-{ networkManager . LocalClientId } ] Incorrect value at index { i } , expected: { expected } , actual: { actual } ") ;
416+ return false ;
417+ }
418+ }
419+ }
420+ }
421+
422+ return true ;
423+ }
288424 }
289425
290426 internal class NetworkListTest : NetworkBehaviour
291427 {
292428 public readonly NetworkList < int > TheList = new ( ) ;
293429 public readonly NetworkList < StructUsedOnlyInNetworkList > TheStructList = new ( ) ;
294430 public readonly NetworkList < FixedString128Bytes > TheLargeList = new ( ) ;
431+ public readonly NetworkList < int > OwnerWriteList = new NetworkList < int > ( default , NetworkVariableReadPermission . Everyone , NetworkVariableWritePermission . Owner ) ;
295432
296433 private void ListChanged ( NetworkListEvent < int > e )
297434 {
@@ -309,6 +446,18 @@ public override void OnDestroy()
309446 base . OnDestroy ( ) ;
310447 }
311448
449+ public override void OnNetworkSpawn ( )
450+ {
451+ if ( IsOwner )
452+ {
453+ for ( int i = 0 ; i < NetworkListTests . SpawnCount ; i ++ )
454+ {
455+ OwnerWriteList . Add ( i ) ;
456+ }
457+ }
458+ base . OnNetworkSpawn ( ) ;
459+ }
460+
312461 public bool ListDelegateTriggered ;
313462 }
314463
0 commit comments