1919using System . Threading . Tasks ;
2020using Akka . Actor ;
2121using Akka . IO ;
22- using Akka . MultiNode . TestAdapter . Helpers ;
2322using Akka . MultiNode . TestAdapter . Internal ;
24- using Akka . MultiNode . TestAdapter . Internal . Environment ;
2523using Akka . MultiNode . TestAdapter . Internal . Persistence ;
2624using Akka . MultiNode . TestAdapter . Internal . Sinks ;
2725using Akka . MultiNode . TestAdapter . Internal . TrxReporter ;
2826using Akka . MultiNode . TestAdapter . NodeRunner ;
2927using Akka . Remote . TestKit ;
30- using Akka . Util ;
3128using Xunit ;
3229using ErrorMessage = Xunit . Sdk . ErrorMessage ;
3330
@@ -100,7 +97,6 @@ private void Initialize(string assemblyPath, MultiNodeTestRunnerOptions options)
10097 EnableAllSinks ( assemblyPath , options ) ;
10198
10299 // Set MNTR environment for correct tests discovery
103- MultiNodeEnvironment . Initialize ( ) ;
104100 }
105101
106102 public MultiNodeTestResult ExecuteSpec ( MultiNodeTest test , MultiNodeTestRunnerOptions options )
@@ -113,6 +109,7 @@ public MultiNodeTestResult ExecuteSpec(MultiNodeTest test, MultiNodeTestRunnerOp
113109 : _tcpLogger . Ask < int > ( TcpLoggingServer . GetBoundPort . Instance ) . Result ;
114110
115111 TestStarted ? . Invoke ( test ) ;
112+ Environment . SetEnvironmentVariable ( MultiNodeFactAttribute . MultiNodeTestEnvironmentName , "1" ) ;
116113 try
117114 {
118115 if ( options . SpecNames != null &&
@@ -132,10 +129,19 @@ public MultiNodeTestResult ExecuteSpec(MultiNodeTest test, MultiNodeTestRunnerOp
132129 var nodes = test . Nodes ;
133130
134131 var result = RunSpec ( options , test , listenPort ) ;
135- if ( result . Status == MultiNodeTestResult . TestStatus . Failed )
136- TestFailed ? . Invoke ( result ) ;
137- else
138- TestPassed ? . Invoke ( result ) ;
132+ switch ( result . Status )
133+ {
134+ case MultiNodeTestResult . TestStatus . Passed :
135+ TestPassed ? . Invoke ( result ) ;
136+ return result ;
137+ case MultiNodeTestResult . TestStatus . Failed :
138+ TestFailed ? . Invoke ( result ) ;
139+ return result ;
140+ case MultiNodeTestResult . TestStatus . Skipped :
141+ TestSkipped ? . Invoke ( test , "Must be run using Akka.MultiNode.TestAdapter" ) ;
142+ return null ;
143+ }
144+
139145 return result ;
140146 }
141147 catch ( Exception e )
@@ -144,6 +150,10 @@ public MultiNodeTestResult ExecuteSpec(MultiNodeTest test, MultiNodeTestRunnerOp
144150 PublishRunnerMessage ( e . Message ) ;
145151 return null ;
146152 }
153+ finally
154+ {
155+ Environment . SetEnvironmentVariable ( MultiNodeFactAttribute . MultiNodeTestEnvironmentName , null ) ;
156+ }
147157 }
148158
149159 /// <summary>
@@ -173,17 +183,23 @@ public void Dispose()
173183 /// </summary>
174184 public static ( List < MultiNodeTest > Tests , List < ErrorMessage > Errors ) DiscoverSpecs ( string assemblyPath )
175185 {
176- MultiNodeEnvironment . Initialize ( ) ;
177-
178- using ( var controller = new XunitFrontController ( AppDomainSupport . IfAvailable , assemblyPath ) )
186+ Environment . SetEnvironmentVariable ( MultiNodeFactAttribute . MultiNodeTestEnvironmentName , "1" ) ;
187+ try
179188 {
180- using ( var discovery = new Discovery ( assemblyPath ) )
189+ using ( var controller = new XunitFrontController ( AppDomainSupport . IfAvailable , assemblyPath ) )
181190 {
182- controller . Find ( false , discovery , TestFrameworkOptions . ForDiscovery ( ) ) ;
183- discovery . Finished . WaitOne ( ) ;
184- return ( discovery . MultiNodeTests , discovery . Errors ) ;
191+ using ( var discovery = new Discovery ( assemblyPath ) )
192+ {
193+ controller . Find ( false , discovery , TestFrameworkOptions . ForDiscovery ( ) ) ;
194+ discovery . Finished . WaitOne ( ) ;
195+ return ( discovery . MultiNodeTests , discovery . Errors ) ;
196+ }
185197 }
186198 }
199+ finally
200+ {
201+ Environment . SetEnvironmentVariable ( MultiNodeFactAttribute . MultiNodeTestEnvironmentName , null ) ;
202+ }
187203 }
188204
189205 private List < MultiNodeTestResult > DiscoverAndRunSpecs ( string assemblyPath , MultiNodeTestRunnerOptions options )
@@ -226,12 +242,20 @@ private List<MultiNodeTestResult> DiscoverAndRunSpecs(string assemblyPath, Multi
226242
227243 // Run test on several nodes and report results
228244 var result = RunSpec ( options , test , listenPort ) ;
229- if ( result . Status == MultiNodeTestResult . TestStatus . Failed )
230- TestFailed ? . Invoke ( result ) ;
231- else
232- TestPassed ? . Invoke ( result ) ;
233-
234- testResults . Add ( result ) ;
245+ switch ( result . Status )
246+ {
247+ case MultiNodeTestResult . TestStatus . Failed :
248+ TestFailed ? . Invoke ( result ) ;
249+ testResults . Add ( result ) ;
250+ break ;
251+ case MultiNodeTestResult . TestStatus . Passed :
252+ TestPassed ? . Invoke ( result ) ;
253+ testResults . Add ( result ) ;
254+ break ;
255+ case MultiNodeTestResult . TestStatus . Skipped :
256+ TestSkipped ? . Invoke ( test , test . SkipReason ) ;
257+ continue ;
258+ }
235259 }
236260 catch ( Exception e )
237261 {
@@ -250,7 +274,7 @@ private MultiNodeTestResult RunSpec(MultiNodeTestRunnerOptions options, MultiNod
250274
251275 var timelineCollector = TestRunSystem . ActorOf ( Props . Create ( ( ) => new TimelineLogCollectorActor ( ) ) ) ;
252276 //TODO: might need to do some validation here to avoid the 260 character max path error on Windows
253- var folder = Directory . CreateDirectory ( Path . Combine ( options . OutputDirectory , test . TestName ) ) ;
277+ var folder = Directory . CreateDirectory ( Path . Combine ( options . OutputDirectory , test . MethodName ) ) ;
254278 var testOutputDir = folder . FullName ;
255279
256280 var testResult = new MultiNodeTestResult ( test ) ;
@@ -270,7 +294,8 @@ private MultiNodeTestResult RunSpec(MultiNodeTestRunnerOptions options, MultiNod
270294 $@ "-Dmultinode.role=""{ nodeTest . Role } """,
271295 $@" - Dmultinode . listen - address = { options . ListenAddress } ",
272296 $@ "-Dmultinode.listen-port={ listenPort } ",
273- $@ "-Dmultinode.test-assembly=""{ test . AssemblyPath } """
297+ $@ "-Dmultinode.test-assembly=""{ test . AssemblyPath } """,
298+ " - Dmultinode . test - runner = \" multinode\" "
274299 } ;
275300
276301 // Configure process for node
@@ -319,7 +344,7 @@ private void DumpAggregatedSpecLogs(
319344
320345 if ( result . Status == MultiNodeTestResult . TestStatus . Failed )
321346 {
322- var failedSpecPath = Path . GetFullPath ( Path . Combine ( options . OutputDirectory , options . FailedSpecsDirectory , $ "{ result . Test . TestName } .txt") ) ;
347+ var failedSpecPath = Path . GetFullPath ( Path . Combine ( options . OutputDirectory , options . FailedSpecsDirectory , $ "{ result . Test . MethodName } .txt") ) ;
323348 var dumpFailureArtifactTask = timelineCollector . Ask < Done > ( new TimelineLogCollectorActor . DumpToFile ( failedSpecPath ) ) ;
324349 dumpTasks . Add ( dumpFailureArtifactTask ) ;
325350 result . Attachments . Add ( new MultiNodeTestResult . Attachment { Title = "Fail log" , Path = failedSpecPath } ) ;
@@ -339,9 +364,12 @@ private void WaitForNodeExit(MultiNodeTestResult result, List<(NodeTest, Process
339364 process . WaitForExit ( ) ;
340365 Console . WriteLine ( $ "Process for test { test . Name } finished with code { process . ExitCode } ") ;
341366 var nodeResult = result . NodeResults . First ( n => n . Index == test . Node ) ;
342- nodeResult . Result = process . ExitCode == 0
343- ? MultiNodeTestResult . TestStatus . Passed
344- : MultiNodeTestResult . TestStatus . Failed ;
367+ nodeResult . Result = process . ExitCode switch
368+ {
369+ 0 => MultiNodeTestResult . TestStatus . Passed ,
370+ 2 => MultiNodeTestResult . TestStatus . Skipped ,
371+ _ => MultiNodeTestResult . TestStatus . Failed
372+ } ;
345373 }
346374 }
347375 finally
@@ -366,7 +394,7 @@ private Process StartNodeProcess(
366394 var nodeIndex = nodeTest . Node ;
367395 var nodeRole = nodeTest . Role ;
368396 var logFilePath = Path . GetFullPath ( Path . Combine ( specFolder . FullName , $ "node{ nodeIndex } __{ nodeRole } __{ _platformName } .txt") ) ;
369- var nodeInfo = new TimelineLogCollectorActor . NodeInfo ( nodeIndex , nodeRole , _platformName , nodeTest . Test . TestName ) ;
397+ var nodeInfo = new TimelineLogCollectorActor . NodeInfo ( nodeIndex , nodeRole , _platformName , nodeTest . Test . MethodName ) ;
370398 var fileActor = TestRunSystem . ActorOf ( Props . Create ( ( ) => new FileSystemAppenderActor ( logFilePath ) ) ) ;
371399 result . Attachments . Add ( new MultiNodeTestResult . Attachment { Title = $ "Node { nodeIndex } [{ nodeRole } ]", Path = logFilePath } ) ;
372400
@@ -377,7 +405,7 @@ private Process StartNodeProcess(
377405 {
378406 if ( p . ExitCode == 0 )
379407 {
380- ReportSpecPassFromExitCode ( nodeIndex , nodeRole , closureTest . Test . TestName ) ;
408+ ReportSpecPassFromExitCode ( nodeIndex , nodeRole , closureTest . Test . MethodName ) ;
381409 }
382410 } ;
383411 opt . OutputDataReceived = ( sender , eventArgs ) =>
@@ -493,12 +521,8 @@ MessageSink CreateVisualizerFileSink()
493521 return new FileSystemMessageSink ( visualizerProps ) ;
494522 }
495523
496- var fileSystemSink = CommandLine . GetProperty ( "multinode.enable-filesink" ) ;
497- if ( ! string . IsNullOrEmpty ( fileSystemSink ) )
498- {
499- SinkCoordinator . Tell ( new SinkCoordinator . EnableSink ( CreateJsonFileSink ( ) ) ) ;
500- SinkCoordinator . Tell ( new SinkCoordinator . EnableSink ( CreateVisualizerFileSink ( ) ) ) ;
501- }
524+ SinkCoordinator . Tell ( new SinkCoordinator . EnableSink ( CreateJsonFileSink ( ) ) ) ;
525+ SinkCoordinator . Tell ( new SinkCoordinator . EnableSink ( CreateVisualizerFileSink ( ) ) ) ;
502526 }
503527
504528 private void AbortTcpLoggingServer ( )
0 commit comments