From 85400ea148753b37a7c5e023c21bca4e6550fd7e Mon Sep 17 00:00:00 2001 From: Jesper Olofsson Date: Wed, 21 May 2025 13:00:13 +0200 Subject: [PATCH 1/4] Add MsBuildArgument constructor supporting multiple values with escaped semicolons. --- src/BenchmarkDotNet/Jobs/Argument.cs | 13 +++++++++++++ .../MsBuildArgumentTests.cs | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/src/BenchmarkDotNet/Jobs/Argument.cs b/src/BenchmarkDotNet/Jobs/Argument.cs index c86c83906a..3fd22f08f4 100644 --- a/src/BenchmarkDotNet/Jobs/Argument.cs +++ b/src/BenchmarkDotNet/Jobs/Argument.cs @@ -48,5 +48,18 @@ public MonoArgument(string value) : base(value) public class MsBuildArgument : Argument { public MsBuildArgument(string value) : base(value) { } + + public MsBuildArgument(string key, params string[] values) + : base($"/p:{key}={EscapeAndJoin(values)}") { } + + private static string EscapeAndJoin(string[] values) + { + return string.Join("%3b", values.Select(EscapeSpecialChars)); + } + + private static string EscapeSpecialChars(string input) + { + return input.Replace(";", "%3B"); + } } } \ No newline at end of file diff --git a/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/MsBuildArgumentTests.cs b/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/MsBuildArgumentTests.cs index f4619040cc..d5e96686ea 100644 --- a/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/MsBuildArgumentTests.cs +++ b/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/MsBuildArgumentTests.cs @@ -25,6 +25,13 @@ public void ProcessIsBuiltWithCustomProperty(bool setCustomProperty) } [Fact] + + public void Constructor_WithKeyAndMultipleValues_ShouldEscapeSemicolons() + { + var arg = new MsBuildArgument("DefineConstants", "FOO", "BAR"); + Assert.Equal("/p:DefineConstants=FOO%3BBAR", arg.TextRepresentation); + } + public void MultipleProcessesAreBuiltWithCorrectProperties() { var config = ManualConfig.CreateEmpty() From 517bd1ce373c809928b3691e151eb854901e7c9d Mon Sep 17 00:00:00 2001 From: Jesper Olofsson Date: Wed, 21 May 2025 16:35:18 +0200 Subject: [PATCH 2/4] Add MsBuildProperty to support quoted, semicolon-separated values - Introduced MsBuildProperty class inheriting from MsBuildArgument that wraps multiple values in quotes and separates them with semicolons. - AddedtestMsBuildProperty_ShouldWrapMultipleValuesInQuotes to verify correct text representation formatting. --- src/BenchmarkDotNet/Jobs/Argument.cs | 13 +++++++++++++ .../MsBuildArgumentTests.cs | 8 ++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/BenchmarkDotNet/Jobs/Argument.cs b/src/BenchmarkDotNet/Jobs/Argument.cs index 3fd22f08f4..6ec416c8e7 100644 --- a/src/BenchmarkDotNet/Jobs/Argument.cs +++ b/src/BenchmarkDotNet/Jobs/Argument.cs @@ -45,6 +45,19 @@ public MonoArgument(string value) : base(value) /// example: new MsBuildArgument("/p:MyCustomSetting=123") /// [PublicAPI] + + /// + /// A specialized MSBuild argument that sets a property using a quoted, semicolon-separated list of values. + /// + public class MsBuildProperty : MsBuildArgument + { + public MsBuildProperty(string key, params string[] values) + : base($"/p:{key}=\"{string.Join(";", values)}") + { + } + + + } public class MsBuildArgument : Argument { public MsBuildArgument(string value) : base(value) { } diff --git a/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/MsBuildArgumentTests.cs b/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/MsBuildArgumentTests.cs index d5e96686ea..22c346ec2d 100644 --- a/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/MsBuildArgumentTests.cs +++ b/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/MsBuildArgumentTests.cs @@ -26,12 +26,12 @@ public void ProcessIsBuiltWithCustomProperty(bool setCustomProperty) [Fact] - public void Constructor_WithKeyAndMultipleValues_ShouldEscapeSemicolons() + public void MsBuildProperty_ShouldWrapMultipleValuesInQuotes() { - var arg = new MsBuildArgument("DefineConstants", "FOO", "BAR"); - Assert.Equal("/p:DefineConstants=FOO%3BBAR", arg.TextRepresentation); + var arg = new MsBuildProperty("DefineConstants", "FOO", "BAR"); + Assert.Equal("/p:DefineConstants=\"FOO;BAR\"", arg.TextRepresentation); } - + [Fact] public void MultipleProcessesAreBuiltWithCorrectProperties() { var config = ManualConfig.CreateEmpty() From 5b4dd4c5bec3ad48aa6bc2aa9866ad832d50b213 Mon Sep 17 00:00:00 2001 From: jespernapp Date: Mon, 8 Sep 2025 10:33:13 +0200 Subject: [PATCH 3/4] Update Argument.cs Co-authored-by: Tim Cassell --- src/BenchmarkDotNet/Jobs/Argument.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/BenchmarkDotNet/Jobs/Argument.cs b/src/BenchmarkDotNet/Jobs/Argument.cs index 6ec416c8e7..261e6d86ac 100644 --- a/src/BenchmarkDotNet/Jobs/Argument.cs +++ b/src/BenchmarkDotNet/Jobs/Argument.cs @@ -61,18 +61,5 @@ public MsBuildProperty(string key, params string[] values) public class MsBuildArgument : Argument { public MsBuildArgument(string value) : base(value) { } - - public MsBuildArgument(string key, params string[] values) - : base($"/p:{key}={EscapeAndJoin(values)}") { } - - private static string EscapeAndJoin(string[] values) - { - return string.Join("%3b", values.Select(EscapeSpecialChars)); - } - - private static string EscapeSpecialChars(string input) - { - return input.Replace(";", "%3B"); - } } } \ No newline at end of file From 12c292007a6165680c53fdc6fd1d1f47d23f24bb Mon Sep 17 00:00:00 2001 From: jespernapp Date: Mon, 8 Sep 2025 10:33:32 +0200 Subject: [PATCH 4/4] Update Argument.cs Co-authored-by: Tim Cassell --- src/BenchmarkDotNet/Jobs/Argument.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BenchmarkDotNet/Jobs/Argument.cs b/src/BenchmarkDotNet/Jobs/Argument.cs index 261e6d86ac..a83c738915 100644 --- a/src/BenchmarkDotNet/Jobs/Argument.cs +++ b/src/BenchmarkDotNet/Jobs/Argument.cs @@ -52,7 +52,7 @@ public MonoArgument(string value) : base(value) public class MsBuildProperty : MsBuildArgument { public MsBuildProperty(string key, params string[] values) - : base($"/p:{key}=\"{string.Join(";", values)}") + : base($"/p:{key}=\\\"{string.Join(";", values)}\\\"") { }