55using System . Text . Json ;
66using System . Text . Json . Serialization ;
77using Microsoft . DotNet . Cli . CommandLine ;
8- using Microsoft . DotNet . Cli . Extensions ;
98using Command = System . CommandLine . Command ;
109
1110namespace Microsoft . DotNet . Cli . Commands . Test ;
@@ -33,145 +32,11 @@ private sealed class GlobalJsonTestNode
3332 public const string Name = "test" ;
3433 public static readonly string DocsLink = "https://aka.ms/dotnet-test" ;
3534
36- public static readonly Option < string > SettingsOption = new Option < string > ( "--settings" , "-s" )
37- {
38- Description = CliCommandStrings . CmdSettingsDescription ,
39- HelpName = CliCommandStrings . CmdSettingsFile
40- } . ForwardAsSingle ( o => $ "-property:VSTestSetting={ SurroundWithDoubleQuotes ( CommandDirectoryContext . GetFullPath ( o ) ) } ") ;
41-
42- public static readonly Option < bool > ListTestsOption = new Option < bool > ( "--list-tests" , "-t" )
43- {
44- Description = CliCommandStrings . CmdListTestsDescription ,
45- Arity = ArgumentArity . Zero
46- } . ForwardAs ( "-property:VSTestListTests=true" ) ;
47-
48- public static readonly Option < string > FilterOption = new Option < string > ( "--filter" )
49- {
50- Description = CliCommandStrings . CmdTestCaseFilterDescription ,
51- HelpName = CliCommandStrings . CmdTestCaseFilterExpression
52- } . ForwardAsSingle ( o => $ "-property:VSTestTestCaseFilter={ SurroundWithDoubleQuotes ( o ! ) } ") ;
53-
54- public static readonly Option < IEnumerable < string > > AdapterOption = new Option < IEnumerable < string > > ( "--test-adapter-path" )
55- {
56- Description = CliCommandStrings . CmdTestAdapterPathDescription ,
57- HelpName = CliCommandStrings . CmdTestAdapterPath
58- } . ForwardAsSingle ( o => $ "-property:VSTestTestAdapterPath={ SurroundWithDoubleQuotes ( string . Join ( ";" , o ! . Select ( CommandDirectoryContext . GetFullPath ) ) ) } ")
59- . AllowSingleArgPerToken ( ) ;
60-
61- public static readonly Option < IEnumerable < string > > LoggerOption = new Option < IEnumerable < string > > ( "--logger" , "-l" )
62- {
63- Description = CliCommandStrings . CmdLoggerDescription ,
64- HelpName = CliCommandStrings . CmdLoggerOption
65- } . ForwardAsSingle ( o =>
66- {
67- var loggersString = string . Join ( ";" , GetSemiColonEscapedArgs ( o ! ) ) ;
68-
69- return $ "-property:VSTestLogger={ SurroundWithDoubleQuotes ( loggersString ) } ";
70- } )
71- . AllowSingleArgPerToken ( ) ;
72-
73- public static readonly Option < string > OutputOption = new Option < string > ( "--output" , "-o" )
74- {
75- Description = CliCommandStrings . CmdOutputDescription ,
76- HelpName = CliCommandStrings . TestCmdOutputDir
77- }
78- . ForwardAsOutputPath ( "OutputPath" , true ) ;
79-
80- public static readonly Option < string > DiagOption = new Option < string > ( "--diag" , "-d" )
81- {
82- Description = CliCommandStrings . CmdPathTologFileDescription ,
83- HelpName = CliCommandStrings . CmdPathToLogFile
84- }
85- . ForwardAsSingle ( o => $ "-property:VSTestDiag={ SurroundWithDoubleQuotes ( CommandDirectoryContext . GetFullPath ( o ) ) } ") ;
86-
87- public static readonly Option < bool > NoBuildOption = new Option < bool > ( "--no-build" )
88- {
89- Description = CliCommandStrings . CmdNoBuildDescription ,
90- Arity = ArgumentArity . Zero
91- } . ForwardAs ( "-property:VSTestNoBuild=true" ) ;
92-
93- public static readonly Option < string > ResultsOption = new Option < string > ( "--results-directory" )
94- {
95- Description = CliCommandStrings . CmdResultsDirectoryDescription ,
96- HelpName = CliCommandStrings . CmdPathToResultsDirectory
97- } . ForwardAsSingle ( o => $ "-property:VSTestResultsDirectory={ SurroundWithDoubleQuotes ( CommandDirectoryContext . GetFullPath ( o ) ) } ") ;
98-
99- public static readonly Option < IEnumerable < string > > CollectOption = new Option < IEnumerable < string > > ( "--collect" )
100- {
101- Description = CliCommandStrings . cmdCollectDescription ,
102- HelpName = CliCommandStrings . cmdCollectFriendlyName
103- } . ForwardAsSingle ( o => $ "-property:VSTestCollect=\" { string . Join ( ";" , GetSemiColonEscapedArgs ( o ! ) ) } \" ")
104- . AllowSingleArgPerToken ( ) ;
105-
106- public static readonly Option < bool > BlameOption = new Option < bool > ( "--blame" )
107- {
108- Description = CliCommandStrings . CmdBlameDescription ,
109- Arity = ArgumentArity . Zero
110- } . ForwardIfEnabled ( "-property:VSTestBlame=true" ) ;
111-
112- public static readonly Option < bool > BlameCrashOption = new Option < bool > ( "--blame-crash" )
113- {
114- Description = CliCommandStrings . CmdBlameCrashDescription ,
115- Arity = ArgumentArity . Zero
116- } . ForwardIfEnabled ( "-property:VSTestBlameCrash=true" ) ;
117-
118- public static readonly Option < string > BlameCrashDumpOption = CreateBlameCrashDumpOption ( ) ;
119-
120- private static Option < string > CreateBlameCrashDumpOption ( )
121- {
122- Option < string > result = new Option < string > ( "--blame-crash-dump-type" )
123- {
124- Description = CliCommandStrings . CmdBlameCrashDumpTypeDescription ,
125- HelpName = CliCommandStrings . CrashDumpTypeArgumentName ,
126- }
127- . ForwardAsMany ( o => [ "-property:VSTestBlameCrash=true" , $ "-property:VSTestBlameCrashDumpType={ o } "] ) ;
128- result . AcceptOnlyFromAmong ( [ "full" , "mini" ] ) ;
129- return result ;
130- }
131-
132- public static readonly Option < bool > BlameCrashAlwaysOption = new Option < bool > ( "--blame-crash-collect-always" )
133- {
134- Description = CliCommandStrings . CmdBlameCrashCollectAlwaysDescription ,
135- Arity = ArgumentArity . Zero
136- } . ForwardIfEnabled ( [ "-property:VSTestBlameCrash=true" , "-property:VSTestBlameCrashCollectAlways=true" ] ) ;
137-
138- public static readonly Option < bool > BlameHangOption = new Option < bool > ( "--blame-hang" )
139- {
140- Description = CliCommandStrings . CmdBlameHangDescription ,
141- Arity = ArgumentArity . Zero
142- } . ForwardAs ( "-property:VSTestBlameHang=true" ) ;
143-
144- public static readonly Option < string > BlameHangDumpOption = CreateBlameHangDumpOption ( ) ;
145-
146- private static Option < string > CreateBlameHangDumpOption ( )
147- {
148- Option < string > result = new Option < string > ( "--blame-hang-dump-type" )
149- {
150- Description = CliCommandStrings . CmdBlameHangDumpTypeDescription ,
151- HelpName = CliCommandStrings . HangDumpTypeArgumentName
152- }
153- . ForwardAsMany ( o => [ "-property:VSTestBlameHang=true" , $ "-property:VSTestBlameHangDumpType={ o } "] ) ;
154- result . AcceptOnlyFromAmong ( [ "full" , "mini" , "none" ] ) ;
155- return result ;
156- }
157-
158- public static readonly Option < string > BlameHangTimeoutOption = new Option < string > ( "--blame-hang-timeout" )
159- {
160- Description = CliCommandStrings . CmdBlameHangTimeoutDescription ,
161- HelpName = CliCommandStrings . HangTimeoutArgumentName
162- } . ForwardAsMany ( o => [ "-property:VSTestBlameHang=true" , $ "-property:VSTestBlameHangTimeout={ o } "] ) ;
163-
164- public static readonly Option < bool > NoLogoOption = CommonOptions . NoLogoOption ( forwardAs : "--property:VSTestNoLogo=true" , description : CliCommandStrings . TestCmdNoLogo ) ;
165-
166- public static readonly Option < bool > NoRestoreOption = CommonOptions . NoRestoreOption ;
167-
16835 public static readonly Option < string > FrameworkOption = CommonOptions . FrameworkOption ( CliCommandStrings . TestFrameworkOptionDescription ) ;
16936
170- public static readonly Option ConfigurationOption = CommonOptions . ConfigurationOption ( CliCommandStrings . TestConfigurationOptionDescription ) ;
37+ public static readonly Option < string ? > ConfigurationOption = CommonOptions . ConfigurationOption ( CliCommandStrings . TestConfigurationOptionDescription ) ;
17138
17239 public static readonly Option < Utils . VerbosityOptions ? > VerbosityOption = CommonOptions . VerbosityOption ( ) ;
173- public static readonly Option < string [ ] > VsTestTargetOption = CommonOptions . RequiredMSBuildTargetOption ( "VSTest" ) ;
174- public static readonly Option < string [ ] > MTPTargetOption = CommonOptions . RequiredMSBuildTargetOption ( CliConstants . MTPTarget ) ;
17540
17641 public static TestRunner GetTestRunner ( )
17742 {
@@ -223,28 +88,7 @@ public static TestRunner GetTestRunner()
22388 return null ;
22489 }
22590
226- public static Command Create ( )
227- {
228- var command = new Command ( Name ) ;
229-
230- switch ( GetTestRunner ( ) )
231- {
232- case TestRunner . VSTest :
233- ConfigureVSTestCommand ( command ) ;
234- break ;
235-
236- case TestRunner . MicrosoftTestingPlatform :
237- ConfigureTestingPlatformCommand ( command ) ;
238- break ;
239-
240- default :
241- throw new InvalidOperationException ( ) ;
242- } ;
243-
244- return command ;
245- }
246-
247- public static void ConfigureTestingPlatformCommand ( Command command )
91+ public static void ConfigureMicrosoftTestingPlatformCommand ( Command command )
24892 {
24993 command . Description = CliCommandStrings . DotnetTestCommandMTPDescription ;
25094 command . Options . Add ( MicrosoftTestingPlatformOptions . ProjectOrSolutionOption ) ;
@@ -259,8 +103,8 @@ public static void ConfigureTestingPlatformCommand(Command command)
259103 command . Options . Add ( CommonOptions . ArchitectureOption ) ;
260104 command . Options . Add ( CommonOptions . EnvOption ) ;
261105 command . Options . Add ( CommonOptions . PropertiesOption ) ;
262- command . Options . Add ( MicrosoftTestingPlatformOptions . ConfigurationOption ) ;
263- command . Options . Add ( MicrosoftTestingPlatformOptions . FrameworkOption ) ;
106+ command . Options . Add ( ConfigurationOption ) ;
107+ command . Options . Add ( FrameworkOption ) ;
264108 command . Options . Add ( CommonOptions . OperatingSystemOption ) ;
265109 command . Options . Add ( CommonOptions . RuntimeOption ( CliCommandStrings . TestRuntimeOptionDescription ) ) ;
266110 command . Options . Add ( VerbosityOption ) ;
@@ -272,7 +116,7 @@ public static void ConfigureTestingPlatformCommand(Command command)
272116 command . Options . Add ( MicrosoftTestingPlatformOptions . ListTestsOption ) ;
273117 command . Options . Add ( MicrosoftTestingPlatformOptions . NoLaunchProfileOption ) ;
274118 command . Options . Add ( MicrosoftTestingPlatformOptions . NoLaunchProfileArgumentsOption ) ;
275- command . Options . Add ( MTPTargetOption ) ;
119+ command . Options . Add ( MicrosoftTestingPlatformOptions . MTPTargetOption ) ;
276120 }
277121
278122 public static void ConfigureVSTestCommand ( Command command )
@@ -284,98 +128,36 @@ public static void ConfigureVSTestCommand(Command command)
284128 // We are on purpose not capturing the solution, project or directory here. We want to pass it to the
285129 // MSBuild command so we are letting it flow.
286130
287- command . Options . Add ( SettingsOption ) ;
288- command . Options . Add ( ListTestsOption ) ;
131+ command . Options . Add ( VSTestOptions . SettingsOption ) ;
132+ command . Options . Add ( VSTestOptions . ListTestsOption ) ;
289133 command . Options . Add ( CommonOptions . TestEnvOption ) ;
290- command . Options . Add ( FilterOption ) ;
291- command . Options . Add ( AdapterOption ) ;
292- command . Options . Add ( LoggerOption ) ;
293- command . Options . Add ( OutputOption ) ;
134+ command . Options . Add ( VSTestOptions . FilterOption ) ;
135+ command . Options . Add ( VSTestOptions . AdapterOption ) ;
136+ command . Options . Add ( VSTestOptions . LoggerOption ) ;
137+ command . Options . Add ( VSTestOptions . OutputOption ) ;
294138 command . Options . Add ( CommonOptions . ArtifactsPathOption ) ;
295- command . Options . Add ( DiagOption ) ;
296- command . Options . Add ( NoBuildOption ) ;
297- command . Options . Add ( ResultsOption ) ;
298- command . Options . Add ( CollectOption ) ;
299- command . Options . Add ( BlameOption ) ;
300- command . Options . Add ( BlameCrashOption ) ;
301- command . Options . Add ( BlameCrashDumpOption ) ;
302- command . Options . Add ( BlameCrashAlwaysOption ) ;
303- command . Options . Add ( BlameHangOption ) ;
304- command . Options . Add ( BlameHangDumpOption ) ;
305- command . Options . Add ( BlameHangTimeoutOption ) ;
306- command . Options . Add ( NoLogoOption ) ;
139+ command . Options . Add ( VSTestOptions . DiagOption ) ;
140+ command . Options . Add ( VSTestOptions . NoBuildOption ) ;
141+ command . Options . Add ( VSTestOptions . ResultsOption ) ;
142+ command . Options . Add ( VSTestOptions . CollectOption ) ;
143+ command . Options . Add ( VSTestOptions . BlameOption ) ;
144+ command . Options . Add ( VSTestOptions . BlameCrashOption ) ;
145+ command . Options . Add ( VSTestOptions . BlameCrashDumpOption ) ;
146+ command . Options . Add ( VSTestOptions . BlameCrashAlwaysOption ) ;
147+ command . Options . Add ( VSTestOptions . BlameHangOption ) ;
148+ command . Options . Add ( VSTestOptions . BlameHangDumpOption ) ;
149+ command . Options . Add ( VSTestOptions . BlameHangTimeoutOption ) ;
150+ command . Options . Add ( VSTestOptions . NoLogoOption ) ;
307151 command . Options . Add ( ConfigurationOption ) ;
308152 command . Options . Add ( FrameworkOption ) ;
309153 command . Options . Add ( CommonOptions . RuntimeOption ( CliCommandStrings . TestRuntimeOptionDescription ) ) ;
310- command . Options . Add ( NoRestoreOption ) ;
154+ command . Options . Add ( CommonOptions . NoRestoreOption ) ;
311155 command . Options . Add ( CommonOptions . InteractiveMsBuildForwardOption ) ;
312156 command . Options . Add ( VerbosityOption ) ;
313157 command . Options . Add ( CommonOptions . ArchitectureOption ) ;
314158 command . Options . Add ( CommonOptions . OperatingSystemOption ) ;
315159 command . Options . Add ( CommonOptions . PropertiesOption ) ;
316160 command . Options . Add ( CommonOptions . DisableBuildServersOption ) ;
317- command . Options . Add ( VsTestTargetOption ) ;
318- }
319-
320- private static string GetSemiColonEscapedstring ( string arg )
321- {
322- if ( arg . IndexOf ( ";" ) != - 1 )
323- {
324- return arg . Replace ( ";" , "%3b" ) ;
325- }
326-
327- return arg ;
328- }
329-
330- private static string [ ] GetSemiColonEscapedArgs ( IEnumerable < string > args )
331- {
332- int counter = 0 ;
333- string [ ] array = new string [ args . Count ( ) ] ;
334-
335- foreach ( string arg in args )
336- {
337- array [ counter ++ ] = GetSemiColonEscapedstring ( arg ) ;
338- }
339-
340- return array ;
341- }
342-
343- /// <summary>
344- /// Adding double quotes around the property helps MSBuild arguments parser and avoid incorrect splits on ',' or ';'.
345- /// </summary>
346- internal /* for testing purposes */ static string SurroundWithDoubleQuotes ( string input )
347- {
348- if ( input is null )
349- {
350- throw new ArgumentNullException ( nameof ( input ) ) ;
351- }
352-
353- // If already escaped by double quotes then return original string.
354- if ( input . StartsWith ( "\" " , StringComparison . Ordinal )
355- && input . EndsWith ( "\" " , StringComparison . Ordinal ) )
356- {
357- return input ;
358- }
359-
360- // We want to count the number of trailing backslashes to ensure
361- // we will have an even number before adding the final double quote.
362- // Otherwise the last \" will be interpreted as escaping the double
363- // quote rather than a backslash and a double quote.
364- var trailingBackslashesCount = 0 ;
365- for ( int i = input . Length - 1 ; i >= 0 ; i -- )
366- {
367- if ( input [ i ] == '\\ ' )
368- {
369- trailingBackslashesCount ++ ;
370- }
371- else
372- {
373- break ;
374- }
375- }
376-
377- return trailingBackslashesCount % 2 == 0
378- ? string . Concat ( "\" " , input , "\" " )
379- : string . Concat ( "\" " , input , "\\ \" " ) ;
161+ command . Options . Add ( VSTestOptions . VsTestTargetOption ) ;
380162 }
381163}
0 commit comments