Skip to content

Commit dbe2eda

Browse files
authored
Adds configuration API and retry policy for temp data (#105)
+ Retry policy for temp data + Library Configuration class + TimeoutHelper.ExponentialBackoffTimeout()
1 parent ca7b86c commit dbe2eda

19 files changed

Lines changed: 345 additions & 147 deletions

File tree

Build/BuildScripts/CodeJam.AppVeyor.NUnit.Tests.ps1

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ mkdir "$env:APPVEYOR_BUILD_FOLDER\_Results" -ErrorAction SilentlyContinue
55
$wc = New-Object System.Net.WebClient
66

77
#run .net tests
8-
$targetsDotNet = "net48;net472;net471;net47;net461;net45;net40;net35;net20" -split ";"
8+
$targetsDotNet = "net48;net472;net471;net47;net461;net45;net40" -split ";"
99
foreach ($target in $targetsDotNet) {
1010
$logFileName = "$env:APPVEYOR_BUILD_FOLDER\_Results\$($target)_nunit_results.xml"
1111
$testAssemblies = (gci -include $include -r | `
1212
where { $_.fullname -match "\\bin\\Release\\$($target)" } | `
1313
select -ExpandProperty FullName)
1414

15+
echo ""
16+
echo "=== $target ==="
1517
echo "nunit3-console $testAssemblies --result=$logFileName"
1618
&"nunit3-console" $testAssemblies "--result=$logFileName"
1719
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
@@ -24,6 +26,29 @@ foreach ($target in $targetsDotNet) {
2426
}
2527
}
2628

29+
#run .net 2.x tests
30+
$targetsDotNet = "net35;net20" -split ";"
31+
foreach ($target in $targetsDotNet) {
32+
$logFileName = "$env:APPVEYOR_BUILD_FOLDER\_Results\$($target)_nunit_results.xml"
33+
$testAssemblies = (gci -include $include -r | `
34+
where { $_.fullname -match "\\bin\\Release\\$($target)" } | `
35+
select -ExpandProperty FullName)
36+
37+
echo ""
38+
echo "=== $target ==="
39+
# HACK: see https://github.com/appveyor/ci/issues/3412 for details
40+
echo "nunit3-console $testAssemblies --result=$logFileName" "--framework=net-4.0"
41+
&"nunit3-console" $testAssemblies "--result=$logFileName" "--framework=net-4.0"
42+
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
43+
44+
echo "UploadFile: https://ci.appveyor.com/api/testresults/nunit3/$env:APPVEYOR_JOB_ID from $logFileName"
45+
$wc.UploadFile("https://ci.appveyor.com/api/testresults/nunit3/$env:APPVEYOR_JOB_ID", "$logFileName")
46+
if ($LastExitCode -ne 0) {
47+
echo "FAIL: UploadFile: https://ci.appveyor.com/api/testresults/nunit3/$env:APPVEYOR_JOB_ID from $logFileName"
48+
$host.SetShouldExit($LastExitCode)
49+
}
50+
}
51+
2752
#run .net core tests
2853
$targetsDotNetCore = "netcoreapp3.0;netcoreapp2.1;netcoreapp1.1" -split ";"
2954
foreach ($target in $targetsDotNetCore) {
@@ -32,6 +57,8 @@ foreach ($target in $targetsDotNetCore) {
3257
where { $_.fullname -match "\\bin\\Release\\$($target)" } | `
3358
select -ExpandProperty FullName)
3459

60+
echo ""
61+
echo "=== $target ==="
3562
echo "dotnet vstest $testAssemblies --logger:'trx;LogFileName=$logFileName'"
3663
dotnet vstest $testAssemblies --logger:"trx;LogFileName=$logFileName"
3764
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }

CodeJam.Blocks.Tests/CodeJam.Blocks.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
<!-- NUnit v3.11 is the last version supporting .NET 2.0 -->
2626
<PackageReference Include="NUnit" Version="[3.11.0]" />
2727
<PackageReference Include="NUnit3TestAdapter" Version="[3.15.1]" />
28-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
28+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="[16.2.0]" />
2929
</ItemGroup>
3030
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp1.1'">
3131
<!-- NUnit v3.9 is the last version supporting .NET Core 1.0 -->

CodeJam.Blocks/Services/ServiceProviderHelper.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,15 @@ public static IDisposable Publish<T>(
9191
{
9292
Code.NotNull(publisher, nameof(publisher));
9393
Code.NotNull(instanceFactory, nameof(instanceFactory));
94-
// DONTTOUCH: for valid overload resolution (fails on net35).
9594

95+
// DONTTOUCH: for valid overload resolution (fails on net35).
96+
#if NET40_OR_GREATER || TARGETS_NETSTANDARD || TARGETS_NETCOREAPP
9697
// ReSharper disable once RedundantCast
97-
return publisher.Publish(typeof(T), instanceFactory);
98+
return publisher.Publish(typeof(T), (Func<IServicePublisher, object>)instanceFactory);
99+
#else
100+
// Hack for CS0030 Cannot convert type 'System.Func<CodeJam.Services.IServicePublisher, T>' to 'System.Func<CodeJam.Services.IServicePublisher, object>'
101+
return publisher.Publish(typeof(T), new Func<IServicePublisher, object>(sp => instanceFactory(sp)));
102+
#endif
98103
}
99104
}
100105
}

CodeJam.Experimental.Tests/UseCases/EnumCodeUseCases.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
using System.Globalization;
44
using System.Threading;
55

6-
using CodeJam.Internal;
7-
86
using JetBrains.Annotations;
97

108
using NUnit.Framework;
@@ -17,26 +15,21 @@ namespace CodeJam.UseCases.EnumHelperSamples
1715
public class EnumCodeUseCases
1816
{
1917
#region Test helpers
20-
private bool? _breakOnException;
2118
private CultureInfo _previousCulture;
2219

2320
[OneTimeSetUp]
2421
[UsedImplicitly]
2522
public void SetUp()
2623
{
27-
_breakOnException = CodeExceptionsHelper.BreakOnException;
2824
_previousCulture = Thread.CurrentThread.CurrentUICulture;
29-
CodeExceptionsHelper.BreakOnException = false;
3025
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
3126
}
3227

3328
[OneTimeTearDown]
3429
[UsedImplicitly]
3530
public void TearDown()
3631
{
37-
Code.NotNull(_breakOnException, nameof(_breakOnException));
3832
Code.NotNull(_previousCulture, nameof(_previousCulture));
39-
CodeExceptionsHelper.BreakOnException = _breakOnException.GetValueOrDefault();
4033
Thread.CurrentThread.CurrentUICulture = _previousCulture;
4134
}
4235
#endregion

CodeJam.Main.Tests/Assertions/CodeTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public void TestLogging()
2525
{
2626
TraceOutputOptions = TraceOptions.None
2727
};
28-
var ts = CodeExceptionsHelper.CodeTraceSource;
28+
var ts = Configuration.CodeTraceSource;
2929
var logLevel = ts.Switch.Level;
3030
try
3131
{

CodeJam.Main.Tests/CodeJam.Main.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<!-- NUnit v3.11 is the last version supporting .NET 2.0 -->
2727
<PackageReference Include="NUnit" Version="[3.11.0]" />
2828
<PackageReference Include="NUnit3TestAdapter" Version="[3.15.1]" />
29-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
29+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="[16.2.0]" />
3030
</ItemGroup>
3131
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp1.1'">
3232
<!-- NUnit v3.9 is the last version supporting .NET Core 1.0 -->

CodeJam.Main.Tests/IO/TempDataTests.cs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,31 @@
22
using System.IO;
33
using System.Runtime.CompilerServices;
44
using System.Text;
5+
using System.Threading;
6+
7+
using CodeJam.Internal;
58

69
using NUnit.Framework;
710

811
namespace CodeJam.IO
912
{
1013
[TestFixture(Category = "IO")]
14+
[NonParallelizable]
1115
public class TempDataTests
1216
{
1317
#region Test helpers
1418
private static void AssertDisposed<T>(Func<T> memberCallback) =>
1519
Assert.Throws<ObjectDisposedException>(() => memberCallback());
16-
#endregion
20+
21+
// DONTTOUCH: DO NOT use [OneTimeSetUp] here as some tests may override the retry policy
22+
[SetUp]
23+
public static void SetupDisableTempDataRetry() =>
24+
Configuration.SetTempDataRetryCallback(a => a());
25+
26+
// DONTTOUCH: DO NOT use [OneTimeTearDown] here as some tests may override the retry policy
27+
[TearDown]
28+
public static void TearDownRestoreTempDataRetry() =>
29+
Configuration.SetTempDataRetryCallback(null);
1730

1831
[MethodImpl(MethodImplOptions.NoInlining)]
1932
private static string CreateAndLeakTempDir(string s)
@@ -26,6 +39,7 @@ private static string CreateAndLeakTempDir(string s)
2639
GC.KeepAlive(dir2);
2740
return dir2Path;
2841
}
42+
#endregion
2943

3044
[Test]
3145
public void TestDirectory()
@@ -98,6 +112,46 @@ public void TestDirectoryNestedContent()
98112
Assert.IsFalse(File.Exists(nestedFile), "File should NOT exist");
99113
}
100114

115+
[Test]
116+
public void TestRetryPolicy()
117+
{
118+
int disposeCallCount = 0;
119+
try
120+
{
121+
Configuration.SetTempDataRetryCallback(
122+
a =>
123+
{
124+
Interlocked.Increment(ref disposeCallCount);
125+
a();
126+
});
127+
128+
string dirPath;
129+
string nestedFile;
130+
using (var dir = TempData.CreateDirectory())
131+
{
132+
dirPath = dir.Path;
133+
nestedFile = Path.Combine(dirPath, "test.tmp");
134+
135+
using (File.Create(nestedFile))
136+
{
137+
Assert.Throws<IOException>(() => dir.Dispose());
138+
Assert.AreEqual(disposeCallCount, 1);
139+
}
140+
141+
Assert.DoesNotThrow(() => dir.Dispose());
142+
Assert.AreEqual(disposeCallCount, 2);
143+
144+
}
145+
Assert.AreEqual(disposeCallCount, 2);
146+
Assert.IsFalse(Directory.Exists(dirPath), "Directory should NOT exist");
147+
Assert.IsFalse(File.Exists(nestedFile), "File should NOT exist");
148+
}
149+
finally
150+
{
151+
Configuration.SetTempDataRetryCallback(null);
152+
}
153+
}
154+
101155
[Test]
102156
public void TestDirectorySpecificPath()
103157
{

CodeJam.Main.Tests/TestTools.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ namespace CodeJam
1616
public static class TestTools
1717
{
1818
[NotNull]
19-
public static Random GetTestRandom() =>
20-
GetTestRandom(new Random().Next());
19+
public static Random GetTestRandom([CallerMemberName] string memberName = "") =>
20+
GetTestRandom(new Random().Next(), memberName);
2121

2222
[NotNull]
2323
[MethodImpl(MethodImplOptions.NoInlining)]

CodeJam.Main.Tests/Threading/TimeoutHelperTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,21 @@ public void TestAdjustTimeoutLimitInfiniteIfDefault()
7474
Assert.AreEqual(dMinus1.AdjustTimeout(d1, infiniteIfDefault), d1);
7575
Assert.AreEqual(dMinus1.AdjustTimeout(dMinus1, infiniteIfDefault), TimeoutHelper.InfiniteTimeSpan);
7676
}
77+
78+
[TestCase(0, 1)]
79+
[TestCase(1, 1)]
80+
[TestCase(4, 8)]
81+
[TestCase(6, 32)]
82+
[TestCase(8, 60)]
83+
[TestCase(10, 60)]
84+
[TestCase(100, 60)]
85+
public void TestBackoff(int retry, int resultSeconds)
86+
{
87+
var delay = TimeSpan.FromSeconds(1);
88+
var max = TimeSpan.FromMinutes(1);
89+
var timeoutSeconds = TimeoutHelper.ExponentialBackoffTimeout(retry, delay, max).TotalSeconds;
90+
91+
Assert.That(timeoutSeconds, Is.InRange(resultSeconds * 0.8, resultSeconds * 1.2));
92+
}
7793
}
7894
}

CodeJam.Main/Assertions/CodeExceptions.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Diagnostics;
33

4+
using CodeJam.Internal;
5+
46
using JetBrains.Annotations;
57

68
using static CodeJam.Internal.CodeExceptionsHelper;

0 commit comments

Comments
 (0)