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); }
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); }