/src/NServiceBus.Core.Tests/Pipeline/PipelineModelBuilderTests.cs

https://github.com/MikeEast/NServiceBus · C# · 306 lines · 248 code · 58 blank · 0 comment · 2 complexity · b3855ee3d415ab6c46ffecb0dc5d8200 MD5 · raw file

  1. namespace NServiceBus.Core.Tests.Pipeline
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Threading.Tasks;
  7. using NServiceBus.Pipeline;
  8. using NUnit.Framework;
  9. public class PipelineModelBuilderTests
  10. {
  11. [Test]
  12. public void ShouldDetectConflictingStepRegistrations()
  13. {
  14. var builder = ConfigurePipelineModelBuilder.Setup()
  15. .Register(RegisterStep.Create("Root1", typeof(RootBehavior), "desc"))
  16. .Register(RegisterStep.Create("Root1", typeof(ChildBehaviorOfChildContextNotInheritedFromParentContext), "desc"))
  17. .Build(typeof(IParentContext));
  18. var ex = Assert.Throws<Exception>(() => builder.Build());
  19. Assert.AreEqual("Step registration with id 'Root1' is already registered for 'NServiceBus.Core.Tests.Pipeline.PipelineModelBuilderTests+RootBehavior'.", ex.Message);
  20. }
  21. [Test]
  22. public void ShouldOnlyAllowReplacementOfExistingRegistrations()
  23. {
  24. var builder = ConfigurePipelineModelBuilder.Setup()
  25. .Register(RegisterStep.Create("Root1", typeof(RootBehavior), "desc"))
  26. .Replace(new ReplaceStep("DoesNotExist", typeof(RootBehavior), "desc"))
  27. .Build(typeof(IParentContext));
  28. var ex = Assert.Throws<Exception>(() => builder.Build());
  29. Assert.AreEqual("Multiple replacements of the same pipeline behaviour is not supported. Make sure that you only register a single replacement for 'DoesNotExist'.", ex.Message);
  30. }
  31. [Test]
  32. public void ShouldAddWhenAddingOrReplacingABehaviorThatDoesntExist()
  33. {
  34. var builder = ConfigurePipelineModelBuilder.Setup()
  35. .Register(RegisterStep.Create("Root1", typeof(RootBehavior), "desc"))
  36. .RegisterOrReplace(RegisterOrReplaceStep.Create("SomeBehaviorOfParentContext", typeof(SomeBehaviorOfParentContext), "desc"))
  37. .Build(typeof(IParentContext));
  38. var model = builder.Build();
  39. Assert.That(model.Count, Is.EqualTo(2));
  40. var addedBehavior = model.FirstOrDefault(x => x.StepId == "SomeBehaviorOfParentContext");
  41. Assert.That(addedBehavior, Is.Not.Null);
  42. Assert.That(addedBehavior.BehaviorType, Is.EqualTo(typeof(SomeBehaviorOfParentContext)));
  43. }
  44. [Test]
  45. public void ShouldReplaceWhenAddingOrReplacingABehaviorThatDoesAlreadyExist()
  46. {
  47. var builder = ConfigurePipelineModelBuilder.Setup()
  48. .Register(RegisterStep.Create("Root1", typeof(RootBehavior), "desc"))
  49. .Register(RegisterStep.Create("SomeBehaviorOfParentContext", typeof(SomeBehaviorOfParentContext), "desc"))
  50. .RegisterOrReplace(RegisterOrReplaceStep.Create("SomeBehaviorOfParentContext", typeof(AnotherBehaviorOfParentContext), "desc"))
  51. .Build(typeof(IParentContext));
  52. var model = builder.Build();
  53. Assert.That(model.Count, Is.EqualTo(2));
  54. var overriddenBehavior = model.FirstOrDefault(x => x.StepId == "SomeBehaviorOfParentContext");
  55. Assert.That(overriddenBehavior, Is.Not.Null);
  56. Assert.That(overriddenBehavior.BehaviorType, Is.EqualTo(typeof(AnotherBehaviorOfParentContext)));
  57. }
  58. [Test]
  59. public void ShouldDetectMissingBehaviorForRootContext()
  60. {
  61. var builder = ConfigurePipelineModelBuilder.Setup()
  62. .Register(RegisterStep.Create("Child", typeof(ChildBehaviorOfChildContext), "desc"))
  63. .Build(typeof(IParentContext));
  64. var ex = Assert.Throws<Exception>(() => builder.Build());
  65. Assert.AreEqual("Can't find any behaviors/connectors for the root context (NServiceBus.Core.Tests.Pipeline.PipelineModelBuilderTests+IParentContext)", ex.Message);
  66. }
  67. [Test]
  68. public void ShouldDetectConflictingStageConnectors()
  69. {
  70. var builder = ConfigurePipelineModelBuilder.Setup()
  71. .Register(RegisterStep.Create("Root1", typeof(RootBehavior), "desc"))
  72. .Register(RegisterStep.Create("ParentContextToChildContextConnector", typeof(ParentContextToChildContextConnector), "desc"))
  73. .Register(RegisterStep.Create("ParentContextToChildContextNotInheritedFromParentContextConnector", typeof(ParentContextToChildContextNotInheritedFromParentContextConnector), "desc"))
  74. .Build(typeof(IParentContext));
  75. var ex = Assert.Throws<Exception>(() => builder.Build());
  76. Assert.AreEqual("Multiple stage connectors found for stage 'NServiceBus.Core.Tests.Pipeline.PipelineModelBuilderTests+IParentContext'. Remove one of: 'NServiceBus.Core.Tests.Pipeline.PipelineModelBuilderTests+ParentContextToChildContextConnector', 'NServiceBus.Core.Tests.Pipeline.PipelineModelBuilderTests+ParentContextToChildContextNotInheritedFromParentContextConnector'", ex.Message);
  77. }
  78. [Test]
  79. public void ShouldDetectNonExistingInsertAfterRegistrations()
  80. {
  81. var someBehaviorRegistration = RegisterStep.Create("SomeBehaviorOfParentContext", typeof(SomeBehaviorOfParentContext), "desc");
  82. var anotherBehaviorRegistration = RegisterStep.Create("AnotherBehaviorOfParentContext", typeof(AnotherBehaviorOfParentContext), "desc");
  83. anotherBehaviorRegistration.InsertAfter("DoesNotExist");
  84. var builder = ConfigurePipelineModelBuilder.Setup()
  85. .Register(someBehaviorRegistration)
  86. .Register(anotherBehaviorRegistration)
  87. .Build(typeof(IParentContext));
  88. var ex = Assert.Throws<Exception>(() => builder.Build());
  89. Assert.AreEqual("Registration 'DoesNotExist' specified in the insertafter of the 'AnotherBehaviorOfParentContext' step does not exist. Current StepIds: 'SomeBehaviorOfParentContext', 'AnotherBehaviorOfParentContext'", ex.Message);
  90. }
  91. [Test]
  92. public void ShouldDetectNonExistingInsertBeforeRegistrations()
  93. {
  94. var someBehaviorRegistration = RegisterStep.Create("SomeBehaviorOfParentContext", typeof(SomeBehaviorOfParentContext), "desc");
  95. var anotherBehaviorRegistration = RegisterStep.Create("AnotherBehaviorOfParentContext", typeof(AnotherBehaviorOfParentContext), "desc");
  96. anotherBehaviorRegistration.InsertBefore("DoesNotExist");
  97. var builder = ConfigurePipelineModelBuilder.Setup()
  98. .Register(someBehaviorRegistration)
  99. .Register(anotherBehaviorRegistration)
  100. .Build(typeof(IParentContext));
  101. var ex = Assert.Throws<Exception>(() => builder.Build());
  102. Assert.AreEqual("Registration 'DoesNotExist' specified in the insertbefore of the 'AnotherBehaviorOfParentContext' step does not exist. Current StepIds: 'SomeBehaviorOfParentContext', 'AnotherBehaviorOfParentContext'", ex.Message);
  103. }
  104. [Test]
  105. public void ShouldDetectRegistrationsWithContextsReachableFromTheRootContext()
  106. {
  107. var builder = ConfigurePipelineModelBuilder.Setup()
  108. .Register(RegisterStep.Create("Root", typeof(RootBehavior), "desc"))
  109. .Register(RegisterStep.Create("ParentContextToChildContextNotInheritedFromParentContextConnector", typeof(ParentContextToChildContextNotInheritedFromParentContextConnector), "desc"))
  110. .Register(RegisterStep.Create("Child", typeof(ChildBehaviorOfChildContextNotInheritedFromParentContext), "desc"))
  111. .Build(typeof(IParentContext));
  112. var model = builder.Build();
  113. Assert.AreEqual(3, model.Count);
  114. }
  115. [Test]
  116. public void ShouldDetectRegistrationsWithContextsNotReachableFromTheRootContext()
  117. {
  118. var builder = ConfigurePipelineModelBuilder.Setup()
  119. .Register(RegisterStep.Create("Root", typeof(RootBehavior), "desc"))
  120. .Register(RegisterStep.Create("ParentContextToChildContextConnector", typeof(ParentContextToChildContextConnector), "desc"))
  121. .Register(RegisterStep.Create("Child", typeof(ChildBehaviorOfChildContextNotInheritedFromParentContext), "desc"))
  122. .Build(typeof(IParentContext));
  123. var model = builder.Build();
  124. Assert.AreEqual(2, model.Count);
  125. }
  126. [Test]
  127. public void ShouldHandleTheTerminator()
  128. {
  129. var builder = ConfigurePipelineModelBuilder.Setup()
  130. .Register(RegisterStep.Create("Root1", typeof(RootBehavior), "desc"))
  131. .Register(RegisterStep.Create("ParentContextToChildContextConnector", typeof(ParentContextToChildContextConnector), "desc"))
  132. .Register(RegisterStep.Create("Child", typeof(ChildBehaviorOfChildContextNotInheritedFromParentContext), "desc"))
  133. .Register(RegisterStep.Create("Terminator", typeof(Terminator), "desc"))
  134. .Build(typeof(IParentContext));
  135. var model = builder.Build();
  136. Assert.AreEqual(3, model.Count);
  137. }
  138. class ConfigurePipelineModelBuilder
  139. {
  140. List<RegisterStep> registrations = new List<RegisterStep>();
  141. List<RegisterOrReplaceStep> registerOrReplacements = new List<RegisterOrReplaceStep>();
  142. List<ReplaceStep> replacements = new List<ReplaceStep>();
  143. public static ConfigurePipelineModelBuilder Setup()
  144. {
  145. return new ConfigurePipelineModelBuilder();
  146. }
  147. public ConfigurePipelineModelBuilder Register(RegisterStep registration)
  148. {
  149. registrations.Add(registration);
  150. return this;
  151. }
  152. public ConfigurePipelineModelBuilder Replace(ReplaceStep registration)
  153. {
  154. replacements.Add(registration);
  155. return this;
  156. }
  157. public ConfigurePipelineModelBuilder RegisterOrReplace(RegisterOrReplaceStep registration)
  158. {
  159. registerOrReplacements.Add(registration);
  160. return this;
  161. }
  162. public PipelineModelBuilder Build(Type parentContextType)
  163. {
  164. return new PipelineModelBuilder(parentContextType, registrations, replacements, registerOrReplacements);
  165. }
  166. }
  167. interface IParentContext : IBehaviorContext { }
  168. class ParentContext : BehaviorContext, IParentContext
  169. {
  170. public ParentContext(IBehaviorContext parentContext)
  171. : base(parentContext)
  172. {
  173. }
  174. }
  175. interface IChildContext : IParentContext { }
  176. class ChildContext : ParentContext, IChildContext
  177. {
  178. public ChildContext(IBehaviorContext parentContext)
  179. : base(parentContext)
  180. {
  181. }
  182. }
  183. interface IChildContextNotInheritedFromParentContext : IBehaviorContext { }
  184. class ChildContextNotInheritedFromParentContext : BehaviorContext
  185. {
  186. public ChildContextNotInheritedFromParentContext(IBehaviorContext parentContext)
  187. : base(parentContext)
  188. {
  189. }
  190. }
  191. class ParentContextToChildContextConnector : StageConnector<IParentContext, IChildContext>
  192. {
  193. public override Task Invoke(IParentContext context, Func<IChildContext, Task> stage)
  194. {
  195. throw new NotImplementedException();
  196. }
  197. }
  198. class Terminator : PipelineTerminator<IChildContext>
  199. {
  200. protected override Task Terminate(IChildContext context)
  201. {
  202. throw new NotImplementedException();
  203. }
  204. }
  205. class ParentContextToChildContextNotInheritedFromParentContextConnector : StageConnector<IParentContext, IChildContextNotInheritedFromParentContext>
  206. {
  207. public override Task Invoke(IParentContext context, Func<IChildContextNotInheritedFromParentContext, Task> stage)
  208. {
  209. throw new NotImplementedException();
  210. }
  211. }
  212. class SomeBehaviorOfParentContext : IBehavior<IParentContext, IParentContext>
  213. {
  214. public Task Invoke(IParentContext context, Func<IParentContext, Task> next)
  215. {
  216. throw new NotImplementedException();
  217. }
  218. }
  219. class AnotherBehaviorOfParentContext : IBehavior<IParentContext, IParentContext>
  220. {
  221. public Task Invoke(IParentContext context, Func<IParentContext, Task> next)
  222. {
  223. throw new NotImplementedException();
  224. }
  225. }
  226. class RootBehavior : IBehavior<IParentContext, IParentContext>
  227. {
  228. public Task Invoke(IParentContext context, Func<IParentContext, Task> next)
  229. {
  230. throw new NotImplementedException();
  231. }
  232. }
  233. class ChildBehaviorOfChildContext : IBehavior<IChildContext, IChildContext>
  234. {
  235. public Task Invoke(IChildContext context, Func<IChildContext, Task> next)
  236. {
  237. throw new NotImplementedException();
  238. }
  239. }
  240. class ChildBehaviorOfChildContextNotInheritedFromParentContext : IBehavior<IChildContextNotInheritedFromParentContext, IChildContextNotInheritedFromParentContext>
  241. {
  242. public Task Invoke(IChildContextNotInheritedFromParentContext context, Func<IChildContextNotInheritedFromParentContext, Task> next)
  243. {
  244. throw new NotImplementedException();
  245. }
  246. }
  247. }
  248. }