diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 034cae4..c31beb8 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"dotnet-format": {
- "version": "4.1.131201",
+ "version": "5.1.225507",
"commands": [
"dotnet-format"
]
diff --git a/Dockerfile b/Dockerfile
index 4d50655..48f0079 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:5.0.202-alpine3.12-amd64 AS build
+FROM mcr.microsoft.com/dotnet/sdk:5.0.202-alpine3.13-amd64 AS build
WORKDIR /app
# Copy csproj and restore as distinct layers
@@ -7,21 +7,14 @@ RUN dotnet restore -r linux-musl-x64
# Copy everything else and build
COPY src/Exercism.TestRunner.CSharp/ ./
-RUN dotnet publish -r linux-musl-x64 -c Release -o /opt/test-runner --no-restore -p:PublishReadyToRun=true
-
-# Pre-install packages for offline usage
-RUN dotnet add package Microsoft.NET.Test.Sdk -v 16.8.3 && \
- dotnet add package xunit -v 2.4.1 && \
- dotnet add package xunit.runner.visualstudio -v 2.4.3 && \
- dotnet add package Exercism.Tests -v 0.1.0-alpha
+RUN dotnet publish -r linux-musl-x64 -c Release -o /opt/test-runner --no-restore --self-contained true
# Build runtime image
-FROM mcr.microsoft.com/dotnet/sdk:5.0.202-alpine3.12-amd64 AS runtime
+FROM mcr.microsoft.com/dotnet/runtime-deps:5.0.5-alpine3.13-amd64 AS runtime
WORKDIR /opt/test-runner
COPY --from=build /opt/test-runner/ .
COPY --from=build /usr/local/bin/ /usr/local/bin/
-COPY --from=build /root/.nuget/packages/ /root/.nuget/packages/
COPY run.sh /opt/test-runner/bin/
diff --git a/src/Exercism.TestRunner.CSharp/Exercism.TestRunner.CSharp.csproj b/src/Exercism.TestRunner.CSharp/Exercism.TestRunner.CSharp.csproj
index a360df8..e9343df 100644
--- a/src/Exercism.TestRunner.CSharp/Exercism.TestRunner.CSharp.csproj
+++ b/src/Exercism.TestRunner.CSharp/Exercism.TestRunner.CSharp.csproj
@@ -6,14 +6,17 @@
false
-
-
-
+
+ true
+
+
-
+
+
+
diff --git a/src/Exercism.TestRunner.CSharp/Options.cs b/src/Exercism.TestRunner.CSharp/Options.cs
index 7a302b5..e1a1e49 100644
--- a/src/Exercism.TestRunner.CSharp/Options.cs
+++ b/src/Exercism.TestRunner.CSharp/Options.cs
@@ -22,10 +22,6 @@ public Options(string slug, string inputDirectory, string outputDirectory) =>
public string TestsFilePath => Path.Combine(InputDirectory, $"{Exercise}Tests.cs");
- public string BuildLogFilePath => Path.Combine(InputDirectory, "msbuild.log");
-
- public string TestResultsFilePath => Path.Combine(InputDirectory, "TestResults", "tests.trx");
-
public string ResultsJsonFilePath => Path.GetFullPath(Path.Combine(OutputDirectory, "results.json"));
private string Exercise => Slug.Dehumanize().Pascalize();
diff --git a/src/Exercism.TestRunner.CSharp/Program.cs b/src/Exercism.TestRunner.CSharp/Program.cs
index 0b5ab7a..d08893e 100644
--- a/src/Exercism.TestRunner.CSharp/Program.cs
+++ b/src/Exercism.TestRunner.CSharp/Program.cs
@@ -15,8 +15,7 @@ private static void CreateTestResults(Options options)
{
Console.WriteLine($"[{DateTimeOffset.UtcNow:u}] Running test runner for '{options.Slug}' solution...");
- var testSuite = TestSuite.FromOptions(options);
- var testRun = testSuite.Run();
+ var testRun = TestSuite.RunTests(options);
testRun.WriteToFile(options.ResultsJsonFilePath);
Console.WriteLine($"[{DateTimeOffset.UtcNow:u}] Ran test runner for '{options.Slug}' solution");
diff --git a/src/Exercism.TestRunner.CSharp/StringExtensions.cs b/src/Exercism.TestRunner.CSharp/StringExtensions.cs
index a8eb2f8..7893652 100644
--- a/src/Exercism.TestRunner.CSharp/StringExtensions.cs
+++ b/src/Exercism.TestRunner.CSharp/StringExtensions.cs
@@ -2,4 +2,7 @@
{
public static string UseUnixNewlines(this string str) =>
str.Replace("\r\n", "\n");
+
+ public static string NullIfEmpty(this string str) =>
+ str == string.Empty ? null : str;
}
\ No newline at end of file
diff --git a/src/Exercism.TestRunner.CSharp/TestCompilation.cs b/src/Exercism.TestRunner.CSharp/TestCompilation.cs
new file mode 100644
index 0000000..48bd5cd
--- /dev/null
+++ b/src/Exercism.TestRunner.CSharp/TestCompilation.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+using Exercism.Tests;
+
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Text;
+
+namespace Exercism.TestRunner.CSharp
+{
+ internal static class TestCompilation
+ {
+ public static Compilation Compile(Options options) =>
+ CSharpCompilation.Create(Guid.NewGuid().ToString("N"), SyntaxTrees(options), References(), CompilationOptions());
+
+ private static IEnumerable SyntaxTrees(Options options)
+ {
+ SyntaxTree ParseSyntaxTree(string file)
+ {
+ var source = SourceText.From(File.OpenRead(file));
+ var syntaxTree = CSharpSyntaxTree.ParseText(source, path: file);
+
+ // We need to rewrite the test suite to un-skip all tests and capture any console output
+ if (file == options.TestsFilePath)
+ {
+ return syntaxTree.Rewrite();
+ }
+
+ return syntaxTree;
+ }
+
+ return Directory.EnumerateFiles(options.InputDirectory, "*.cs", SearchOption.AllDirectories)
+ .Select(ParseSyntaxTree);
+ }
+
+ private static CSharpCompilationOptions CompilationOptions() =>
+ new(OutputKind.DynamicallyLinkedLibrary, optimizationLevel: OptimizationLevel.Release);
+
+ private static IEnumerable References()
+ {
+ var trustedAssembliesPaths = ((string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES"))!.Split(Path.PathSeparator);
+ return trustedAssembliesPaths
+ .Select(p => MetadataReference.CreateFromFile(p))
+ .Append(MetadataReference.CreateFromFile(typeof(Xunit.FactAttribute).Assembly.Location))
+ .Append(MetadataReference.CreateFromFile(typeof(Xunit.Assert).Assembly.Location))
+ .Append(MetadataReference.CreateFromFile(typeof(TaskAttribute).Assembly.Location));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Exercism.TestRunner.CSharp/TestResultParser.cs b/src/Exercism.TestRunner.CSharp/TestResultParser.cs
index e9befb6..eaa3f5b 100644
--- a/src/Exercism.TestRunner.CSharp/TestResultParser.cs
+++ b/src/Exercism.TestRunner.CSharp/TestResultParser.cs
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
-using System.IO;
using System.Linq;
-using System.Xml.Serialization;
using Humanizer;
@@ -10,80 +8,71 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Xunit.Runners;
+
namespace Exercism.TestRunner.CSharp
{
internal static class TestResultParser
{
- internal static TestResult[] FromFile(string logFilePath, SyntaxTree testsSyntaxTree)
+ public static TestResult[] FromTests(IEnumerable tests, SyntaxTree testsSyntaxTree)
{
- using var fileStream = File.OpenRead(logFilePath);
- var result = (XmlTestRun)new XmlSerializer(typeof(XmlTestRun)).Deserialize(fileStream);
-
- if (result.Results == null)
- return Array.Empty();
-
- return result.ToTestResults(testsSyntaxTree);
- }
-
- private static TestResult[] ToTestResults(this XmlTestRun result, SyntaxTree testsSyntaxTree)
- {
- var methodDeclarations =
+ var testMethods =
testsSyntaxTree
.GetRoot()
.DescendantNodes()
.OfType()
.ToArray();
-
- var testResults =
- from unitTestResult in result.Results.UnitTestResult
- let testMethodDeclaration = unitTestResult.TestMethod(methodDeclarations)
- orderby testMethodDeclaration.GetLocation().GetLineSpan().StartLinePosition.Line
- select ToTestResult(unitTestResult, testMethodDeclaration);
- return testResults.ToArray();
+ return tests
+ .Select(test => (test: test, testMethod: test.TestMethod(testMethods)))
+ .OrderBy(testAndMethod => Array.IndexOf(testMethods, testAndMethod.testMethod))
+ .Select(testAndMethod => FromTest(testAndMethod.test, testAndMethod.testMethod))
+ .ToArray();
}
- private static TestResult ToTestResult(XmlUnitTestResult xmlUnitTestResult, MethodDeclarationSyntax testMethodDeclaration) =>
+ private static TestResult FromTest(TestInfo test, MethodDeclarationSyntax testMethod) =>
+ test switch
+ {
+ TestFailedInfo failedTest => FromFailedTest(failedTest, testMethod),
+ TestPassedInfo passedTest => FromPassedTest(passedTest, testMethod),
+ _ => throw new ArgumentOutOfRangeException(nameof(test))
+ };
+
+ private static TestResult FromFailedTest(TestFailedInfo info, MethodDeclarationSyntax testMethod) =>
new()
{
- Name = xmlUnitTestResult.Name(),
- Status = xmlUnitTestResult.Status(),
- Message = xmlUnitTestResult.Message(),
- Output = xmlUnitTestResult.Output(),
- TaskId = testMethodDeclaration.TaskId(),
- TestCode = testMethodDeclaration.TestCode()
+ Name = info.Name(),
+ Status = TestStatus.Fail,
+ Message = info.Message(),
+ Output = info.Output(),
+ TaskId = testMethod.TaskId(),
+ TestCode = testMethod.TestCode()
};
- private static MethodDeclarationSyntax TestMethod(this XmlUnitTestResult xmlUnitTestResult, IEnumerable methodDeclarations)
- {
- var classAndMethodName = xmlUnitTestResult.TestName.Split(".");
- var className = classAndMethodName[0];
- var methodName = classAndMethodName[1];
+ private static TestResult FromPassedTest(TestPassedInfo info, MethodDeclarationSyntax testMethod) =>
+ new()
+ {
+ Name = info.Name(),
+ Status = TestStatus.Pass,
+ Output = info.Output(),
+ TaskId = testMethod.TaskId(),
+ TestCode = testMethod.TestCode()
+ };
- return methodDeclarations.Single(method =>
- method.Identifier.Text == methodName &&
+ private static MethodDeclarationSyntax TestMethod(this TestInfo testInfo, IEnumerable methodDeclarations) =>
+ methodDeclarations.Single(method =>
+ method.Identifier.Text == testInfo.MethodName &&
method.Parent is ClassDeclarationSyntax classDeclaration &&
- classDeclaration.Identifier.Text == className);
- }
-
- private static string Name(this XmlUnitTestResult xmlUnitTestResult) =>
- xmlUnitTestResult.TestName
- .Substring(xmlUnitTestResult.TestName.LastIndexOf(".", StringComparison.Ordinal) + 1)
- .Humanize();
+ classDeclaration.Identifier.Text == testInfo.TypeName);
- private static TestStatus Status(this XmlUnitTestResult xmlUnitTestResult) =>
- xmlUnitTestResult.Outcome switch
- {
- "Passed" => TestStatus.Pass,
- "Failed" => TestStatus.Fail,
- _ => TestStatus.Error
- };
+ private static string Name(this TestInfo testInfo) =>
+ testInfo.MethodName.Humanize();
- private static string Message(this XmlUnitTestResult xmlUnitTestResult) =>
- xmlUnitTestResult.Output?.ErrorInfo?.Message?.UseUnixNewlines()?.Trim();
+ private static string Message(this TestFailedInfo testInfo) =>
+ testInfo.ExceptionMessage.UseUnixNewlines()?.Trim();
- private static string Output(this XmlUnitTestResult xmlUnitTestResult) =>
- xmlUnitTestResult.Output?.StdOut?.UseUnixNewlines()?.Trim();
+ private static string Output(this TestExecutedInfo testInfo) =>
+ testInfo.Output.UseUnixNewlines().Trim().NullIfEmpty();
private static string TestCode(this MethodDeclarationSyntax testMethod)
{
@@ -108,50 +97,4 @@ private static string TestCode(this MethodDeclarationSyntax testMethod)
.Select(taskNumberExpression => (int?)taskNumberExpression.Token.Value!)
.FirstOrDefault();
}
-
- [XmlRoot(ElementName = "Output", Namespace = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010")]
- public class XmlOutput
- {
- [XmlElement(ElementName = "StdOut", Namespace = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010")]
- public string StdOut { get; set; }
-
- [XmlElement(ElementName = "ErrorInfo",
- Namespace = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010")]
- public XmlErrorInfo ErrorInfo { get; set; }
- }
-
- [XmlRoot(ElementName = "UnitTestResult", Namespace = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010")]
- public class XmlUnitTestResult
- {
- [XmlElement(ElementName = "Output", Namespace = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010")]
- public XmlOutput Output { get; set; }
-
- [XmlAttribute(AttributeName = "testName")]
- public string TestName { get; set; }
-
- [XmlAttribute(AttributeName = "outcome")]
- public string Outcome { get; set; }
- }
-
- [XmlRoot(ElementName = "ErrorInfo", Namespace = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010")]
- public class XmlErrorInfo
- {
- [XmlElement(ElementName = "Message", Namespace = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010")]
- public string Message { get; set; }
- }
-
- [XmlRoot(ElementName = "Results", Namespace = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010")]
- public class XmlResults
- {
- [XmlElement(ElementName = "UnitTestResult",
- Namespace = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010")]
- public List UnitTestResult { get; set; }
- }
-
- [XmlRoot(ElementName = "TestRun", Namespace = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010")]
- public class XmlTestRun
- {
- [XmlElement(ElementName = "Results", Namespace = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010")]
- public XmlResults Results { get; set; }
- }
}
\ No newline at end of file
diff --git a/src/Exercism.TestRunner.CSharp/TestRun.cs b/src/Exercism.TestRunner.CSharp/TestRun.cs
index 3a6710a..4ea1a65 100644
--- a/src/Exercism.TestRunner.CSharp/TestRun.cs
+++ b/src/Exercism.TestRunner.CSharp/TestRun.cs
@@ -16,7 +16,7 @@ internal class TestResult
[JsonPropertyName("status")]
public TestStatus Status { get; set; }
-
+
[JsonPropertyName("task_id")]
public int? TaskId { get; set; }
@@ -34,7 +34,7 @@ internal class TestRun
{
[JsonPropertyName("version")]
public int Version { get; set; } = 3;
-
+
[JsonPropertyName("status")]
public TestStatus Status { get; set; }
diff --git a/src/Exercism.TestRunner.CSharp/TestRunParser.cs b/src/Exercism.TestRunner.CSharp/TestRunParser.cs
index 3abdc26..1c9b606 100644
--- a/src/Exercism.TestRunner.CSharp/TestRunParser.cs
+++ b/src/Exercism.TestRunner.CSharp/TestRunParser.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -9,29 +8,12 @@ namespace Exercism.TestRunner.CSharp
{
internal static class TestRunParser
{
- public static TestRun Parse(Options options, SyntaxTree testsSyntaxTree)
- {
- var logLines = File.ReadLines(options.BuildLogFilePath);
- var buildFailed = logLines.Any();
-
- if (buildFailed)
- {
- return TestRunWithError(logLines);
- }
-
- return TestRunWithoutError(options, testsSyntaxTree);
- }
-
- private static TestRun TestRunWithoutError(Options options, SyntaxTree testsSyntaxTree)
- {
- var testResults = TestResultParser.FromFile(options.TestResultsFilePath, testsSyntaxTree);
-
- return new TestRun
+ public static TestRun TestRunWithoutError(TestResult[] testResults) =>
+ new()
{
Status = testResults.ToTestStatus(),
Tests = testResults
};
- }
private static TestStatus ToTestStatus(this TestResult[] tests)
{
@@ -44,31 +26,19 @@ private static TestStatus ToTestStatus(this TestResult[] tests)
return TestStatus.Error;
}
- private static TestRun TestRunWithError(IEnumerable logLines) =>
- new TestRun
+ public static TestRun TestRunWithError(Diagnostic[] logLines) =>
+ new()
{
Message = string.Join("\n", logLines.Select(NormalizeLogLine)),
Status = TestStatus.Error,
Tests = Array.Empty()
};
- private static string NormalizeLogLine(this string logLine) =>
- logLine.RemoveProjectReference().RemovePath().UseUnixNewlines().Trim();
+ private static string NormalizeLogLine(this Diagnostic diagnostic) =>
+ diagnostic.ToString().RemovePath(diagnostic).UseUnixNewlines().Trim();
- private static string RemoveProjectReference(this string logLine) =>
- logLine[..(logLine.LastIndexOf('[') - 1)];
-
- private static string RemovePath(this string logLine)
- {
- var testFileIndex = logLine.IndexOf(".cs(", StringComparison.Ordinal);
- if (testFileIndex == -1)
- return logLine;
-
- var lastDirectorySeparatorIndex = logLine.LastIndexOf(Path.DirectorySeparatorChar, testFileIndex);
- if (lastDirectorySeparatorIndex == -1)
- return logLine;
-
- return logLine.Substring(lastDirectorySeparatorIndex + 1);
- }
+ private static string RemovePath(this string logLine, Diagnostic diagnostic) =>
+ logLine.Replace(diagnostic.Location.SourceTree.FilePath,
+ Path.GetFileName(diagnostic.Location.SourceTree.FilePath));
}
}
\ No newline at end of file
diff --git a/src/Exercism.TestRunner.CSharp/TestRunner.cs b/src/Exercism.TestRunner.CSharp/TestRunner.cs
new file mode 100644
index 0000000..004e58b
--- /dev/null
+++ b/src/Exercism.TestRunner.CSharp/TestRunner.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Threading;
+
+using Microsoft.CodeAnalysis;
+
+using Xunit.Runners;
+
+namespace Exercism.TestRunner.CSharp
+{
+ internal static class TestRunner
+ {
+ public static TestResult[] RunTests(Compilation compilation, Options options)
+ {
+ var outputPath = Path.Combine(Path.GetTempPath(), compilation.SourceModule.Name);
+ compilation.Emit(outputPath);
+ Assembly.LoadFrom(outputPath);
+
+ var tests = new ConcurrentStack();
+ var finished = new ManualResetEventSlim();
+ var runner = AssemblyRunner.WithoutAppDomain(outputPath);
+ runner.OnTestFailed += info => tests.Push(info);
+ runner.OnTestPassed += info => tests.Push(info);
+ runner.OnExecutionComplete += _ => finished.Set();
+
+ runner.Start();
+ finished.Wait();
+
+ var testsSyntaxTree = compilation.SyntaxTrees.First(tree => tree.FilePath == options.TestsFilePath);
+ return TestResultParser.FromTests(tests, testsSyntaxTree);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Exercism.TestRunner.CSharp/TestSuite.cs b/src/Exercism.TestRunner.CSharp/TestSuite.cs
index bc9850d..b547e59 100644
--- a/src/Exercism.TestRunner.CSharp/TestSuite.cs
+++ b/src/Exercism.TestRunner.CSharp/TestSuite.cs
@@ -1,54 +1,24 @@
-using System.Diagnostics;
-using System.IO;
+using System.Linq;
using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
namespace Exercism.TestRunner.CSharp
{
- internal class TestSuite
+ internal static class TestSuite
{
- private readonly SyntaxTree _originalSyntaxTree;
- private readonly Options _options;
-
- private TestSuite(SyntaxTree originalSyntaxTree, Options options)
- {
- _originalSyntaxTree = originalSyntaxTree;
- _options = options;
- }
-
- public TestRun Run()
+ public static TestRun RunTests(Options options)
{
- Rewrite();
- RunDotnetTest();
- UndoRewrite();
+ var compilation = TestCompilation.Compile(options);
- return TestRunParser.Parse(_options, _originalSyntaxTree);
- }
+ var errors = compilation.GetDiagnostics()
+ .Where(diag => diag.Severity == DiagnosticSeverity.Error)
+ .ToArray();
- private void RunDotnetTest()
- {
- var command = "dotnet";
- var arguments = $"test --verbosity=quiet --logger \"trx;LogFileName={Path.GetFileName(_options.TestResultsFilePath)}\" /flp:v=q";
+ if (errors.Any())
+ return TestRunParser.TestRunWithError(errors);
- var processStartInfo = new ProcessStartInfo(command, arguments)
- {
- WorkingDirectory = Path.GetDirectoryName(_options.TestsFilePath)!,
- RedirectStandardInput = true,
- RedirectStandardError = true,
- RedirectStandardOutput = true
- };
- Process.Start(processStartInfo)?.WaitForExit();
- }
-
- private void Rewrite() => File.WriteAllText(_options.TestsFilePath, _originalSyntaxTree.Rewrite().ToString());
-
- private void UndoRewrite() => File.WriteAllText(_options.TestsFilePath, _originalSyntaxTree.ToString());
-
- public static TestSuite FromOptions(Options options)
- {
- var originalSyntaxTree = CSharpSyntaxTree.ParseText(File.ReadAllText(options.TestsFilePath));
- return new TestSuite(originalSyntaxTree, options);
+ var testResults = TestRunner.RunTests(compilation, options);
+ return TestRunParser.TestRunWithoutError(testResults);
}
}
}
\ No newline at end of file
diff --git a/src/Exercism.TestRunner.CSharp/TestsRewriter.cs b/src/Exercism.TestRunner.CSharp/TestsRewriter.cs
index 263870a..8a9f0b7 100644
--- a/src/Exercism.TestRunner.CSharp/TestsRewriter.cs
+++ b/src/Exercism.TestRunner.CSharp/TestsRewriter.cs
@@ -12,8 +12,7 @@ public static SyntaxTree Rewrite(this SyntaxTree tree) =>
tree.WithRootAndOptions(tree.GetRoot().Rewrite(), tree.Options);
private static SyntaxNode Rewrite(this SyntaxNode node) =>
- node
- .UnskipTests()
+ node.UnskipTests()
.CaptureConsoleOutput();
private static SyntaxNode UnskipTests(this SyntaxNode testsRoot) =>
@@ -130,34 +129,7 @@ public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) =>
ArgumentList(
SingletonSeparatedList(
Argument(
- IdentifierName("_stringWriter")))))),
- ExpressionStatement(
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName("System"),
- IdentifierName("Diagnostics")),
- IdentifierName("Trace")),
- IdentifierName("Listeners")),
- IdentifierName("Add")))
- .WithArgumentList(
- ArgumentList(
- SingletonSeparatedList(
- Argument(
- ObjectCreationExpression(
- QualifiedName(
- QualifiedName(
- IdentifierName("System"),
- IdentifierName("Diagnostics")),
- IdentifierName("ConsoleTraceListener")))
- .WithArgumentList(
- ArgumentList())))))))),
+ IdentifierName("_stringWriter")))))))),
MethodDeclaration(
PredefinedType(
Token(SyntaxKind.VoidKeyword)),
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Exercism.TestRunner.CSharp.IntegrationTests.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Exercism.TestRunner.CSharp.IntegrationTests.csproj
index d416643..dc94ae7 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Exercism.TestRunner.CSharp.IntegrationTests.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Exercism.TestRunner.CSharp.IntegrationTests.csproj
@@ -6,7 +6,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/NormalizationExtensions.cs b/test/Exercism.TestRunner.CSharp.IntegrationTests/NormalizationExtensions.cs
index 6670240..865222a 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/NormalizationExtensions.cs
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/NormalizationExtensions.cs
@@ -12,6 +12,6 @@ private static string NormalizeNewlines(this string json) =>
json.Replace("\r\n", "\n");
private static JsonSerializerSettings CreateJsonSerializerSettings() =>
- new JsonSerializerSettings { ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() } };
+ new() { ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() } };
}
}
\ No newline at end of file
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/AllTestsWithTask/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/AllTestsWithTask/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/AllTestsWithTask/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/AllTestsWithTask/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleCompileErrors/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleCompileErrors/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleCompileErrors/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleCompileErrors/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestClassesWithAllPasses/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestClassesWithAllPasses/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestClassesWithAllPasses/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestClassesWithAllPasses/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithAllPasses/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithAllPasses/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithAllPasses/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithAllPasses/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithMultipleFails/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithMultipleFails/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithMultipleFails/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithMultipleFails/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithSingleFail/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithSingleFail/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithSingleFail/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithSingleFail/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutput/Fake.cs b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutput/Fake.cs
index 089f84e..d5d8795 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutput/Fake.cs
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutput/Fake.cs
@@ -5,10 +5,10 @@ public static class Fake
{
public static int Add(int x, int y)
{
- System.Diagnostics.Trace.Write("String ");
+ Console.Out.Write("String ");
Console.Write("without ");
Console.Error.Write("params ");
- System.Diagnostics.Debug.Write("output");
+ Console.Write("output");
return x + y;
}
@@ -19,9 +19,9 @@ public static int Sub(int x, int y)
public static int Mul(int x, int y)
{
- System.Diagnostics.Trace.WriteLine("String with params output");
+ Console.WriteLine("String with params output");
System.Console.WriteLine("Values used:");
- Debug.WriteLine("{0}, {1}", 2, true);
+ Console.WriteLine("{0}, {1}", 2, true);
System.Console.Out.WriteLine("-----");
return x * y;
}
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutput/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutput/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutput/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutput/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutputExceedingLimit/Fake.cs b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutputExceedingLimit/Fake.cs
index da1131a..00801a8 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutputExceedingLimit/Fake.cs
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutputExceedingLimit/Fake.cs
@@ -5,7 +5,7 @@ public static class Fake
{
public static int Add(int x, int y)
{
- Trace.WriteLine(new string('a', 498) + 'b' + 'c' + 'd');
+ Console.WriteLine(new string('a', 498) + 'b' + 'c' + 'd');
return x + y;
}
@@ -13,7 +13,7 @@ public static int Add(int x, int y)
public static int Mul(int x, int y)
{
- Debug.WriteLine("Maximum not exceeded");
+ Console.WriteLine("Maximum not exceeded");
return x * y;
}
}
\ No newline at end of file
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutputExceedingLimit/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutputExceedingLimit/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutputExceedingLimit/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/MultipleTestsWithTestOutputExceedingLimit/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NoTasks/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NoTasks/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NoTasks/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NoTasks/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NoTests/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NoTests/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NoTests/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NoTests/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NotImplemented/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NotImplemented/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NotImplemented/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NotImplemented/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NotImplemented/expected_results.json b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NotImplemented/expected_results.json
index 351211a..edce11c 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NotImplemented/expected_results.json
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/NotImplemented/expected_results.json
@@ -5,7 +5,7 @@
{
"name": "Add should add numbers",
"status": "fail",
- "message": "System.NotImplementedException : Please implement the Fake.Add method",
+ "message": "Please implement the Fake.Add method",
"test_code": "Assert.Equal(3, Fake.Add(1, 1))"
}
]
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleCompileError/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleCompileError/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleCompileError/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleCompileError/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleTestThatFails/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleTestThatFails/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleTestThatFails/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleTestThatFails/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleTestThatPasses/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleTestThatPasses/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleTestThatPasses/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleTestThatPasses/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleTestThatPassesWithDifferentSlug/Foo.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleTestThatPassesWithDifferentSlug/Foo.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleTestThatPassesWithDifferentSlug/Foo.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SingleTestThatPassesWithDifferentSlug/Foo.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SomeTestsWithTask/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SomeTestsWithTask/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SomeTestsWithTask/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/SomeTestsWithTask/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/TestsInDifferentFormats/Fake.csproj b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/TestsInDifferentFormats/Fake.csproj
index 5e8fe89..d6a2c1b 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/TestsInDifferentFormats/Fake.csproj
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/Solutions/TestsInDifferentFormats/Fake.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/TestRunResultReader.cs b/test/Exercism.TestRunner.CSharp.IntegrationTests/TestRunResultReader.cs
index d9d4db7..be8d0f5 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/TestRunResultReader.cs
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/TestRunResultReader.cs
@@ -55,7 +55,7 @@ private struct TestRunResult
{
[JsonPropertyName("version")]
public int Version { get; set; }
-
+
[JsonPropertyName("status")]
public TestStatus Status { get; set; }
@@ -76,7 +76,7 @@ private struct TestResult
[JsonPropertyName("name")]
public string Name { get; set; }
-
+
[JsonPropertyName("task_id")]
public int? TaskId { get; set; }
diff --git a/test/Exercism.TestRunner.CSharp.IntegrationTests/TestSolutionRunner.cs b/test/Exercism.TestRunner.CSharp.IntegrationTests/TestSolutionRunner.cs
index c6f8486..1d2fdf4 100644
--- a/test/Exercism.TestRunner.CSharp.IntegrationTests/TestSolutionRunner.cs
+++ b/test/Exercism.TestRunner.CSharp.IntegrationTests/TestSolutionRunner.cs
@@ -21,7 +21,20 @@ private static void RunTestRunner(TestSolution testSolution)
}
private static void RunTestRunnerUsingDocker(TestSolution testSolution) =>
- Process.Start("docker", $"run -v {testSolution.DirectoryFullPath}:/solution -v {testSolution.DirectoryFullPath}:/results exercism/csharp-test-runner {testSolution.Slug} /solution /results")!.WaitForExit();
+ Process.Start("docker",
+ new[]
+ {
+ "run",
+ "--network", "none",
+ "--read-only",
+ "--mount", $"type=bind,src={testSolution.DirectoryFullPath},dst=/solution",
+ "--mount", $"type=bind,src={testSolution.DirectoryFullPath},dst=/output",
+ "--mount", "type=tmpfs,dst=/tmp",
+ "exercism/csharp-test-runner",
+ testSolution.Slug,
+ "/solution",
+ "/output"
+ })!.WaitForExit();
private static void RunTestRunnerWithoutDocker(TestSolution testSolution) =>
Program.Main(new[] { testSolution.Slug, testSolution.DirectoryFullPath, testSolution.DirectoryFullPath });