public Configure GetConfiguration(RunDescriptor runDescriptor, EndpointConfiguration endpointConfiguration,
            IConfigurationSource configSource)
        {
            var settings = runDescriptor.Settings;

            var types = GetTypesToUse(endpointConfiguration);

            var transportToUse = settings.GetOrNull("Transport");

            SetupLogging(endpointConfiguration);

            Configure.Features.Enable<Sagas>();

            var config = Configure.With(types)
                                  .DefineEndpointName(endpointConfiguration.EndpointName)
                                  .DefineBuilder(settings.GetOrNull("Builder"))
                                  .CustomConfigurationSource(configSource)
                                  .DefineSerializer(settings.GetOrNull("Serializer"))
                                  .DefineTransport(transportToUse)
                                  .InMemorySagaPersister();

            if (transportToUse == null || transportToUse.Contains("Msmq") || transportToUse.Contains("SqlServer") ||
                transportToUse.Contains("RabbitMq"))
                config.UseInMemoryTimeoutPersister();

            if (transportToUse == null || transportToUse.Contains("Msmq") || transportToUse.Contains("SqlServer"))
                config.InMemorySubscriptionStorage();

            config.InMemorySagaPersister();

            return config.UnicastBus();
        }
        public Configure GetConfiguration(RunDescriptor runDescriptor, EndpointConfiguration endpointConfiguration,
            IConfigurationSource configSource)
        {
            Configure.ScaleOut(_ => _.UseSingleBrokerQueue());

            new Bootstrapper();

            //We need this hack here because by default we include all assemblies minus Plugins but for these tests we need to exclude other tests!
            for (var index = 0; index < Configure.TypesToScan.Count;)
            {
                var type = Configure.TypesToScan[index];

                if (type.Assembly != Assembly.GetExecutingAssembly())
                {
                    index++;
                    continue;
                }

                if (!(type.DeclaringType == endpointConfiguration.BuilderType.DeclaringType ||
                      type.DeclaringType == endpointConfiguration.BuilderType))
                {
                    Configure.TypesToScan.RemoveAt(index);
                }
                else
                {
                    index++;
                }
            }

            LogManager.Configuration = SetupLogging(endpointConfiguration);

            return Configure.Instance;
        }
        public Configure GetConfiguration(RunDescriptor runDescriptor, EndpointConfiguration endpointConfiguration,
            IConfigurationSource configSource)
        {
            var settings = runDescriptor.Settings;

            var types = GetTypesScopedByTestClass(endpointConfiguration);

            var transportToUse = AcceptanceTest.GetTransportIntegrationFromEnvironmentVar();
            SetupLogging(endpointConfiguration);

            Configure.Features.Enable<Sagas>();
            Configure.ScaleOut(_ => _.UseSingleBrokerQueue());

            AddMoreConfig();

            var config = Configure.With(types)
                .DefiningEventsAs(t => typeof(IEvent).IsAssignableFrom(t) || IsExternalContract(t))
                .DefineEndpointName(endpointConfiguration.EndpointName)
                .CustomConfigurationSource(configSource)
                .DefineBuilder(settings.GetOrNull("Builder"));

            SetSerializer(config);

            config
                .DefineTransport(transportToUse)
                .InMemorySagaPersister()
                .UseInMemoryTimeoutPersister();

            if (transportToUse == null || transportToUse is MsmqTransportIntegration || transportToUse is SqlServerTransportIntegration || transportToUse is AzureStorageQueuesTransportIntegration)
            {
                config.InMemorySubscriptionStorage();
            }

            return config.UnicastBus();
        }
        public BusConfiguration GetConfiguration(RunDescriptor runDescriptor, EndpointConfiguration endpointConfiguration, IConfigurationSource configSource, Action<BusConfiguration> configurationBuilderCustomization)
        {
            var settings = runDescriptor.Settings;

            var types = GetTypesToUse(endpointConfiguration);

            var config = new BusConfiguration();
            config.EndpointName(endpointConfiguration.EndpointName);
            config.TypesToScan(types);
            config.CustomConfigurationSource(configSource);
            config.UsePersistence<InMemoryPersistence>();
            config.PurgeOnStartup(true);

            // Plugin a behavior that listens for subscription messages
            config.Pipeline.Register<SubscriptionBehavior.Registration>();
            config.RegisterComponents(c => c.ConfigureComponent<SubscriptionBehavior>(DependencyLifecycle.InstancePerCall));
            
            // Important: you need to make sure that the correct ScenarioContext class is available to your endpoints and tests
            config.RegisterComponents(r =>
            {
                r.RegisterSingleton(runDescriptor.ScenarioContext.GetType(), runDescriptor.ScenarioContext);
                r.RegisterSingleton(typeof(ScenarioContext), runDescriptor.ScenarioContext);
            });

            // Call extra custom action if provided
            if (configurationBuilderCustomization != null)
            {
                configurationBuilderCustomization(config);
            }

            return config;
        }
