Skip to content

Commit

Permalink
fix identifier recording shared state (#1257)
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonCropp authored Jul 26, 2024
1 parent c527a28 commit 3f8adb0
Show file tree
Hide file tree
Showing 8 changed files with 27 additions and 71 deletions.
2 changes: 2 additions & 0 deletions docs/mdsource/recording.source.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ To avoid grouping use [Stop](#stop).

Recording can be grouped by an identifier.

The identifier should be statically unique. For example a fully qualified test name or a GUID.

snippet: RecordingIdentifier

Results in:
Expand Down
10 changes: 6 additions & 4 deletions docs/recording.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public Task SameKey()
return Verify("TheValue");
}
```
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L288-L299' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingSameKey' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L281-L292' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingSameKey' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Results in:
Expand All @@ -143,6 +143,8 @@ To avoid grouping use [Stop](#stop).

Recording can be grouped by an identifier.

The identifier should be statically unique. For example a fully qualified test name or a GUID.

<!-- snippet: RecordingIdentifier -->
<a id='snippet-RecordingIdentifier'></a>
```cs
Expand Down Expand Up @@ -186,7 +188,7 @@ public Task Case()
return Verify("TheValue");
}
```
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L310-L321' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingIgnoreCase' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L303-L314' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingIgnoreCase' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Results in:
Expand Down Expand Up @@ -305,7 +307,7 @@ public Task Clear()
return Verify();
}
```
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L208-L220' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingClear' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L201-L213' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingClear' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Results in:
Expand Down Expand Up @@ -341,7 +343,7 @@ public Task PauseResume()
return Verify();
}
```
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L232-L247' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingPauseResume' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L225-L240' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingPauseResume' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Results in:
Expand Down
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project>
<PropertyGroup>
<NoWarn>CS1591;CS0649;xUnit1026;xUnit1013;CS1573;VerifyTestsProjectDir;VerifySetParameters;PolyFillTargetsForNuget</NoWarn>
<Version>26.1.1</Version>
<Version>26.1.2</Version>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>preview</LangVersion>
<AssemblyVersion>1.0.0</AssemblyVersion>
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

15 changes: 4 additions & 11 deletions src/Verify.Tests/RecordingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,18 +167,11 @@ public Task StopNotInResult()
#endregion

[Fact]
public void StartIdentifierThatDoesntFinish()
public Task StopIdentifier()
{
Recording.Start("identifierOverlap");
Recording.Add("identifierOverlap", "name", "value");
}

[Fact]
public Task StopIdentifierOverlap()
{
Recording.Start("identifierOverlap");
Recording.Add("identifierOverlap", "name", "value");
return Verify(Recording.Stop("identifierOverlap"));
Recording.Start("identifier");
Recording.Add("identifier", "name", "value");
return Verify(Recording.Stop("identifier"));
}

[Fact]
Expand Down
62 changes: 14 additions & 48 deletions src/Verify/Recording/Recording_Named.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,25 @@

public static partial class Recording
{
static AsyncLocal<ConcurrentDictionary<string, State>?> asyncLocalNamed = new();
// The identifier should be statically unique. For example a fully qualified test name or a GUID.
// so it is ok for this to be shared state
static ConcurrentDictionary<string, State> namedState = new(StringComparer.OrdinalIgnoreCase);

public static void Add(string identifier, string name, object item) =>
CurrentStateNamed(identifier)
.Add(name, item);

public static void TryAdd(string identifier, string name, object item)
{
var states = asyncLocalNamed.Value;
if (states != null)
if (namedState.TryGetValue(identifier, out var state))
{
if (states.TryGetValue(identifier, out var state))
{
state.Add(name, item);
}
state.Add(name, item);
}
}

public static bool IsRecording(string identifier)
{
var states = asyncLocalNamed.Value;
if (states == null)
{
return false;
}

if (!states.TryGetValue(identifier, out var state))
if (!namedState.TryGetValue(identifier, out var state))
{
return false;
}
Expand All @@ -50,14 +42,10 @@ public static bool TryStop(
string identifier,
[NotNullWhen(true)] out IReadOnlyCollection<ToAppend>? recorded)
{
var states = asyncLocalNamed.Value;
if (states != null)
if (namedState.TryRemove(identifier, out var state))
{
if (states.TryRemove(identifier, out var state))
{
recorded = state.Items;
return true;
}
recorded = state.Items;
return true;
}

recorded = null;
Expand All @@ -66,9 +54,7 @@ public static bool TryStop(

static State CurrentStateNamed(string identifier, [CallerMemberName] string caller = "")
{
var states = asyncLocalNamed.Value;
if (states != null &&
states.TryGetValue(identifier, out var state))
if (namedState.TryGetValue(identifier, out var state))
{
return state;
}
Expand All @@ -78,9 +64,7 @@ static State CurrentStateNamed(string identifier, [CallerMemberName] string call

public static IDisposable Start(string identifier)
{
var states = asyncLocalNamed.Value ??= new(StringComparer.OrdinalIgnoreCase);

if (!states.TryAdd(identifier, new()))
if (!namedState.TryAdd(identifier, new()))
{
throw new("Recording already started");
}
Expand All @@ -101,13 +85,7 @@ public static void Pause(string identifier) =>

public static void TryPause(string identifier)
{
var states = asyncLocalNamed.Value;
if (states == null)
{
return;
}

if (states.TryGetValue(identifier, out var state))
if (namedState.TryGetValue(identifier, out var state))
{
state.Pause();
}
Expand All @@ -119,13 +97,7 @@ public static void Resume(string identifier) =>

public static void TryResume(string identifier)
{
var states = asyncLocalNamed.Value;
if (states == null)
{
return;
}

if (states.TryGetValue(identifier, out var state))
if (namedState.TryGetValue(identifier, out var state))
{
state.Resume();
}
Expand All @@ -137,13 +109,7 @@ public static void Clear(string identifier) =>

public static void TryClear(string identifier)
{
var states = asyncLocalNamed.Value;
if (states == null)
{
return;
}

if (states.TryGetValue(identifier, out var state))
if (namedState.TryGetValue(identifier, out var state))
{
state.Clear();
}
Expand Down

0 comments on commit 3f8adb0

Please sign in to comment.