103 lines
3.3 KiB
C#
103 lines
3.3 KiB
C#
using System.Diagnostics;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace Tests.Helpers;
|
|
|
|
public static class LocalServer
|
|
{
|
|
private static Process? _process;
|
|
public static string? BaseUrl { get; private set; }
|
|
|
|
public static async Task StartAsync()
|
|
{
|
|
if (_process != null) return;
|
|
|
|
var root = FindProjectRoot();
|
|
var webProject = Path.Combine(root, "Web");
|
|
|
|
Console.WriteLine($"[DEBUG_LOG] Starting local server for project: {webProject}");
|
|
|
|
_process = new Process
|
|
{
|
|
StartInfo = new ProcessStartInfo
|
|
{
|
|
FileName = "dotnet",
|
|
Arguments = $"run --project \"{webProject}\" --urls http://127.0.0.1:0",
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
UseShellExecute = false,
|
|
CreateNoWindow = true,
|
|
WorkingDirectory = root
|
|
}
|
|
};
|
|
|
|
var tcs = new TaskCompletionSource<string>();
|
|
|
|
_process.OutputDataReceived += (s, e) =>
|
|
{
|
|
if (string.IsNullOrEmpty(e.Data)) return;
|
|
Console.WriteLine($"[SERVER] {e.Data}");
|
|
var match = Regex.Match(e.Data, @"Now listening on:\s+(http://127.0.0.1:\d+)");
|
|
if (match.Success) tcs.TrySetResult(match.Groups[1].Value);
|
|
};
|
|
|
|
_process.ErrorDataReceived += (s, e) =>
|
|
{
|
|
if (!string.IsNullOrEmpty(e.Data))
|
|
Console.Error.WriteLine($"[SERVER ERROR] {e.Data}");
|
|
};
|
|
|
|
_process.Start();
|
|
_process.BeginOutputReadLine();
|
|
_process.BeginErrorReadLine();
|
|
|
|
// Wait for the URL to be parsed from output
|
|
BaseUrl = await Task.WhenAny(tcs.Task, Task.Delay(30000)) == tcs.Task
|
|
? tcs.Task.Result
|
|
: null;
|
|
|
|
if (BaseUrl == null)
|
|
{
|
|
Stop();
|
|
throw new Exception("Timeout waiting for local server to start and provide a URL.");
|
|
}
|
|
|
|
Console.WriteLine($"[DEBUG_LOG] Local server started at: {BaseUrl}");
|
|
}
|
|
|
|
public static void Stop()
|
|
{
|
|
if (_process != null && !_process.HasExited)
|
|
{
|
|
Console.WriteLine("[DEBUG_LOG] Stopping local server...");
|
|
_process.Kill(true);
|
|
_process.Dispose();
|
|
_process = null;
|
|
}
|
|
}
|
|
|
|
private static string FindProjectRoot()
|
|
{
|
|
var current = AppDomain.CurrentDomain.BaseDirectory;
|
|
while (!string.IsNullOrEmpty(current) && !File.Exists(Path.Combine(current, "IGP.sln")))
|
|
{
|
|
var parent = Path.GetDirectoryName(current);
|
|
if (parent == current) break;
|
|
current = parent;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(current) || !File.Exists(Path.Combine(current, "IGP.sln")))
|
|
{
|
|
// Fallback to searching up from current directory if BaseDirectory fails
|
|
current = Directory.GetCurrentDirectory();
|
|
while (!string.IsNullOrEmpty(current) && !File.Exists(Path.Combine(current, "IGP.sln")))
|
|
{
|
|
var parent = Path.GetDirectoryName(current);
|
|
if (parent == current) break;
|
|
current = parent;
|
|
}
|
|
}
|
|
|
|
return current ?? throw new Exception("Could not find project root containing IGP.sln");
|
|
}
|
|
} |