Example #5
0
        public Result Initialize(RunDescriptor run, EndpointBehaviour endpointBehaviour, IDictionary<Type, string> routingTable, string endpointName)
        {
            try
            {
                behaviour = endpointBehaviour;
                scenarioContext = run.ScenarioContext;
                configuration = ((IEndpointConfigurationFactory)Activator.CreateInstance(endpointBehaviour.EndpointBuilderType)).Get();
                configuration.EndpointName = endpointName;

                if (!string.IsNullOrEmpty(configuration.CustomMachineName))
                {
                    NServiceBus.Support.RuntimeEnvironment.MachineNameAction = () => configuration.CustomMachineName;
                }

                //apply custom config settings
                endpointBehaviour.CustomConfig.ForEach(customAction => customAction(config));
                config = configuration.GetConfiguration(run, routingTable);

                if (scenarioContext != null)
                {
                    config.Configurer.RegisterSingleton(scenarioContext.GetType(), scenarioContext);
                    scenarioContext.ContextPropertyChanged += scenarioContext_ContextPropertyChanged;
                }

                bus = config.CreateBus();

                Configure.Instance.ForInstallationOn<Windows>().Install();

                Task.Factory.StartNew(() =>
                    {
                        while (!stopped)
                        {
                            contextChanged.WaitOne(TimeSpan.FromSeconds(5)); //we spin around each 5 s since the callback mechanism seems to be shaky

                            lock (behaviour)
                            {

                                foreach (var when in behaviour.Whens)
                                {
                                    if (executedWhens.Contains(when.Id))
                                        continue;

                                    if(when.ExecuteAction(scenarioContext, bus))
                                        executedWhens.Add(when.Id);
                                }
                            }
                        }
                    });

                return Result.Success();
            }
            catch (Exception ex)
            {
                Logger.Error("Failed to initalize endpoint " + endpointName, ex);
                return Result.Failure(ex);
            }
        }
        public Configure GetConfiguration(RunDescriptor runDescriptor, EndpointConfiguration endpointConfiguration, IConfigurationSource configSource)
        {
            Configure.Serialization.Xml();

            return Configure.With(AllAssemblies.Except(Assembly.GetExecutingAssembly().FullName))
                            .DefaultBuilder()
                            .UseTransport<Msmq>()
                            .UnicastBus();
        }
Example #7
0
        public void Merge(RunDescriptor descriptorToAdd)
        {
            Key += "." + descriptorToAdd.Key;

            foreach (var setting in descriptorToAdd.Settings)
            {
                Settings[setting.Key] = setting.Value;
            }
        }
