mirror of
https://github.com/Smaug123/unofficial-nunit-runner
synced 2025-10-05 17:38:40 +00:00
Obtain a compatible runtime from runconfig (#35)
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,3 +10,4 @@ result
|
||||
.analyzerpackages/
|
||||
analysis.sarif
|
||||
.direnv/
|
||||
Generated*.fs
|
||||
|
@@ -1,8 +1,10 @@
|
||||
namespace TestRunner
|
||||
|
||||
open System
|
||||
open WoofWare.DotnetRuntimeLocator
|
||||
open System.IO
|
||||
open System.Reflection
|
||||
open System.Runtime.Loader
|
||||
|
||||
// Fix for https://github.com/Smaug123/unofficial-nunit-runner/issues/8
|
||||
// Set AppContext.BaseDirectory to where the test DLL is.
|
||||
@@ -15,7 +17,91 @@ type SetBaseDir (testDll : FileInfo) =
|
||||
member _.Dispose () =
|
||||
AppContext.SetData ("APP_CONTEXT_BASE_DIRECTORY", oldBaseDir)
|
||||
|
||||
|
||||
type Ctx (dll : FileInfo, runtimes : DirectoryInfo list) =
|
||||
inherit AssemblyLoadContext ()
|
||||
|
||||
override this.Load (target : AssemblyName) : Assembly =
|
||||
let path = Path.Combine (dll.Directory.FullName, $"%s{target.Name}.dll")
|
||||
|
||||
if File.Exists path then
|
||||
this.LoadFromAssemblyPath path
|
||||
else
|
||||
|
||||
runtimes
|
||||
|> List.tryPick (fun di ->
|
||||
let path = Path.Combine (di.FullName, $"%s{target.Name}.dll")
|
||||
|
||||
if File.Exists path then
|
||||
this.LoadFromAssemblyPath path |> Some
|
||||
else
|
||||
None
|
||||
)
|
||||
|> Option.defaultValue null
|
||||
|
||||
|
||||
module Program =
|
||||
let selectRuntime
|
||||
(config : RuntimeOptions)
|
||||
(f : DotnetEnvironmentInfo)
|
||||
: Choice<DotnetEnvironmentFrameworkInfo, DotnetEnvironmentSdkInfo> option
|
||||
=
|
||||
let rollForward =
|
||||
match Environment.GetEnvironmentVariable "DOTNET_ROLL_FORWARD" with
|
||||
| null ->
|
||||
config.RollForward
|
||||
|> Option.map RollForward.Parse
|
||||
|> Option.defaultValue RollForward.Minor
|
||||
| s -> RollForward.Parse s
|
||||
|
||||
let desired = Version config.Framework.Version
|
||||
|
||||
match rollForward with
|
||||
| RollForward.Minor ->
|
||||
let available =
|
||||
f.Frameworks
|
||||
|> Seq.choose (fun fi ->
|
||||
if fi.Name = config.Framework.Name then
|
||||
Some (fi, Version fi.Version)
|
||||
else
|
||||
None
|
||||
)
|
||||
|> Seq.filter (fun (_, version) -> version.Major = desired.Major && version.Minor >= desired.Minor)
|
||||
|> Seq.tryMinBy (fun (_, version) -> version.Minor, version.Build)
|
||||
|
||||
match available with
|
||||
| Some (f, _) -> Some (Choice1Of2 f)
|
||||
| None ->
|
||||
// TODO: maybe we can ask the SDK. But we keep on trucking: maybe we're self-contained,
|
||||
// and we'll actually find all the runtime next to the DLL.
|
||||
None
|
||||
| _ -> failwith "non-minor RollForward not supported yet; please shout if you want it"
|
||||
|
||||
let locateRuntimes (dll : FileInfo) : DirectoryInfo list =
|
||||
let runtimeConfig =
|
||||
let name =
|
||||
if not (dll.Name.EndsWith (".dll", StringComparison.OrdinalIgnoreCase)) then
|
||||
failwith $"Expected DLL %s{dll.FullName} to end in .dll"
|
||||
|
||||
dll.Name.Substring (0, dll.Name.Length - 4)
|
||||
|
||||
Path.Combine (dll.Directory.FullName, $"%s{name}.runtimeconfig.json")
|
||||
|> File.ReadAllText
|
||||
|> System.Text.Json.Nodes.JsonNode.Parse
|
||||
|> RuntimeConfig.jsonParse
|
||||
|> fun f -> f.RuntimeOptions
|
||||
|
||||
let availableRuntimes = DotnetEnvironmentInfo.Get ()
|
||||
|
||||
let runtime = selectRuntime runtimeConfig availableRuntimes
|
||||
|
||||
match runtime with
|
||||
| None ->
|
||||
// Keep on trucking: let's be optimistic and hope that we're self-contained.
|
||||
[ dll.Directory ]
|
||||
| Some (Choice1Of2 runtime) -> [ dll.Directory ; DirectoryInfo runtime.Path ]
|
||||
| Some (Choice2Of2 sdk) -> [ dll.Directory ; DirectoryInfo sdk.Path ]
|
||||
|
||||
let main argv =
|
||||
let testDll, filter =
|
||||
match argv |> List.ofSeq with
|
||||
@@ -32,7 +118,8 @@ module Program =
|
||||
|
||||
use _ = new SetBaseDir (testDll)
|
||||
|
||||
let assy = Assembly.LoadFrom testDll.FullName
|
||||
let ctx = Ctx (testDll, locateRuntimes testDll)
|
||||
let assy = ctx.LoadFromAssemblyPath testDll.FullName
|
||||
|
||||
let anyFailures =
|
||||
assy.ExportedTypes
|
||||
|
50
TestRunner/RuntimeConfig.fs
Normal file
50
TestRunner/RuntimeConfig.fs
Normal file
@@ -0,0 +1,50 @@
|
||||
namespace TestRunner
|
||||
|
||||
open System
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
[<JsonParse>]
|
||||
type FrameworkDescription =
|
||||
{
|
||||
Name : string
|
||||
Version : string
|
||||
}
|
||||
|
||||
[<JsonParse>]
|
||||
type RuntimeOptions =
|
||||
{
|
||||
Tfm : string
|
||||
Framework : FrameworkDescription
|
||||
RollForward : string option
|
||||
}
|
||||
|
||||
[<JsonParse>]
|
||||
type RuntimeConfig =
|
||||
{
|
||||
RuntimeOptions : RuntimeOptions
|
||||
}
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
type RollForward =
|
||||
| Minor
|
||||
| Major
|
||||
| LatestPatch
|
||||
| LatestMinor
|
||||
| LatestMajor
|
||||
| Disable
|
||||
|
||||
static member Parse (s : string) : RollForward =
|
||||
if s.Equals ("minor", StringComparison.OrdinalIgnoreCase) then
|
||||
RollForward.Minor
|
||||
elif s.Equals ("major", StringComparison.OrdinalIgnoreCase) then
|
||||
RollForward.Major
|
||||
elif s.Equals ("latestpatch", StringComparison.OrdinalIgnoreCase) then
|
||||
RollForward.LatestPatch
|
||||
elif s.Equals ("latestminor", StringComparison.OrdinalIgnoreCase) then
|
||||
RollForward.LatestMinor
|
||||
elif s.Equals ("latestmajor", StringComparison.OrdinalIgnoreCase) then
|
||||
RollForward.LatestMajor
|
||||
elif s.Equals ("disable", StringComparison.OrdinalIgnoreCase) then
|
||||
RollForward.Disable
|
||||
else
|
||||
failwith $"Could not interpret '%s{s}' as a RollForward"
|
22
TestRunner/Seq.fs
Normal file
22
TestRunner/Seq.fs
Normal file
@@ -0,0 +1,22 @@
|
||||
namespace TestRunner
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal Seq =
|
||||
|
||||
let tryMinBy (f : 'a -> 'b) (s : 'a seq) : 'a option =
|
||||
use enum = s.GetEnumerator ()
|
||||
|
||||
if not (enum.MoveNext ()) then
|
||||
None
|
||||
else
|
||||
|
||||
let mutable answer = enum.Current
|
||||
let mutable fAnswer = f enum.Current
|
||||
|
||||
while enum.MoveNext () do
|
||||
let fNext = f enum.Current
|
||||
|
||||
if fNext < fAnswer then
|
||||
answer <- enum.Current
|
||||
|
||||
Some answer
|
@@ -15,9 +15,15 @@
|
||||
<PackageTags>nunit;test;runner</PackageTags>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<WarnOn>FS3559</WarnOn>
|
||||
<WoofWareMyriadPluginVersion>2.1.40</WoofWareMyriadPluginVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="RuntimeConfig.fs" />
|
||||
<Compile Include="GeneratedRuntimeConfig.fs">
|
||||
<MyriadFile>RuntimeConfig.fs</MyriadFile>
|
||||
</Compile>
|
||||
<Compile Include="Seq.fs" />
|
||||
<Compile Include="Progress.fs" />
|
||||
<Compile Include="Program.fs" />
|
||||
<None Include="..\README.md">
|
||||
@@ -32,6 +38,13 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Spectre.Console" Version="0.49.1" />
|
||||
<PackageReference Include="WoofWare.DotnetRuntimeLocator" Version="0.1.2" />
|
||||
<PackageReference Include="WoofWare.Myriad.Plugins.Attributes" Version="3.1.4" />
|
||||
<PackageReference Include="Myriad.SDK" Version="0.8.3" />
|
||||
<PackageReference Include="WoofWare.Myriad.Plugins" Version="$(WoofWareMyriadPluginVersion)" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<MyriadSdkGenerator Include="$(NuGetPackageRoot)/woofware.myriad.plugins/$(WoofWareMyriadPluginVersion)/lib/net6.0/WoofWare.Myriad.Plugins.dll" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
0
TestRunner/myriad.toml
Normal file
0
TestRunner/myriad.toml
Normal file
20
nix/deps.nix
20
nix/deps.nix
@@ -61,6 +61,11 @@
|
||||
version = "17.10.0";
|
||||
sha256 = "1bl471s7fx9jycr0cc8rylwf34mrvlg9qn1an6l86nisavfcyb7v";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Myriad.Sdk";
|
||||
version = "0.8.3";
|
||||
sha256 = "0qv78c5s5m04xb8h17nnn2ig26zcyya91k2dpj745cm1cbnzvvgc";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Nerdbank.GitVersioning";
|
||||
version = "3.6.139";
|
||||
@@ -176,6 +181,21 @@
|
||||
version = "7.0.3";
|
||||
sha256 = "0zjrnc9lshagm6kdb9bdh45dmlnkpwcpyssa896sda93ngbmj8k9";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "WoofWare.DotnetRuntimeLocator";
|
||||
version = "0.1.2";
|
||||
sha256 = "0kwkq28ddzc0bpr22jmgcl8dhnhg776gf6l054rsxw8lrvpwhmv9";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "WoofWare.Myriad.Plugins";
|
||||
version = "2.1.40";
|
||||
sha256 = "025lv42zjvqpr2di0iaqhqpricqary3l2a3cxgjjl0zxzflfbmx2";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "WoofWare.Myriad.Plugins.Attributes";
|
||||
version = "3.1.4";
|
||||
sha256 = "06yw013f2qs2r8bxvja2c5kzbqc5knd3sc3pf6w5gaz4fbzwc2c3";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "WoofWare.PrattParser";
|
||||
version = "0.1.2";
|
||||
|
Reference in New Issue
Block a user