com.wallstop-studios.dxmessaging 2.1.0 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/.github/workflows/dotnet-tests.yml +72 -0
  2. package/.lychee.toml +4 -2
  3. package/AGENTS.md +1 -0
  4. package/Docs/Comparisons.md +4 -4
  5. package/Docs/EmitShorthands.md +2 -2
  6. package/Docs/Helpers.md +90 -75
  7. package/Docs/Install.md +2 -1
  8. package/Docs/Patterns.md +1 -1
  9. package/Docs/Performance.md +13 -11
  10. package/Docs/QuickStart.md +1 -2
  11. package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll +0 -0
  12. package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll.meta +13 -2
  13. package/Editor/Analyzers/Microsoft.CodeAnalysis.dll +0 -0
  14. package/Editor/Analyzers/Microsoft.CodeAnalysis.dll.meta +11 -0
  15. package/Editor/Analyzers/System.Collections.Immutable.dll +0 -0
  16. package/Editor/Analyzers/System.Collections.Immutable.dll.meta +11 -0
  17. package/Editor/Analyzers/System.Reflection.Metadata.dll +0 -0
  18. package/Editor/Analyzers/System.Reflection.Metadata.dll.meta +13 -2
  19. package/Editor/Analyzers/System.Runtime.CompilerServices.Unsafe.dll +0 -0
  20. package/Editor/Analyzers/System.Runtime.CompilerServices.Unsafe.dll.meta +11 -0
  21. package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
  22. package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll.meta +3 -2
  23. package/Editor/AssemblyInfo.cs +3 -0
  24. package/Editor/AssemblyInfo.cs.meta +3 -0
  25. package/Editor/CustomEditors/MessagingComponentEditor.cs +21 -0
  26. package/Editor/SetupCscRsp.cs +133 -53
  27. package/Editor/Testing/MessagingComponentEditorHarness.cs +218 -0
  28. package/Editor/Testing/MessagingComponentEditorHarness.cs.meta +3 -0
  29. package/Editor/Testing.meta +3 -0
  30. package/README.md +9 -3
  31. package/Runtime/AssemblyInfo.cs +1 -0
  32. package/Runtime/Core/Attributes/DxAutoConstructorAttribute.cs +1 -1
  33. package/Runtime/Core/Attributes/DxBroadcastMessageAttribute.cs +1 -1
  34. package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs +1 -1
  35. package/Runtime/Core/Attributes/DxTargetedMessageAttribute.cs +1 -1
  36. package/Runtime/Core/Attributes/DxUntargetedMessageAttribute.cs +1 -1
  37. package/Runtime/Core/Diagnostics/MessageEmissionData.cs +26 -11
  38. package/Runtime/Core/Extensions/MessageBusExtensions.cs +2 -2
  39. package/Runtime/Core/Extensions/MessageExtensions.cs +2 -2
  40. package/Runtime/Core/InstanceId.cs +5 -3
  41. package/Runtime/Core/MessageBus/MessageBus.cs +4 -4
  42. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +2 -2
  43. package/Runtime/Core/MessageBus/MessagingRegistration.cs +3 -3
  44. package/Runtime/Core/MessageHandler.cs +34 -2
  45. package/Runtime/Core/MessageRegistrationToken.cs +2 -2
  46. package/Runtime/Core/Messages/IBroadcastMessage.cs +1 -1
  47. package/Runtime/Core/Messages/ITargetedMessage.cs +1 -1
  48. package/Runtime/Core/Messages/IUntargetedMessage.cs +1 -1
  49. package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs +2 -0
  50. package/Runtime/Unity/InitialGlobalMessageBusProvider.cs +2 -0
  51. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs +2 -0
  52. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs +2 -0
  53. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs +2 -0
  54. package/Runtime/Unity/MessageAwareComponent.cs +2 -0
  55. package/Runtime/Unity/MessageBusProviderHandle.cs +4 -0
  56. package/Runtime/Unity/MessagingComponent.cs +27 -7
  57. package/Runtime/Unity/MessagingComponentInstaller.cs +2 -0
  58. package/Runtime/Unity/ScriptableMessageBusProvider.cs +2 -0
  59. package/Samples~/DI/Reflex/SampleInstaller.cs +6 -6
  60. package/Samples~/DI/VContainer/SampleLifetimeScope.cs +7 -9
  61. package/Samples~/DI/Zenject/SampleInstaller.cs +6 -8
  62. package/SourceGenerators/Directory.Build.props +9 -0
  63. package/{package-lock.json.meta → SourceGenerators/Directory.Build.props.meta} +2 -2
  64. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs +19 -24
  65. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs +87 -27
  66. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj +24 -4
  67. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DocsSnippetCompilationTests.cs +193 -0
  68. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DocsSnippetCompilationTests.cs.meta +11 -0
  69. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DxAutoConstructorGeneratorDiagnosticsTests.cs +69 -0
  70. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DxAutoConstructorGeneratorDiagnosticsTests.cs.meta +11 -0
  71. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DxMessageIdGeneratorDiagnosticsTests.cs +66 -0
  72. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DxMessageIdGeneratorDiagnosticsTests.cs.meta +11 -0
  73. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/GeneratorTestUtilities.cs +155 -0
  74. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/GeneratorTestUtilities.cs.meta +11 -0
  75. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/WallstopStudios.DxMessaging.SourceGenerators.Tests.csproj +20 -0
  76. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/WallstopStudios.DxMessaging.SourceGenerators.Tests.csproj.meta +7 -0
  77. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests.meta +8 -0
  78. package/Tests/Editor/MessagingComponentEditorHarnessTests.cs +243 -0
  79. package/Tests/Editor/MessagingComponentEditorHarnessTests.cs.meta +3 -0
  80. package/Tests/Editor/MessagingComponentSerializationTests.cs +129 -0
  81. package/Tests/Editor/MessagingComponentSerializationTests.cs.meta +3 -0
  82. package/Tests/Editor/WallstopStudios.DxMessaging.Tests.Editor.asmdef +19 -0
  83. package/Tests/Editor/WallstopStudios.DxMessaging.Tests.Editor.asmdef.meta +3 -0
  84. package/Tests/Editor.meta +3 -0
  85. package/Tests/Runtime/Benchmarks/BenchmarkSession.cs +3 -0
  86. package/Tests/Runtime/Benchmarks/BenchmarkTestBase.cs +3 -0
  87. package/Tests/Runtime/Benchmarks/ComparisonPerformanceTests.cs +3 -0
  88. package/Tests/Runtime/Benchmarks/PerformanceTests.cs +137 -0
  89. package/Tests/Runtime/Core/AlternateBusTests.cs +3 -0
  90. package/Tests/Runtime/Core/BroadcastTests.cs +3 -0
  91. package/Tests/Runtime/Core/CyclicBufferTests.cs +3 -0
  92. package/Tests/Runtime/Core/DefaultBusFallbackTests.cs +5 -2
  93. package/Tests/Runtime/Core/DiagnosticsTests.cs +3 -0
  94. package/Tests/Runtime/Core/EdgeCaseTests.cs +3 -0
  95. package/Tests/Runtime/Core/EnablementTests.cs +3 -0
  96. package/Tests/Runtime/Core/Extensions/MessageExtensionsProviderTests.cs +2 -2
  97. package/Tests/Runtime/Core/GenericMessageTests.cs +3 -0
  98. package/Tests/Runtime/Core/GlobalAcceptAllTests.cs +3 -0
  99. package/Tests/Runtime/Core/InterceptorCancellationTests.cs +3 -0
  100. package/Tests/Runtime/Core/LifecycleTests.cs +3 -0
  101. package/Tests/Runtime/Core/MessageEmissionDataTests.cs +70 -0
  102. package/Tests/Runtime/Core/MessageEmissionDataTests.cs.meta +11 -0
  103. package/Tests/Runtime/Core/MessagingComponentLifecycleTests.cs +3 -0
  104. package/Tests/Runtime/Core/MessagingTestBase.cs +3 -0
  105. package/Tests/Runtime/Core/MutationDedupeTests.cs +3 -0
  106. package/Tests/Runtime/Core/MutationDestructionTests.cs +3 -0
  107. package/Tests/Runtime/Core/MutationDuringEmissionTests.cs +3 -0
  108. package/Tests/Runtime/Core/MutationGlobalAddTests.cs +3 -0
  109. package/Tests/Runtime/Core/MutationInterceptorTests.cs +3 -0
  110. package/Tests/Runtime/Core/MutationPostProcessorAcrossHandlersTests.cs +3 -0
  111. package/Tests/Runtime/Core/MutationPostProcessorMoreTests.cs +3 -0
  112. package/Tests/Runtime/Core/MutationPriorityTests.cs +3 -0
  113. package/Tests/Runtime/Core/NominalTests.cs +3 -0
  114. package/Tests/Runtime/Core/OrderingTests.cs +3 -0
  115. package/Tests/Runtime/Core/OverDeregistrationTests.cs +3 -0
  116. package/Tests/Runtime/Core/PostProcessorTests.cs +3 -0
  117. package/Tests/Runtime/Core/ReflexiveErrorTests.cs +3 -0
  118. package/Tests/Runtime/Core/ReflexiveMessageWarningTests.cs +4 -1
  119. package/Tests/Runtime/Core/ReflexiveTests.cs +3 -0
  120. package/Tests/Runtime/Core/RegistrationTests.cs +3 -0
  121. package/Tests/Runtime/Core/StringShorthandTests.cs +3 -0
  122. package/Tests/Runtime/Core/TargetedTests.cs +3 -0
  123. package/Tests/Runtime/Core/TypedShorthandTests.cs +3 -0
  124. package/Tests/Runtime/Core/UntargetedEquivalenceTests.cs +3 -0
  125. package/Tests/Runtime/Core/UntargetedPrefreezeTests.cs +14 -78
  126. package/Tests/Runtime/Core/UntargetedTests.cs +3 -0
  127. package/Tests/Runtime/Integrations/Reflex/ReflexIntegrationTests.cs +4 -1
  128. package/Tests/Runtime/Integrations/VContainer/VContainerIntegrationTests.cs +3 -0
  129. package/Tests/Runtime/Integrations/Zenject/ZenjectIntegrationTests.cs +3 -0
  130. package/Tests/Runtime/Scripts/Components/GenericMessageAwareComponent.cs +3 -0
  131. package/Tests/Runtime/Scripts/Components/ManualListenerComponent.cs +3 -0
  132. package/Tests/Runtime/Scripts/Components/ReflexiveReceiverComponent.cs +3 -0
  133. package/Tests/Runtime/TestUtilities/UnityFixtureBase.cs +3 -0
  134. package/Tests/Runtime/Unity/MessageBusProviderAssetTests.cs +3 -0
  135. package/Tests/Runtime/Unity/MessageBusProviderHandleTests.cs +87 -3
  136. package/Tests/Runtime/Unity/MessagingComponentInstallerSceneTests.cs +109 -0
  137. package/Tests/Runtime/Unity/MessagingComponentInstallerSceneTests.cs.meta +11 -0
  138. package/Tests/Runtime/Unity/MessagingComponentProviderIntegrationTests.cs +159 -17
  139. package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj +20 -7
  140. package/package.json +1 -1
