First version added.
This commit is contained in:
1 parent
e126a9d81b
commit
d054376f71
21 files changed
+711
-3
No files matched your search
@@ -0,0 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoFixture" Version="4.17.0" />
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.3" />
|
||||
<PackageReference Include="FluentAssertions" Version="6.8.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.0.2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.0.2" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.2.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Huffman.Tree\Huffman.Tree.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,93 @@
|
||||
using AutoFixture;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using FluentAssertions;
|
||||
using MoreLinq;
|
||||
|
||||
namespace Huffman.Tree.Tests
|
||||
{
|
||||
[TestClass]
|
||||
[MemoryDiagnoser]
|
||||
public class HuffmanTreeTests
|
||||
{
|
||||
public readonly record struct TestCase
|
||||
{
|
||||
public (string token, long frequency)[] Tokens { get; init; }
|
||||
public (string token, int[] bits)[] Expected { get; init; }
|
||||
}
|
||||
|
||||
private static IEnumerable<TestCase> TestCases => EnumerateTestCases().SelectMany(x => x.OfType<TestCase>());
|
||||
|
||||
private IEnumerable<HuffmanToken<string>>? _codes;
|
||||
private (string token, long frequency)[] _tokens;
|
||||
|
||||
public HuffmanTreeTests()
|
||||
{
|
||||
_tokens = TestCases.First().Tokens;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DynamicData(nameof(EnumerateTestCases), DynamicDataSourceType.Method)]
|
||||
public void BuildTreeShouldSuccess(TestCase testCase)
|
||||
{
|
||||
// This is to overcome the requirement for BuildTree() to be argument- & deferred-result-free. It's required by BenchmarkDotNet.
|
||||
_tokens = testCase.Tokens;
|
||||
BuildTree();
|
||||
PrintCodesToOutput();
|
||||
ValidateCodes(testCase.Expected);
|
||||
}
|
||||
|
||||
private void ValidateCodes((string token, int[] bits)[] expected)
|
||||
{
|
||||
var expectedBits = expected.Select(x => (x.token, x.bits.Select(bit => Convert.ToBoolean(bit))));
|
||||
_ = _codes.Should().NotBeNull();
|
||||
_ = _codes!.Select(x => (x.Token, x.Code))
|
||||
.Should()
|
||||
.NotBeNull().And
|
||||
.BeEquivalentTo(expectedBits);
|
||||
}
|
||||
|
||||
private void PrintCodesToOutput()
|
||||
{
|
||||
foreach (var node in _codes!)
|
||||
{
|
||||
string bits = node.Code!.AsString();
|
||||
Console.WriteLine($"{node.Token} => {bits}");
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> EnumerateTestCases()
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
new TestCase
|
||||
{
|
||||
// test case
|
||||
Tokens = new[] { ("a", 10L), ("b", 5L), ("c", 2L), ("d", 14L), ("e", 15L), (";", long.MaxValue) },
|
||||
// expected result
|
||||
Expected = new[] { (";", new[] { 1 }), ("a", new[] { 0, 0, 1 }), ("b", new[] { 0, 0, 0, 1 }), ("c", new[] { 0, 0, 0, 0 }), ("d", new[] { 0, 1, 0 }), ("e", new[] { 0, 1, 1 }) }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void BuildTree()
|
||||
{
|
||||
_codes = _tokens?.AsHuffmanTree().Nodes.OfType<HuffmanToken<string>>();
|
||||
// We keep this assertions here because we want to build all the codes. For this we need to access each of them.
|
||||
_ = _codes.Should().NotBeNull().And.AllSatisfy(node => node.Code!.AsString().Should().NotBeNull().And.NotBe(string.Empty));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
[TestMethod]
|
||||
public void BuildTree100()
|
||||
{
|
||||
var fixture = new Fixture();
|
||||
var collection = fixture.CreateMany<(string token, long frequency)>(100);
|
||||
_tokens = collection.ToArray();
|
||||
_codes = _tokens?.AsHuffmanTree().Nodes.OfType<HuffmanToken<string>>();
|
||||
_codes.ForEach(x => Console.WriteLine($"{x.Token} => {x.Code.AsString()}"));
|
||||
// We keep this assertions here because we want to build all the codes. For this we need to access each of them.
|
||||
_ = _codes.Should().NotBeNull().And.AllSatisfy(node => node.Code!.AsString().Should().NotBeNull().And.NotBe(string.Empty));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
global using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
Reference in new issue
Block a user