From 1e2a47e7dfa3edc18b46d7ebd0873625d6e369da Mon Sep 17 00:00:00 2001 From: Nate Pink Date: Wed, 1 Jul 2026 10:47:21 -0400 Subject: [PATCH 1/3] Fix for space in path to assembies. Fixes #https://github.com/Particular/docs.particular.net/issues/8368 --- src/Particular.PlatformSample/AppLauncher.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Particular.PlatformSample/AppLauncher.cs b/src/Particular.PlatformSample/AppLauncher.cs index 4720180..8d96453 100644 --- a/src/Particular.PlatformSample/AppLauncher.cs +++ b/src/Particular.PlatformSample/AppLauncher.cs @@ -166,12 +166,14 @@ public void ServicePulse(int port, int serviceControlPort, int monitoringPort, s void StartProcess(string assemblyPath, Dictionary environmentVariables = null) { var workingDirectory = Path.GetDirectoryName(assemblyPath)!; - - var startInfo = new ProcessStartInfo("dotnet", assemblyPath) + var startInfo = new ProcessStartInfo("dotnet") { WorkingDirectory = workingDirectory, UseShellExecute = false }; + // Adding the assembly path to the argument list to prevent the path from being separated in to different arguments + // by the ProcessStartInfo constructor by spaces. + startInfo.ArgumentList.Add(assemblyPath); if (environmentVariables is not null) { From f85c957202b50e8b4f64a03cb51adb0c00489766 Mon Sep 17 00:00:00 2001 From: Nate Pink Date: Wed, 1 Jul 2026 11:28:03 -0400 Subject: [PATCH 2/3] Add a test to catch reintroduction of bug. --- .../VisualTestsSpaceInPath.cs | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/Particular.PlatformSample.Tests/VisualTestsSpaceInPath.cs diff --git a/src/Particular.PlatformSample.Tests/VisualTestsSpaceInPath.cs b/src/Particular.PlatformSample.Tests/VisualTestsSpaceInPath.cs new file mode 100644 index 0000000..a0ffa21 --- /dev/null +++ b/src/Particular.PlatformSample.Tests/VisualTestsSpaceInPath.cs @@ -0,0 +1,101 @@ +namespace Particular.PlatformSample.Tests; + +using System; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using NUnit.Framework; +using OpenQA.Selenium; +using OpenQA.Selenium.Chrome; + +[FixtureLifeCycle(LifeCycle.SingleInstance)] +[Parallelizable(ParallelScope.None)] +public class VisualTestsSpaceInPath +{ + Task launcherTask; + CancellationTokenSource closePlatformTokenSource; + ChromeDriver driver; + + [OneTimeSetUp] + public async Task Setup() + { + closePlatformTokenSource = new CancellationTokenSource(); + + launcherTask = Task.Run(async () => + { + await PlatformLauncher.Launch(cancellationToken: closePlatformTokenSource.Token); + }); + + using var timeoutTokenSource = new CancellationTokenSource(60_000); + + while (TestPortsInternal.ServicePulse == 0) + { + await Task.Delay(1000, closePlatformTokenSource.Token); + } + + await Network.WaitForHttpOk($"http://localhost:{TestPortsInternal.ServicePulse}", cancellationToken: timeoutTokenSource.Token); + + var chromeOpts = new ChromeOptions(); + chromeOpts.AddArgument("--headless=new"); + chromeOpts.AddArgument("--disable-gpu"); + chromeOpts.AddArgument("--ignore-certificate-errors"); + chromeOpts.AddArgument("--disable-extensions"); + chromeOpts.AddArgument("--no-sandbox"); + chromeOpts.AddArgument("--disable-dev-shm-usage"); + chromeOpts.AddArgument("--disk-cache-size=1"); + chromeOpts.AddArgument("--media-cache-size=1"); + chromeOpts.AddArgument("--incognito"); + chromeOpts.AddArgument("--remote-debugging-port=9222"); + chromeOpts.AddArgument("--aggressive-cache-discard"); + + if (Environment.GetEnvironmentVariable("CI") == "true") + { + var runnerTemp = Environment.GetEnvironmentVariable("RUNNER_TEMP"); + var dataDir = Path.Combine(runnerTemp, "browser-testing with spaces"); + Directory.CreateDirectory(dataDir); + chromeOpts.AddArgument($"--user-data-dir={dataDir}"); + } + + var chromeService = ChromeDriverService.CreateDefaultService(); + driver = new ChromeDriver(chromeService, chromeOpts, TimeSpan.FromSeconds(90)); + } + + [OneTimeTearDown] + public async Task TearDown() + { + await closePlatformTokenSource.CancelAsync(); + await launcherTask; + closePlatformTokenSource.Dispose(); + driver.Close(); + driver.Dispose(); + } + + [Test(Description = "Checks that ServicePulse is connected to ServiceControl and the endpoints are being monitored when there is a space in the path to the assemblies")] + public async Task ShouldBeConnected() + { + await Task.Delay(2000); + driver.Navigate().GoToUrl($"http://localhost:{TestPortsInternal.ServicePulse}/#/dashboard"); + await Task.Delay(10_000); + + var connectionFailedSpans = driver.FindElements(By.CssSelector(".connection-failed")); + Assert.That(connectionFailedSpans.Count, Is.EqualTo(0)); + + var connectionOkSpans = driver.FindElements(By.CssSelector(".pa-connection-success")); + Assert.That(connectionOkSpans.Count, Is.EqualTo(2)); + } + + [Test(Description = "Checks the monitoring page functionality when there is a space in the path to the assemblies")] + public async Task CheckMonitoringPage() + { + await Task.Delay(2000); + driver.Navigate().GoToUrl($"http://localhost:{TestPortsInternal.ServicePulse}/#/monitoring"); + await Task.Delay(10_000); + + var primaryButtons = driver.FindElements(By.CssSelector(".btn.btn-primary")); + var noEndpointsButton = primaryButtons.Where(b => b.Text.Contains("how to enable endpoint monitoring")).FirstOrDefault(); + + Assert.That(noEndpointsButton, Is.Not.Null); + Assert.That(noEndpointsButton.GetAttribute("href"), Is.EqualTo("https://docs.particular.net/monitoring/metrics/")); + } +} From 7161e58a5034ee3c675ed99a8f708496332d5e84 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 2 Jul 2026 07:22:21 -0700 Subject: [PATCH 3/3] Revert "Add a test to catch reintroduction of bug." This reverts commit f85c957202b50e8b4f64a03cb51adb0c00489766. --- .../VisualTestsSpaceInPath.cs | 101 ------------------ 1 file changed, 101 deletions(-) delete mode 100644 src/Particular.PlatformSample.Tests/VisualTestsSpaceInPath.cs diff --git a/src/Particular.PlatformSample.Tests/VisualTestsSpaceInPath.cs b/src/Particular.PlatformSample.Tests/VisualTestsSpaceInPath.cs deleted file mode 100644 index a0ffa21..0000000 --- a/src/Particular.PlatformSample.Tests/VisualTestsSpaceInPath.cs +++ /dev/null @@ -1,101 +0,0 @@ -namespace Particular.PlatformSample.Tests; - -using System; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using NUnit.Framework; -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; - -[FixtureLifeCycle(LifeCycle.SingleInstance)] -[Parallelizable(ParallelScope.None)] -public class VisualTestsSpaceInPath -{ - Task launcherTask; - CancellationTokenSource closePlatformTokenSource; - ChromeDriver driver; - - [OneTimeSetUp] - public async Task Setup() - { - closePlatformTokenSource = new CancellationTokenSource(); - - launcherTask = Task.Run(async () => - { - await PlatformLauncher.Launch(cancellationToken: closePlatformTokenSource.Token); - }); - - using var timeoutTokenSource = new CancellationTokenSource(60_000); - - while (TestPortsInternal.ServicePulse == 0) - { - await Task.Delay(1000, closePlatformTokenSource.Token); - } - - await Network.WaitForHttpOk($"http://localhost:{TestPortsInternal.ServicePulse}", cancellationToken: timeoutTokenSource.Token); - - var chromeOpts = new ChromeOptions(); - chromeOpts.AddArgument("--headless=new"); - chromeOpts.AddArgument("--disable-gpu"); - chromeOpts.AddArgument("--ignore-certificate-errors"); - chromeOpts.AddArgument("--disable-extensions"); - chromeOpts.AddArgument("--no-sandbox"); - chromeOpts.AddArgument("--disable-dev-shm-usage"); - chromeOpts.AddArgument("--disk-cache-size=1"); - chromeOpts.AddArgument("--media-cache-size=1"); - chromeOpts.AddArgument("--incognito"); - chromeOpts.AddArgument("--remote-debugging-port=9222"); - chromeOpts.AddArgument("--aggressive-cache-discard"); - - if (Environment.GetEnvironmentVariable("CI") == "true") - { - var runnerTemp = Environment.GetEnvironmentVariable("RUNNER_TEMP"); - var dataDir = Path.Combine(runnerTemp, "browser-testing with spaces"); - Directory.CreateDirectory(dataDir); - chromeOpts.AddArgument($"--user-data-dir={dataDir}"); - } - - var chromeService = ChromeDriverService.CreateDefaultService(); - driver = new ChromeDriver(chromeService, chromeOpts, TimeSpan.FromSeconds(90)); - } - - [OneTimeTearDown] - public async Task TearDown() - { - await closePlatformTokenSource.CancelAsync(); - await launcherTask; - closePlatformTokenSource.Dispose(); - driver.Close(); - driver.Dispose(); - } - - [Test(Description = "Checks that ServicePulse is connected to ServiceControl and the endpoints are being monitored when there is a space in the path to the assemblies")] - public async Task ShouldBeConnected() - { - await Task.Delay(2000); - driver.Navigate().GoToUrl($"http://localhost:{TestPortsInternal.ServicePulse}/#/dashboard"); - await Task.Delay(10_000); - - var connectionFailedSpans = driver.FindElements(By.CssSelector(".connection-failed")); - Assert.That(connectionFailedSpans.Count, Is.EqualTo(0)); - - var connectionOkSpans = driver.FindElements(By.CssSelector(".pa-connection-success")); - Assert.That(connectionOkSpans.Count, Is.EqualTo(2)); - } - - [Test(Description = "Checks the monitoring page functionality when there is a space in the path to the assemblies")] - public async Task CheckMonitoringPage() - { - await Task.Delay(2000); - driver.Navigate().GoToUrl($"http://localhost:{TestPortsInternal.ServicePulse}/#/monitoring"); - await Task.Delay(10_000); - - var primaryButtons = driver.FindElements(By.CssSelector(".btn.btn-primary")); - var noEndpointsButton = primaryButtons.Where(b => b.Text.Contains("how to enable endpoint monitoring")).FirstOrDefault(); - - Assert.That(noEndpointsButton, Is.Not.Null); - Assert.That(noEndpointsButton.GetAttribute("href"), Is.EqualTo("https://docs.particular.net/monitoring/metrics/")); - } -}