@@ -0,0 +1,129 @@
1
+ #if UNITY_EDITOR && UNITY_2021_3_OR_NEWER
2
+ namespace DxMessaging.Tests.Editor
3
+ {
4
+ using System.Collections.Generic;
5
+ using DxMessaging.Core.MessageBus;
6
+ using DxMessaging.Unity;
7
+ using NUnit.Framework;
8
+ using UnityEditor;
9
+ using UnityEngine;
10
+ using Object = UnityEngine.Object;
11
+
12
+ [TestFixture]
13
+ public sealed class MessagingComponentSerializationTests
14
+ {
15
+ private readonly List<Object> _createdObjects = new();
16
+ private readonly List<string> _createdAssetPaths = new();
17
+
18
+ [TearDown]
19
+ public void TearDown()
20
+ {
21
+ foreach (Object instance in _createdObjects)
22
+ {
23
+ if (instance != null && !EditorUtility.IsPersistent(instance))
24
+ {
25
+ Object.DestroyImmediate(instance);
26
+ }
27
+ }
28
+ _createdObjects.Clear();
29
+
30
+ foreach (string assetPath in _createdAssetPaths)
31
+ {
32
+ if (!string.IsNullOrEmpty(assetPath))
33
+ {
34
+ AssetDatabase.DeleteAsset(assetPath);
35
+ }
36
+ }
37
+ _createdAssetPaths.Clear();
38
+ AssetDatabase.Refresh();
39
+ }
40
+
41
+ [Test]
42
+ public void SerializedProviderHandleSurvivesJsonRoundtrip()
43
+ {
44
+ MessageBus messageBus = new();
45
+ TestScriptableMessageBusProvider provider =
46
+ ScriptableObject.CreateInstance<TestScriptableMessageBusProvider>();
47
+ provider.Configure(messageBus);
48
+ string assetPath = AssetDatabase.GenerateUniqueAssetPath(
49
+ "Assets/__TempTestProvider.asset"
50
+ );
51
+ AssetDatabase.CreateAsset(provider, assetPath);
52
+ AssetDatabase.SaveAssets();
53
+ AssetDatabase.ImportAsset(assetPath);
54
+ _createdAssetPaths.Add(assetPath);
55
+
56
+ GameObject owner = Track(new GameObject("OriginalComponentOwner"));
57
+ MessagingComponent original = owner.AddComponent<MessagingComponent>();
58
+ original.Configure(
59
+ new MessageBusProviderHandle(provider),
60
+ MessageBusRebindMode.RebindActive
61
+ );
62
+
63
+ SerializedObject originalSerialized = new(original);
64
+ SerializedProperty autoConfigureProperty = originalSerialized.FindProperty(
65
+ "autoConfigureSerializedProviderOnAwake"
66
+ );
67
+ Assert.IsNotNull(autoConfigureProperty, "Expected auto configure property to exist.");
68
+ autoConfigureProperty.boolValue = true;
69
+ originalSerialized.ApplyModifiedPropertiesWithoutUndo();
70
+
71
+ string serializedJson = EditorJsonUtility.ToJson(original);
72
+ Assert.IsFalse(
73
+ string.IsNullOrEmpty(serializedJson),
74
+ "JSON serialization should produce content."
75
+ );
76
+
77
+ GameObject cloneOwner = Track(new GameObject("ClonedComponentOwner"));
78
+ MessagingComponent clone = cloneOwner.AddComponent<MessagingComponent>();
79
+ EditorJsonUtility.FromJsonOverwrite(serializedJson, clone);
80
+
81
+ Assert.IsTrue(
82
+ clone.SerializedProviderHandle.TryGetProvider(
83
+ out IMessageBusProvider resolvedProvider
84
+ ),
85
+ "Serialized provider handle should still resolve after JSON roundtrip."
86
+ );
87
+ Assert.AreSame(provider, resolvedProvider, "Provider reference should be preserved.");
88
+ Assert.AreSame(
89
+ provider,
90
+ clone.SerializedProviderHandle.SerializedProvider,
91
+ "Provider asset reference should be preserved."
92
+ );
93
+
94
+ IMessageBus resolvedBus = clone.SerializedProviderHandle.ResolveBus();
95
+ Assert.AreSame(
96
+ messageBus,
97
+ resolvedBus,
98
+ "Resolved bus should match the original provider configuration."
99
+ );
100
+ }
101
+
102
+ private T Track<T>(T unityObject)
103
+ where T : Object
104
+ {
105
+ if (unityObject != null)
106
+ {
107
+ _createdObjects.Add(unityObject);
108
+ }
109
+
110
+ return unityObject;
111
+ }
112
+
113
+ private sealed class TestScriptableMessageBusProvider : ScriptableMessageBusProvider
114
+ {
115
+ private IMessageBus _bus;
116
+
117
+ internal void Configure(IMessageBus bus)
118
+ {
119
+ _bus = bus;
120
+ }
121
+
122
+ public override IMessageBus Resolve()
123
+ {
124
+ return _bus;
125
+ }
126
+ }
127
+ }
128
+ }
129
+ #endif
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: add9131c704f47c39fbef33dbf71faa0
3
+ timeCreated: 1761880591
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "WallstopStudios.DxMessaging.Tests.Editor",
3
+ "rootNamespace": "DxMessaging.Tests.Editor",
4
+ "references": [
5
+ "UnityEditor.TestRunner",
6
+ "UnityEngine.TestRunner",
7
+ "WallstopStudios.DxMessaging",
8
+ "WallstopStudios.DxMessaging.Editor"
9
+ ],
10
+ "includePlatforms": ["Editor"],
11
+ "excludePlatforms": [],
12
+ "allowUnsafeCode": false,
13
+ "overrideReferences": true,
14
+ "precompiledReferences": ["nunit.framework.dll"],
15
+ "autoReferenced": true,
16
+ "defineConstraints": ["UNITY_INCLUDE_TESTS"],
17
+ "versionDefines": [],
18
+ "noEngineReferences": false
19
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 824502f38a4d40908d0cc74ba7eda5cb
3
+ timeCreated: 1761880591
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 3dfad12af65044df8412cc4a1c7ebc7b
3
+ timeCreated: 1761880591
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Benchmarks
2
3
  {
3
4
  using System;
@@ -442,3 +443,5 @@ namespace DxMessaging.Tests.Runtime.Benchmarks
442
443
  }
