-
Notifications
You must be signed in to change notification settings - Fork 149
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added tests for SocketException using --explore
- Loading branch information
Showing
12 changed files
with
393 additions
and
0 deletions.
There are no files selected for viewing
19 changes: 19 additions & 0 deletions
19
src/NUnitEngine/mock-assembly/AccessesCurrentTestContextDuringDiscovery.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using NUnit.Framework; | ||
|
||
namespace NUnit.Tests | ||
{ | ||
public class AccessesCurrentTestContextDuringDiscovery | ||
{ | ||
public static int[] TestCases() | ||
{ | ||
var _ = TestContext.CurrentContext; | ||
return new[] { 0 }; | ||
} | ||
|
||
[TestCaseSource(nameof(TestCases))] | ||
public void Access_by_TestCaseSource(int arg) { } | ||
|
||
[Test] | ||
public void Access_by_ValueSource([ValueSource(nameof(TestCases))] int arg) { } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using System; | ||
using System.Threading; | ||
|
||
namespace NUnit.Engine.Tests.Helpers | ||
{ | ||
public static class On | ||
{ | ||
public static IDisposable Dispose(Action action) => new OnDisposeAction(action); | ||
private sealed class OnDisposeAction : IDisposable | ||
{ | ||
private Action action; | ||
|
||
public OnDisposeAction(Action action) | ||
{ | ||
this.action = action; | ||
} | ||
|
||
public void Dispose() => Interlocked.Exchange(ref action, null)?.Invoke(); | ||
} | ||
} | ||
} |
116 changes: 116 additions & 0 deletions
116
src/NUnitEngine/nunit.engine.tests/Helpers/ProcessUtils.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Text; | ||
|
||
namespace NUnit.Engine.Tests.Helpers | ||
{ | ||
public static class ProcessUtils | ||
{ | ||
public static ProcessResult Run(ProcessStartInfo startInfo) | ||
{ | ||
startInfo.UseShellExecute = false; | ||
startInfo.RedirectStandardOutput = true; | ||
startInfo.RedirectStandardError = true; | ||
startInfo.CreateNoWindow = true; | ||
|
||
using (var process = new Process { StartInfo = startInfo }) | ||
{ | ||
var standardStreamData = new List<StandardStreamData>(); | ||
var currentData = new StringBuilder(); | ||
var currentDataIsError = false; | ||
|
||
process.OutputDataReceived += (sender, e) => | ||
{ | ||
if (e.Data == null) return; | ||
if (currentDataIsError) | ||
{ | ||
if (currentData.Length != 0) | ||
standardStreamData.Add(new StandardStreamData(currentDataIsError, currentData.ToString())); | ||
currentData = new StringBuilder(); | ||
currentDataIsError = false; | ||
} | ||
currentData.AppendLine(e.Data); | ||
}; | ||
process.ErrorDataReceived += (sender, e) => | ||
{ | ||
if (e.Data == null) return; | ||
if (!currentDataIsError) | ||
{ | ||
if (currentData.Length != 0) | ||
standardStreamData.Add(new StandardStreamData(currentDataIsError, currentData.ToString())); | ||
currentData = new StringBuilder(); | ||
currentDataIsError = true; | ||
} | ||
currentData.AppendLine(e.Data); | ||
}; | ||
|
||
process.Start(); | ||
process.BeginOutputReadLine(); | ||
process.BeginErrorReadLine(); | ||
process.WaitForExit(); | ||
|
||
if (currentData.Length != 0) | ||
standardStreamData.Add(new StandardStreamData(currentDataIsError, currentData.ToString())); | ||
|
||
return new ProcessResult(process.ExitCode, standardStreamData.ToArray()); | ||
} | ||
} | ||
|
||
[DebuggerDisplay("{ToString(),nq}")] | ||
public struct ProcessResult | ||
{ | ||
public ProcessResult(int exitCode, StandardStreamData[] standardStreamData) | ||
{ | ||
ExitCode = exitCode; | ||
StandardStreamData = standardStreamData; | ||
} | ||
|
||
public int ExitCode { get; } | ||
public StandardStreamData[] StandardStreamData { get; } | ||
|
||
public override string ToString() => ToString(true); | ||
|
||
/// <param name="showStreamSource">If true, appends "[stdout] " or "[stderr] " to the beginning of each line.</param> | ||
public string ToString(bool showStreamSource) | ||
{ | ||
var r = new StringBuilder("Exit code ").Append(ExitCode); | ||
|
||
if (StandardStreamData.Length != 0) r.AppendLine(); | ||
|
||
foreach (var data in StandardStreamData) | ||
{ | ||
if (showStreamSource) | ||
{ | ||
var lines = data.Data.Split(new[] { Environment.NewLine }, StringSplitOptions.None); | ||
|
||
// StandardStreamData.Data always ends with a blank line, so skip that | ||
for (var i = 0; i < lines.Length - 1; i++) | ||
r.Append(data.IsError ? "[stderr] " : "[stdout] ").AppendLine(lines[i]); | ||
} | ||
else | ||
{ | ||
r.Append(data.Data); | ||
} | ||
} | ||
|
||
return r.ToString(); | ||
} | ||
} | ||
|
||
[DebuggerDisplay("{ToString(),nq}")] | ||
public struct StandardStreamData | ||
{ | ||
public StandardStreamData(bool isError, string data) | ||
{ | ||
IsError = isError; | ||
Data = data; | ||
} | ||
|
||
public bool IsError { get; } | ||
public string Data { get; } | ||
|
||
public override string ToString() => (IsError ? "[stderr] " : "[stdout] ") + Data; | ||
} | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
src/NUnitEngine/nunit.engine.tests/Helpers/ShadowCopyUtils.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Reflection; | ||
|
||
namespace NUnit.Engine.Tests.Helpers | ||
{ | ||
public static class ShadowCopyUtils | ||
{ | ||
/// <summary> | ||
/// Returns the transitive closure of assemblies needed to copy. | ||
/// Deals with assembly names rather than paths to work with runners that shadow copy. | ||
/// </summary> | ||
public static ICollection<string> GetAllNeededAssemblyPaths(params string[] assemblyNames) | ||
{ | ||
var r = new HashSet<string>(StringComparer.OrdinalIgnoreCase); | ||
|
||
var dependencies = StackEnumerator.Create( | ||
from assemblyName in assemblyNames | ||
select new AssemblyName(assemblyName)); | ||
|
||
foreach (var dependencyName in dependencies) | ||
{ | ||
var dependency = Assembly.ReflectionOnlyLoad(dependencyName.FullName); | ||
|
||
if (!dependency.GlobalAssemblyCache && r.Add(Path.GetFullPath(dependency.Location))) | ||
{ | ||
dependencies.Recurse(dependency.GetReferencedAssemblies()); | ||
} | ||
} | ||
|
||
return r; | ||
} | ||
} | ||
} |
76 changes: 76 additions & 0 deletions
76
src/NUnitEngine/nunit.engine.tests/Helpers/StackEnumerator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.ComponentModel; | ||
using System.Linq; | ||
|
||
namespace NUnit.Engine.Tests.Helpers | ||
{ | ||
public static class StackEnumerator | ||
{ | ||
public static StackEnumerator<T> Create<T>(params T[] initial) => new StackEnumerator<T>(initial); | ||
public static StackEnumerator<T> Create<T>(IEnumerable<T> initial) => new StackEnumerator<T>(initial); | ||
public static StackEnumerator<T> Create<T>(IEnumerator<T> initial) => new StackEnumerator<T>(initial); | ||
} | ||
|
||
public sealed class StackEnumerator<T> : IDisposable | ||
{ | ||
private readonly Stack<IEnumerator<T>> stack = new Stack<IEnumerator<T>>(); | ||
private IEnumerator<T> current; | ||
|
||
public bool MoveNext() | ||
{ | ||
while (!current.MoveNext()) | ||
{ | ||
current.Dispose(); | ||
if (stack.Count == 0) return false; | ||
current = stack.Pop(); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
public T Current => current.Current; | ||
|
||
public void Recurse(IEnumerator<T> newCurrent) | ||
{ | ||
if (newCurrent == null) return; | ||
stack.Push(current); | ||
current = newCurrent; | ||
} | ||
public void Recurse(IEnumerable<T> newCurrent) | ||
{ | ||
if (newCurrent == null) return; | ||
Recurse(newCurrent.GetEnumerator()); | ||
} | ||
public void Recurse(params T[] newCurrent) | ||
{ | ||
Recurse((IEnumerable<T>)newCurrent); | ||
} | ||
|
||
public StackEnumerator(IEnumerator<T> initial) | ||
{ | ||
current = initial ?? Enumerable.Empty<T>().GetEnumerator(); | ||
} | ||
public StackEnumerator(IEnumerable<T> initial) : this(initial?.GetEnumerator()) | ||
{ | ||
} | ||
public StackEnumerator(params T[] initial) : this((IEnumerable<T>)initial) | ||
{ | ||
} | ||
|
||
// Foreach support | ||
[EditorBrowsable(EditorBrowsableState.Never)] | ||
public StackEnumerator<T> GetEnumerator() | ||
{ | ||
return this; | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
current.Dispose(); | ||
foreach (var item in stack) | ||
item.Dispose(); | ||
stack.Clear(); | ||
} | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
src/NUnitEngine/nunit.engine.tests/Integration/DirectoryWithNeededAssemblies.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System; | ||
using System.IO; | ||
using NUnit.Engine.Tests.Helpers; | ||
|
||
namespace NUnit.Engine.Tests.Integration | ||
{ | ||
internal sealed class DirectoryWithNeededAssemblies : IDisposable | ||
{ | ||
public string Directory { get; } | ||
|
||
/// <summary> | ||
/// Returns the transitive closure of assemblies needed to copy. | ||
/// Deals with assembly names rather than paths to work with runners that shadow copy. | ||
/// </summary> | ||
public DirectoryWithNeededAssemblies(params string[] assemblyNames) | ||
{ | ||
Directory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); | ||
System.IO.Directory.CreateDirectory(Directory); | ||
|
||
foreach (var neededAssembly in ShadowCopyUtils.GetAllNeededAssemblyPaths(assemblyNames)) | ||
{ | ||
File.Copy(neededAssembly, Path.Combine(Directory, Path.GetFileName(neededAssembly))); | ||
} | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
System.IO.Directory.Delete(Directory, true); | ||
} | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
src/NUnitEngine/nunit.engine.tests/Integration/IntegrationTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using NUnit.Framework; | ||
|
||
namespace NUnit.Engine.Tests.Integration | ||
{ | ||
[TestFixture, Category("Integration")] | ||
public abstract class IntegrationTests | ||
{ | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
src/NUnitEngine/nunit.engine.tests/Integration/MockAssemblyInDirectoryWithFramework.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using System; | ||
using System.IO; | ||
using NUnit.Framework; | ||
|
||
namespace NUnit.Engine.Tests.Integration | ||
{ | ||
internal sealed class MockAssemblyInDirectoryWithFramework : IDisposable | ||
{ | ||
private readonly DirectoryWithNeededAssemblies directory; | ||
|
||
public string MockAssemblyDll => Path.Combine(directory.Directory, "mock-assembly.dll"); | ||
|
||
public MockAssemblyInDirectoryWithFramework() | ||
{ | ||
directory = new DirectoryWithNeededAssemblies("mock-assembly"); | ||
|
||
Assert.That(Path.Combine(directory.Directory, "nunit.framework.dll"), Does.Exist, "This test must be run with nunit.framework.dll in the same directory as the mock assembly."); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
directory.Dispose(); | ||
} | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
src/NUnitEngine/nunit.engine.tests/Integration/RemoteAgentTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using System.Diagnostics; | ||
using NUnit.Engine.Tests.Helpers; | ||
using NUnit.Framework; | ||
|
||
namespace NUnit.Engine.Tests.Integration | ||
{ | ||
public sealed class RemoteAgentTests : IntegrationTests | ||
{ | ||
[Test] | ||
public void Explore_does_not_throw_SocketException() | ||
{ | ||
using (var runner = new RunnerInDirectoryWithoutFramework()) | ||
using (var test = new MockAssemblyInDirectoryWithFramework()) | ||
{ | ||
for (var times = 0; times < 3; times++) | ||
{ | ||
var result = ProcessUtils.Run(new ProcessStartInfo(runner.ConsoleExe, $"--explore \"{test.MockAssemblyDll}\"")); | ||
Assert.That(result.StandardStreamData, Has.None.With.Property("Data").Contains("System.Net.Sockets.SocketException")); | ||
Assert.That(result.StandardStreamData, Has.None.With.Property("IsError").True); | ||
Assert.That(result, Has.Property("ExitCode").Zero); | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.