public void Process_FailsIfNotInitialized() { var stage = ProcessingPipelineStage.Create <TStage>("Stage", null); var message = MessagePool.GetUninitializedMessage(); Assert.Throws <InvalidOperationException>(() => stage.ProcessMessage(message)); }
public void Adding_And_Getting_Next_Stages() { // create stage 1 and stage 2 following stage 1 var stage1 = ProcessingPipelineStage.Create <TStage>("Stage1", null); var stage2 = stage1.AddNextStage <TStage>("Stage2"); var stages12 = new HashSet <TStage> { stage1, stage2 }; // stage 1 should have stage 2 as following stage Assert.Single(stage1.NextStages); Assert.Same(stage2, stage1.NextStages.First()); // stage 2 should have no following stages Assert.Empty(stage2.NextStages); // stage 1 and 2 should be returned by GetAllStages() of stage 1 var stages1 = new HashSet <ProcessingPipelineStage>(); stage1.GetAllStages(stages1); Assert.Equal(2, stages1.Count); Assert.Equal(stages12, stages1); // stage 2 should have no following stages Assert.Empty(stage2.NextStages); var stages2 = new HashSet <ProcessingPipelineStage>(); stage2.GetAllStages(stages2); Assert.Single(stages2); Assert.Same(stage2, stages2.First()); }
public void Process_Standalone(bool processSyncReturnValue) { var callback = new Callback { ProcessSyncCallbackReturnValue = processSyncReturnValue }; var stage = ProcessingPipelineStage.Create <CallbackPipelineStage>("Callback", null); stage.ProcessingCallback = callback.ProcessSyncCallback; // initialize the stage Assert.False(stage.IsInitialized); stage.Initialize(); Assert.True(stage.IsInitialized); // process a log message var message = MessagePool.GetUninitializedMessage(); Assert.False(callback.ProcessSyncCallbackWasCalled); stage.ProcessMessage(message); Assert.True(callback.ProcessSyncCallbackWasCalled); Assert.Same(message, callback.MessagePassedToProcessSyncCallback); // shut the stage down stage.Shutdown(); Assert.False(stage.IsInitialized); }
/// <summary> /// Initializes a new instance of the <see cref="SettingProxy{T}"/> class. /// </summary> /// <param name="stage">The processing pipeline stage the setting belongs to.</param> /// <param name="configuration">The pipeline stage configuration containing the setting.</param> /// <param name="name">Name of the setting.</param> /// <param name="defaultValue">Default value of the setting.</param> internal SettingProxy( ProcessingPipelineStage stage, IProcessingPipelineStageConfiguration configuration, string name, T defaultValue) : this(stage, configuration, name, defaultValue, null, null) { }
/// <summary> /// Adds the specified pipeline stage to the processing pipeline. /// If there another pipeline stage was added before, a splitter is inserted to run both pipeline stages in parallel. /// </summary> /// <typeparam name="TPipelineStage">Type of the pipeline stage to add.</typeparam> /// <param name="name">Name of the pipeline stage to add.</param> /// <param name="initializer">Initializer that configures the pipeline stage.</param> /// <returns>The added pipeline stage.</returns> public TPipelineStage Add <TPipelineStage>( string name, ProcessingPipelineStageInitializer <TPipelineStage> initializer) where TPipelineStage : ProcessingPipelineStage, new() { // create and configure the pipeline stage var stage = ProcessingPipelineStage.Create <TPipelineStage>(name, mConfiguration); initializer?.Invoke(stage); // link pipeline stage with previously added stages, if necessary if (mPipelineStage != null) { if (ReferenceEquals(mPipelineStage, mSplitter)) { mSplitter.AddNextStage(stage); } else { mSplitter = ProcessingPipelineStage.Create <SplitterPipelineStage>("Splitter (automatically injected)", mConfiguration); mSplitter.AddNextStage(mPipelineStage); mSplitter.AddNextStage(stage); mPipelineStage = mSplitter; } } else { mPipelineStage = stage; } return(stage); }
public void Process_WithFollowingStage() { var stage1 = ProcessingPipelineStage.Create <ProcessingPipelineTestStage>("Stage1", null); var stage2 = stage1.AddNextStage <ProcessingPipelineTestStage>("Stage2"); // initialize the stages Assert.False(stage1.IsInitialized); Assert.False(stage2.IsInitialized); stage1.Initialize(); Assert.True(stage1.IsInitialized); Assert.True(stage2.IsInitialized); // process a log message var message = MessagePool.GetUninitializedMessage(); Assert.False(stage1.ProcessSyncWasCalled); Assert.False(stage2.ProcessSyncWasCalled); stage1.ProcessMessage(message); Assert.True(stage1.ProcessSyncWasCalled); Assert.True(stage2.ProcessSyncWasCalled); Assert.Same(message, stage1.MessagePassedToProcessSync); Assert.Same(message, stage2.MessagePassedToProcessSync); // shut the stages down stage1.Shutdown(); Assert.False(stage1.IsInitialized); Assert.False(stage2.IsInitialized); }
public void Process_WithFollowingStage() { var stage1 = ProcessingPipelineStage.Create <AsyncProcessingPipelineTestStage>("Stage1", null); var stage2 = stage1.AddNextStage <AsyncProcessingPipelineTestStage>("Stage2"); // initialize the stages Assert.False(stage1.IsInitialized); Assert.False(stage2.IsInitialized); stage1.Initialize(); Assert.True(stage1.IsInitialized); Assert.True(stage2.IsInitialized); // process a log message var message = MessagePool.GetUninitializedMessage(); Assert.False(stage1.ProcessSyncWasCalled); Assert.False(stage2.ProcessSyncWasCalled); Assert.False(stage1.ProcessAsyncWasCalled); Assert.False(stage2.ProcessAsyncWasCalled); stage1.ProcessMessage(message); Assert.True(stage1.ProcessSyncWasCalled); Assert.True(stage2.ProcessSyncWasCalled); Assert.Same(message, stage1.MessagePassedToProcessSync); Assert.Same(message, stage2.MessagePassedToProcessSync); // give the processing threads time to call ProcessAsync() Thread.Sleep(500); Assert.True(stage1.ProcessAsyncWasCalled); Assert.True(stage2.ProcessAsyncWasCalled); Assert.Single(stage1.MessagesPassedToProcessAsync); Assert.Single(stage2.MessagesPassedToProcessAsync); Assert.Same(message, stage1.MessagesPassedToProcessAsync.First()); Assert.Same(message, stage2.MessagesPassedToProcessAsync.First()); }
public void Initialize_Standalone() { var stage = ProcessingPipelineStage.Create <TStage>("Stage", null); Assert.False(stage.IsInitialized); stage.Initialize(); Assert.True(stage.IsInitialized); }
public void MapLogLevelToStream_FailsIfInitialized() { var stage = ProcessingPipelineStage.Create <ConsoleWriterPipelineStage>("Console", null); stage.Initialize(); Assert.Throws <InvalidOperationException>(() => stage.MapLogLevelToStream(LogLevel.Notice, ConsoleOutputStream.Stdout)); stage.Shutdown(); }
public void StreamByLevelOverrides_FailsIfInitialized() { var stage = ProcessingPipelineStage.Create <ConsoleWriterPipelineStage>("Console", null); stage.Initialize(); Assert.Throws <InvalidOperationException>(() => stage.StreamByLevelOverrides = new Dictionary <LogLevel, ConsoleOutputStream>()); stage.Shutdown(); }
private void Create() { // do not use CreateStage() to emphasize that the constructor is tested var stage = ProcessingPipelineStage.Create <SplitterPipelineStage>("Splitter", null); Assert.Empty(stage.Settings); Assert.Empty(stage.NextStages); }
private void Create() { var stage = ProcessingPipelineStage.Create <CallbackPipelineStage>("Callback", null); Assert.Null(stage.ProcessingCallback); Assert.Empty(stage.NextStages); Assert.Empty(stage.Settings); }
public void Formatter_SetSuccessfully() { var stage = ProcessingPipelineStage.Create <TStage>("Stage", null); var formatter = new TestFormatter(); stage.Formatter = formatter; Assert.Same(formatter, stage.Formatter); }
public void Formatter_FailsIfInitialized() { var stage = ProcessingPipelineStage.Create <TStage>("Stage", null); var formatter = new TestFormatter(); stage.Initialize(); Assert.Throws <InvalidOperationException>(() => stage.Formatter = formatter); stage.Shutdown(); }
private void Create() { var callback = new Callback(); var stage = ProcessingPipelineStage.Create <AsyncCallbackPipelineStage>("Callback", null); Assert.Null(stage.SynchronousProcessingCallback); Assert.Null(stage.AsynchronousProcessingCallback); Assert.Empty(stage.NextStages); Assert.Empty(stage.Settings); }
public void Create() { var stage = ProcessingPipelineStage.Create <ConsoleWriterPipelineStage>("Console", null); Assert.Equal(sDefaultSettings, stage.Settings.ToDictionary(x => x.Key, x => x.Value.Value)); Assert.Equal(ConsoleOutputStream.Stdout, stage.DefaultStream); Assert.Same(Console.Out, stage.OutputStream); Assert.Same(Console.Error, stage.ErrorStream); Assert.Empty(stage.StreamByLevelOverrides); }
/// <summary> /// Tests whether creating a new stage succeeds and the stage is in the expected state /// (as far as the state of the base class is concerned). /// </summary> public override void Create_And_Check_BaseClass_State() { // run base class creation test base.Create_And_Check_BaseClass_State(); // check state introduced with the TextWriterPipelineStage class var stage = ProcessingPipelineStage.Create <TStage>("Stage", null); Assert.NotNull(stage.Formatter); }
public void Initialize_Specific_Standalone() { var stage = ProcessingPipelineStage.Create <ProcessingPipelineTestStage>("Stage", null); Assert.False(stage.IsInitialized); Assert.False(stage.OnInitializeWasCalled); stage.Initialize(); Assert.True(stage.OnInitializeWasCalled); Assert.True(stage.IsInitialized); }
public void Create() { var stage = ProcessingPipelineStage.Create <ProcessingPipelineTestStage>("Stage", null); // check properties of the base pipeline stage Assert.Empty(stage.Settings); // check properties of test pipeline stage Assert.False(stage.OnInitializeWasCalled); Assert.False(stage.OnShutdownWasCalled); }
public void Initialize_WithFollowingStage() { var stage1 = ProcessingPipelineStage.Create <TStage>("Stage1", null); var stage2 = stage1.AddNextStage <AsyncProcessingPipelineTestStage>("Stage2", null); Assert.False(stage1.IsInitialized); Assert.False(stage2.IsInitialized); stage1.Initialize(); Assert.True(stage1.IsInitialized); Assert.True(stage2.IsInitialized); }
/// <summary> /// Creates a new instance of the pipeline stage. /// </summary> /// <param name="name">Name of the pipeline stage (must be unique throughout the entire processing pipeline).</param> /// <returns>The created stage.</returns> private FileWriterPipelineStage CreateStage(string name) { string path = Path.GetFullPath($"TestLog_{Guid.NewGuid():N}.log"); mTemporaryFiles.Add(path); var stage = ProcessingPipelineStage.Create <FileWriterPipelineStage>(name, null); stage.Path = path; stage.Append = false; return(stage); }
public void Initialize_FailsIfAlreadyInitialized() { var stage = ProcessingPipelineStage.Create <TStage>("Stage", null); // initialize the first time Assert.False(stage.IsInitialized); stage.Initialize(); Assert.True(stage.IsInitialized); // initialize once again Assert.Throws <InvalidOperationException>(() => stage.Initialize()); }
public void Shutdown_Standalone() { var stage = ProcessingPipelineStage.Create <TStage>("Stage", null); // initialize the stage Assert.False(stage.IsInitialized); stage.Initialize(); Assert.True(stage.IsInitialized); // shut the stage down stage.Shutdown(); Assert.False(stage.IsInitialized); }
/// <summary> /// Removes the specified pipeline stage from the list of following pipeline stages. /// </summary> /// <param name="stage">Pipeline stage to remove.</param> /// <returns> /// true, if the specified pipeline stage was removed successfully; /// false, if the specified pipeline stage is not one of the following pipeline stages of the current stage. /// </returns> public bool RemoveNextStage(ProcessingPipelineStage stage) { if (stage == null) { throw new ArgumentNullException(nameof(stage)); } lock (Sync) { for (int i = 0; i < mNextStages.Length; i++) { if (mNextStages[i] == stage) { // found the stage // shut the stage down, if necessary if (mInitialized) { try { stage.Shutdown(); } catch (Exception ex) { // swallow exception to avoid crashing the application, if the exception is not handled properly Debug.Fail("The pipeline stage threw an exception while shutting down", ex.ToString()); } } // remove the stage var copy = new ProcessingPipelineStage[mNextStages.Length - 1]; for (int j = 0, k = 0; j < mNextStages.Length; j++, k++) { if (mNextStages[j] == stage) { k--; continue; } copy[k] = mNextStages[j]; } mNextStages = copy; return(true); } } return(false); } }
public void Create() { var stage = ProcessingPipelineStage.Create <AsyncProcessingPipelineTestStage>("Stage", null); // check properties of the base pipeline stage Assert.Empty(stage.Settings); Assert.Equal(500, stage.MessageQueueSize); Assert.False(stage.DiscardMessagesIfQueueFull); Assert.Equal(TimeSpan.FromSeconds(5), stage.ShutdownTimeout); // check properties of test pipeline stage Assert.False(stage.OnInitializeWasCalled); Assert.False(stage.OnShutdownWasCalled); }
public void Process_WithFollowingStage(bool processSyncReturnValue) { var callback1 = new Callback { ProcessSyncCallbackReturnValue = processSyncReturnValue }; var callback2 = new Callback { ProcessSyncCallbackReturnValue = processSyncReturnValue }; var stage1 = ProcessingPipelineStage.Create <CallbackPipelineStage>("Callback1", null); var stage2 = stage1.AddNextStage <CallbackPipelineStage>("Callback2"); stage1.ProcessingCallback = callback1.ProcessSyncCallback; stage2.ProcessingCallback = callback2.ProcessSyncCallback; // initialize the stages Assert.False(stage1.IsInitialized); Assert.False(stage2.IsInitialized); stage1.Initialize(); Assert.True(stage1.IsInitialized); Assert.True(stage2.IsInitialized); // process a log message var message = MessagePool.GetUninitializedMessage(); Assert.False(callback1.ProcessSyncCallbackWasCalled); Assert.False(callback2.ProcessSyncCallbackWasCalled); stage1.ProcessMessage(message); if (processSyncReturnValue) { // the message should have traveled through stage 1 and 2 Assert.True(callback1.ProcessSyncCallbackWasCalled); Assert.True(callback2.ProcessSyncCallbackWasCalled); Assert.Same(message, callback1.MessagePassedToProcessSyncCallback); Assert.Same(message, callback2.MessagePassedToProcessSyncCallback); } else { // the message should have traveled through stage 1 only Assert.True(callback1.ProcessSyncCallbackWasCalled); Assert.False(callback2.ProcessSyncCallbackWasCalled); Assert.Same(message, callback1.MessagePassedToProcessSyncCallback); Assert.Null(callback2.MessagePassedToProcessSyncCallback); } // shut the stages down stage1.Shutdown(); Assert.False(stage1.IsInitialized); Assert.False(stage2.IsInitialized); }
public void Initialize_Specific_WithFollowingStage() { var stage1 = ProcessingPipelineStage.Create <ProcessingPipelineTestStage>("Stage1", null); var stage2 = stage1.AddNextStage <ProcessingPipelineTestStage>("Stage2"); Assert.False(stage1.IsInitialized); Assert.False(stage2.IsInitialized); Assert.False(stage1.OnInitializeWasCalled); Assert.False(stage2.OnInitializeWasCalled); stage1.Initialize(); Assert.True(stage1.OnInitializeWasCalled); Assert.True(stage2.OnInitializeWasCalled); Assert.True(stage1.IsInitialized); Assert.True(stage2.IsInitialized); }
public void Process_Standalone(bool processSyncReturnValue, bool queueForAsyncProcessing) { var callback = new Callback { ProcessSyncCallbackReturnValue = processSyncReturnValue, ProcessSyncCallbackQueueForAsyncProcessing = queueForAsyncProcessing }; var stage = ProcessingPipelineStage.Create <AsyncCallbackPipelineStage>("Callback", null); stage.SynchronousProcessingCallback = callback.ProcessSyncCallback; stage.AsynchronousProcessingCallback = callback.ProcessAsyncCallback; // initialize the stage Assert.False(stage.IsInitialized); stage.Initialize(); Assert.True(stage.IsInitialized); // process a log message var message = MessagePool.GetUninitializedMessage(); Assert.False(callback.ProcessSyncCallbackWasCalled); stage.ProcessMessage(message); // wait for the message to travel through asynchronous processing Thread.Sleep(500); // check synchronous processing Assert.True(callback.ProcessSyncCallbackWasCalled); Assert.Same(message, callback.MessagePassedToProcessSyncCallback); // check asynchronous processing if (queueForAsyncProcessing) { Assert.True(callback.ProcessAsyncCallbackWasCalled); Assert.Single(callback.MessagesPassedToProcessAsyncCallback); Assert.Same(message, callback.MessagesPassedToProcessAsyncCallback.First()); } else { Assert.False(callback.ProcessAsyncCallbackWasCalled); Assert.Empty(callback.MessagesPassedToProcessAsyncCallback); } // shut the stage down stage.Shutdown(); Assert.False(stage.IsInitialized); }
/// <summary> /// Configures the specified pipeline stage to receive log messages, when the current stage has completed running /// its <see cref="ProcessMessage"/> method. The method must return <c>true</c> to call the following stage. /// The pipeline stage must use the same log configuration as the current stage and it must not be initialized, yet. /// </summary> /// <param name="stage">The pipeline stage that should follow the current stage.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="stage"/> is <c>null</c>. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="stage"/> is already initialized or its configuration is not the same as the configuration of the current state. /// </exception> public void AddNextStage(ProcessingPipelineStage stage) { if (stage == null) { throw new ArgumentNullException(nameof(stage)); } if (stage.IsInitialized) { throw new ArgumentException("The stage to add must not be initialized.", nameof(stage)); } if (!ReferenceEquals(stage.Configuration, Configuration)) { throw new ArgumentException("The stage must use the same configuration as the current stage.", nameof(stage)); } lock (Sync) { var oldNextStages = mNextStages; var copy = new ProcessingPipelineStage[mNextStages.Length + 1]; Array.Copy(mNextStages, copy, mNextStages.Length); copy[copy.Length - 1] = stage; mNextStages = copy; // initialize the added stage, if this stage is initialized if (mInitialized) { try { stage.Initialize(); } catch (Exception) { try { stage.Shutdown(); } catch (Exception ex) { // swallow exception to avoid crashing the application, if the exception is not handled properly Debug.Fail("The pipeline stage threw an exception while shutting down", ex.ToString()); } mNextStages = oldNextStages; throw; } } } }
public void MapLogLevelToStream(List <Tuple <LogLevel, ConsoleOutputStream> > mappings) { var stage = ProcessingPipelineStage.Create <ConsoleWriterPipelineStage>("Console", null); // add the mappings and calculate the expected result var expectedMapping = new Dictionary <LogLevel, ConsoleOutputStream>(); foreach (var mapping in mappings) { expectedMapping[mapping.Item1] = mapping.Item2; stage.MapLogLevelToStream(mapping.Item1, mapping.Item2); } // check that the 'StreamByLevelOverrides' property reflects the overrides Assert.Equal(expectedMapping, stage.StreamByLevelOverrides); }