443
444
  }
444
445
  }
446
+
447
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Benchmarks
2
3
  {
3
4
  using System;
@@ -92,3 +93,5 @@ namespace DxMessaging.Tests.Runtime.Benchmarks
92
93
  }
93
94
  }
94
95
  }
96
+
97
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Benchmarks
2
3
  {
3
4
  using System;
@@ -393,3 +394,5 @@ namespace DxMessaging.Tests.Runtime.Benchmarks
393
394
  #endif
394
395
  }
395
396
  }
397
+
398
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Benchmarks
2
3
  {
3
4
  using System;
@@ -65,6 +66,12 @@ namespace DxMessaging.Tests.Runtime.Benchmarks
65
66
  RunWithComponent(component =>
66
67
  NoCopyUntargeted(timer, timeout, component, untargetedMessage)
67
68
  );
69
+ RunWithComponent(component =>
70
+ InterceptorHeavyUntargeted(timer, timeout, component, untargetedMessage)
71
+ );
72
+ RunWithComponent(component =>
73
+ PostProcessorHeavyUntargeted(timer, timeout, component, untargetedMessage)
74
+ );
68
75
  RunWithComponent(component =>
69
76
  ReflexiveOneArgument(timer, timeout, component.gameObject, reflexiveMessage)
70
77
  );
@@ -482,5 +489,135 @@ namespace DxMessaging.Tests.Runtime.Benchmarks
482
489
  ++count;
483
490
  }