Example #8
0
        public async Task Initialize(RunDescriptor run, EndpointBehavior endpointBehavior,
            IDictionary<Type, string> routingTable, string endpointName)
        {
            try
            {
                behavior = endpointBehavior;
                scenarioContext = run.ScenarioContext;
                runSettings = run.Settings;
                var endpointConfigurationFactory = (IEndpointConfigurationFactory)Activator.CreateInstance(endpointBehavior.EndpointBuilderType);
                endpointConfigurationFactory.ScenarioContext = run.ScenarioContext;
                configuration = endpointConfigurationFactory.Get();
                configuration.EndpointName = endpointName;

                if (!string.IsNullOrEmpty(configuration.CustomMachineName))
                {
                    RuntimeEnvironment.MachineNameAction = () => configuration.CustomMachineName;
                }

                //apply custom config settings
                if (configuration.GetConfiguration == null)
                {
                    throw new Exception($"Missing EndpointSetup<T> in the constructor of {endpointName} endpoint.");
                }
                endpointConfiguration = await configuration.GetConfiguration(run, routingTable).ConfigureAwait(false);
                RegisterInheritanceHierarchyOfContextInSettings(scenarioContext);

                endpointBehavior.CustomConfig.ForEach(customAction => customAction(endpointConfiguration, scenarioContext));

                if (configuration.SendOnly)
                {
                    endpointConfiguration.SendOnly();
                }

                startable = await Endpoint.Create(endpointConfiguration).ConfigureAwait(false);

                if (!configuration.SendOnly)
                {
                    var transportInfrastructure = endpointConfiguration.GetSettings().Get<TransportInfrastructure>();
                    scenarioContext.HasNativePubSubSupport = transportInfrastructure.OutboundRoutingPolicy.Publishes == OutboundRoutingType.Multicast;
                }
            }
            catch (Exception ex)
            {
                Logger.Error("Failed to initialize endpoint " + endpointName, ex);
                throw;
            }
        }
        public Configure GetConfiguration(RunDescriptor runDescriptor, EndpointConfiguration endpointConfiguration,
            IConfigurationSource configSource)
        {
            Configure.ScaleOut(_ => _.UseSingleBrokerQueue());

            var configure = Configure.With(GetTypesScopedByTestClass(endpointConfiguration));

            var transportToUse = AcceptanceTest.GetTransportIntegrationFromEnvironmentVar();

            Action action = transportToUse.OnEndpointShutdown;
            SettingsHolder.Set("CleanupTransport", action);

            new Bootstrapper(configure: configure);

            LogManager.Configuration = SetupLogging(endpointConfiguration);

            return Configure.Instance;
        }
        public Configure GetConfiguration(RunDescriptor runDescriptor, EndpointConfiguration endpointConfiguration,
            IConfigurationSource configSource)
        {
            var settings = runDescriptor.Settings;

            var types = GetTypesToUse(endpointConfiguration);

            var transportToUse = AcceptanceTest.GetTransportIntegrationFromEnvironmentVar();
            SetupLogging(endpointConfiguration);

            Configure.Features.Enable<Sagas>();
            Configure.ScaleOut(_ => _.UseSingleBrokerQueue());

            AddMoreConfig();

            var config = Configure.With(types)
                .DefineEndpointName(endpointConfiguration.EndpointName)
                .CustomConfigurationSource(configSource)
                .DefineBuilder(settings.GetOrNull("Builder"))
                .DefineSerializer(settings.GetOrNull("Serializer"))
                .DefineTransport(transportToUse)
                .InMemorySagaPersister();


            if (transportToUse == null || transportToUse is MsmqTransportIntegration || transportToUse is SqlServerTransportIntegration ||
                transportToUse is RabbitMqTransportIntegration)
            {
                config.UseInMemoryTimeoutPersister();
            }

            if (transportToUse == null || transportToUse is MsmqTransportIntegration || transportToUse is SqlServerTransportIntegration)
            {
                config.InMemorySubscriptionStorage();
            }

            config.InMemorySagaPersister();

            return config.UnicastBus();
        }
        static RunResult PerformTestRun(IList<EndpointBehaviour> behaviorDescriptors, IList<IScenarioVerification> shoulds, RunDescriptor runDescriptor, Func<ScenarioContext, bool> done)
        {
            var runResult = new RunResult
                {
                    ScenarioContext = runDescriptor.ScenarioContext
                };

            var runTimer = new Stopwatch();

            runTimer.Start();

            try
            {
                List<ActiveRunner> runners = InitializeRunners(runDescriptor, behaviorDescriptors);

                try
                {
                    runResult.ActiveEndpoints = runners.Select(r => r.EndpointName).ToList();

                    PerformScenarios(runDescriptor,runners, () => done(runDescriptor.ScenarioContext));
                }
                finally
                {
                    UnloadAppDomains(runners);
                }

                runTimer.Stop();

                Parallel.ForEach(runners, runner => shoulds.Where(s => s.ContextType == runDescriptor.ScenarioContext.GetType()).ToList()
                                                           .ForEach(v => v.Verify(runDescriptor.ScenarioContext)));
            }
            catch (Exception ex)
            {
                runResult.Failed = true;
                runResult.Exception = ex;
            }

            runResult.TotalTime = runTimer.Elapsed;

            return runResult;
        }
        static void PerformScenarios(RunDescriptor runDescriptor,IEnumerable<ActiveRunner> runners, Func<bool> done)
        {
            var endpoints = runners.Select(r => r.Instance).ToList();

            StartEndpoints(endpoints);

            runDescriptor.ScenarioContext.EndpointsStarted = true;

            var startTime = DateTime.UtcNow;
            var maxTime = runDescriptor.TestExecutionTimeout;

            Task.WaitAll(endpoints.Select(endpoint => Task.Factory.StartNew(() => SpinWait.SpinUntil(done, maxTime))).Cast<Task>().ToArray(), maxTime);

            try
            {
                if ((DateTime.UtcNow - startTime) > maxTime)
                {
                    throw new ScenarioException(GenerateTestTimedOutMessage(endpoints, maxTime));
                }
            }
            finally
            {
                StopEndpoints(endpoints);
            }
        }
        static List<ActiveRunner> InitializeRunners(RunDescriptor runDescriptor, IList<EndpointBehaviour> behaviorDescriptors)
        {
            var runners = new List<ActiveRunner>();
            var routingTable = CreateRoutingTable(runDescriptor, behaviorDescriptors);

            foreach (var behaviorDescriptor in behaviorDescriptors)
            {
                var endpointName = GetEndpointNameForRun(runDescriptor, behaviorDescriptor);
                var runner = PrepareRunner(endpointName, behaviorDescriptor.AppConfig);
                var result = runner.Instance.Initialize(runDescriptor, behaviorDescriptor, routingTable, endpointName);

                // Extend the lease to the timeout value specified.
                ILease serverLease = (ILease)RemotingServices.GetLifetimeService(runner.Instance);

                // Add the execution time + additional time for the endpoints to be able to stop gracefully
                var totalLifeTime = runDescriptor.TestExecutionTimeout.Add(TimeSpan.FromMinutes(2));
                serverLease.Renew(totalLifeTime);

                if (result.Failed)
                {
                    throw new ScenarioException(string.Format("Endpoint {0} failed to initialize - {1}", runner.Instance.Name(), result.ExceptionMessage));
                }

                runners.Add(runner);
            }

            return runners;
        }
 static string GetEndpointNameForRun(RunDescriptor runDescriptor, EndpointBehaviour endpointBehaviour)
 {
     var endpointName = Conventions.EndpointNamingConvention(endpointBehaviour.EndpointBuilderType) + "." +
                        runDescriptor.Key;
     return endpointName;
 }
        static IDictionary<Type, string> CreateRoutingTable(RunDescriptor runDescriptor, IEnumerable<EndpointBehaviour> behaviorDescriptors)
        {
            var routingTable = new Dictionary<Type, string>();

            foreach (var behaviorDescriptor in behaviorDescriptors)
            {
                routingTable[behaviorDescriptor.EndpointBuilderType] = GetEndpointNameForRun(runDescriptor, behaviorDescriptor);
            }

            return routingTable;
        }
