Skip to content

Commit

Permalink
Additional coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkCiliaVincenti committed Dec 29, 2023
1 parent c8660d7 commit f044a3f
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 42 deletions.
4 changes: 4 additions & 0 deletions AsyncKeyedLock.Tests/AsyncKeyedLock.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>

<SignAssembly>True</SignAssembly>

<AssemblyOriginatorKeyFile>AsyncKeyedLock.Tests.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>

<ItemGroup>
Expand Down
Binary file added AsyncKeyedLock.Tests/AsyncKeyedLock.Tests.snk
Binary file not shown.
57 changes: 57 additions & 0 deletions AsyncKeyedLock.Tests/StripedAsyncKeyedLocker/OriginalTests.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,70 @@
using AsyncKeyedLock.Tests.Helpers;
using FluentAssertions;
using ListShuffle;
using System.Collections;
using System.Collections.Concurrent;
using Xunit;

namespace AsyncKeyedLock.Tests.StripedAsyncKeyedLocker
{
public class OriginalTests
{
[Fact]
public void TestHashHelpersIsPrime0DoesNotThrow()
{
Action action = () =>
{
var asyncKeyedLocker = new StripedAsyncKeyedLocker<string>(0);
};
action.Should().NotThrow();
}

[Fact]
public void TestHashHelpersIsPrime1DoesNotThrow()
{
Action action = () =>
{
var asyncKeyedLocker = new StripedAsyncKeyedLocker<string>(1);
};
action.Should().NotThrow();
}

[Fact]
public void TestHashHelpersIsPrime7199370DoesNotThrow()
{
Action action = () =>
{
var asyncKeyedLocker = new StripedAsyncKeyedLocker<string>(7199370);
};
action.Should().NotThrow();
}

[Fact]
public void TestHashHelpersIsPrime7199371DoesNotThrow()
{
Action action = () =>
{
var asyncKeyedLocker = new StripedAsyncKeyedLocker<string>(7199372);
};
action.Should().NotThrow();
}

[Fact]
public void TestHashHelpersIsPrimeNegative1ThrowsArgumentException()
{
Action action = () =>
{
var asyncKeyedLocker = new StripedAsyncKeyedLocker<string>(-1);
};
action.Should().Throw<ArgumentException>();
}

[Fact]
public void TestHashHelpersIsPrime2()
{
HashHelpers.IsPrime(2).Should().Be(true);
}

[Fact]
public async Task TestTimeout()
{
Expand Down
43 changes: 1 addition & 42 deletions AsyncKeyedLock/HashHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
// This code is taken directly from Microsoft's source code with minor alterations. Credit belongs to Microsoft.
// This code is taken directly from Microsoft's source code with some alterations. Credit belongs to Microsoft.

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Runtime.CompilerServices;

namespace System.Collections
{
internal static partial class HashHelpers
Expand Down Expand Up @@ -84,43 +81,5 @@ public static int GetPrime(int min)
}
return min;
}

// Returns size of hashtable to grow to.
public static int ExpandPrime(int oldSize)
{
int newSize = 2 * oldSize;

// Allow the hashtables to grow to maximum possible size (~2G elements) before encountering capacity overflow.
// Note that this check works even when _items.Length overflowed thanks to the (uint) cast
if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize)
{
Debug.Assert(MaxPrimeArrayLength == GetPrime(MaxPrimeArrayLength), "Invalid MaxPrimeArrayLength");
return MaxPrimeArrayLength;
}

return GetPrime(newSize);
}

/// <summary>Returns approximate reciprocal of the divisor: ceil(2**64 / divisor).</summary>
/// <remarks>This should only be used on 64-bit.</remarks>
public static ulong GetFastModMultiplier(uint divisor) =>
ulong.MaxValue / divisor + 1;

/// <summary>Performs a mod operation using the multiplier pre-computed with <see cref="GetFastModMultiplier"/>.</summary>
/// <remarks>This should only be used on 64-bit.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint FastMod(uint value, uint divisor, ulong multiplier)
{
// We use modified Daniel Lemire's fastmod algorithm (https://github.com/dotnet/runtime/pull/406),
// which allows to avoid the long multiplication if the divisor is less than 2**31.
Debug.Assert(divisor <= int.MaxValue);

// This is equivalent of (uint)Math.BigMul(multiplier * value, divisor, out _). This version
// is faster than BigMul currently because we only need the high bits.
uint highbits = (uint)(((((multiplier * value) >> 32) + 1) * divisor) >> 32);

Debug.Assert(highbits == value % divisor);
return highbits;
}
}
}
9 changes: 9 additions & 0 deletions AsyncKeyedLock/StripedAsyncKeyedLocker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
using System.Threading;
using System.Threading.Tasks;

[assembly: InternalsVisibleTo("AsyncKeyedLock.Tests, PublicKey=002400000480000094000000060200000024000052534131000" +
"4000001000100a5cffbe51901ba498a225214c7eee4ff5f0341aad9f7605a596e72dbffdf234bcf2c157f7e3a4e2a3900cbc0d3919a6b" +
"938cdf09e2aa5949fdd8f1dbda151853a00a08578724fb36f8c44112dadf388f75a5aab469f51a43b49f2e2fce355357291b01471606b" +
"0c071fd5fe1641f1c7b0165d16f365748a613671681938cf6c1")]
namespace AsyncKeyedLock
{
/// <summary>
Expand Down Expand Up @@ -923,5 +927,10 @@ public bool IsInUse(TKey key)
{
return Get(key).SemaphoreSlim.CurrentCount < MaxCount;
}

internal bool IsPrime(int candidate)
{
return HashHelpers.IsPrime(candidate);
}
}
}

0 comments on commit f044a3f

Please sign in to comment.