484
491
  }
492
+
493
+ private void InterceptorHeavyUntargeted(
494
+ Stopwatch timer,
495
+ TimeSpan timeout,
496
+ EmptyMessageAwareComponent component,
497
+ SimpleUntargetedMessage message
498
+ )
499
+ {
500
+ int handlerInvocationCount = 0;
501
+ int interceptorInvocationCount = 0;
502
+ MessageRegistrationToken token = GetToken(component);
503
+
504
+ const int InterceptorCount = 8;
505
+ for (int i = 0; i < InterceptorCount; ++i)
506
+ {
507
+ token.RegisterUntargetedInterceptor<SimpleUntargetedMessage>(
508
+ (ref SimpleUntargetedMessage _) =>
509
+ {
510
+ ++interceptorInvocationCount;
511
+ return true;
512
+ }
513
+ );
514
+ }
515
+
516
+ token.RegisterUntargeted<SimpleUntargetedMessage>(Handle);
517
+ message.EmitUntargeted();
518
+
519
+ timer.Restart();
520
+ do
521
+ {
522
+ for (int i = 0; i < NumInvocationsPerIteration; ++i)
523
+ {
524
+ message.EmitUntargeted();
525
+ }
526
+ } while (timer.Elapsed < timeout);
527
+
528
+ bool allocating;
529
+ try
530
+ {
531
+ Assert.That(() => message.EmitUntargeted(), Is.Not.AllocatingGCMemory());
532
+ allocating = false;
533
+ }
534
+ catch
535
+ {
536
+ allocating = true;
537
+ }
538
+
539
+ Assert.Greater(
540
+ interceptorInvocationCount,
541
+ 0,
542
+ "Interceptor-heavy benchmark should invoke registered interceptors."
543
+ );
544
+
545
+ DisplayCount(
546
+ "DxMessaging (Untargeted) - Interceptors",
547
+ handlerInvocationCount,
548
+ timeout,
549
+ allocating
550
+ );
551
+ return;
552
+
553
+ void Handle(ref SimpleUntargetedMessage _)
554
+ {
555
+ ++handlerInvocationCount;
556
+ }
557
+ }
558
+
559
+ private void PostProcessorHeavyUntargeted(
560
+ Stopwatch timer,
561
+ TimeSpan timeout,
562
+ EmptyMessageAwareComponent component,
563
+ SimpleUntargetedMessage message
564
+ )
565
+ {
566
+ int handlerInvocationCount = 0;
567
+ int postProcessorInvocationCount = 0;
568
+ MessageRegistrationToken token = GetToken(component);
569
+
570
+ const int PostProcessorCount = 8;
571
+ for (int i = 0; i < PostProcessorCount; ++i)
572
+ {
573
+ token.RegisterUntargetedPostProcessor<SimpleUntargetedMessage>(
574
+ (ref SimpleUntargetedMessage _) => ++postProcessorInvocationCount
575
+ );
576
+ }
577
+
578
+ token.RegisterUntargeted<SimpleUntargetedMessage>(Handle);
579
+ message.EmitUntargeted();
580
+
581
+ timer.Restart();
582
+ do
583
+ {
584
+ for (int i = 0; i < NumInvocationsPerIteration; ++i)
585
+ {
586
+ message.EmitUntargeted();
587
+ }
588
+ } while (timer.Elapsed < timeout);
589
+
590
+ bool allocating;
591
+ try
592
+ {
593
+ Assert.That(() => message.EmitUntargeted(), Is.Not.AllocatingGCMemory());
594
+ allocating = false;
595
+ }
596
+ catch
597
+ {
598
+ allocating = true;
599
+ }
600
+
601
+ Assert.Greater(
602
+ postProcessorInvocationCount,
603
+ 0,
604
+ "Post-processor benchmark should invoke registered post-processors."
605
+ );
606
+
607
+ DisplayCount(
608
+ "DxMessaging (Untargeted) - Post-Processors",
609
+ handlerInvocationCount,
610
+ timeout,
611
+ allocating
612
+ );
613
+ return;
614
+
615
+ void Handle(ref SimpleUntargetedMessage _)
616
+ {
617
+ ++handlerInvocationCount;
618
+ }
619
+ }
485
620
  }