Example #16
0
        static List<ActiveRunner> InitializeRunners(RunDescriptor runDescriptor, IList<EndpointBehavior> behaviorDescriptors)
        {
            var runners = new List<ActiveRunner>();
            var routingTable = CreateRoutingTable(behaviorDescriptors);

            foreach (var behaviorDescriptor in behaviorDescriptors)
            {
                var endpointName = GetEndpointNameForRun(behaviorDescriptor);

                if (endpointName.Length > 77)
                {
                    throw new Exception(string.Format("Endpoint name '{0}' is larger than 77 characters and will cause issues with MSMQ queue names. Please rename your test class or endpoint!",endpointName));
                }

                var runner = PrepareRunner(endpointName, behaviorDescriptor.AppConfig, runDescriptor.UseSeparateAppdomains);
                var result = runner.Instance.Initialize(runDescriptor, behaviorDescriptor, routingTable, endpointName);

                if (runDescriptor.UseSeparateAppdomains)
                {
                    // Extend the lease to the timeout value specified.
                    var serverLease = (ILease)RemotingServices.GetLifetimeService(runner.Instance);

                    // Add the execution time + additional time for the endpoints to be able to stop gracefully
                    var totalLifeTime = runDescriptor.TestExecutionTimeout.Add(TimeSpan.FromMinutes(2));
                    serverLease.Renew(totalLifeTime);
                }

                if (result.Failed)
                {
                    throw new ScenarioException(string.Format("Endpoint {0} failed to initialize", runner.Instance.Name()), result.Exception);
                }

                runners.Add(runner);
            }

            return runners;
        }
