Skip to content

Commit 0abe9ca

Browse files
authored
Continuous Benchmark (#162)
* Do a Benchmark * Test out new v1 * No Linux? * Fix tests * Use Solution Filters * Exclude Ios from cross-platform because of novotnyllc/MSBuildSdkExtras#102 * Fix paths * Use every feature that make sense * Build Everything * Use Exponential instead * Run benchmark 1 * Run benchmark 2 * Just don't do microbenchmarks... * Be more lenient with respect to CI fluctuations * Note * Ready * Update Avalonia
1 parent 89696e3 commit 0abe9ca

File tree

35 files changed

+352
-226
lines changed

35 files changed

+352
-226
lines changed

.github/workflows/Benchmark.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Benchmark
2+
3+
on: [push, pull_request]
4+
jobs:
5+
Rendering:
6+
runs-on: windows-latest
7+
steps:
8+
- uses: actions/checkout@v2
9+
with:
10+
submodules: 'recursive'
11+
- name: Setup .NET Core
12+
uses: actions/setup-dotnet@v1
13+
with:
14+
dotnet-version: 3.1.401
15+
- run: dotnet run -p CSharpMath.Rendering.Benchmarks
16+
- name: Store benchmark result
17+
uses: Happypig375/github-action-benchmark@v1
18+
with:
19+
name: CSharpMath.Rendering.Benchmarks
20+
tool: 'benchmarkdotnet'
21+
output-file-path: .benchmarkresults/results/CSharpMath.Rendering.Benchmarks.Program-report-full-compressed.json
22+
github-token: ${{ github.token }}
23+
auto-push: ${{ github.ref == 'refs/heads/master' }} # Push and deploy GitHub pages branch automatically
24+
alert-threshold: 140% # Should not be lower than 140% to take account of fluctuations of CI load, see https://github.com/verybadcat/CSharpMath/commit/51a3c066372ab486edb44a424c6ba61ea35914c5
25+
comment-on-alert: true # Show alert with commit comment on detecting possible performance regression
26+
fail-on-alert: true
27+
alert-comment-cc-users: '@Happypig375'

.github/workflows/Build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Build
22

33
on: [push, pull_request]
44
jobs:
5-
all_projects:
5+
Everything:
66
runs-on: windows-latest
77
steps:
88
- uses: actions/checkout@v2
@@ -11,7 +11,7 @@ jobs:
1111
- name: Setup .NET Core
1212
uses: actions/setup-dotnet@v1
1313
with:
14-
dotnet-version: '3.1.302'
14+
dotnet-version: '3.1.401'
1515
- name: Setup NuGet
1616
uses: NuGet/setup-nuget@v1.0.2
1717
- name: Setup MSBuild Path

.github/workflows/Release.yml

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,35 +13,16 @@ jobs:
1313
- name: Setup .NET Core
1414
uses: actions/setup-dotnet@v1
1515
with:
16-
dotnet-version: '3.1.302'
16+
dotnet-version: '3.1.401'
1717
- name: Build GitHub Releases draft artifacts
1818
env:
1919
RELEASE_NOTES: |
2020
# ${{ github.event.release.name }}
2121
2222
${{ github.event.release.body }}
23-
# run: dotnet test CSharpMath.CrossPlatform.slnf
24-
run: | # https://github.com/dotnet/sdk/issues/10409, https://github.com/dotnet/sdk/issues/11417
25-
# .NET Core MSBuild cannot parse , and ; correctly so we replace them with substitutions: https://github.com/dotnet/msbuild/issues/471#issuecomment-366268743
26-
# https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion
27-
# ${parameter/pattern/string} If pattern begins with ‘/’, all matches of pattern are replaced with string. Normally only the first match is replaced.
28-
RELEASE_NOTES=${RELEASE_NOTES//,/%2C}
29-
RELEASE_NOTES=${RELEASE_NOTES//;/%3B}
30-
for p in\
31-
"CSharpMath.CoreTests"\
32-
"CSharpMath.Editor.Tests"\
33-
"CSharpMath.Editor.Tests.FSharp"\
34-
"CSharpMath.Evaluation.Tests"\
35-
`# "CSharpMath.Ios" # https://github.com/dotnet/sdk/issues/11108 + https://github.com/release-drafter/release-drafter/issues/558`\
36-
"CSharpMath.Rendering.Tests"\
37-
"CSharpMath.Rendering.Text.Tests"\
38-
"CSharpMath.Xaml.Tests"\
39-
"CSharpMath.Xaml.Tests.NuGet"\
40-
"Typography/Typography.TextBreak/Typography.TextBreak.UnitTests"
41-
do
42-
# -r for restore
43-
dotnet msbuild -r -p:Configuration=Release -p:PackageVersion="${{ github.event.release.tag_name }}" -p:PackageReleaseNotes="$RELEASE_NOTES" "$p"
44-
done
23+
run: |
24+
# -r for restore
25+
dotnet msbuild -r -p:Configuration=Release -p:PackageVersion="${{ github.event.release.tag_name }}" -p:PackageReleaseNotes="$RELEASE_NOTES" CSharpMath.CrossPlatform.slnf
4526
- name: Upload to GitHub Releases
4627
uses: svenstaro/upload-release-action@v2
4728
with:
@@ -51,11 +32,6 @@ jobs:
5132
file_glob: true
5233
overwrite: true
5334
- name: Upload to NuGet
54-
run: |
55-
for x in `ls .nupkgs/*.nupkg`
56-
do
57-
# Use --skip-duplicate since we want re-runs of this workflow to succeed in case of network issues
58-
dotnet nuget push $x -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json --skip-duplicate
59-
done
60-
# Following command does not work... https://github.com/NuGet/Home/issues/9867
61-
# dotnet nuget push .nupkgs/ -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json --skip-duplicate
35+
run: | # We use double quotes to avoid shell globbing: https://github.com/NuGet/Home/issues/4393#issuecomment-667618120
36+
# Use --skip-duplicate since we want re-runs of this workflow to succeed in case of network issues
37+
dotnet nuget push ".nupkgs/*.nupkg" -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json --skip-duplicate

.github/workflows/Test.yml

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- name: Setup .NET Core # Required to execute ReportGenerator
1717
uses: actions/setup-dotnet@v1
1818
with:
19-
dotnet-version: '3.1.302'
19+
dotnet-version: '3.1.401'
2020
- name: Update dependencies in CSharpMath.Xaml.Tests.NuGet
2121
run: |
2222
dotnet tool install -g dotnet-outdated
@@ -32,28 +32,16 @@ jobs:
3232
# ${{ steps.release_drafter.outputs.name }}
3333
3434
${{ steps.release_drafter.outputs.body }}
35-
# run: dotnet test CSharpMath.CrossPlatform.slnf
35+
# run: dotnet test
3636
run: | # https://github.com/dotnet/sdk/issues/10409, https://github.com/dotnet/sdk/issues/11417
3737
# .NET Core MSBuild cannot parse , and ; correctly so we replace them with substitutions: https://github.com/dotnet/msbuild/issues/471#issuecomment-366268743
3838
# https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion
3939
# ${parameter/pattern/string} If pattern begins with ‘/’, all matches of pattern are replaced with string. Normally only the first match is replaced.
4040
RELEASE_NOTES=${RELEASE_NOTES//,/%2C}
4141
RELEASE_NOTES=${RELEASE_NOTES//;/%3B}
42-
for p in\
43-
"CSharpMath.CoreTests"\
44-
"CSharpMath.Editor.Tests"\
45-
"CSharpMath.Editor.Tests.FSharp"\
46-
"CSharpMath.Evaluation.Tests"\
47-
`# "CSharpMath.Ios" # https://github.com/dotnet/sdk/issues/11108 + https://github.com/release-drafter/release-drafter/issues/558`\
48-
"CSharpMath.Rendering.Tests"\
49-
"CSharpMath.Rendering.Text.Tests"\
50-
"CSharpMath.Xaml.Tests"\
51-
"CSharpMath.Xaml.Tests.NuGet"\
52-
"Typography/Typography.TextBreak/Typography.TextBreak.UnitTests"
53-
do
54-
# --collect:"XPlat Code Coverage" means collect test coverage with https://github.com/coverlet-coverage/coverlet
55-
dotnet test "$p" -c Release -l GitHubActions --blame --collect:"XPlat Code Coverage" -r .testcoverage -p:PackageReleaseNotes="$RELEASE_NOTES" -p:PackageVersion=${{ steps.release_drafter.outputs.tag_name || format('{0}-pr', github.event.number) }}-ci-${{ github.sha }}
56-
done
42+
43+
# --collect:"XPlat Code Coverage" means collect test coverage with https://github.com/coverlet-coverage/coverlet
44+
dotnet test CSharpMath.CrossPlatform.slnf -c Release -l GitHubActions --blame --collect:"XPlat Code Coverage" -r .testcoverage -p:PackageReleaseNotes="$RELEASE_NOTES" -p:PackageVersion=${{ steps.release_drafter.outputs.tag_name || format('{0}-pr', github.event.number) }}-ci-${{ github.sha }}
5745
- name: Run ReportGenerator on Test Coverage results
5846
uses: danielpalme/ReportGenerator-GitHub-Action@4.6.4
5947
with:
@@ -98,14 +86,8 @@ jobs:
9886
# Original code before using this tool:
9987
# # Non-Windows platforms require --store-password-in-clear-text: https://github.com/NuGet/Home/issues/1851
10088
# dotnet nuget add source https://nuget.pkg.github.com/verybadcat/index.json -n github -u verybadcat -p ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text
101-
# for x in `ls .nupkgs/*.nupkg` # Don't let GitHub Releases interpret .snupkg as .nupkg
102-
# do
103-
# # The GitHub Package registry does not support .snupkg files so we specify --no-symbols
104-
# # Use --skip-duplicate since we want re-runs of this workflow to succeed in case of network issues
105-
# dotnet nuget push $x --source "github" --skip-duplicate --no-symbols
106-
# done
107-
# # Following command does not work... https://github.com/NuGet/Home/issues/9867
108-
# # dotnet nuget push .nupkgs/*.nupkg --source "github" --skip-duplicate --no-symbols # Don't let GitHub Releases interpret .snupkg as .nupkg
89+
# # We use double quotes to avoid shell globbing: https://github.com/NuGet/Home/issues/4393#issuecomment-667618120
90+
# dotnet nuget push ".nupkgs/*.nupkg" --source "github" --skip-duplicate --no-symbols # Don't let GitHub Releases interpret .snupkg as .nupkg
10991
Ios:
11092
runs-on: macos-latest
11193
steps:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ CSharpMath.Rendering.Tests/*/*.*.png
99
CSharpMath.Xaml.Tests.NuGet/Test.*.png
1010

1111
# Ignore generated content
12+
/.benchmarkresults
1213
/.nupkgs
1314
/.testcoverage
1415

CSharpMath.Avalonia.Example/CSharpMath.Avalonia.Example.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
<Compile Update="**\*.xaml.cs" DependentUpon="%(Filename)" />
1010
<AvaloniaResource Include="**\*.xaml" />
1111
<EmbeddedResource Include="..\Icon.png" Link="Icon.png" />
12-
<PackageReference Include="Avalonia.Desktop" Version="0.10.0-preview2" />
13-
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.0-preview2" />
12+
<PackageReference Include="Avalonia.Desktop" Version="$(AvaloniaVersion)" />
13+
<PackageReference Include="Avalonia.Diagnostics" Version="$(AvaloniaVersion)" />
1414
<ProjectReference Include="..\CSharpMath.Avalonia\CSharpMath.Avalonia.csproj" />
1515
<ProjectReference Include="..\CSharpMath.Evaluation\CSharpMath.Evaluation.csproj" />
1616
</ItemGroup>

CSharpMath.Avalonia/CSharpMath.Avalonia.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<ItemGroup>
1111
<Compile Update="**\*.xaml.cs" DependentUpon="%(Filename)" />
1212
<AvaloniaResource Include="**\*.xaml" />
13-
<PackageReference Include="Avalonia" Version="0.10.0-preview2" />
13+
<PackageReference Include="Avalonia" Version="$(AvaloniaVersion)" />
1414
<ProjectReference Include="..\CSharpMath.Rendering\CSharpMath.Rendering.csproj" />
1515
</ItemGroup>
1616

CSharpMath.Avalonia/Extensions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ public static void DrawAsPng<TContent>
4949
float textPainterCanvasWidth = TextPainter.DefaultCanvasWidth,
5050
CSharpMathTextAlignment alignment = CSharpMathTextAlignment.TopLeft) where TContent : class {
5151
if (!(painter.Measure(textPainterCanvasWidth) is { } size)) return;
52+
// RenderTargetBitmap does not support zero width/height. ArgumentException will be thrown.
53+
if (size.Width is 0) size.Width = 1;
54+
if (size.Height is 0) size.Height = 1;
5255
using var bitmap =
5356
new RenderTargetBitmap(new PixelSize((int)size.Width, (int)size.Height));
5457
bitmap.Render(new DrawVisual<TContent>(painter, size, alignment));

CSharpMath.CoreTests/DictionaryTests.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33

44
namespace CSharpMath.CoreTests {
55
public class DictionaryTests {
6-
private AliasBiDictionary<string, int> InitTestDict() {
7-
return new AliasBiDictionary<string, int>{
6+
private AliasBiDictionary<string, int> InitTestDict() =>
7+
new AliasBiDictionary<string, int> {
88
{ "0", 0 },
99
{ "zero", 0 },
1010
{ "1", 1 }
1111
};
12-
}
1312
[Theory]
1413
[InlineData("0", 2, 2, true)]
1514
[InlineData("zero", 2, 2, true)]

CSharpMath.CoreTests/LaTeXParserTest.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,10 @@ public void TestCases2() {
10191019
Assert.Equal(@"\left\{ \, \begin{array}{ll}\textstyle y=x^2-x+3&\textstyle \mathrm{for\ }x\leq 0\\ \textstyle y=x^2+\sqrt{x}-\frac{2}{x}&\textstyle \mathrm{for\ }x>0\end{array}\right. ", LaTeXParser.MathListToLaTeX(list).ToString());
10201020
}
10211021

1022+
[Fact]
1023+
public void TestEmptyLookup() =>
1024+
Assert.Throws<ArgumentException>(() => LaTeXSettings.Commands.TryLookup(ReadOnlySpan<char>.Empty));
1025+
10221026
[Fact]
10231027
public void TestCustom() {
10241028
lock (LaTeXSettings.Commands) {
@@ -1459,6 +1463,8 @@ public void TestHelpfulErrorMessage(string input, int index, string expected) {
14591463
}
14601464

14611465
const string EnquiryControlChar = "\x5"; // https://en.wikipedia.org/wiki/Enquiry_character
1466+
const string HighSurrogate = "\uD83F"; // High surrogate for U+1FFFF (Noncharacter)
1467+
const string LowSurrogate = "\uDFFF"; // Low surrogate for U+1FFFF (Noncharacter)
14621468
[Theory,
14631469
InlineData(@"\", @"Error: Invalid command \
14641470
\
@@ -1640,5 +1646,39 @@ public void TestErrors(string badInput, string expected) {
16401646
Assert.Null(list);
16411647
Assert.Equal(expected.Replace("\r", null), actual);
16421648
}
1649+
// With InlineData, strings are normalized so invalid surrogate pairs will be replaced with U+FFFD
1650+
[Fact]
1651+
public void TestErrorSurrogates() {
1652+
foreach (var (badInput, expected) in new[] {
1653+
(HighSurrogate, @$"Error: Low surrogate not found after high surrogate
1654+
{HighSurrogate}
1655+
↑ (pos 1)"),
1656+
(LowSurrogate, @$"Error: High surrogate not found before low surrogate
1657+
{LowSurrogate}
1658+
↑ (pos 1)"),
1659+
($"{HighSurrogate}a", @$"Error: Low surrogate not found after high surrogate
1660+
{HighSurrogate}a
1661+
↑ (pos 1)"),
1662+
($"{LowSurrogate}a", @$"Error: High surrogate not found before low surrogate
1663+
{LowSurrogate}a
1664+
↑ (pos 1)"),
1665+
($"a{HighSurrogate}", @$"Error: Low surrogate not found after high surrogate
1666+
a{HighSurrogate}
1667+
↑ (pos 2)"),
1668+
($"a{LowSurrogate}", @$"Error: High surrogate not found before low surrogate
1669+
a{LowSurrogate}
1670+
↑ (pos 2)"),
1671+
($"a{HighSurrogate}a", @$"Error: Low surrogate not found after high surrogate
1672+
a{HighSurrogate}a
1673+
↑ (pos 2)"),
1674+
($"a{LowSurrogate}a", @$"Error: High surrogate not found before low surrogate
1675+
a{LowSurrogate}a
1676+
↑ (pos 2)"),
1677+
}) {
1678+
var (list, actual) = LaTeXParser.MathListFromLaTeX(badInput);
1679+
Assert.Null(list);
1680+
Assert.Equal(expected.Replace("\r", null), actual);
1681+
}
1682+
}
16431683
}
16441684
}

0 commit comments

Comments
 (0)