486
621
  }
622
+
623
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System.Collections;
@@ -80,3 +81,5 @@ namespace DxMessaging.Tests.Runtime.Core
80
81
  }
81
82
  }
82
83
  }
84
+
85
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System.Collections;
@@ -895,3 +896,5 @@ namespace DxMessaging.Tests.Runtime.Core
895
896
  }
896
897
  }
897
898
  }
899
+
900
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System.Collections;
@@ -68,3 +69,5 @@ namespace DxMessaging.Tests.Runtime.Core
68
69
  }
69
70
  }
70
71
  }
72
+
73
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System.Collections;
@@ -20,9 +21,9 @@ namespace DxMessaging.Tests.Runtime.Core
20
21
  [TearDown]
21
22
  public void TearDown()
22
23
  {
23
- foreach (var token in _tokens)
24
+ foreach (MessageRegistrationToken token in _tokens)
24
25
  {
25
- foreach (var handle in _handles)
26
+ foreach (MessageRegistrationHandle handle in _handles)
26
27
  {
27
28
  token.RemoveRegistration(handle);
28
29
  }
@@ -331,3 +332,5 @@ namespace DxMessaging.Tests.Runtime.Core
331
332
  }
332
333
  }
333
334
  }
335
+
336
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System.Collections;
@@ -116,3 +117,5 @@ namespace DxMessaging.Tests.Runtime.Core
116
117
  }
