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)
 {
 }
示例#5
0
        /// <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);
        }
示例#7
0
        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);
        }
示例#13
0
        public void Formatter_SetSuccessfully()
        {
            var stage     = ProcessingPipelineStage.Create <TStage>("Stage", null);
            var formatter = new TestFormatter();

            stage.Formatter = formatter;
            Assert.Same(formatter, stage.Formatter);
        }
示例#14
0
        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();
        }
示例#15
0
        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);
        }
示例#17
0
        /// <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);
        }
示例#21
0
        /// <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);
        }
示例#24
0
        /// <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);
            }
        }
示例#25
0
        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);
        }
示例#28
0
        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);
        }
示例#29
0
        /// <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);
        }