diff --git a/src/NServiceBus.Router.AcceptanceTests/Infrastructure/BrokerSettings.cs b/src/NServiceBus.Router.AcceptanceTests/Infrastructure/BrokerSettings.cs index fd103b8..6156219 100644 --- a/src/NServiceBus.Router.AcceptanceTests/Infrastructure/BrokerSettings.cs +++ b/src/NServiceBus.Router.AcceptanceTests/Infrastructure/BrokerSettings.cs @@ -31,7 +31,12 @@ public void Charlie() { SetStoragePath("Charlie"); } - + + public void Delta() + { + SetStoragePath("Delta"); + } + public void Yankee() { SetStoragePath("Yankee"); diff --git a/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_connecting_to_two_routers.cs b/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_connecting_to_two_routers.cs new file mode 100644 index 0000000..1b69c4d --- /dev/null +++ b/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_connecting_to_two_routers.cs @@ -0,0 +1,132 @@ +using System.Threading.Tasks; +using NServiceBus.AcceptanceTesting; +using NUnit.Framework; + +namespace NServiceBus.Router.AcceptanceTests.MultipleRouters +{ + using AcceptanceTesting.Customization; + + [TestFixture] + public class When_connecting_to_two_routers : NServiceBusAcceptanceTest + { + [Test] + public async Task Should_deliver_the_messages_to_destination_endpoints() + { + var result = await Scenario.Define() + .WithRouter("RouterA", cfg => + { + cfg.AddInterface("Left", false).Broker().Charlie(); + cfg.AddInterface("Right", false).Broker().Alpha(); + + cfg.UseStaticRoutingProtocol().AddForwardRoute("Left", "Right"); + }) + .WithRouter("RouterB", cfg => + { + cfg.AddInterface("Left", false).Broker().Charlie(); + cfg.AddInterface("Right", false).Broker().Bravo(); + + cfg.UseStaticRoutingProtocol().AddForwardRoute("Left", "Right"); + }) + .WithEndpoint(c => c.When(async s => + { + await s.Send(new MyRequestA()); + await s.Send(new MyRequestB()); + })) + .WithEndpoint() + .WithEndpoint() + .Done(c => c.ReceivedByB && c.ReceivedByA) + .Run(); + + Assert.IsTrue(result.ReceivedByB); + Assert.IsTrue(result.ReceivedByA); + } + + class Context : ScenarioContext + { + public bool ReceivedByA { get; set; } + public bool ReceivedByB { get; set; } + } + + class Sender : EndpointConfigurationBuilder + { + public Sender() + { + EndpointSetup(c => + { + c.ConfigureBroker().Charlie(); + var routing = c.ConfigureRouting(); + + var routerA = routing.ConnectToRouter("RouterA"); + routerA.RouteToEndpoint(typeof(MyRequestA), Conventions.EndpointNamingConvention(typeof(ReceiverA))); + + var routerB = routing.ConnectToRouter("RouterB"); + routerB.RouteToEndpoint(typeof(MyRequestB), Conventions.EndpointNamingConvention(typeof(ReceiverB))); + }); + } + } + + class ReceiverA : EndpointConfigurationBuilder + { + public ReceiverA() + { + EndpointSetup(c => + { + //No bridge configuration needed for reply + c.ConfigureBroker().Alpha(); + }); + } + + class MyRequestHandler : IHandleMessages + { + Context scenarioContext; + + public MyRequestHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(MyRequestA requestA, IMessageHandlerContext context) + { + scenarioContext.ReceivedByA = true; + return Task.CompletedTask; + } + } + } + + class ReceiverB : EndpointConfigurationBuilder + { + public ReceiverB() + { + EndpointSetup(c => + { + //No bridge configuration needed for reply + c.ConfigureBroker().Bravo(); + }); + } + + class MyRequestHandler : IHandleMessages + { + Context scenarioContext; + + public MyRequestHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(MyRequestB requestB, IMessageHandlerContext context) + { + scenarioContext.ReceivedByB = true; + return Task.CompletedTask; + } + } + } + + class MyRequestA : IMessage + { + } + + class MyRequestB : IMessage + { + } + } +} diff --git a/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_publishing_via_double_unicast_bridge.cs b/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_publishing_via_double_unicast_bridge.cs new file mode 100644 index 0000000..c12346a --- /dev/null +++ b/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_publishing_via_double_unicast_bridge.cs @@ -0,0 +1,98 @@ +using System.Threading.Tasks; +using NServiceBus.AcceptanceTesting; +using NUnit.Framework; + +namespace NServiceBus.Router.AcceptanceTests.MultipleRouters +{ + using AcceptanceTesting.Customization; + + [TestFixture] + public class When_publishing_via_double_unicast_bridge : NServiceBusAcceptanceTest + { + [Test] + public async Task It_should_deliver_the_message() + { + var result = await Scenario.Define() + .WithRouter("Green-Blue", cfg => + { + cfg.AddInterface("Green", false).Broker().Alpha(); + cfg.AddInterface("Blue", false).Broker().Bravo(); + + cfg.UseStaticRoutingProtocol().AddForwardRoute("Blue", "Green"); + }) + .WithRouter("Blue-Red", cfg => + { + cfg.AddInterface("Blue", false).Broker().Bravo(); + cfg.AddInterface("Red", false).Broker().Charlie(); + + cfg.UseStaticRoutingProtocol().AddForwardRoute("Red", "Blue", "Green-Blue"); + }) + .WithEndpoint(c => c.When(x => x.EventSubscribed, s => s.Publish(new MyEvent()))) + .WithEndpoint() + .Done(c => c.EventDelivered) + .Run(); + + Assert.IsTrue(result.EventDelivered); + } + + class Context : ScenarioContext + { + public bool EventDelivered { get; set; } + public bool EventSubscribed { get; set; } + } + + class Publisher : EndpointConfigurationBuilder + { + public Publisher() + { + EndpointSetup(c => + { + //No bridge configuration needed for publisher + c.ConfigureBroker().Alpha(); + + c.ConfigureRouting().EnableMessageDrivenPubSubCompatibilityMode(); + + c.OnEndpointSubscribed((args, context) => + { + context.EventSubscribed = true; + }); + }); + } + } + + class Subscriber : EndpointConfigurationBuilder + { + public Subscriber() + { + EndpointSetup(c => + { + c.ConfigureBroker().Charlie(); + + var routing = c.ConfigureRouting(); + var ramp = routing.ConnectToRouter("Blue-Red"); + ramp.RegisterPublisher(typeof(MyEvent), Conventions.EndpointNamingConvention(typeof(Publisher))); + }); + } + + class MyEventHandler : IHandleMessages + { + Context scenarioContext; + + public MyEventHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(MyEvent message, IMessageHandlerContext context) + { + scenarioContext.EventDelivered = true; + return Task.CompletedTask; + } + } + } + + class MyEvent : IEvent + { + } + } +} diff --git a/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_publishing_via_double_unicast_multicast_bridge.cs b/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_publishing_via_double_unicast_multicast_bridge.cs new file mode 100644 index 0000000..db48848 --- /dev/null +++ b/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_publishing_via_double_unicast_multicast_bridge.cs @@ -0,0 +1,98 @@ +using System.Threading.Tasks; +using NServiceBus.AcceptanceTesting; +using NUnit.Framework; + +namespace NServiceBus.Router.AcceptanceTests.MultipleRouters +{ + using AcceptanceTesting.Customization; + + [TestFixture] + public class When_publishing_via_double_unicast_multicast_bridge : NServiceBusAcceptanceTest + { + [Test] + public async Task It_should_deliver_the_message() + { + var result = await Scenario.Define() + .WithRouter("Green-Blue", cfg => + { + cfg.AddInterface("Green", false).Broker().Alpha(); + cfg.AddInterface("Blue", false).Broker().Bravo(); + + cfg.UseStaticRoutingProtocol().AddForwardRoute("Blue", "Green"); + }) + .WithRouter("Blue-Red", cfg => + { + cfg.AddInterface("Blue", false).Broker().Bravo(); + cfg.AddInterface("Red", false).Broker().Charlie(); + + cfg.UseStaticRoutingProtocol().AddForwardRoute("Red", "Blue", "Green-Blue"); + }) + .WithEndpoint(c => c.When(x => x.EventSubscribed, s => s.Publish(new MyEvent()))) + .WithEndpoint() + .Done(c => c.EventDelivered) + .Run(); + + Assert.IsTrue(result.EventDelivered); + } + + class Context : ScenarioContext + { + public bool EventDelivered { get; set; } + public bool EventSubscribed { get; set; } + } + + class Publisher : EndpointConfigurationBuilder + { + public Publisher() + { + EndpointSetup(c => + { + //No bridge configuration needed for publisher + c.ConfigureBroker().Alpha(); + + c.ConfigureRouting().EnableMessageDrivenPubSubCompatibilityMode(); + + c.OnEndpointSubscribed((args, context) => + { + context.EventSubscribed = true; + }); + }); + } + } + + class Subscriber : EndpointConfigurationBuilder + { + public Subscriber() + { + EndpointSetup(c => + { + c.ConfigureBroker().Charlie(); + + var routing = c.ConfigureRouting(); + var bridge = routing.ConnectToRouter("Blue-Red"); + bridge.RegisterPublisher(typeof(MyEvent), Conventions.EndpointNamingConvention(typeof(Publisher))); + }); + } + + class MyEventHandler : IHandleMessages + { + Context scenarioContext; + + public MyEventHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(MyEvent message, IMessageHandlerContext context) + { + scenarioContext.EventDelivered = true; + return Task.CompletedTask; + } + } + } + + class MyEvent : IEvent + { + } + } +} diff --git a/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_sender_delegates_routing.cs b/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_sender_delegates_routing.cs new file mode 100644 index 0000000..f906419 --- /dev/null +++ b/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_sender_delegates_routing.cs @@ -0,0 +1,131 @@ +using System.Threading.Tasks; +using NServiceBus.AcceptanceTesting; +using NUnit.Framework; + +namespace NServiceBus.Router.AcceptanceTests.MultipleRouters +{ + using System; + using AcceptanceTesting.Customization; + + [TestFixture] + public class When_sender_delegates_routing : NServiceBusAcceptanceTest + { + static string ReceiverEndpoint => Conventions.EndpointNamingConvention(typeof(Receiver)); + + [Test] + public async Task Should_use_custom_destination_finder_on_destinations_router() + { + var result = await Scenario.Define() + .WithRouter("Green-Blue", cfg => + { + cfg.AddInterface("Green", false).Broker().Alpha(); + cfg.AddInterface("Blue", false).Broker().Bravo(); + + cfg.UseStaticRoutingProtocol().AddRoute((iface, destination) => destination.Site == "MySite", "Site = MySite", "Blue-Red", "Blue"); + }) + .WithRouter("Blue-Red", cfg => + { + cfg.AddInterface("Blue", false).Broker().Bravo(); + cfg.AddInterface("Red", false).Broker().Charlie(); + + var staticRouting = cfg.UseStaticRoutingProtocol(); + staticRouting.AddForwardRoute("Blue", "Red"); + cfg.AddRule(_ => new CustomDestinationRule()); + }) + .WithEndpoint(c => c.When(s => + { + var ops = new SendOptions(); + ops.SendToSites("MySite"); + return s.Send(new MyRequest(), ops); + })) + .WithEndpoint() + .Done(c => c.RequestReceived && c.ResponseReceived) + .Run(); + + Assert.IsTrue(result.RequestReceived); + Assert.IsTrue(result.ResponseReceived); + } + + class CustomDestinationRule : IRule + { + public Task Invoke(SendPreroutingContext context, Func next) + { + context.Destinations.Add(new Destination(ReceiverEndpoint, null)); + return next(context); + } + } + + class Context : ScenarioContext + { + public bool RequestReceived { get; set; } + public bool ResponseReceived { get; set; } + } + + class Sender : EndpointConfigurationBuilder + { + public Sender() + { + EndpointSetup(c => + { + c.ConfigureBroker().Alpha(); + + var routing = c.ConfigureRouting(); + var router = routing.ConnectToRouter("Green-Blue"); + router.DelegateRouting(typeof(MyRequest)); + }); + } + + class MyResponseHandler : IHandleMessages + { + Context scenarioContext; + + public MyResponseHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(MyResponse response, IMessageHandlerContext context) + { + scenarioContext.ResponseReceived = true; + return Task.CompletedTask; + } + } + } + + class Receiver : EndpointConfigurationBuilder + { + public Receiver() + { + EndpointSetup(c => + { + //No bridge configuration needed for reply + c.ConfigureBroker().Charlie(); + }); + } + + class MyRequestHandler : IHandleMessages + { + Context scenarioContext; + + public MyRequestHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(MyRequest request, IMessageHandlerContext context) + { + scenarioContext.RequestReceived = true; + return context.Reply(new MyResponse()); + } + } + } + + class MyRequest : IMessage + { + } + + class MyResponse : IMessage + { + } + } +} diff --git a/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_sending_between_sites.cs b/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_sending_between_sites.cs new file mode 100644 index 0000000..ad274fa --- /dev/null +++ b/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_sending_between_sites.cs @@ -0,0 +1,191 @@ +using System; +using System.Threading.Tasks; +using NServiceBus.AcceptanceTesting; +using NUnit.Framework; + +namespace NServiceBus.Router.AcceptanceTests.MultipleRouters +{ + [TestFixture] + public class When_sending_between_sites : NServiceBusAcceptanceTest + { + const string ReceiverEndpoint = "SendingBetweenSites.Receiver"; + + [Test] + public async Task Should_deliver_the_reply_back() + { + var result = await Scenario.Define() + .WithRouter("Green-Yellow", cfg => + { + cfg.AddInterface("Green", false).Broker().Alpha(); + cfg.AddInterface("Yellow", false).Broker().Bravo(); + + var routeTable = cfg.UseStaticRoutingProtocol(); + routeTable.AddRoute((i, d) => i == "Green" && d.Endpoint == ReceiverEndpoint && d.Site == "Blue", + $"Endpoint = {ReceiverEndpoint} AND Interface = Green AND Site = Blue", + "Yellow-Blue", "Yellow"); + routeTable.AddRoute((i, d) => i == "Green" && d.Endpoint == ReceiverEndpoint && d.Site == "Red", + $"Endpoint = {ReceiverEndpoint} AND Interface = Green AND Site = Red", + "Yellow-Red", "Yellow"); + }) + .WithRouter("Yellow-Blue", cfg => + { + cfg.AddInterface("Yellow", false).Broker().Bravo(); + cfg.AddInterface("Blue", false).Broker().Charlie(); + + var routeTable = cfg.UseStaticRoutingProtocol(); + routeTable.AddForwardRoute("Yellow", "Blue"); + }) + .WithRouter("Yellow-Red", cfg => + { + cfg.AddInterface("Yellow", false).Broker().Bravo(); + cfg.AddInterface("Red", false).Broker().Delta(); + + var routeTable = cfg.UseStaticRoutingProtocol(); + routeTable.AddForwardRoute("Yellow", "Red"); + }) + .WithEndpoint(c => c.When(async s => + { + await SendToSite(s, "Blue").ConfigureAwait(false); + await SendToSite(s, "Red").ConfigureAwait(false); + })) + .WithEndpoint() + .WithEndpoint() + .Done(c => c.BlueRequestReceived + && c.BlueResponseReceived + && c.RedRequestReceived + && c.RedResponseReceived) + .Run(TimeSpan.FromSeconds(30)); + + Assert.IsTrue(result.BlueResponseReceived); + Assert.IsTrue(result.RedResponseReceived); + } + + static Task SendToSite(IMessageSession s, string site) + { + var ops = new SendOptions(); + ops.SendToSites(site); + return s.Send(new MyRequest(), ops); + } + + class Context : ScenarioContext + { + public bool RedRequestReceived { get; set; } + public bool RedResponseReceived { get; set; } + public bool BlueRequestReceived { get; set; } + public bool BlueResponseReceived { get; set; } + } + + class Sender : EndpointConfigurationBuilder + { + public Sender() + { + EndpointSetup(c => + { + c.ConfigureBroker().Alpha(); + + var routing = c.ConfigureRouting(); + var bridge = routing.ConnectToRouter("Green-Yellow"); + bridge.RouteToEndpoint(typeof(MyRequest), ReceiverEndpoint); + }); + } + + class BlueResponseHandler : IHandleMessages + { + Context scenarioContext; + + public BlueResponseHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(BlueResponse response, IMessageHandlerContext context) + { + scenarioContext.BlueResponseReceived = true; + return Task.CompletedTask; + } + } + + class RedResponseHandler : IHandleMessages + { + Context scenarioContext; + + public RedResponseHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(RedResponse request, IMessageHandlerContext context) + { + scenarioContext.RedResponseReceived = true; + return Task.CompletedTask; + } + } + } + + class BlueReceiver : EndpointConfigurationBuilder + { + public BlueReceiver() + { + EndpointSetup(c => + { + c.ConfigureBroker().Charlie(); + }).CustomEndpointName(ReceiverEndpoint); + } + + class MyRequestHandler : IHandleMessages + { + Context scenarioContext; + + public MyRequestHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(MyRequest request, IMessageHandlerContext context) + { + scenarioContext.BlueRequestReceived = true; + return context.Reply(new BlueResponse()); + } + } + } + + class RedReceiver : EndpointConfigurationBuilder + { + public RedReceiver() + { + EndpointSetup(c => + { + c.ConfigureBroker().Delta(); + }).CustomEndpointName(ReceiverEndpoint); + } + + class MyRequestHandler : IHandleMessages + { + Context scenarioContext; + + public MyRequestHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(MyRequest request, IMessageHandlerContext context) + { + scenarioContext.RedRequestReceived = true; + return context.Reply(new RedResponse()); + } + } + } + + class MyRequest : IMessage + { + } + + class BlueResponse : IMessage + { + } + + class RedResponse : IMessage + { + } + } +} diff --git a/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_sending_via_three_routers.cs b/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_sending_via_three_routers.cs new file mode 100644 index 0000000..255eca2 --- /dev/null +++ b/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_sending_via_three_routers.cs @@ -0,0 +1,119 @@ +using System.Threading.Tasks; +using NServiceBus.AcceptanceTesting; +using NUnit.Framework; + +namespace NServiceBus.Router.AcceptanceTests.MultipleRouters +{ + using AcceptanceTesting.Customization; + + [TestFixture] + public class When_sending_via_three_routers : NServiceBusAcceptanceTest + { + [Test] + public async Task Should_deliver_the_reply() + { + var result = await Scenario.Define() + .WithRouter("Green-Blue", cfg => + { + cfg.AddInterface("Green", false).Broker().Alpha(); + cfg.AddInterface("Blue", false).Broker().Bravo(); + + cfg.UseStaticRoutingProtocol().AddForwardRoute("Green", "Blue", "Blue-Red"); + }) + .WithRouter("Blue-Red", cfg => + { + cfg.AddInterface("Blue", false).Broker().Bravo(); + cfg.AddInterface("Red", false).Broker().Charlie(); + + cfg.UseStaticRoutingProtocol().AddForwardRoute("Blue", "Red", "Red-Yellow"); + }) + .WithRouter("Red-Yellow", cfg => + { + cfg.AddInterface("Red", false).Broker().Charlie(); + cfg.AddInterface("Yellow", false).Broker().Delta(); + + cfg.UseStaticRoutingProtocol().AddForwardRoute("Red", "Yellow"); + }) + .WithEndpoint(c => c.When(s => s.Send(new MyRequest()))) + .WithEndpoint() + .Done(c => c.RequestReceived && c.ResponseReceived) + .Run(); + + Assert.IsTrue(result.RequestReceived); + Assert.IsTrue(result.ResponseReceived); + } + + class Context : ScenarioContext + { + public bool RequestReceived { get; set; } + public bool ResponseReceived { get; set; } + } + + class Sender : EndpointConfigurationBuilder + { + public Sender() + { + EndpointSetup(c => + { + c.ConfigureBroker().Alpha(); + + var routing = c.ConfigureRouting(); + var bridge = routing.ConnectToRouter("Green-Blue"); + bridge.RouteToEndpoint(typeof(MyRequest), Conventions.EndpointNamingConvention(typeof(Receiver))); + }); + } + + class MyResponseHandler : IHandleMessages + { + Context scenarioContext; + + public MyResponseHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(MyResponse response, IMessageHandlerContext context) + { + scenarioContext.ResponseReceived = true; + return Task.CompletedTask; + } + } + } + + class Receiver : EndpointConfigurationBuilder + { + public Receiver() + { + EndpointSetup(c => + { + //No bridge configuration needed for reply + c.ConfigureBroker().Delta(); + }); + } + + class MyRequestHandler : IHandleMessages + { + Context scenarioContext; + + public MyRequestHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(MyRequest request, IMessageHandlerContext context) + { + scenarioContext.RequestReceived = true; + return context.Reply(new MyResponse()); + } + } + } + + class MyRequest : IMessage + { + } + + class MyResponse : IMessage + { + } + } +} \ No newline at end of file diff --git a/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_sending_via_two_routers.cs b/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_sending_via_two_routers.cs new file mode 100644 index 0000000..cd5db7b --- /dev/null +++ b/src/NServiceBus.Router.AcceptanceTests/MultipleRouters/When_sending_via_two_routers.cs @@ -0,0 +1,175 @@ +using System; +using System.Threading.Tasks; +using NServiceBus.AcceptanceTesting; +using NUnit.Framework; + +namespace NServiceBus.Router.AcceptanceTests.MultipleRouters +{ + using AcceptanceTesting.Customization; + + [TestFixture] + public class When_sending_via_two_routers : NServiceBusAcceptanceTest + { + [Test] + public async Task Should_deliver_the_reply_back() + { + var result = await Scenario.Define() + .WithRouter("Green-Blue", cfg => + { + cfg.AddInterface("Green", false).Broker().Alpha(); + cfg.AddInterface("Blue", false).Broker().Bravo(); + + var routeTable = cfg.UseStaticRoutingProtocol(); + routeTable.AddForwardRoute("Blue", "Green"); + routeTable.AddForwardRoute("Green", "Blue", "Red-Blue"); + }) + .WithRouter("Red-Blue", cfg => + { + cfg.AddInterface("Blue", false).Broker().Bravo(); + cfg.AddInterface("Red", false).Broker().Charlie(); + + var routeTable = cfg.UseStaticRoutingProtocol(); + routeTable.AddForwardRoute("Blue", "Red"); + routeTable.AddForwardRoute("Red", "Blue", "Green-Blue"); + }) + .WithEndpoint(c => c.When(s => + { + var ops = new SendOptions(); + //ops.SendToSites("Red"); + return s.Send(new GreenRequest(), ops); + })) + .WithEndpoint(c => c.When(s => + { + var ops = new SendOptions(); + //ops.SendToSites("Green"); + return s.Send(new RedRequest(), ops); + })) + .Done(c => c.GreenRequestReceived + && c.GreenResponseReceived + && c.RedRequestReceived + && c.RedResponseReceived) + .Run(TimeSpan.FromSeconds(30)); + + Assert.IsTrue(result.GreenRequestReceived); + Assert.IsTrue(result.GreenResponseReceived); + } + + class Context : ScenarioContext + { + public bool GreenRequestReceived { get; set; } + public bool GreenResponseReceived { get; set; } + public bool RedRequestReceived { get; set; } + public bool RedResponseReceived { get; set; } + } + + class GreenEndpoint : EndpointConfigurationBuilder + { + public GreenEndpoint() + { + EndpointSetup(c => + { + c.ConfigureBroker().Alpha(); + + var routing = c.ConfigureRouting(); + var bridge = routing.ConnectToRouter("Green-Blue"); + bridge.RouteToEndpoint(typeof(GreenRequest), Conventions.EndpointNamingConvention(typeof(RedEndpoint))); + }); + } + + class GreenResponseHandler : IHandleMessages + { + Context scenarioContext; + + public GreenResponseHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(GreenResponse response, IMessageHandlerContext context) + { + scenarioContext.GreenResponseReceived = true; + return Task.CompletedTask; + } + } + + class RedRequestHandler : IHandleMessages + { + Context scenarioContext; + + public RedRequestHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(RedRequest request, IMessageHandlerContext context) + { + scenarioContext.RedRequestReceived = true; + return context.Reply(new RedResponse()); + } + } + } + + class RedEndpoint : EndpointConfigurationBuilder + { + public RedEndpoint() + { + EndpointSetup(c => + { + c.ConfigureBroker().Charlie(); + + var routing = c.ConfigureRouting(); + var bridge = routing.ConnectToRouter("Red-Blue"); + bridge.RouteToEndpoint(typeof(RedRequest), Conventions.EndpointNamingConvention(typeof(GreenEndpoint))); + }); + } + + class RedResponseHandler : IHandleMessages + { + Context scenarioContext; + + public RedResponseHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(RedResponse response, IMessageHandlerContext context) + { + scenarioContext.RedResponseReceived = true; + return Task.CompletedTask; + } + } + + class GreenRequestHandler : IHandleMessages + { + Context scenarioContext; + + public GreenRequestHandler(Context scenarioContext) + { + this.scenarioContext = scenarioContext; + } + + public Task Handle(GreenRequest request, IMessageHandlerContext context) + { + scenarioContext.GreenRequestReceived = true; + return context.Reply(new GreenResponse()); + } + } + } + + class GreenRequest : IMessage + { + } + + class GreenResponse : IMessage + { + } + + class RedRequest : IMessage + { + } + + class RedResponse : IMessage + { + } + } +}