117
118
  }
118
119
  }
120
+
121
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  // ReSharper disable AccessToModifiedClosure
2
3
  namespace DxMessaging.Tests.Runtime.Core
3
4
  {
@@ -577,3 +578,5 @@ namespace DxMessaging.Tests.Runtime.Core
577
578
  }
578
579
  }
579
580
  }
581
+
582
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System.Collections;
@@ -67,3 +68,5 @@ namespace DxMessaging.Tests.Runtime.Core
67
68
  }
68
69
  }
69
70
  }
71
+
72
+ #endif
@@ -204,7 +204,7 @@ namespace DxMessaging.Tests.Runtime.Core.Extensions
204
204
 
205
205
  MessageHandler handler = new(new InstanceId(601), providerBus) { active = true };
206
206
  MessageRegistrationToken token = MessageRegistrationToken.Create(handler, providerBus);
207
- string? received = null;
207
+ string received = null;
208
208
  _ = token.RegisterTargeted(target, (ref StringMessage m) => received = m.message);
209
209
  token.Enable();
210
210
 
@@ -213,7 +213,7 @@ namespace DxMessaging.Tests.Runtime.Core.Extensions
213
213
  globalHandler,
214
214
  MessageHandler.MessageBus
215
215
  );
216
- string? globalReceived = null;
216
+ string globalReceived = null;
217
217
  _ = globalToken.RegisterTargeted(
218
218
  target,
219
219
  (ref StringMessage m) => globalReceived = m.message
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using DxMessaging.Core;
@@ -45,3 +46,5 @@ namespace DxMessaging.Tests.Runtime.Core
45
46
  }
