Example #1
0
        public void OnlyOneThreadIsInsideThePreviousPipelineStagesGetValueFunctionAtATime()
        {
            var container = new Container();

            int EnsureOnlyOne()
            {
                if (container.Thread != null)
                {
                    throw new Exception();
                }

                container.Thread = Thread.CurrentThread;

                if (container.Thread != Thread.CurrentThread)
                {
                    throw new Exception();
                }

                container.Thread = null;
                return(1);
            }

            var input = new DataRetrievalPipelineStage <int>("", EnsureOnlyOne);
            var sut   = new ThreadSafePipelineStage <int>(input);
            var tasks = Enumerable.Repeat(0, 1000).Select(_ => Task.Run(sut.GetValue)).ToArray();

            Task.WaitAll(tasks);
            Assert.Pass("No exceptions were thrown, indicating that no concurrency issues were found.");
        }
        public void DataRetrievalAlwaysCallsTheSpecifiedFunctionOnGetValueCall()
        {
            var value = new ValueRepository(2);

            var sut = new DataRetrievalPipelineStage <int>("name", value.GetValue);

            PipelineAssert.Value(sut, value.Value);
            Assert.AreEqual(1, value.NumCalls);

            sut.GetValue();
            sut.GetValue();
            sut.GetValue();
            sut.GetValue();
            Assert.AreEqual(5, value.NumCalls);
        }
Example #3
0
        public void ConcurrentRetrievalsRetrievesOnlyOnceFromUpstreamStage()
        {
            using var completeRetrievalFlag = new EventWaitHandle(false, EventResetMode.ManualReset);
            using var semaphore             = new SemaphoreSlim(0);

            var input     = new DataRetrievalPipelineStage <object>("", () => { completeRetrievalFlag.WaitOne(); return(new object()); });
            var inputTest = input.AttachTestStage();

            var sut = new ThreadSafePipelineStage <object>(inputTest);

            object GetObject()
            {
                semaphore.Release();
                return(sut.GetValue());
            }

            var task1 = Task.Run(GetObject);
            var task2 = Task.Run(GetObject);

            // Attempt to get both tasks to be inside the GetValue method of the pipeline stage.
            // This is, sadly, the best we can do with the current design.
            // At least we at this stage know that both tasks are in a running state.
            var threeSeconds = TimeSpan.FromSeconds(3);

            Assert.IsTrue(semaphore.Wait(threeSeconds));
            Assert.IsTrue(semaphore.Wait(threeSeconds));
            Thread.Sleep(threeSeconds);

            completeRetrievalFlag.Set();

            Assert.IsTrue(Task.WaitAll(new[] { task1, task2 }, threeSeconds));

            var result1 = task1.Result;
            var result2 = task2.Result;

            Assert.AreSame(result1, result2);
        }