mirror of
https://github.com/Smaug123/unofficial-nunit-runner
synced 2025-10-06 09:48:40 +00:00
Compare commits
3 Commits
WoofWare.N
...
WoofWare.N
Author | SHA1 | Date | |
---|---|---|---|
|
a694637958 | ||
|
8626cc1252 | ||
|
0287a6b7eb |
1
.fantomasignore
Normal file
1
.fantomasignore
Normal file
@@ -0,0 +1 @@
|
||||
.direnv/
|
@@ -12,6 +12,7 @@
|
||||
<Compile Include="RunSubProcess.fs" />
|
||||
<Compile Include="TestNonParallel.fs" />
|
||||
<Compile Include="TestParallel.fs" />
|
||||
<Compile Include="TestParallelIndividualTest.fs" />
|
||||
<Compile Include="TestStdout.fs" />
|
||||
<Compile Include="TestParameterisedFixture.fs" />
|
||||
<Compile Include="TestSetUp.fs" />
|
||||
|
59
Consumer/TestParallelIndividualTest.fs
Normal file
59
Consumer/TestParallelIndividualTest.fs
Normal file
@@ -0,0 +1,59 @@
|
||||
namespace Consumer
|
||||
|
||||
open System
|
||||
open System.Collections.Concurrent
|
||||
open System.Threading
|
||||
open NUnit.Framework
|
||||
open FsUnitTyped
|
||||
|
||||
// These tests are flaky if the bug https://github.com/Smaug123/unofficial-nunit-runner/issues/168 is unfixed.
|
||||
[<TestFixture>]
|
||||
module TestParallelIndividualTest =
|
||||
|
||||
type private Transitions =
|
||||
| Started of int
|
||||
| LockAcquired of int
|
||||
| Exited of int
|
||||
|
||||
let locker = obj ()
|
||||
let private sequence = ConcurrentQueue<Transitions> ()
|
||||
|
||||
[<Test>]
|
||||
[<Parallelizable(ParallelScope.None)>]
|
||||
let ``does not run in parallel`` () =
|
||||
sequence.Enqueue (Transitions.Started 0)
|
||||
let entered = Monitor.TryEnter (locker, TimeSpan.Zero)
|
||||
|
||||
if entered then
|
||||
sequence.Enqueue (Transitions.LockAcquired 0)
|
||||
Monitor.Exit locker
|
||||
sequence.Enqueue (Transitions.Exited 0)
|
||||
else
|
||||
sequence.Enqueue (Transitions.Exited 0)
|
||||
failwith "failed to acquire the lock"
|
||||
|
||||
[<Test>]
|
||||
let ``unrestricted parallelism`` () =
|
||||
sequence.Enqueue (Transitions.Started 1)
|
||||
let entered = Monitor.TryEnter (locker, TimeSpan.Zero)
|
||||
|
||||
if entered then
|
||||
sequence.Enqueue (Transitions.LockAcquired 1)
|
||||
Monitor.Exit locker
|
||||
sequence.Enqueue (Transitions.Exited 1)
|
||||
else
|
||||
sequence.Enqueue (Transitions.Exited 1)
|
||||
failwith "failed to acquire the lock"
|
||||
|
||||
[<OneTimeTearDown>]
|
||||
let ``It worked`` () =
|
||||
let sequence = sequence |> Seq.toList
|
||||
|
||||
let allowed n =
|
||||
[ Transitions.Started n ; Transitions.LockAcquired n ; Transitions.Exited n ]
|
||||
|
||||
if sequence <> allowed 0 @ allowed 1 && sequence <> allowed 1 @ allowed 0 then
|
||||
let s = sequence |> Seq.map string<Transitions> |> String.concat "\n"
|
||||
failwith $"Unexpected sequence!\n%s{s}"
|
||||
|
||||
()
|
@@ -41,12 +41,16 @@ module AssemblyLevelAttributes =
|
||||
| [ v ] ->
|
||||
match v.Value with
|
||||
| :? int as v ->
|
||||
match v with
|
||||
| 512 -> levelPar, Some (Parallelizable.Yes AssemblyParallelScope.Fixtures)
|
||||
| 256 -> levelPar, Some (Parallelizable.Yes AssemblyParallelScope.Children)
|
||||
| 257 -> failwith "ParallelScope.All is invalid on assemblies; only Fixtures or Children"
|
||||
| 1 -> failwith "ParallelScope.Self is invalid on assemblies; only Fixtures or Children"
|
||||
| v -> failwith $"Could not recognise value %i{v} of parallel scope on assembly"
|
||||
match ParallelScope.ofInt v with
|
||||
| ParallelScope.Fixtures ->
|
||||
levelPar, Some (Parallelizable.Yes AssemblyParallelScope.Fixtures)
|
||||
| ParallelScope.Children ->
|
||||
levelPar, Some (Parallelizable.Yes AssemblyParallelScope.Children)
|
||||
| ParallelScope.None -> levelPar, Some Parallelizable.No
|
||||
| ParallelScope.All ->
|
||||
failwith "ParallelScope.All is invalid on assemblies; only Fixtures or Children"
|
||||
| ParallelScope.Self ->
|
||||
failwith "ParallelScope.Self is invalid on assemblies; only Fixtures or Children"
|
||||
| v -> failwith $"Unexpectedly non-int value %O{v} of parallel scope on assembly"
|
||||
| _ -> failwith "unexpectedly got multiple args to Parallelizable on assembly"
|
||||
| _ -> levelPar, par
|
||||
|
@@ -61,6 +61,24 @@ type Parallelizable<'scope> =
|
||||
/// This test must always be run on its own.
|
||||
| No
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Parallelizable =
|
||||
/// Functorial map.
|
||||
let inline map<'a, 'b> ([<InlineIfLambda>] f : 'a -> 'b) (p : Parallelizable<'a>) : Parallelizable<'b> =
|
||||
match p with
|
||||
| Parallelizable.No -> Parallelizable.No
|
||||
| Parallelizable.Yes a -> Parallelizable.Yes (f a)
|
||||
|
||||
/// Functorial bind.
|
||||
let inline bind<'a, 'b>
|
||||
([<InlineIfLambda>] f : 'a -> Parallelizable<'b>)
|
||||
(p : Parallelizable<'a>)
|
||||
: Parallelizable<'b>
|
||||
=
|
||||
match p with
|
||||
| Parallelizable.No -> Parallelizable.No
|
||||
| Parallelizable.Yes a -> f a
|
||||
|
||||
/// A single method or member which holds some tests. (Often such a member will represent only one test, but e.g.
|
||||
/// if it has [<TestCaseSource>] then it represents multiple tests.)
|
||||
type SingleTestMethod =
|
||||
|
29
WoofWare.NUnitTestRunner.Lib/ParallelScope.fs
Normal file
29
WoofWare.NUnitTestRunner.Lib/ParallelScope.fs
Normal file
@@ -0,0 +1,29 @@
|
||||
namespace WoofWare.NUnitTestRunner
|
||||
|
||||
/// Our own strongly-typed rendering of the NUnit ParallelScope enum.
|
||||
/// This is more tightly modelled by ClassParallelScope and AssemblyParallelScope in our own domain; this type exists
|
||||
/// for the initial interop.
|
||||
[<RequireQualifiedAccess>]
|
||||
type ParallelScope =
|
||||
/// Corresponds to NUnit's ParallelScope.Fixtures.
|
||||
| Fixtures
|
||||
/// Corresponds to NUnit's ParallelScope.Children.
|
||||
| Children
|
||||
/// Corresponds to NUnit's ParallelScope.All.
|
||||
| All
|
||||
/// Corresponds to NUnit's ParallelScope.Self.
|
||||
| Self
|
||||
/// Corresponds to NUnit's ParallelScope.None.
|
||||
| None
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module ParallelScope =
|
||||
/// Convert the weakly-typed C# enum that is NUnit's `ParallelScope` to a strongly-typed representation.
|
||||
let ofInt (n : int) =
|
||||
match n with
|
||||
| 512 -> ParallelScope.Fixtures
|
||||
| 256 -> ParallelScope.Children
|
||||
| 257 -> ParallelScope.All
|
||||
| 1 -> ParallelScope.Self
|
||||
| 2 -> ParallelScope.None
|
||||
| _ -> failwith $"Unrecognised ParallelScope enum: %i{n}"
|
@@ -94,7 +94,27 @@ module SingleTestMethod =
|
||||
match par with
|
||||
| Some _ -> failwith $"Got multiple parallelization attributes on %s{method.Name}"
|
||||
| None ->
|
||||
(remaining, isTest, sources, hasData, mods, cats, repeat, comb, Some (Parallelizable.Yes ()))
|
||||
let arg =
|
||||
match Seq.toList attr.ConstructorArguments with
|
||||
| [] -> Parallelizable.Yes ()
|
||||
| [ x ] ->
|
||||
if x.ArgumentType.Name <> "ParallelScope" then
|
||||
failwith
|
||||
$"Got argument %O{x.Value} of unrecognised type %s{x.ArgumentType.Name} on [<Parallelizable>] attribute; expected ParallelScope"
|
||||
|
||||
match ParallelScope.ofInt (unbox<int> x.Value) with
|
||||
| ParallelScope.Children ->
|
||||
failwith
|
||||
$"Unexpected ParallelScope.Children on test %s{method.Name}; this is not valid on individual tests"
|
||||
| ParallelScope.Fixtures ->
|
||||
failwith
|
||||
$"Unexpected ParallelScope.Children on test %s{method.Name}; this is not valid on individual tests"
|
||||
| ParallelScope.All
|
||||
| ParallelScope.Self -> Parallelizable.Yes ()
|
||||
| ParallelScope.None -> Parallelizable.No
|
||||
| s -> failwith $"Got multiple arguments on a [<Parallelizable>] attribute: %O{s}"
|
||||
|
||||
(remaining, isTest, sources, hasData, mods, cats, repeat, comb, Some arg)
|
||||
| s when s.StartsWith ("NUnit.Framework", StringComparison.Ordinal) ->
|
||||
failwith $"Unrecognised attribute on function %s{method.Name}: %s{attr.AttributeType.FullName}"
|
||||
| _ -> (attr :: remaining, isTest, sources, hasData, mods, cats, repeat, comb, par)
|
||||
|
@@ -231,6 +231,9 @@ WoofWare.NUnitTestRunner.Modifier.IsIgnored [property]: [read-only] bool
|
||||
WoofWare.NUnitTestRunner.Modifier.NewExplicit [static method]: string option -> WoofWare.NUnitTestRunner.Modifier
|
||||
WoofWare.NUnitTestRunner.Modifier.NewIgnored [static method]: string option -> WoofWare.NUnitTestRunner.Modifier
|
||||
WoofWare.NUnitTestRunner.Modifier.Tag [property]: [read-only] int
|
||||
WoofWare.NUnitTestRunner.Parallelizable inherit obj
|
||||
WoofWare.NUnitTestRunner.Parallelizable.bind [static method]: ('a -> 'b WoofWare.NUnitTestRunner.Parallelizable) -> 'a WoofWare.NUnitTestRunner.Parallelizable -> 'b WoofWare.NUnitTestRunner.Parallelizable
|
||||
WoofWare.NUnitTestRunner.Parallelizable.map [static method]: ('a -> 'b) -> 'a WoofWare.NUnitTestRunner.Parallelizable -> 'b WoofWare.NUnitTestRunner.Parallelizable
|
||||
WoofWare.NUnitTestRunner.Parallelizable`1 inherit obj, implements 'scope WoofWare.NUnitTestRunner.Parallelizable System.IEquatable, System.Collections.IStructuralEquatable, 'scope WoofWare.NUnitTestRunner.Parallelizable System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 2 cases
|
||||
WoofWare.NUnitTestRunner.Parallelizable`1+Tags inherit obj
|
||||
WoofWare.NUnitTestRunner.Parallelizable`1+Tags.No [static field]: int = 1
|
||||
@@ -255,6 +258,38 @@ WoofWare.NUnitTestRunner.ParallelQueue.Run [method]: WoofWare.NUnitTestRunner.Te
|
||||
WoofWare.NUnitTestRunner.ParallelQueue.RunTestSetup [method]: WoofWare.NUnitTestRunner.TestFixtureRunningToken -> (unit -> 'a) -> ('a * WoofWare.NUnitTestRunner.TestFixtureSetupToken) System.Threading.Tasks.Task
|
||||
WoofWare.NUnitTestRunner.ParallelQueue.RunTestTearDown [method]: WoofWare.NUnitTestRunner.TestFixtureSetupToken -> (unit -> 'a) -> ('a * WoofWare.NUnitTestRunner.TestFixtureTearDownToken) System.Threading.Tasks.Task
|
||||
WoofWare.NUnitTestRunner.ParallelQueue.StartTestFixture [method]: WoofWare.NUnitTestRunner.TestFixture -> WoofWare.NUnitTestRunner.TestFixtureRunningToken System.Threading.Tasks.Task
|
||||
WoofWare.NUnitTestRunner.ParallelScope inherit obj, implements WoofWare.NUnitTestRunner.ParallelScope System.IEquatable, System.Collections.IStructuralEquatable, WoofWare.NUnitTestRunner.ParallelScope System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 5 cases
|
||||
WoofWare.NUnitTestRunner.ParallelScope+Tags inherit obj
|
||||
WoofWare.NUnitTestRunner.ParallelScope+Tags.All [static field]: int = 2
|
||||
WoofWare.NUnitTestRunner.ParallelScope+Tags.Children [static field]: int = 1
|
||||
WoofWare.NUnitTestRunner.ParallelScope+Tags.Fixtures [static field]: int = 0
|
||||
WoofWare.NUnitTestRunner.ParallelScope+Tags.None [static field]: int = 4
|
||||
WoofWare.NUnitTestRunner.ParallelScope+Tags.Self [static field]: int = 3
|
||||
WoofWare.NUnitTestRunner.ParallelScope.All [static property]: [read-only] WoofWare.NUnitTestRunner.ParallelScope
|
||||
WoofWare.NUnitTestRunner.ParallelScope.Children [static property]: [read-only] WoofWare.NUnitTestRunner.ParallelScope
|
||||
WoofWare.NUnitTestRunner.ParallelScope.Equals [method]: (WoofWare.NUnitTestRunner.ParallelScope, System.Collections.IEqualityComparer) -> bool
|
||||
WoofWare.NUnitTestRunner.ParallelScope.Fixtures [static property]: [read-only] WoofWare.NUnitTestRunner.ParallelScope
|
||||
WoofWare.NUnitTestRunner.ParallelScope.get_All [static method]: unit -> WoofWare.NUnitTestRunner.ParallelScope
|
||||
WoofWare.NUnitTestRunner.ParallelScope.get_Children [static method]: unit -> WoofWare.NUnitTestRunner.ParallelScope
|
||||
WoofWare.NUnitTestRunner.ParallelScope.get_Fixtures [static method]: unit -> WoofWare.NUnitTestRunner.ParallelScope
|
||||
WoofWare.NUnitTestRunner.ParallelScope.get_IsAll [method]: unit -> bool
|
||||
WoofWare.NUnitTestRunner.ParallelScope.get_IsChildren [method]: unit -> bool
|
||||
WoofWare.NUnitTestRunner.ParallelScope.get_IsFixtures [method]: unit -> bool
|
||||
WoofWare.NUnitTestRunner.ParallelScope.get_IsNone [method]: unit -> bool
|
||||
WoofWare.NUnitTestRunner.ParallelScope.get_IsSelf [method]: unit -> bool
|
||||
WoofWare.NUnitTestRunner.ParallelScope.get_None [static method]: unit -> WoofWare.NUnitTestRunner.ParallelScope
|
||||
WoofWare.NUnitTestRunner.ParallelScope.get_Self [static method]: unit -> WoofWare.NUnitTestRunner.ParallelScope
|
||||
WoofWare.NUnitTestRunner.ParallelScope.get_Tag [method]: unit -> int
|
||||
WoofWare.NUnitTestRunner.ParallelScope.IsAll [property]: [read-only] bool
|
||||
WoofWare.NUnitTestRunner.ParallelScope.IsChildren [property]: [read-only] bool
|
||||
WoofWare.NUnitTestRunner.ParallelScope.IsFixtures [property]: [read-only] bool
|
||||
WoofWare.NUnitTestRunner.ParallelScope.IsNone [property]: [read-only] bool
|
||||
WoofWare.NUnitTestRunner.ParallelScope.IsSelf [property]: [read-only] bool
|
||||
WoofWare.NUnitTestRunner.ParallelScope.None [static property]: [read-only] WoofWare.NUnitTestRunner.ParallelScope
|
||||
WoofWare.NUnitTestRunner.ParallelScope.Self [static property]: [read-only] WoofWare.NUnitTestRunner.ParallelScope
|
||||
WoofWare.NUnitTestRunner.ParallelScope.Tag [property]: [read-only] int
|
||||
WoofWare.NUnitTestRunner.ParallelScopeModule inherit obj
|
||||
WoofWare.NUnitTestRunner.ParallelScopeModule.ofInt [static method]: int -> WoofWare.NUnitTestRunner.ParallelScope
|
||||
WoofWare.NUnitTestRunner.SingleTestMethod inherit obj, implements WoofWare.NUnitTestRunner.SingleTestMethod System.IEquatable, System.Collections.IStructuralEquatable
|
||||
WoofWare.NUnitTestRunner.SingleTestMethod..ctor [constructor]: (System.Reflection.MethodInfo, WoofWare.NUnitTestRunner.TestKind, WoofWare.NUnitTestRunner.Modifier list, string list, int option, WoofWare.NUnitTestRunner.Combinatorial option, unit WoofWare.NUnitTestRunner.Parallelizable option)
|
||||
WoofWare.NUnitTestRunner.SingleTestMethod.Categories [property]: [read-only] string list
|
||||
|
@@ -620,14 +620,16 @@ module TestFixture =
|
||||
| [ v ] ->
|
||||
match v.Value with
|
||||
| :? int as v ->
|
||||
match v with
|
||||
| 512 -> categories, args, Some (Parallelizable.Yes ClassParallelScope.Fixtures)
|
||||
| 256 -> categories, args, Some (Parallelizable.Yes ClassParallelScope.Children)
|
||||
| 257 -> categories, args, Some (Parallelizable.Yes ClassParallelScope.All)
|
||||
| 1 -> categories, args, Some (Parallelizable.Yes ClassParallelScope.Self)
|
||||
| v ->
|
||||
failwith
|
||||
$"Could not recognise value %i{v} of parallel scope in %s{parentType.FullName}"
|
||||
match ParallelScope.ofInt v with
|
||||
| ParallelScope.Fixtures ->
|
||||
categories, args, Some (Parallelizable.Yes ClassParallelScope.Fixtures)
|
||||
| ParallelScope.Children ->
|
||||
categories, args, Some (Parallelizable.Yes ClassParallelScope.Children)
|
||||
| ParallelScope.All ->
|
||||
categories, args, Some (Parallelizable.Yes ClassParallelScope.All)
|
||||
| ParallelScope.Self ->
|
||||
categories, args, Some (Parallelizable.Yes ClassParallelScope.Self)
|
||||
| ParallelScope.None -> categories, args, Some Parallelizable.No
|
||||
| v ->
|
||||
failwith
|
||||
$"Unexpectedly non-int value %O{v} of parallel scope in %s{parentType.FullName}"
|
||||
|
@@ -23,6 +23,7 @@
|
||||
<Compile Include="GeneratedRuntimeConfig.fs">
|
||||
<MyriadFile>RuntimeConfig.fs</MyriadFile>
|
||||
</Compile>
|
||||
<Compile Include="ParallelScope.fs" />
|
||||
<Compile Include="DotnetRuntime.fs" />
|
||||
<Compile Include="Array.fs" />
|
||||
<Compile Include="List.fs" />
|
||||
@@ -50,7 +51,7 @@
|
||||
<PackageReference Include="WoofWare.PrattParser" Version="0.2.2" />
|
||||
<PackageReference Update="FSharp.Core" Version="6.0.1" />
|
||||
<PackageReference Include="WoofWare.DotnetRuntimeLocator" Version="0.1.9" />
|
||||
<PackageReference Include="WoofWare.Myriad.Plugins.Attributes" Version="3.6.3" />
|
||||
<PackageReference Include="WoofWare.Myriad.Plugins.Attributes" Version="3.6.4" />
|
||||
<PackageReference Include="Myriad.SDK" Version="0.8.3" PrivateAssets="all" />
|
||||
<PackageReference Include="WoofWare.Myriad.Plugins" Version="$(WoofWareMyriadPluginVersion)" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "0.17",
|
||||
"version": "0.18",
|
||||
"publicReleaseRefSpec": [
|
||||
"^refs/heads/main$"
|
||||
],
|
||||
|
6
flake.lock
generated
6
flake.lock
generated
@@ -20,11 +20,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1729265718,
|
||||
"narHash": "sha256-4HQI+6LsO3kpWTYuVGIzhJs1cetFcwT7quWCk/6rqeo=",
|
||||
"lastModified": 1729850857,
|
||||
"narHash": "sha256-WvLXzNNnnw+qpFOmgaM3JUlNEH+T4s22b5i2oyyCpXE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "ccc0c2126893dd20963580b6478d1a10a4512185",
|
||||
"rev": "41dea55321e5a999b17033296ac05fe8a8b5a257",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@@ -328,8 +328,8 @@
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "WoofWare.Myriad.Plugins.Attributes";
|
||||
version = "3.6.3";
|
||||
hash = "sha256-KcswaTwDnZ+cGtFNdnWKQMhAPBVvaWtAVR+3eQYv0Ko=";
|
||||
version = "3.6.4";
|
||||
hash = "sha256-fNWldUSkIxq5Y9nqIRSrEE8R+/pUcX1Ji/wkomATg+4=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "WoofWare.PrattParser";
|
||||
|
Reference in New Issue
Block a user