diff --git a/src/Draco.Examples.Tests/Draco.Examples.Tests.csproj b/src/Draco.Examples.Tests/Draco.Examples.Tests.csproj index 9a518a918..6784cbac8 100644 --- a/src/Draco.Examples.Tests/Draco.Examples.Tests.csproj +++ b/src/Draco.Examples.Tests/Draco.Examples.Tests.csproj @@ -6,6 +6,10 @@ true + + + + diff --git a/src/Draco.Examples.Tests/ExamplesTests.cs b/src/Draco.Examples.Tests/ExamplesTests.cs index 381ff2cf7..75c522206 100644 --- a/src/Draco.Examples.Tests/ExamplesTests.cs +++ b/src/Draco.Examples.Tests/ExamplesTests.cs @@ -1,43 +1,31 @@ using System.Diagnostics; using System.Text; using DiffEngine; +using Draco.ProjectSystem; namespace Draco.Examples.Tests; +// NOTE: Unnfortunately the tooling seemms to have a race condition if we attempt a design-time build here +// So we order to first run the examples, and then the design-time build +[TestCaseOrderer("Draco.Examples.Tests.PriorityOrderer", "Draco.Examples.Tests")] public sealed class ExamplesTests { - public static IEnumerable TestData - { - get + // Each directory contains a projectfile, and a verification file, return each pair + public static IEnumerable TestData => TestUtils.ExampleDirectories + .Select(directory => new object[] { - // Get all example projects - // We exclude the "Toolchain" folder, in case the user has installed it in the examples directory - var exampleProjectDirectories = Directory - .GetDirectories("examples", "*", SearchOption.TopDirectoryOnly) - .Where(d => Path.GetFileName(d) != "Toolchain"); - // Each directory contains a projectfile, and a verification file, return each pair - return exampleProjectDirectories - .Select(directory => new object[] - { - // Search for the dracoproj file - Directory.GetFiles(directory, "*.dracoproj").Single(), - // The verification file is always named "verify.txt" - Path.Combine(directory, "verify.txt"), - }); - } - } - - private const string DescriptionForNotInstalledToolchain = """ - Note, that you need to have the toolchain installed in the examples directory, in order to run these tests. - You can do that by running the install_toolchain.ps1 script in the scripts directory and passing in the path to the examples directory. - """; + // Search for the dracoproj file + Directory.GetFiles(directory, "*.dracoproj").Single(), + // The verification file is always named "verify.txt" + Path.Combine(directory, "verify.txt"), + }); public ExamplesTests() { DiffTools.UseOrder(DiffTool.VisualStudioCode, DiffTool.VisualStudio, DiffTool.Rider); } - [Theory] + [Theory, TestPriority(1)] [MemberData(nameof(TestData))] public async Task RunExample(string projectFile, string verifiedFile) { @@ -67,13 +55,22 @@ public async Task RunExample(string projectFile, string verifiedFile) } var gotOutput = standardOutput.ToString(); + var standardError = new StringBuilder(); + while (!process.StandardError.EndOfStream) + { + var line = process.StandardError.ReadLine(); + standardError.AppendLine(line); + } + var gotError = standardError.ToString(); + // Wait for the process to exit process.WaitForExit(); // Verify that the process exited successfully Assert.True(process.ExitCode == 0, $""" The process exited with a non-zero exit code ({process.ExitCode}). - {DescriptionForNotInstalledToolchain} + Message: {gotError} + {TestUtils.DescriptionForNotInstalledToolchain} """); // Configure verifier @@ -84,4 +81,22 @@ public async Task RunExample(string projectFile, string verifiedFile) // Compare output to the verified file await Verify(gotOutput, settings); } + + [Fact, TestPriority(2)] + public void DesignTimeBuild() + { + // Iniitialize the workspace + var workspace = Workspace.Initialize(TestUtils.ExamplesDirectory); + + // Assert we have projects in there + var projects = workspace.Projects.ToList(); + Assert.NotEmpty(projects); + + // Run the design time build for each + foreach (var project in projects) + { + var buildResult = project.BuildDesignTime(); + Assert.True(buildResult.Success, buildResult.Log); + } + } } diff --git a/src/Draco.Examples.Tests/PriorityOrderer.cs b/src/Draco.Examples.Tests/PriorityOrderer.cs new file mode 100644 index 000000000..d8c46674d --- /dev/null +++ b/src/Draco.Examples.Tests/PriorityOrderer.cs @@ -0,0 +1,44 @@ +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace Draco.Examples.Tests; + +internal sealed class PriorityOrderer : ITestCaseOrderer +{ + public IEnumerable OrderTestCases(IEnumerable testCases) where TTestCase : ITestCase + { + var sortedMethods = new SortedDictionary>(); + + foreach (var testCase in testCases) + { + var priority = 0; + + foreach (var attr in testCase.TestMethod.Method.GetCustomAttributes((typeof(TestPriorityAttribute).AssemblyQualifiedName))) + { + priority = attr.GetNamedArgument("Priority"); + } + + GetOrCreate(sortedMethods, priority).Add(testCase); + } + + foreach (var list in sortedMethods.Keys.Select(priority => sortedMethods[priority])) + { + list.Sort((x, y) => StringComparer.OrdinalIgnoreCase.Compare(x.TestMethod.Method.Name, y.TestMethod.Method.Name)); + foreach (var testCase in list) + { + yield return testCase; + } + } + } + + private static TValue GetOrCreate(IDictionary dictionary, TKey key) + where TValue : new() + { + if (dictionary.TryGetValue(key, out var result)) return result; + + result = new(); + dictionary[key] = result; + + return result; + } +} diff --git a/src/Draco.Examples.Tests/TestPriorityAttribute.cs b/src/Draco.Examples.Tests/TestPriorityAttribute.cs new file mode 100644 index 000000000..ef878278d --- /dev/null +++ b/src/Draco.Examples.Tests/TestPriorityAttribute.cs @@ -0,0 +1,7 @@ +namespace Draco.Examples.Tests; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] +public sealed class TestPriorityAttribute(int priority) : Attribute +{ + public int Priority => priority; +} diff --git a/src/Draco.Examples.Tests/TestUtils.cs b/src/Draco.Examples.Tests/TestUtils.cs new file mode 100644 index 000000000..e7cf0fdd7 --- /dev/null +++ b/src/Draco.Examples.Tests/TestUtils.cs @@ -0,0 +1,27 @@ +namespace Draco.Examples.Tests; + +/// +/// Utilities for these tests. +/// +internal static class TestUtils +{ + /// + /// A string describing that the toolchain needs to be installed in the examples directory. + /// + public const string DescriptionForNotInstalledToolchain = """ + Note, that you need to have the toolchain installed in the examples directory, in order to run these tests. + You can do that by running the install_toolchain.ps1 script in the scripts directory and passing in the path to the examples directory. + """; + + /// + /// The root examples directory. + /// + public const string ExamplesDirectory = "examples"; + + /// + /// Retrieves all example project directories. + /// + public static IEnumerable ExampleDirectories => Directory + .GetDirectories(ExamplesDirectory, "*", SearchOption.TopDirectoryOnly) + .Where(d => Path.GetFileName(d) != "Toolchain"); +} diff --git a/src/Draco.LanguageServer/Draco.LanguageServer.csproj b/src/Draco.LanguageServer/Draco.LanguageServer.csproj index 2d4f0a506..a94443055 100644 --- a/src/Draco.LanguageServer/Draco.LanguageServer.csproj +++ b/src/Draco.LanguageServer/Draco.LanguageServer.csproj @@ -17,12 +17,12 @@ - - - - - - + + + + + + diff --git a/src/Draco.ProjectSystem/Draco.ProjectSystem.csproj b/src/Draco.ProjectSystem/Draco.ProjectSystem.csproj index ef36a0544..142ed0144 100644 --- a/src/Draco.ProjectSystem/Draco.ProjectSystem.csproj +++ b/src/Draco.ProjectSystem/Draco.ProjectSystem.csproj @@ -1,11 +1,11 @@ - - - - - - - + + + + + + +