Skip to content

Commit 603ed9a

Browse files
committed
Merge pull request #224 from graemefoster/bug-concurrency-issue-on-context-lookup
Test / fix for concurrency issue when using bddfy with parallel runners
2 parents 3cb8303 + 5132942 commit 603ed9a

3 files changed

Lines changed: 51 additions & 13 deletions

File tree

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Linq;
3+
using System.Threading.Tasks;
4+
using TestStack.BDDfy.Tests.Stories;
5+
using Xunit;
6+
7+
namespace TestStack.BDDfy.Tests.Concurrency
8+
{
9+
public class ParallelRunnerScenario
10+
{
11+
[Fact]
12+
public async Task CanHandleMultipleThreadsExecutingBddfyConcurrently()
13+
{
14+
try
15+
{
16+
await Task.WhenAll(
17+
Enumerable.Range(0, 100)
18+
.Select(_ => Task.Run(() => new DummyScenario().BDDfy<ParallelRunnerScenario>())));
19+
}
20+
catch (Exception e)
21+
{
22+
Assert.False(true, "Threw exception " + e);
23+
}
24+
}
25+
}
26+
}

src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
<Compile Include="Arguments\ArgumentsProvidedForGiven.cs" />
7171
<Compile Include="Arguments\ArgumentsProvidedForThen.cs" />
7272
<Compile Include="Arguments\MultipleArgumentsProvidedForTheSameStep.cs" />
73+
<Compile Include="Concurrency\ParallelRunnerScenario.cs" />
7374
<Compile Include="Configuration\EmptyScenario.cs" />
7475
<Compile Include="Configuration\SequentialKeyGeneratorTests.cs" />
7576
<Compile Include="Configuration\StepExecutorTests.cs" />
@@ -192,6 +193,7 @@
192193
<Content Include="TagsTests.TagsAreReportedInHtmlReport.approved.txt" />
193194
<Content Include="TagsTests.TagsAreReportedInTextReport.approved.txt" />
194195
</ItemGroup>
196+
<ItemGroup />
195197
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
196198
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
197199
<PropertyGroup>

src/TestStack.BDDfy/TestContext.cs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace TestStack.BDDfy
55
public class TestContext : ITestContext
66
{
77
private static readonly Dictionary<object, ITestContext> ContextLookup = new Dictionary<object, ITestContext>();
8+
private static object _dictionaryLock = new object();
89

910
private TestContext(object testObject)
1011
{
@@ -17,15 +18,18 @@ public static void SetContext(object testObject, ITestContext context)
1718
var fluentBuilder = testObject as IFluentStepBuilder;
1819
if (fluentBuilder != null) testObject = fluentBuilder.TestObject;
1920

20-
if (ContextLookup.ContainsKey(testObject))
21+
lock (_dictionaryLock)
2122
{
22-
var oldContext = ContextLookup[testObject];
23-
context.Examples = oldContext.Examples;
24-
ContextLookup[testObject] = new TestContext(testObject);
25-
}
26-
else
27-
{
28-
ContextLookup.Add(testObject, context);
23+
if (ContextLookup.ContainsKey(testObject))
24+
{
25+
var oldContext = ContextLookup[testObject];
26+
context.Examples = oldContext.Examples;
27+
ContextLookup[testObject] = new TestContext(testObject);
28+
}
29+
else
30+
{
31+
ContextLookup.Add(testObject, context);
32+
}
2933
}
3034
}
3135

@@ -34,16 +38,22 @@ public static ITestContext GetContext(object testObject)
3438
var fluentBuilder = testObject as IFluentStepBuilder;
3539
if (fluentBuilder != null) testObject = fluentBuilder.TestObject;
3640

37-
if (!ContextLookup.ContainsKey(testObject))
38-
ContextLookup.Add(testObject, new TestContext(testObject));
41+
lock (_dictionaryLock)
42+
{
43+
if (!ContextLookup.ContainsKey(testObject))
44+
ContextLookup.Add(testObject, new TestContext(testObject));
3945

40-
return ContextLookup[testObject];
46+
return ContextLookup[testObject];
47+
}
4148
}
4249

4350
public static void ClearContextFor(object testObject)
4451
{
45-
if (ContextLookup.ContainsKey(testObject))
46-
ContextLookup.Remove(testObject);
52+
lock (_dictionaryLock)
53+
{
54+
if (ContextLookup.ContainsKey(testObject))
55+
ContextLookup.Remove(testObject);
56+
}
4757
}
4858

4959
public ExampleTable Examples { get; set; }

0 commit comments

Comments
 (0)