Example #17
0
        static async Task<RunResult> PerformTestRun(List<EndpointBehavior> behaviorDescriptors, List<IScenarioVerification> shoulds, RunDescriptor runDescriptor, Func<ScenarioContext, bool> done)
        {
            var runResult = new RunResult
            {
                ScenarioContext = runDescriptor.ScenarioContext
            };

            var runTimer = new Stopwatch();
            runTimer.Start();

            try
            {
                var endpoints = await InitializeRunners(runDescriptor, behaviorDescriptors).ConfigureAwait(false);

                runResult.ActiveEndpoints = endpoints.Select(r => r.EndpointName).ToList();

                await PerformScenarios(runDescriptor, endpoints, () => done(runDescriptor.ScenarioContext)).ConfigureAwait(false);

                runTimer.Stop();

                foreach (var v in shoulds.Where(s => s.ContextType == runDescriptor.ScenarioContext.GetType()))
                {
                    v.Verify(runDescriptor.ScenarioContext);
                }
            }
            catch (Exception ex)
            {
                runResult.Failed = true;
                runResult.Exception = ex;
            }

            runResult.TotalTime = runTimer.Elapsed;

            return runResult;
        }
Example #18
0
 protected bool Equals(RunDescriptor other)
 {
     return string.Equals(Key, other.Key);
 }
Example #19
0
        static async Task PerformScenarios(RunDescriptor runDescriptor, IEnumerable<ActiveRunner> runners, Func<bool> done)
        {
            using (var cts = new CancellationTokenSource())
            {
                var endpoints = runners.Select(r => r.Instance).ToList();

                // ReSharper disable once LoopVariableIsNeverChangedInsideLoop
                try
                {
                    await StartEndpoints(endpoints, cts).ConfigureAwait(false);
                    runDescriptor.ScenarioContext.EndpointsStarted = true;
                    await ExecuteWhens(endpoints, cts).ConfigureAwait(false);

                    var startTime = DateTime.UtcNow;
                    var maxTime = runDescriptor.Settings.TestExecutionTimeout ?? TimeSpan.FromSeconds(90);
                    while (!done() && !cts.Token.IsCancellationRequested)
                    {
                        if (DateTime.UtcNow - startTime > maxTime)
                        {
                            ThrowOnFailedMessages(runDescriptor, endpoints);
                            throw new TimeoutException(GenerateTestTimedOutMessage(maxTime));
                        }

                        await Task.Delay(1).ConfigureAwait(false);
                    }

                    startTime = DateTime.UtcNow;
                    var unfinishedFailedMessagesMaxWaitTime = TimeSpan.FromSeconds(30);
                    while (runDescriptor.ScenarioContext.UnfinishedFailedMessages.Values.Any(x => x))
                    {
                        if (DateTime.UtcNow - startTime > unfinishedFailedMessagesMaxWaitTime)
                        {
                            throw new Exception("Some failed messages were not handled by the recoverability feature.");
                        }

                        await Task.Delay(1).ConfigureAwait(false);
                    }
                }
                finally
                {
                    await StopEndpoints(endpoints).ConfigureAwait(false);
                }

                ThrowOnFailedMessages(runDescriptor, endpoints);
            }
        }
