66using BenchmarkDotNet . Engines ;
77using BenchmarkDotNet . Environments ;
88using BenchmarkDotNet . Exporters ;
9- using BenchmarkDotNet . Helpers ;
10- using BenchmarkDotNet . Reports ;
119using BenchmarkDotNet . Exporters . Csv ;
1210using BenchmarkDotNet . Exporters . Json ;
1311using BenchmarkDotNet . Exporters . OpenMetrics ;
1412using BenchmarkDotNet . Exporters . Xml ;
13+ using BenchmarkDotNet . Helpers ;
1514using BenchmarkDotNet . Jobs ;
1615using BenchmarkDotNet . Loggers ;
1716using BenchmarkDotNet . Portability ;
17+ using BenchmarkDotNet . Reports ;
1818using BenchmarkDotNet . Tests . Loggers ;
1919using BenchmarkDotNet . Tests . Mocks ;
2020using BenchmarkDotNet . Tests . XUnit ;
2121using BenchmarkDotNet . Toolchains ;
2222using BenchmarkDotNet . Toolchains . CoreRun ;
2323using BenchmarkDotNet . Toolchains . DotNetCli ;
24+ using BenchmarkDotNet . Toolchains . Framework ;
2425using BenchmarkDotNet . Toolchains . InProcess . Emit ;
2526using BenchmarkDotNet . Toolchains . Mono ;
26- using BenchmarkDotNet . Toolchains . Wasm ;
2727using BenchmarkDotNet . Toolchains . NativeAot ;
28- using BenchmarkDotNet . Toolchains . Framework ;
29- using Perfolizer . Horology ;
30- using System . Reflection ;
3128using BenchmarkDotNet . Toolchains . NetCoreApp ;
3229using BenchmarkDotNet . Toolchains . R2R ;
30+ using BenchmarkDotNet . Toolchains . Wasm ;
31+ using Perfolizer . Horology ;
32+ using System . Reflection ;
3333
3434namespace BenchmarkDotNet . Tests
3535{
@@ -1025,6 +1025,7 @@ public void UserCanSpecifyWasmMainJsTemplate()
10251025 [ InlineData ( "--filter abc" , "--filter *" ) ]
10261026 [ InlineData ( "-f abc" , "--filter *" ) ]
10271027 [ InlineData ( "-f *" , "--filter *" ) ]
1028+ [ InlineData ( "--filter abc -f abc" , "--filter *" ) ]
10281029 [ InlineData ( "--runtimes net7.0 --join" , "--filter * --join --runtimes net7.0" ) ]
10291030 [ InlineData ( "--join abc" , "--filter * --join" ) ]
10301031 public void CheckUpdateValidArgs ( string strArgs , string expected )
@@ -1036,21 +1037,273 @@ public void CheckUpdateValidArgs(string strArgs, string expected)
10361037 }
10371038
10381039 [ Theory ]
1039- [ InlineData ( "--filter abc -f abc" ) ]
10401040 [ InlineData ( "--runtimes net" ) ]
1041+ [ InlineData ( "--job dry --job short" ) ]
1042+ [ InlineData ( "--join --join" ) ]
10411043 public void CheckUpdateInvalidArgs ( string strArgs )
10421044 {
1045+ // Arrange
10431046 var args = strArgs . Split ( ) ;
1047+
1048+ // Act
10441049 bool isSuccess = ConfigParser . TryUpdateArgs ( args , out var updatedArgs , options => options . Filters = [ "*" ] ) ;
10451050
1046- Assert . Null ( updatedArgs ) ;
1047- Assert . False ( isSuccess ) ;
1051+ // Assert
1052+ updatedArgs . Should ( ) . BeNull ( ) ;
1053+ isSuccess . Should ( ) . BeFalse ( ) ;
10481054 }
10491055
10501056 private string GetDummyWasmEngine ( )
10511057 {
10521058 // We know, that this file exists, that's enough.
10531059 return $ "--wasmEngine={ Assembly . GetExecutingAssembly ( ) . Location } ";
10541060 }
1061+
1062+ [ Fact ]
1063+ public void UserCanSpecifyRuntimes_WithMultipleOptions ( )
1064+ {
1065+ // Arrange
1066+ var logger = new OutputLogger ( Output ) ;
1067+ string [ ] args = [ "--runtimes" , "net8.0" , "--runtimes" , "net9.0" ] ;
1068+
1069+ // Act
1070+ var ( isSuccess , config , options ) = ConfigParser . Parse ( args , logger ) ;
1071+
1072+ // Assert
1073+ isSuccess . Should ( ) . BeTrue ( ) ;
1074+ config . Should ( ) . NotBeNull ( ) ;
1075+ options . Should ( ) . NotBeNull ( ) ;
1076+ options . Runtimes . Should ( ) . Equal ( "net8.0" , "net9.0" ) ;
1077+ config . GetJobs ( ) . Should ( ) . HaveCount ( 2 ) ;
1078+ config . GetJobs ( ) . First ( ) . Meta . Baseline . Should ( ) . BeTrue ( ) ;
1079+ logger . GetLog ( ) . Should ( ) . BeEmpty ( ) ;
1080+ }
1081+
1082+ [ Fact ]
1083+ public void UserCanSpecifyExporters_WithMultipleOptions ( )
1084+ {
1085+ // Arrange
1086+ var logger = new OutputLogger ( Output ) ;
1087+ string [ ] args = [ "--exporters" , "json" , "--exporters" , "html" ] ;
1088+
1089+ // Act
1090+ var ( isSuccess , config , _) = ConfigParser . Parse ( args , logger ) ;
1091+
1092+ // Assert
1093+ isSuccess . Should ( ) . BeTrue ( ) ;
1094+ config . Should ( ) . NotBeNull ( ) ;
1095+ config . GetExporters ( ) . Should ( ) . Contain ( JsonExporter . Default ) ;
1096+ config . GetExporters ( ) . Should ( ) . Contain ( HtmlExporter . Default ) ;
1097+ logger . GetLog ( ) . Should ( ) . BeEmpty ( ) ;
1098+ }
1099+
1100+ [ Theory ]
1101+ [ InlineData ( "--filter" , "A" , "--filter" , "B" ) ]
1102+ [ InlineData ( "-f" , "A" , "--filter" , "B" ) ]
1103+ public void UserCanSpecifyFilter_WithMultipleOptions ( params string [ ] args )
1104+ {
1105+ // Arrange
1106+ var logger = new OutputLogger ( Output ) ;
1107+
1108+ // Act
1109+ var ( isSuccess , _, options ) = ConfigParser . Parse ( args , logger ) ;
1110+
1111+ // Assert
1112+ isSuccess . Should ( ) . BeTrue ( ) ;
1113+ options . Should ( ) . NotBeNull ( ) ;
1114+ options . Filters . Should ( ) . Equal ( "A" , "B" ) ;
1115+ logger . GetLog ( ) . Should ( ) . BeEmpty ( ) ;
1116+ }
1117+
1118+ [ Fact ]
1119+ public void UserCanSpecifyCoreRunPaths_WithMultipleOptions ( )
1120+ {
1121+ // Arrange
1122+ var logger = new OutputLogger ( Output ) ;
1123+ var path1 = typeof ( object ) . Assembly . Location ;
1124+ var path2 = typeof ( ConfigParserTests ) . Assembly . Location ;
1125+
1126+ // Act
1127+ var ( isSuccess , config , _) = ConfigParser . Parse ( [ "--coreRun" , path1 , "--coreRun" , path2 ] , logger ) ;
1128+
1129+ // Assert
1130+ isSuccess . Should ( ) . BeTrue ( ) ;
1131+ config . Should ( ) . NotBeNull ( ) ;
1132+ config . GetJobs ( ) . Should ( ) . HaveCount ( 2 ) ;
1133+ logger . GetLog ( ) . Should ( ) . BeEmpty ( ) ;
1134+ }
1135+
1136+ [ Fact ]
1137+ public void UserCanSpecifyEnvVars_WithMultipleOptions ( )
1138+ {
1139+ // Arrange
1140+ var logger = new OutputLogger ( Output ) ;
1141+ string [ ] args = [ "--envVars" , "K1:V1" , "--envVars" , "K2:V2" ] ;
1142+
1143+ // Act
1144+ var ( isSuccess , config , _) = ConfigParser . Parse ( args , logger ) ;
1145+
1146+ // Assert
1147+ isSuccess . Should ( ) . BeTrue ( ) ;
1148+ config . Should ( ) . NotBeNull ( ) ;
1149+ config . GetJobs ( ) . Single ( ) . Environment . EnvironmentVariables . Should ( ) . HaveCount ( 2 ) ;
1150+ logger . GetLog ( ) . Should ( ) . BeEmpty ( ) ;
1151+ }
1152+
1153+ [ Fact ]
1154+ public void UserCanSpecifyRuntimes_WithSingleOption ( )
1155+ {
1156+ // Arrange
1157+ var logger = new OutputLogger ( Output ) ;
1158+ string [ ] args = [ "--runtimes" , "net8.0" , "net9.0" ] ;
1159+
1160+ // Act
1161+ var ( isSuccess , config , options ) = ConfigParser . Parse ( args , logger ) ;
1162+
1163+ // Assert
1164+ isSuccess . Should ( ) . BeTrue ( ) ;
1165+ config . Should ( ) . NotBeNull ( ) ;
1166+ options . Should ( ) . NotBeNull ( ) ;
1167+ config . GetJobs ( ) . Should ( ) . HaveCount ( 2 ) ;
1168+ logger . GetLog ( ) . Should ( ) . BeEmpty ( ) ;
1169+ }
1170+
1171+ [ Fact ]
1172+ public void UserCanSpecifyCounters_WithMultipleOptions ( )
1173+ {
1174+ // Arrange
1175+ var logger = new OutputLogger ( Output ) ;
1176+ string [ ] args =
1177+ [
1178+ "--counters" , $ "{ nameof ( HardwareCounter . CacheMisses ) } +{ nameof ( HardwareCounter . InstructionRetired ) } ",
1179+ "--counters" , nameof ( HardwareCounter . BranchMispredictions )
1180+ ] ;
1181+
1182+ // Act
1183+ var ( isSuccess , config , _) = ConfigParser . Parse ( args , logger ) ;
1184+
1185+ // Assert
1186+ isSuccess . Should ( ) . BeTrue ( ) ;
1187+ config . Should ( ) . NotBeNull ( ) ;
1188+ config ! . GetHardwareCounters ( ) . Should ( ) . HaveCount ( 3 ) ;
1189+ logger . GetLog ( ) . Should ( ) . BeEmpty ( ) ;
1190+ }
1191+
1192+ [ Fact ]
1193+ public void OptionAfterDashDashIsTreatedAsValue ( )
1194+ {
1195+ // Arrange
1196+ var logger = new OutputLogger ( Output ) ;
1197+ string [ ] args = [ "--job" , "dry" , "--" , "--job" , "short" ] ;
1198+
1199+ // Act
1200+ var ( isSuccess , _, _) = ConfigParser . Parse ( args , logger ) ;
1201+
1202+ // Assert
1203+ isSuccess . Should ( ) . BeTrue ( ) ;
1204+ logger . GetLog ( ) . Should ( ) . BeEmpty ( ) ;
1205+ }
1206+
1207+ [ Fact ]
1208+ public void UserCanNotSpecifyCounters_MoreThan3_RaiseError ( )
1209+ {
1210+ // Arrange
1211+ var logger = new OutputLogger ( Output ) ;
1212+ string [ ] args =
1213+ [
1214+ "--counters" , $ "{ nameof ( HardwareCounter . CacheMisses ) } +{ nameof ( HardwareCounter . InstructionRetired ) } ",
1215+ "--counters" , $ "{ nameof ( HardwareCounter . BranchMispredictions ) } +{ nameof ( HardwareCounter . Timer ) } "
1216+ ] ;
1217+
1218+ // Act
1219+ var ( isSuccess , _, _) = ConfigParser . Parse ( args , logger ) ;
1220+
1221+ // Assert
1222+ isSuccess . Should ( ) . BeFalse ( ) ;
1223+
1224+ var log = logger . GetLog ( ) . Trim ( ) ;
1225+ log . Should ( ) . Be ( "You can't use more than 3 HardwareCounters at the same time." ) ;
1226+ }
1227+
1228+ [ Fact ]
1229+ public void UserCanNotSpecifyCounters_WrongName ( )
1230+ {
1231+ // Arrange
1232+ var logger = new OutputLogger ( Output ) ;
1233+ string [ ] args = [ "--counters" , nameof ( HardwareCounter . CacheMisses ) , "--counters" , "WRONG_NAME" ] ;
1234+
1235+ // Act
1236+ var ( isSuccess , _, _) = ConfigParser . Parse ( args , logger ) ;
1237+
1238+ // Assert
1239+ isSuccess . Should ( ) . BeFalse ( ) ;
1240+
1241+ var log = logger . GetLog ( ) . Trim ( ) ;
1242+ log . Should ( ) . Be ( "The provided hardware counter \" WRONG_NAME\" is invalid. Available options are: NotSet+Timer+TotalIssues+BranchInstructions+CacheMisses+BranchMispredictions+TotalCycles+UnhaltedCoreCycles+InstructionRetired+UnhaltedReferenceCycles+LlcReference+LlcMisses+BranchInstructionRetired+BranchMispredictsRetired." ) ;
1243+ }
1244+
1245+ [ Theory ]
1246+ [ InlineData ( "--join" , "--join" ) ]
1247+ [ InlineData ( "--inProcess" , "--inProcess" ) ]
1248+ [ InlineData ( "--memory" , "--memory" ) ]
1249+ [ InlineData ( "-tm" , "-m" ) ]
1250+ [ InlineData ( "-mm" ) ]
1251+ public void UserCanNotSpecify_MultipleSameBooleanOptions ( params string [ ] args )
1252+ {
1253+ // Arrange
1254+ var logger = new OutputLogger ( Output ) ;
1255+
1256+ // Act
1257+ var ( isSuccess , _, _) = ConfigParser . Parse ( args , logger ) ;
1258+
1259+ // Assert
1260+ isSuccess . Should ( ) . BeFalse ( ) ;
1261+
1262+ var log = logger . GetLog ( ) . Trim ( ) ;
1263+ log . Should ( ) . Match ( $ "Option '*' is defined multiple times.") ;
1264+ }
1265+
1266+ [ Theory ]
1267+ [ InlineData ( "-tm" ) ]
1268+ [ InlineData ( "-m" , "-t" ) ]
1269+ public void UserCanSpecify_BundledDifferentBooleanOptions ( params string [ ] args )
1270+ {
1271+ // Arrange
1272+ var logger = new OutputLogger ( Output ) ;
1273+
1274+ // Act
1275+ var ( isSuccess , _, options ) = ConfigParser . Parse ( args , logger ) ;
1276+
1277+ // Assert
1278+ isSuccess . Should ( ) . BeTrue ( ) ;
1279+ logger . GetLog ( ) . Should ( ) . BeEmpty ( ) ;
1280+
1281+ options . Should ( ) . NotBeNull ( ) ;
1282+ options . UseThreadingDiagnoser . Should ( ) . BeTrue ( ) ;
1283+ options . UseMemoryDiagnoser . Should ( ) . BeTrue ( ) ;
1284+ }
1285+
1286+ [ Theory ]
1287+ [ InlineData ( "--job" , "dry" , "--job" , "short" ) ]
1288+ [ InlineData ( "--job=dry" , "--job=short" ) ]
1289+ [ InlineData ( "-j" , "dry" , "-j" , "short" ) ]
1290+ [ InlineData ( "-j" , "dry" , "--job" , "short" ) ]
1291+ [ InlineData ( "--JOB" , "dry" , "--job" , "short" ) ]
1292+ [ InlineData ( "--launchCount" , "1" , "--launchCount" , "2" ) ]
1293+ [ InlineData ( "--title" , "A" , "--title" , "B" ) ]
1294+ public void UserCanNotSpecify_MultipleSameScalarOptions ( params string [ ] args )
1295+ {
1296+ // Arrange
1297+ var logger = new OutputLogger ( Output ) ;
1298+
1299+ // Act
1300+ var ( isSuccess , _, _) = ConfigParser . Parse ( args , logger ) ;
1301+
1302+ // Assert
1303+ isSuccess . Should ( ) . BeFalse ( ) ;
1304+
1305+ var log = logger . GetLog ( ) . Trim ( ) ;
1306+ log . Should ( ) . Match ( "Option '*' is defined multiple times." ) ;
1307+ }
10551308 }
10561309}
0 commit comments