46
47
  }
47
48
  }
49
+
50
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System;
@@ -188,3 +189,5 @@ namespace DxMessaging.Tests.Runtime.Core
188
189
  }
189
190
  }
190
191
  }
192
+
193
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System.Collections;
@@ -168,3 +169,5 @@ namespace DxMessaging.Tests.Runtime.Core
168
169
  }
169
170
  }
170
171
  }
172
+
173
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System.Collections;
@@ -70,3 +71,5 @@ namespace DxMessaging.Tests.Runtime.Core
70
71
  }
71
72
  }
72
73
  }
74
+
75
+ #endif
@@ -0,0 +1,70 @@
1
+ namespace DxMessaging.Tests.Runtime.Core
2
+ {
3
+ using System;
4
+ using System.Linq;
5
+ using DxMessaging.Core;
6
+ using DxMessaging.Core.Diagnostics;
7
+ using DxMessaging.Core.Messages;
8
+ using NUnit.Framework;
9
+
10
+ public sealed class MessageEmissionDataTests
11
+ {
12
+ [Test]
13
+ public void StackTraceOmitsDxMessagingFrames()
14
+ {
15
+ MessageEmissionData data = CaptureMessageEmission();
16
+
17
+ Assert.IsFalse(
18
+ string.IsNullOrWhiteSpace(data.stackTrace),
19
+ "Stack trace should capture emission site."
20
+ );
21
+
22
+ string[] lines = data.stackTrace.Split(
23
+ new[] { "\r\n", "\n" },
24
+ StringSplitOptions.RemoveEmptyEntries
25
+ );
26
+
27
+ bool containsInternalFrame = lines.Any(line =>
28
+ line.Contains("DxMessaging.Core.", StringComparison.Ordinal)
29
+ || line.Contains("DxMessaging.Unity.", StringComparison.Ordinal)
30
+ );
31
+ if (containsInternalFrame)
32
+ {
33
+ Assert.Fail(
34
+ $"Stack trace should omit DxMessaging internal frames.{Environment.NewLine}{data.stackTrace}"
35
+ );
36
+ }
37
+
38
+ bool containsTestMethod = lines.Any(line =>
39
+ line.Contains(nameof(StackTraceOmitsDxMessagingFrames), StringComparison.Ordinal)
40
+ );
41
+ if (!containsTestMethod)
42
+ {
43
+ Assert.Fail(
44
+ $"Stack trace should include calling test method for debugging context.{Environment.NewLine}{data.stackTrace}"
45
+ );
46
+ }
47
+ }
48
+
49
+ [Test]
50
+ public void ContextIsCapturedWhenProvided()
51
+ {
52
+ InstanceId expectedContext = new(12345);
53
+ MessageEmissionData data = new(new TestUntargetedMessage(), expectedContext);
54
+
55
+ Assert.That(
56
+ data.context.HasValue,
57
+ Is.True,
58
+ "Context should be captured when supplied."
59
+ );
60
+ Assert.That(data.context.Value, Is.EqualTo(expectedContext));
61
+ }
62
+
63
+ private static MessageEmissionData CaptureMessageEmission()
64
+ {
65
+ return new MessageEmissionData(new TestUntargetedMessage());
66
+ }
67
+
68
+ private readonly struct TestUntargetedMessage : IUntargetedMessage { }
69
+ }
70
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: aa2a8eed3f943a2419acdc40a9da37c0
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System.Collections;
@@ -87,3 +88,5 @@ namespace DxMessaging.Tests.Runtime.Core
87
88
  }