Example #20
0
 public RunDescriptor(RunDescriptor template)
 {
     Settings = template.Settings.ToDictionary(entry => entry.Key,
                                               entry => entry.Value);
     Key = template.Key;
 }
Example #21
0
        static void ThrowOnFailedMessages(RunDescriptor runDescriptor, List<EndpointRunner> endpoints)
        {
            var unexpectedFailedMessages = runDescriptor.ScenarioContext.FailedMessages
                .Where(kvp => endpoints.Single(e => e.Name() == kvp.Key).FailOnErrorMessage)
                .SelectMany(kvp => kvp.Value)
                .ToList();

            if (unexpectedFailedMessages.Any())
            {
                throw new MessagesFailedException(unexpectedFailedMessages, runDescriptor.ScenarioContext);
            }
        }
Example #22
0
        static async Task<ActiveRunner[]> InitializeRunners(RunDescriptor runDescriptor, List<EndpointBehavior> endpointBehaviors)
        {
            var routingTable = CreateRoutingTable(endpointBehaviors);

            var runnerInitializations = endpointBehaviors.Select(async endpointBehavior =>
            {
                var endpointName = GetEndpointNameForRun(endpointBehavior);

                if (endpointName.Length > 77)
                {
                    throw new Exception($"Endpoint name '{endpointName}' is larger than 77 characters and will cause issues with MSMQ queue names. Rename the test class or endpoint.");
                }

                var runner = new ActiveRunner
                {
                    Instance = new EndpointRunner(),
                    EndpointName = endpointName
                };

                try
                {
                    await runner.Instance.Initialize(runDescriptor, endpointBehavior, routingTable, endpointName).ConfigureAwait(false);
                }
                catch (Exception)
                {
                    Console.WriteLine($"Endpoint {runner.Instance.Name()} failed to initialize");
                    throw;
                }

                return runner;
            });

            try
            {
                var x = await Task.WhenAll(runnerInitializations).ConfigureAwait(false);
                return x;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }
Example #23
0
        static RunResult PerformTestRun(IList<EndpointBehavior> behaviorDescriptors, IList<IScenarioVerification> shoulds, RunDescriptor runDescriptor, Func<ScenarioContext, bool> done, Func<Exception, bool> allowedExceptions)
        {
            var runResult = new RunResult
            {
                ScenarioContext = runDescriptor.ScenarioContext
            };

            var runTimer = new Stopwatch();

            runTimer.Start();

            try
            {
                var runners = InitializeRunners(runDescriptor, behaviorDescriptors);

                try
                {
                    runResult.ActiveEndpoints = runners.Select(r => r.EndpointName).ToList();

                    PerformScenarios(runDescriptor, runners, () =>
                    {
                        if (!string.IsNullOrEmpty(runDescriptor.ScenarioContext.Exceptions))
                        {
                            var ex = new Exception(runDescriptor.ScenarioContext.Exceptions);
                            if (!allowedExceptions(ex))
                            {
                                throw new Exception("Failures in endpoints");
                            }
                        }
                        return done(runDescriptor.ScenarioContext);
                    });
                }
                finally
                {
                    if (runDescriptor.UseSeparateAppdomains)
                    {
                        UnloadAppDomains(runners);
                    }
                }

                runTimer.Stop();

                Parallel.ForEach(runners, runner =>
                {
                    foreach (var v in shoulds.Where(s => s.ContextType == runDescriptor.ScenarioContext.GetType()))
                    {
                        v.Verify(runDescriptor.ScenarioContext);
                    }
                });
            }
            catch (Exception ex)
            {
                runResult.Failed = true;
                runResult.Exception = ex;
            }

            runResult.TotalTime = runTimer.Elapsed;

            return runResult;
        }
Example #24
0
        public Result Initialize(RunDescriptor run, EndpointBehavior endpointBehavior,
            IDictionary<Type, string> routingTable, string endpointName)
        {
            try
            {
                runDescriptor = run;
                behavior = endpointBehavior;
                scenarioContext = run.ScenarioContext;
                configuration =
                    ((IEndpointConfigurationFactory)Activator.CreateInstance(endpointBehavior.EndpointBuilderType))
                        .Get();
                configuration.EndpointName = endpointName;

                if (!string.IsNullOrEmpty(configuration.CustomMachineName))
                {
                    RuntimeEnvironment.MachineNameAction = () => configuration.CustomMachineName;
                }

                //apply custom config settings
                var busConfiguration = configuration.GetConfiguration(run, routingTable);

                scenarioContext.ContextPropertyChanged += scenarioContext_ContextPropertyChanged;

                endpointBehavior.CustomConfig.ForEach(customAction => customAction(busConfiguration));

                if (configuration.SendOnly)
                {
                    sendOnlyBus = Bus.CreateSendOnly(busConfiguration);
                }
                else
                {
                    bus = Bus.Create(busConfiguration);
                    var transportDefinition = ((UnicastBus)bus).Settings.Get<TransportDefinition>();

                    scenarioContext.HasNativePubSubSupport = transportDefinition.HasNativePubSubSupport;
                }


                executeWhens = Task.Factory.StartNew(() =>
                {
                    while (!stopped)
                    {
                        //we spin around each 5s since the callback mechanism seems to be shaky
                        contextChanged.Wait(TimeSpan.FromSeconds(5));

                        lock (behavior)
                        {
                            foreach (var when in behavior.Whens)
                            {
                                if (executedWhens.Contains(when.Id))
                                {
                                    continue;
                                }

                                if (when.ExecuteAction(scenarioContext, bus))
                                {
                                    executedWhens.Add(when.Id);
                                }
                            }
                        }
                    }
                });

                return Result.Success();
            }
            catch (Exception ex)
            {
                Logger.Error("Failed to initialize endpoint " + endpointName, ex);
                return Result.Failure(ex);
            }
        }
        public Result Initialize(RunDescriptor run, EndpointBehavior endpointBehavior,
            IDictionary<Type, string> routingTable, string endpointName)
        {
            try
            {
                behavior = endpointBehavior;
                scenarioContext = run.ScenarioContext;
                configuration =
                    ((IEndpointConfigurationFactory) Activator.CreateInstance(endpointBehavior.EndpointBuilderType))
                        .Get();
                configuration.EndpointName = endpointName;

                if (!string.IsNullOrEmpty(configuration.CustomMachineName))
                {
                    RuntimeEnvironment.MachineNameAction = () => configuration.CustomMachineName;
                }

                //apply custom config settings
                endpointBehavior.CustomConfig.ForEach(customAction => customAction(config));
                config = configuration.GetConfiguration(run, routingTable);

                if (scenarioContext != null)
                {
                    config.Configurer.RegisterSingleton(scenarioContext.GetType(), scenarioContext);
                    scenarioContext.ContextPropertyChanged += scenarioContext_ContextPropertyChanged;
                }

                bus = config.CreateBus();

                Configure.Instance.ForInstallationOn<Windows>().Install();

                stopToken = stopSource.Token;

                if (behavior.Whens.Count == 0)
                {
                    executeWhens = Task.FromResult(0);
                }
                else
                {
                    executeWhens = Task.Factory.StartNew(async () =>
                    {
                        var executedWhens = new List<Guid>();

                        while (!stopToken.IsCancellationRequested)
                        {
                            if (executedWhens.Count == behavior.Whens.Count)
                            {
                                break;
                            }

                            //we spin around each 5s since the callback mechanism seems to be shaky
                            await contextChanged.WaitAsync(TimeSpan.FromSeconds(5), stopToken);

                            if (stopToken.IsCancellationRequested)
                                break;

                            foreach (var when in behavior.Whens)
                            {
                                if (executedWhens.Contains(when.Id))
                                {
                                    continue;
                                }

                                if (when.ExecuteAction(scenarioContext, bus))
                                {
                                    executedWhens.Add(when.Id);
                                }
                            }
                        }
                    }, stopToken).Unwrap();
                }

                return Result.Success();
            }
            catch (Exception ex)
            {
                Logger.Error("Failed to initialize endpoint " + endpointName, ex);
                return Result.Failure(ex);
            }
        }