Skip to content

Commit 346383b

Browse files
authored
Merge pull request #10 from MeowServer/DevMeow
Merge Dev Branch V5.4.3
2 parents 1c59028 + a97d063 commit 346383b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1388
-274
lines changed

HintServiceExample/Plugin.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class Plugin : LabApi.Loader.Features.Plugins.Plugin
1717
public override string Name => "HintServiceExample";
1818
public override string Author => "MeowServer";
1919
public override string Description => "A example plugin for HSM";
20-
public override Version Version { get; } = new Version(5, 4, 2);
20+
public override Version Version { get; } = new Version(5, 4, 3);
2121
public override Version RequiredApiVersion { get; } = Version.Parse(LabApi.Features.LabApiProperties.CompiledVersion);
2222
public override void Enable()
2323
{
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
using HintServiceMeow.Core.Utilities;
2+
using Microsoft.VisualStudio.TestTools.UnitTesting;
3+
using System;
4+
5+
namespace HintServiceMeow.Tests
6+
{
7+
[TestClass]
8+
public class CacheTests
9+
{
10+
[TestMethod]
11+
[ExpectedException(typeof(ArgumentOutOfRangeException))]
12+
public void Constructor_Throws_OnInvalidMaxSize()
13+
{
14+
var cache = new Cache<string, int>(0);
15+
}
16+
17+
[TestMethod]
18+
[ExpectedException(typeof(ArgumentNullException))]
19+
public void Add_Throws_OnNullKey()
20+
{
21+
var cache = new Cache<string, int>(5);
22+
cache.Add(null, 1);
23+
}
24+
25+
[TestMethod]
26+
public void Add_And_TryGet_ReturnsCorrectValue()
27+
{
28+
var cache = new Cache<string, int>(3);
29+
cache.Add("a", 1);
30+
cache.Add("b", 2);
31+
32+
Assert.IsTrue(cache.TryGet("a", out int v1));
33+
Assert.AreEqual(1, v1);
34+
Assert.IsTrue(cache.TryGet("b", out int v2));
35+
Assert.AreEqual(2, v2);
36+
Assert.IsFalse(cache.TryGet("c", out _));
37+
}
38+
39+
[TestMethod]
40+
public void TryRemove_RemovesItem_And_ReturnsValue()
41+
{
42+
var cache = new Cache<string, int>(3);
43+
cache.Add("a", 1);
44+
cache.Add("b", 2);
45+
46+
Assert.IsTrue(cache.TryRemove("a", out int val));
47+
Assert.AreEqual(1, val);
48+
Assert.IsFalse(cache.TryGet("a", out _));
49+
50+
Assert.IsFalse(cache.TryRemove("c", out _));
51+
}
52+
53+
[TestMethod]
54+
public void Add_Replaces_OldValue()
55+
{
56+
var cache = new Cache<string, int>(3);
57+
cache.Add("a", 1);
58+
cache.Add("a", 2);
59+
60+
Assert.IsTrue(cache.TryGet("a", out int v));
61+
Assert.AreEqual(2, v);
62+
}
63+
64+
[TestMethod]
65+
public void Capacity_Is_Respected_And_LRU_Removed()
66+
{
67+
var cache = new Cache<string, int>(2);
68+
cache.Add("a", 1);
69+
cache.Add("b", 2);
70+
71+
// a, b in cache (a is oldest, b is newest)
72+
cache.Add("c", 3); // Should remove "a"
73+
74+
Assert.IsFalse(cache.TryGet("a", out _));
75+
Assert.IsTrue(cache.TryGet("b", out int v2) && v2 == 2);
76+
Assert.IsTrue(cache.TryGet("c", out int v3) && v3 == 3);
77+
}
78+
79+
[TestMethod]
80+
public void Access_Updates_LRU_Order()
81+
{
82+
var cache = new Cache<string, int>(2);
83+
cache.Add("a", 1); // a
84+
cache.Add("b", 2); // b,a
85+
cache.TryGet("a", out _); // a,b
86+
cache.Add("c", 3); // b should be removed here
87+
88+
Assert.IsTrue(cache.TryGet("a", out int v1) && v1 == 1);
89+
Assert.IsTrue(cache.TryGet("c", out int v2) && v2 == 3);
90+
Assert.IsFalse(cache.TryGet("b", out _));
91+
}
92+
93+
[TestMethod]
94+
public void TryRemove_OnNonExistentKey_DoesNothing()
95+
{
96+
var cache = new Cache<string, int>(2);
97+
cache.Add("a", 1);
98+
Assert.IsFalse(cache.TryRemove("x", out _));
99+
}
100+
101+
[TestMethod]
102+
public void Multiple_Keys_Work()
103+
{
104+
var cache = new Cache<int, string>(10);
105+
for (int i = 0; i < 10; i++)
106+
cache.Add(i, i.ToString());
107+
108+
for (int i = 0; i < 10; i++)
109+
Assert.IsTrue(cache.TryGet(i, out string s) && s == i.ToString());
110+
}
111+
112+
[TestMethod]
113+
public void Cache_Thread_Safety()
114+
{
115+
var cache = new Cache<int, int>(1000);
116+
var random = new Random();
117+
int threadCount = 8;
118+
var threads = new System.Threading.Thread[threadCount];
119+
120+
for (int t = 0; t < threadCount; t++)
121+
{
122+
threads[t] = new System.Threading.Thread(() =>
123+
{
124+
for (int i = 0; i < 5000; i++)
125+
{
126+
int key = random.Next(0, 1500);
127+
cache.Add(key, key);
128+
cache.TryGet(key, out _);
129+
cache.TryRemove(key, out _);
130+
}
131+
});
132+
}
133+
134+
foreach (var th in threads) th.Start();
135+
foreach (var th in threads) th.Join();
136+
137+
// No exception = passed test
138+
Assert.IsTrue(true);
139+
}
140+
}
141+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.props')" />
4+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
5+
<PropertyGroup>
6+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
7+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
8+
<ProjectGuid>{4D5AD48B-E99A-45A1-91E3-F1C01AF31B6C}</ProjectGuid>
9+
<OutputType>Library</OutputType>
10+
<AppDesignerFolder>Properties</AppDesignerFolder>
11+
<RootNamespace>HintServiceMeow.Tests</RootNamespace>
12+
<AssemblyName>HintServiceMeow.Tests</AssemblyName>
13+
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
14+
<FileAlignment>512</FileAlignment>
15+
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
16+
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
17+
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
18+
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
19+
<IsCodedUITest>False</IsCodedUITest>
20+
<TestProjectType>UnitTest</TestProjectType>
21+
<NuGetPackageImportStamp>
22+
</NuGetPackageImportStamp>
23+
</PropertyGroup>
24+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
25+
<DebugSymbols>true</DebugSymbols>
26+
<DebugType>full</DebugType>
27+
<Optimize>false</Optimize>
28+
<OutputPath>bin\Debug\</OutputPath>
29+
<DefineConstants>DEBUG;TRACE</DefineConstants>
30+
<ErrorReport>prompt</ErrorReport>
31+
<WarningLevel>4</WarningLevel>
32+
</PropertyGroup>
33+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
34+
<DebugType>pdbonly</DebugType>
35+
<Optimize>true</Optimize>
36+
<OutputPath>bin\Release\</OutputPath>
37+
<DefineConstants>TRACE</DefineConstants>
38+
<ErrorReport>prompt</ErrorReport>
39+
<WarningLevel>4</WarningLevel>
40+
</PropertyGroup>
41+
<ItemGroup>
42+
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
43+
<HintPath>..\packages\MSTest.TestFramework.2.2.10\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
44+
</Reference>
45+
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
46+
<HintPath>..\packages\MSTest.TestFramework.2.2.10\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
47+
</Reference>
48+
<Reference Include="System" />
49+
<Reference Include="System.Core" />
50+
</ItemGroup>
51+
<ItemGroup>
52+
<Compile Include="CacheTests.cs" />
53+
<Compile Include="Logger.cs" />
54+
<Compile Include="PeriodicRunnerTests.cs" />
55+
<Compile Include="Properties\AssemblyInfo.cs" />
56+
<Compile Include="TaskSchedulerTests.cs" />
57+
<Compile Include="TestInit.cs" />
58+
<Compile Include="UpdateAnalyzerTest.cs" />
59+
</ItemGroup>
60+
<ItemGroup>
61+
<None Include="packages.config" />
62+
</ItemGroup>
63+
<ItemGroup>
64+
<ProjectReference Include="..\HintServiceMeow\HintServiceMeow.csproj">
65+
<Project>{097b585f-438d-4d50-a8ac-0fe0e3a7de77}</Project>
66+
<Name>HintServiceMeow</Name>
67+
</ProjectReference>
68+
</ItemGroup>
69+
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
70+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
71+
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
72+
<PropertyGroup>
73+
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
74+
</PropertyGroup>
75+
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.props'))" />
76+
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.targets'))" />
77+
</Target>
78+
<Import Project="..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.targets')" />
79+
</Project>

HintServiceMeow.Tests/Logger.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using HintServiceMeow.Core.Interface;
2+
using System;
3+
4+
namespace HintServiceMeow.Tests
5+
{
6+
public class TestLogger : ILogger
7+
{
8+
public void Info(object message)
9+
{
10+
Console.Write("[Test][Info]");
11+
Console.WriteLine(message);
12+
}
13+
14+
public void Error(object message)
15+
{
16+
Console.Write("[Test][Error]");
17+
Console.WriteLine(message);
18+
}
19+
}
20+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
using HintServiceMeow.Core.Utilities;
2+
using Microsoft.VisualStudio.TestTools.UnitTesting;
3+
using System;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
7+
namespace HintServiceMeow.Tests
8+
{
9+
[TestClass]
10+
public class PeriodicRunnerTests
11+
{
12+
private static readonly TimeSpan ShortInterval = TimeSpan.FromMilliseconds(30);
13+
14+
private static TimeSpan GetLength(TimeSpan interval, int times)
15+
{
16+
return TimeSpan.FromTicks((long)(interval.Ticks * times));
17+
}
18+
19+
[TestMethod]
20+
public async Task Start_RunsPeriodically()
21+
{
22+
int count = 0;
23+
24+
using (var runner = PeriodicRunner.Start(
25+
() =>
26+
{
27+
Interlocked.Increment(ref count);
28+
return Task.CompletedTask;
29+
},
30+
ShortInterval,
31+
runImmediately: false))
32+
{
33+
await Task.Delay(GetLength(ShortInterval, 5));
34+
Assert.IsTrue(count >= 4);
35+
}
36+
}
37+
38+
[TestMethod]
39+
public async Task Start_WithRunImmediately_InvokesAtOnce()
40+
{
41+
int count = 0;
42+
43+
using (var runner = PeriodicRunner.Start(
44+
() =>
45+
{
46+
Interlocked.Increment(ref count);
47+
return Task.CompletedTask;
48+
},
49+
ShortInterval,
50+
runImmediately: true))
51+
{
52+
await Task.Delay(TimeSpan.FromMilliseconds(10));
53+
Assert.AreEqual(1, count);
54+
}
55+
}
56+
57+
[TestMethod]
58+
public async Task PauseAndResume_Works()
59+
{
60+
int count = 0;
61+
62+
using (var runner = PeriodicRunner.Start(
63+
() =>
64+
{
65+
Interlocked.Increment(ref count);
66+
return Task.CompletedTask;
67+
},
68+
ShortInterval))
69+
{
70+
await Task.Delay(GetLength(ShortInterval, 3));
71+
int beforePause = count;
72+
73+
runner.Pause();
74+
await Task.Delay(GetLength(ShortInterval, 4));
75+
Assert.AreEqual(beforePause, count);
76+
77+
runner.Resume();
78+
await Task.Delay(GetLength(ShortInterval, 3));
79+
Assert.IsTrue(count > beforePause);
80+
}
81+
}
82+
83+
[TestMethod]
84+
public async Task Dispose_StopsFurtherInvocations()
85+
{
86+
int count = 0;
87+
var runner = PeriodicRunner.Start(
88+
() =>
89+
{
90+
Interlocked.Increment(ref count);
91+
return Task.CompletedTask;
92+
},
93+
ShortInterval);
94+
95+
await Task.Delay(GetLength(ShortInterval, 3));
96+
int beforeDispose = count;
97+
98+
runner.Dispose();
99+
await Task.Delay(GetLength(ShortInterval, 4));
100+
Assert.AreEqual(beforeDispose, count);
101+
102+
await runner.CurrentTask;
103+
}
104+
105+
[TestMethod]
106+
public async Task Callback_Exception_IsSwallowedAndContinues()
107+
{
108+
int count = 0;
109+
110+
using (var runner = PeriodicRunner.Start(
111+
() =>
112+
{
113+
int cur = Interlocked.Increment(ref count);
114+
if (cur == 1)
115+
throw new InvalidOperationException("Test");
116+
return Task.CompletedTask;
117+
},
118+
ShortInterval))
119+
{
120+
await Task.Delay(GetLength(ShortInterval, 4));
121+
Assert.IsTrue(count >= 3);
122+
}
123+
}
124+
125+
[TestMethod]
126+
[ExpectedException(typeof(ArgumentOutOfRangeException))]
127+
public void NegativeInterval_Throws()
128+
{
129+
PeriodicRunner.Start(() => Task.CompletedTask,
130+
TimeSpan.FromMilliseconds(-1));
131+
}
132+
}
133+
}

0 commit comments

Comments
 (0)