88
89
  }
89
90
  }
91
+
92
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System;
@@ -206,3 +207,5 @@ namespace DxMessaging.Tests.Runtime.Core
206
207
  }
207
208
  }
208
209
  }
210
+
211
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System.Collections;
@@ -96,3 +97,5 @@ namespace DxMessaging.Tests.Runtime.Core
96
97
  }
97
98
  }
98
99
  }
100
+
101
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System.Collections;
@@ -432,3 +433,5 @@ namespace DxMessaging.Tests.Runtime.Core
432
433
  }
433
434
  }
434
435
  }
436
+
437
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System.Collections;
@@ -2019,3 +2020,5 @@ namespace DxMessaging.Tests.Runtime.Core
2019
2020
  }
2020
2021
  }
2021
2022
  }
2023
+
2024
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System.Collections;
@@ -97,3 +98,5 @@ namespace DxMessaging.Tests.Runtime.Core
97
98
  }
98
99
  }
99
100
  }
101
+
102
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System.Collections;
@@ -185,3 +186,5 @@ namespace DxMessaging.Tests.Runtime.Core
185
186
  }
186
187
  }
187
188
  }
189
+
190
+ #endif
@@ -1,3 +1,4 @@
1
+ #if UNITY_2021_3_OR_NEWER
1
2
  namespace DxMessaging.Tests.Runtime.Core
2
3
  {
3
4
  using System.Collections;
@@ -104,3 +105,5 @@ namespace DxMessaging.Tests.Runtime.Core
104
105
  }
105
106
  }
106
107
  }
108
+
109
+ #endif