public void Activate_is_not_called_until_dependencies_return_true() { var activations = 0; var notifications = new List <bool>(); var subject = new BehaviorSubject <bool>(false); var activator = new FeatureActivator(() => activations++, dependsOn: subject); disposables.Add(activator.Subscribe(notifications.Add)); Assert.That(activations, Is.EqualTo(0)); Assert.That(notifications.IsSameSequenceAs(false)); subject.OnNext(false); Assert.That(activations, Is.EqualTo(0)); Assert.That(notifications.IsSameSequenceAs(false)); subject.OnNext(true); Assert.That(activations, Is.EqualTo(1)); Assert.That(notifications.IsSameSequenceAs(false, true)); disposables.Add(activator.Subscribe(notifications.Add)); Assert.That(activations, Is.EqualTo(1)); Assert.That(notifications.IsSameSequenceAs(false, true, true)); }
public void Should_activate_upstream_dependencies_first() { var order = new List <Feature>(); var dependingFeature = new DependsOnOne_Feature { OnActivation = f => order.Add(f) }; var feature = new MyFeature1 { OnActivation = f => order.Add(f) }; var settings = new SettingsHolder(); var featureSettings = new FeatureActivator(settings); featureSettings.Add(dependingFeature); featureSettings.Add(feature); settings.EnableFeatureByDefault <MyFeature1>(); featureSettings.SetupFeatures(new FakeFeatureConfigurationContext()); Assert.True(dependingFeature.IsActive); Assert.IsInstanceOf <MyFeature1>(order.First(), "Upstream dependencies should be activated first"); }
public void Is_available_by_default() { var activated = false; var activator = new FeatureActivator(() => { activated = true; }); Assert.That(activator.First(), Is.True); Assert.That(activated); }
public void When_there_are_multiple_dependencies_they_must_all_return_true_before_Activate_is_called() { var activations = 0; var dependency1 = new BehaviorSubject <bool>(false); var dependency2 = new BehaviorSubject <bool>(false); var activator = new FeatureActivator( activate: () => activations++, dependsOn: new[] { dependency1, dependency2 }); var notifications = new List <bool>(); disposables.Add(activator.Subscribe(notifications.Add)); Assert.That(activations, Is.EqualTo(0)); Assert.That(notifications.IsSameSequenceAs(false)); dependency1.OnNext(true); Assert.That(activations, Is.EqualTo(0)); Assert.That(notifications.IsSameSequenceAs(false)); dependency2.OnNext(true); Assert.That(activations, Is.EqualTo(1)); Assert.That(notifications.IsSameSequenceAs(false, true)); }
public void Activate_is_not_called_more_than_once_during_concurrent_calls_when_activator_has_no_dependencies() { var activations = 0; var notifications = 0; var barrier = new Barrier(2); var activator = new FeatureActivator(() => { Interlocked.Increment(ref activations); barrier.SignalAndWait(); }); for (var i = 0; i < 10; i++) { disposables.Add(activator .ObserveOn(NewThreadScheduler.Default) .SubscribeOn(NewThreadScheduler.Default) .Subscribe(n => { Console.WriteLine(Thread.CurrentThread.ManagedThreadId); Interlocked.Increment(ref notifications); })); } // give both subscribers enough time to make sure one has advanced to the activator barrier Thread.Sleep(500); barrier.SignalAndWait(); // give them enough time to propagate their notifications Thread.Sleep(500); Assert.That(activations, Is.EqualTo(1)); Assert.That(notifications, Is.EqualTo(10)); }
public ActivatableFeature(params IObservable <bool>[] dependsOn) { availability = new FeatureActivator( Activate, Deactivate, dependsOn); }
public void Should_activate_all_upstream_deps_when_chain_deep() { var defaultsOrder = new List <Feature>(); var level1 = new Level1 { OnDefaults = f => defaultsOrder.Add(f) }; var level2 = new Level2 { OnDefaults = f => defaultsOrder.Add(f) }; var level3 = new Level3 { OnDefaults = f => defaultsOrder.Add(f) }; var settings = new SettingsHolder(); var featureSettings = new FeatureActivator(settings); //the orders matter here to expose a bug featureSettings.Add(level3); featureSettings.Add(level2); featureSettings.Add(level1); featureSettings.SetupFeatures(new FeatureConfigurationContext(null)); Assert.True(level1.IsActive, "Level1 wasn't activated"); Assert.True(level2.IsActive, "Level2 wasn't activated"); Assert.True(level3.IsActive, "Level3 wasn't activated"); Assert.IsInstanceOf <Level1>(defaultsOrder[0], "Upstream deps should be activated first"); Assert.IsInstanceOf <Level2>(defaultsOrder[1], "Upstream deps should be activated first"); Assert.IsInstanceOf <Level3>(defaultsOrder[2], "Upstream deps should be activated first"); }
internal void Initialize() { WireUpConfigSectionOverrides(); featureActivator = new FeatureActivator(Settings); configurer.RegisterSingleton(featureActivator); ForAllTypes <Feature>(TypesToScan, t => featureActivator.Add(t.Construct <Feature>())); ForAllTypes <IWantToRunWhenConfigurationIsComplete>(TypesToScan, t => configurer.ConfigureComponent(t, DependencyLifecycle.InstancePerCall)); ForAllTypes <IWantToRunWhenBusStartsAndStops>(TypesToScan, t => configurer.ConfigureComponent(t, DependencyLifecycle.InstancePerCall)); ActivateAndInvoke <IWantToRunBeforeConfigurationIsFinalized>(TypesToScan, t => t.Run(this)); var featureStats = featureActivator.SetupFeatures(new FeatureConfigurationContext(this)); configurer.RegisterSingleton(featureStats); featureActivator.RegisterStartupTasks(configurer); localAddress = Settings.LocalAddress(); foreach (var o in Builder.BuildAll <IWantToRunWhenConfigurationIsComplete>()) { o.Run(this); } }
public void Should_activate_named_dependency_first() { var order = new List<Feature>(); var dependingFeature = new DependsOnOneByName_Feature { OnActivation = f => order.Add(f) }; var feature = new MyFeature2 { OnActivation = f => order.Add(f) }; var settings = new SettingsHolder(); var featureSettings = new FeatureActivator(settings); featureSettings.Add(dependingFeature); featureSettings.Add(feature); settings.EnableFeatureByDefault<MyFeature2>(); featureSettings.SetupFeatures(null, null, null, null); Assert.True(dependingFeature.IsActive); Assert.IsInstanceOf<MyFeature2>(order.First(), "Upstream dependencies should be activated first"); }
public ActivatableFeature(params IObservable<bool>[] dependsOn) { availability = new FeatureActivator( Activate, Deactivate, dependsOn); }
public StartableEndpoint(SettingsHolder settings, IBuilder builder, FeatureActivator featureActivator, PipelineConfiguration pipelineConfiguration, IReadOnlyCollection <IWantToRunWhenBusStartsAndStops> startables) { this.settings = settings; this.builder = builder; this.featureActivator = featureActivator; this.pipelineConfiguration = pipelineConfiguration; this.startables = startables; }
protected OnOffFeature(bool @on) { availability = new BehaviorSubject<bool>(@on); activator = new FeatureActivator( Activate, Deactivate, availability); }
public void RegisterFeatureEnabledStatusInSettings(List <Type> concreteTypes) { featureActivator = new FeatureActivator(settings); foreach (var type in concreteTypes.Where(t => IsFeature(t))) { featureActivator.Add(type.Construct <Feature>()); } }
FeatureActivator BuildFeatureActivator(IEnumerable<Type> concreteTypes) { var featureActivator = new FeatureActivator(settings); foreach (var type in concreteTypes.Where(IsFeature)) { featureActivator.Add(type.Construct<Feature>()); } return featureActivator; }
public void RegisterFeatureEnabledStatusInSettings(HostingComponent.Configuration hostingConfiguration) { featureActivator = new FeatureActivator(settings); foreach (var type in hostingConfiguration.AvailableTypes.Where(t => IsFeature(t))) { featureActivator.Add(type.Construct <Feature>()); } }
public StartableEndpoint(SettingsHolder settings, IBuilder builder, FeatureActivator featureActivator, TransportInfrastructure transportInfrastructure, ReceiveComponent receiveComponent, CriticalError criticalError, IMessageSession messageSession) { this.criticalError = criticalError; this.settings = settings; this.builder = builder; this.featureActivator = featureActivator; this.transportInfrastructure = transportInfrastructure; this.receiveComponent = receiveComponent; this.messageSession = messageSession; }
FeatureActivator BuildFeatureActivator(IEnumerable <Type> concreteTypes) { var featureActivator = new FeatureActivator(settings); foreach (var type in concreteTypes.Where(t => IsFeature(t))) { featureActivator.Add(type.Construct <Feature>()); } return(featureActivator); }
public void Should_only_activate_features_if_dependencies_are_met(FeatureCombinations setup) { var featureSettings = new FeatureActivator(new SettingsHolder()); var dependingFeature = setup.DependingFeature; featureSettings.Add(dependingFeature); Array.ForEach(setup.AvailableFeatures, featureSettings.Add); featureSettings.SetupFeatures(null, null, null, null); Assert.AreEqual(setup.ShouldBeActive, dependingFeature.IsActive); }
public void Should_register_defaults_if_feature_is_activated() { var settings = new SettingsHolder(); var featureSettings = new FeatureActivator(settings); featureSettings.Add(new MyFeatureWithDefaults()); featureSettings.SetupFeatures(new FeatureConfigurationContext(null)); Assert.True(settings.HasSetting("Test1")); }
public void When_there_are_multiple_subscribers_then_activate_is_not_called_repeatedly() { var activations = 0; var activator = new FeatureActivator(() => activations++); disposables.Add(activator.Subscribe(_ => { })); disposables.Add(activator.Subscribe(_ => { })); disposables.Add(activator.Subscribe(_ => { })); Assert.That(activations, Is.EqualTo(1)); }
public void Should_not_register_defaults_if_feature_is_not_activated() { var settings = new SettingsHolder(); var featureSettings = new FeatureActivator(settings); featureSettings.Add(new MyFeatureWithDefaultsNotActive()); featureSettings.Add(new MyFeatureWithDefaultsNotActiveDueToUnsatisfiedPrerequisite()); featureSettings.SetupFeatures(new FeatureConfigurationContext(null)); Assert.False(settings.HasSetting("Test1")); Assert.False(settings.HasSetting("Test2")); }
public StartableEndpoint(SettingsHolder settings, IBuilder builder, FeatureActivator featureActivator, PipelineConfiguration pipelineConfiguration, IEventAggregator eventAggregator, TransportInfrastructure transportInfrastructure, CriticalError criticalError) { this.criticalError = criticalError; this.settings = settings; this.builder = builder; this.featureActivator = featureActivator; this.pipelineConfiguration = pipelineConfiguration; this.eventAggregator = eventAggregator; this.transportInfrastructure = transportInfrastructure; pipelineCache = new PipelineCache(builder, settings); messageSession = new MessageSession(new RootContext(builder, pipelineCache, eventAggregator)); }
public void Deactivate_is_not_called_until_after_activate_has_been_called() { var deactivations = 0; var subject = new BehaviorSubject <bool>(false); var activator = new FeatureActivator(() => { }, () => deactivations++, dependsOn: subject); disposables.Add(activator.Subscribe(_ => { })); subject.OnNext(true); Assert.That(deactivations, Is.EqualTo(0)); subject.OnNext(false); Assert.That(deactivations, Is.EqualTo(1)); }
public void Should_not_activate_features_with_unmet_dependencies() { var feature = new FeatureWithStartupTask(); var featureSettings = new FeatureActivator(new SettingsHolder()); featureSettings.Add(feature); var builder = new FakeBuilder(typeof(FeatureWithStartupTask.Runner)); featureSettings.SetupFeatures(new FeatureConfigurationContext(null)); featureSettings.StartFeatures(builder); featureSettings.StopFeatures(builder); Assert.True(FeatureWithStartupTask.Runner.Started); Assert.True(FeatureWithStartupTask.Runner.Stopped); }
public void Should_check_prerequisites() { var featureWithTrueCondition = new MyFeatureWithSatisfiedPrerequisite(); var featureWithFalseCondition = new MyFeatureWithUnsatisfiedPrerequisite(); var featureSettings = new FeatureActivator(new SettingsHolder()); featureSettings.Add(featureWithTrueCondition); featureSettings.Add(featureWithFalseCondition); featureSettings.SetupFeatures(new FeatureConfigurationContext(null)); Assert.True(featureWithTrueCondition.IsActive); Assert.False(featureWithFalseCondition.IsActive); Assert.AreEqual("The description", featureSettings.Status.Single(s => s.Name == featureWithFalseCondition.Name).PrerequisiteStatus.Reasons.First()); }
public void Should_enable_features_in_defaults() { var defaultsOrder = new List <Feature>(); var activatedOrder = new List <Feature>(); var level1 = new Activate1 { OnActivation = f => activatedOrder.Add(f), OnDefaults = f => defaultsOrder.Add(f) }; var level2 = new Activate2 { OnActivation = f => activatedOrder.Add(f), OnDefaults = f => defaultsOrder.Add(f) }; var level3 = new Activate3 { OnActivation = f => activatedOrder.Add(f), OnDefaults = f => defaultsOrder.Add(f) }; var settings = new SettingsHolder(); var featureSettings = new FeatureActivator(settings); //the orders matter here to expose a bug featureSettings.Add(level3); featureSettings.Add(level2); featureSettings.Add(level1); featureSettings.SetupFeatures(new FeatureConfigurationContext(null)); Assert.True(level1.IsActive, "Activate1 wasn't activated"); Assert.True(level2.IsActive, "Activate2 wasn't activated"); Assert.True(level3.IsActive, "Activate3 wasn't activated"); Assert.IsInstanceOf <Activate1>(defaultsOrder[0], "Upstream deps should be activated first"); Assert.IsInstanceOf <Activate2>(defaultsOrder[1], "Upstream deps should be activated first"); Assert.IsInstanceOf <Activate3>(defaultsOrder[2], "Upstream deps should be activated first"); CollectionAssert.AreEqual(defaultsOrder, activatedOrder); }
public void Should_activate_all_upstream_dependencies_first() { var order = new List<Feature>(); var dependingFeature = new DependsOnAtLeastOne_Feature { OnActivation = f => order.Add(f) }; var feature = new MyFeature1 { OnActivation = f => order.Add(f) }; var feature2 = new MyFeature2 { OnActivation = f => order.Add(f) }; var feature3 = new MyFeature3 { OnActivation = f => order.Add(f) }; var settings = new SettingsHolder(); var featureSettings = new FeatureActivator(settings); featureSettings.Add(dependingFeature); featureSettings.Add(feature); featureSettings.Add(feature2); featureSettings.Add(feature3); settings.EnableFeatureByDefault<MyFeature1>(); settings.EnableFeatureByDefault<MyFeature2>(); settings.EnableFeatureByDefault<MyFeature3>(); featureSettings.SetupFeatures(null, null, null, null); Assert.True(dependingFeature.IsActive); Assert.IsInstanceOf<MyFeature1>(order[0], "Upstream dependencies should be activated first"); Assert.IsInstanceOf<MyFeature2>(order[1], "Upstream dependencies should be activated first"); Assert.IsInstanceOf<MyFeature3>(order[2], "Upstream dependencies should be activated first"); }
public void Produces_a_value_each_time_the_aggregate_availability_of_dependencies_changes() { var dependency = new BehaviorSubject<bool>(false); var activator = new FeatureActivator(() => { }, dependsOn: dependency); var notifications = new List<bool>(); disposables.Add(activator.Subscribe(notifications.Add)); dependency.OnNext(false); dependency.OnNext(false); dependency.OnNext(true); dependency.OnNext(true); dependency.OnNext(true); dependency.OnNext(true); dependency.OnNext(false); dependency.OnNext(false); dependency.OnNext(false); Assert.That(notifications.IsSameSequenceAs(false, true, false)); }
public void Produces_a_value_each_time_the_aggregate_availability_of_dependencies_changes() { var dependency = new BehaviorSubject <bool>(false); var activator = new FeatureActivator(() => { }, dependsOn: dependency); var notifications = new List <bool>(); disposables.Add(activator.Subscribe(notifications.Add)); dependency.OnNext(false); dependency.OnNext(false); dependency.OnNext(true); dependency.OnNext(true); dependency.OnNext(true); dependency.OnNext(true); dependency.OnNext(false); dependency.OnNext(false); dependency.OnNext(false); Assert.That(notifications.IsSameSequenceAs(false, true, false)); }
public void Should_throw_exception_when_dependency_cycle_is_found() { var order = new List<Feature>(); var level1 = new CycleLevel1 { OnActivation = f => order.Add(f) }; var level2 = new CycleLevel2 { OnActivation = f => order.Add(f) }; var settings = new SettingsHolder(); var featureSettings = new FeatureActivator(settings); featureSettings.Add(level1); featureSettings.Add(level2); Assert.Throws<ArgumentException>(() => featureSettings.SetupFeatures(null, null, null, null)); }
public void When_any_dependency_produces_false_then_deactivate_is_called() { var deactivations = 0; var dependency1 = new BehaviorSubject <bool>(true); var dependency2 = new BehaviorSubject <bool>(true); var activator = new FeatureActivator( activate: () => { }, deactivate: () => deactivations++, dependsOn: new[] { dependency1, dependency2 }); var notifications = new List <bool>(); disposables.Add(activator.Subscribe(notifications.Add)); Assert.That(deactivations, Is.EqualTo(0)); Assert.That(notifications.IsSameSequenceAs(true)); dependency1.OnNext(false); Assert.That(deactivations, Is.EqualTo(1)); Assert.That(notifications.IsSameSequenceAs(true, false)); }
public void Activate_is_not_called_more_than_once_during_concurrent_calls_when_activator_has_dependencies() { var activations = 0; var notifications = 0; var barrier = new Barrier(2); var subject = new BehaviorSubject <bool>(false); var activator = new FeatureActivator(() => { Console.WriteLine("activated!"); Interlocked.Increment(ref activations); barrier.SignalAndWait(); }, dependsOn: subject); for (var i = 0; i < 10; i++) { disposables.Add(activator .ObserveOn(NewThreadScheduler.Default) .SubscribeOn(NewThreadScheduler.Default) .Subscribe(n => { Console.WriteLine(Thread.CurrentThread.ManagedThreadId); Interlocked.Increment(ref notifications); })); } new Thread(() => subject.OnNext(true)).Start(); // give both subscribers enough time to make sure one has advanced to the activator barrier Thread.Sleep(1000); barrier.SignalAndWait(3000); // give them enough time to propagate their notifications Thread.Sleep(1000); Assert.That(notifications, Is.AtLeast(10)); // sanity check Assert.That(activations, Is.EqualTo(1)); }
public void Should_not_activate_feature_when_named_dependency_disabled() { var order = new List<Feature>(); var dependingFeature = new DependsOnOneByName_Feature { OnActivation = f => order.Add(f) }; var feature = new MyFeature2 { OnActivation = f => order.Add(f) }; var settings = new SettingsHolder(); var featureSettings = new FeatureActivator(settings); featureSettings.Add(dependingFeature); featureSettings.Add(feature); featureSettings.SetupFeatures(null, null, null, null); Assert.False(dependingFeature.IsActive); Assert.IsEmpty(order); }
public static NamedServiceContainer.ActivationCallback Create(Type type) { FeatureActivator activator = new FeatureActivator(type); return new NamedServiceContainer.ActivationCallback(activator.Activate); }
protected SingleActivationFeature() { activator = new FeatureActivator(Activate, dependsOn: Observable.Return(IsAvailable)); }
public void Activate_is_not_called_until_dependencies_return_true() { var activations = 0; var notifications = new List<bool>(); var subject = new BehaviorSubject<bool>(false); var activator = new FeatureActivator(() => activations++, dependsOn: subject); disposables.Add(activator.Subscribe(notifications.Add)); Assert.That(activations, Is.EqualTo(0)); Assert.That(notifications.IsSameSequenceAs(false)); subject.OnNext(false); Assert.That(activations, Is.EqualTo(0)); Assert.That(notifications.IsSameSequenceAs(false)); subject.OnNext(true); Assert.That(activations, Is.EqualTo(1)); Assert.That(notifications.IsSameSequenceAs(false, true)); disposables.Add(activator.Subscribe(notifications.Add)); Assert.That(activations, Is.EqualTo(1)); Assert.That(notifications.IsSameSequenceAs(false, true, true)); }
public void When_there_are_multiple_dependencies_they_must_all_return_true_before_Activate_is_called() { var activations = 0; var dependency1 = new BehaviorSubject<bool>(false); var dependency2 = new BehaviorSubject<bool>(false); var activator = new FeatureActivator( activate: () => activations++, dependsOn: new[] { dependency1, dependency2 }); var notifications = new List<bool>(); disposables.Add(activator.Subscribe(notifications.Add)); Assert.That(activations, Is.EqualTo(0)); Assert.That(notifications.IsSameSequenceAs(false)); dependency1.OnNext(true); Assert.That(activations, Is.EqualTo(0)); Assert.That(notifications.IsSameSequenceAs(false)); dependency2.OnNext(true); Assert.That(activations, Is.EqualTo(1)); Assert.That(notifications.IsSameSequenceAs(false, true)); }
public void Activate_is_not_called_more_than_once_during_concurrent_calls_when_activator_has_dependencies() { var activations = 0; var notifications = 0; var barrier = new Barrier(2); var subject = new BehaviorSubject<bool>(false); var activator = new FeatureActivator(() => { Console.WriteLine("activated!"); Interlocked.Increment(ref activations); barrier.SignalAndWait(); }, dependsOn: subject); for (var i = 0; i < 10; i++) { disposables.Add(activator .ObserveOn(NewThreadScheduler.Default) .SubscribeOn(NewThreadScheduler.Default) .Subscribe(n => { Console.WriteLine(Thread.CurrentThread.ManagedThreadId); Interlocked.Increment(ref notifications); })); } new Thread(() => subject.OnNext(true)).Start(); // give both subscribers enough time to make sure one has advanced to the activator barrier Thread.Sleep(1000); barrier.SignalAndWait(3000); // give them enough time to propagate their notifications Thread.Sleep(1000); Assert.That(notifications, Is.AtLeast(10)); // sanity check Assert.That(activations, Is.EqualTo(1)); }
public void Deactivate_is_not_called_until_after_activate_has_been_called() { var deactivations = 0; var subject = new BehaviorSubject<bool>(false); var activator = new FeatureActivator(() => { }, () => deactivations++, dependsOn: subject); disposables.Add(activator.Subscribe(_ => { })); subject.OnNext(true); Assert.That(deactivations, Is.EqualTo(0)); subject.OnNext(false); Assert.That(deactivations, Is.EqualTo(1)); }
public void Is_not_initially_available_if_dependency_returns_false() { var activator = new FeatureActivator(() => { }, dependsOn: Observable.Return(false)); Assert.That(activator.First(), Is.False); }
public void Init() { settings = new SettingsHolder(); settings.Set <TransportDefinition>(new MsmqTransport()); featureSettings = new FeatureActivator(settings); }
public void When_any_dependency_produces_false_then_deactivate_is_called() { var deactivations = 0; var dependency1 = new BehaviorSubject<bool>(true); var dependency2 = new BehaviorSubject<bool>(true); var activator = new FeatureActivator( activate: () => { }, deactivate: () => deactivations++, dependsOn: new[] { dependency1, dependency2 }); var notifications = new List<bool>(); disposables.Add(activator.Subscribe(notifications.Add)); Assert.That(deactivations, Is.EqualTo(0)); Assert.That(notifications.IsSameSequenceAs(true)); dependency1.OnNext(false); Assert.That(deactivations, Is.EqualTo(1)); Assert.That(notifications.IsSameSequenceAs(true, false)); }