15 changed files with 191 additions and 18 deletions
@ -0,0 +1,18 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net6.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
<IsPackable>false</IsPackable> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\modules\common\LINGYUN.Abp.IdGenerator\LINGYUN.Abp.IdGenerator.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,42 @@ |
|||||
|
using LINGYUN.Abp.Tests; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IdGenerator; |
||||
|
|
||||
|
public class AbpIdGeneratorModuleTestBase : AbpTestsBase<AbpIdGeneratorModuleTestModule> |
||||
|
{ |
||||
|
protected IDistributedIdGenerator DistributedIdGenerator { get; set; } |
||||
|
|
||||
|
private void GenerateId(long[] idArray, int startIndex, int endIndex) |
||||
|
{ |
||||
|
for (int i = startIndex; i < endIndex; i++) |
||||
|
{ |
||||
|
idArray[i] = DistributedIdGenerator.Create(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected long[] GenerateIdInSingleThread(int countIds) |
||||
|
{ |
||||
|
long[] ids = new long[countIds]; |
||||
|
|
||||
|
GenerateId(ids, 0, ids.Length); |
||||
|
|
||||
|
return ids; |
||||
|
} |
||||
|
|
||||
|
protected long[] GenerateIdInMutiThread(int countThreads, int countIdsPerThread) |
||||
|
{ |
||||
|
List<Task> tasks = new(); |
||||
|
long[] idArray = new long[countThreads * countIdsPerThread]; |
||||
|
|
||||
|
for (int i = 0; i < countThreads; i++) |
||||
|
{ |
||||
|
int threadId = i; |
||||
|
tasks.Add(Task.Run(() => GenerateId(idArray, threadId * countIdsPerThread, (threadId + 1) * countIdsPerThread))); |
||||
|
} |
||||
|
Task.WaitAll(tasks.ToArray()); |
||||
|
|
||||
|
return idArray; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
using LINGYUN.Abp.IdGenerator.Snowflake; |
||||
|
using LINGYUN.Abp.Tests; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IdGenerator; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpIdGeneratorModule), |
||||
|
typeof(AbpTestsBaseModule))] |
||||
|
public class AbpIdGeneratorModuleTestModule : AbpModule |
||||
|
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
PreConfigure<SnowflakeIdOptions>(options => |
||||
|
{ |
||||
|
options.WorkerId = 30010 - 30000; |
||||
|
options.WorkerIdBits = 5; |
||||
|
options.DatacenterId = 1; |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
using Shouldly; |
||||
|
using System.Linq; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IdGenerator; |
||||
|
|
||||
|
public class IdGeneratorTests : AbpIdGeneratorModuleTestBase |
||||
|
{ |
||||
|
public IdGeneratorTests() |
||||
|
{ |
||||
|
DistributedIdGenerator = GetRequiredService<IDistributedIdGenerator>(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void IdShouldBeUnique_SingleThread() |
||||
|
{ |
||||
|
const int countIds = 50000; |
||||
|
long[] ids = GenerateIdInSingleThread(countIds); |
||||
|
|
||||
|
var finalIds = ids.GroupBy(id => id).Select(d => d.Key).ToArray(); |
||||
|
finalIds.Length.ShouldBe(countIds); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void IdShouldBeUnique_MultiThread() |
||||
|
{ |
||||
|
const int countIdsPerThread = 50000; |
||||
|
const int countThreads = 8; |
||||
|
long[] ids = GenerateIdInMutiThread(countThreads, countIdsPerThread); |
||||
|
|
||||
|
var finalIds = ids.GroupBy(id => id).Select(d => d.Key).ToArray(); |
||||
|
finalIds.Length.ShouldBe(countThreads * countIdsPerThread); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,51 @@ |
|||||
|
using LINGYUN.Abp.IdGenerator.Snowflake; |
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using Shouldly; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IdGenerator; |
||||
|
|
||||
|
public class SnowflakeIdGeneratorTests : AbpIdGeneratorModuleTestBase |
||||
|
{ |
||||
|
public SnowflakeIdGeneratorTests() |
||||
|
{ |
||||
|
DistributedIdGenerator = null; |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(-1, 5)] |
||||
|
[InlineData(0, 5)] |
||||
|
[InlineData(10, 5)] |
||||
|
[InlineData(31, 5)] |
||||
|
[InlineData(32, 5)] |
||||
|
[InlineData(30010, 5)] |
||||
|
public void WorkerIdShouldInRange(int workerId, int workerIdBits) |
||||
|
{ |
||||
|
var snowflakeIdGenerator = SnowflakeIdGenerator.Create(new SnowflakeIdOptions |
||||
|
{ |
||||
|
WorkerId = workerId, |
||||
|
WorkerIdBits = workerIdBits |
||||
|
}); |
||||
|
|
||||
|
snowflakeIdGenerator.WorkerId.ShouldBeInRange(0, (long)Math.Pow(2, workerIdBits) - 1); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void BiggerWorkerIdMakeIdRepeated() |
||||
|
{ |
||||
|
var snowflakeIdGenerator = SnowflakeIdGenerator.Create(new SnowflakeIdOptions |
||||
|
{ |
||||
|
WorkerId = 30010, |
||||
|
WorkerIdBits = 5 |
||||
|
}); |
||||
|
snowflakeIdGenerator.GetType().GetProperty("WorkerId").SetValue(snowflakeIdGenerator, 30010); |
||||
|
DistributedIdGenerator = snowflakeIdGenerator; |
||||
|
|
||||
|
const int countIds = 50000; |
||||
|
long[] ids = GenerateIdInSingleThread(countIds); |
||||
|
|
||||
|
var finalIds = ids.GroupBy(id => id).Select(d => d.Key).ToArray(); |
||||
|
finalIds.Length.ShouldBeLessThan(countIds); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue