Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Embedded Web Host and add Nuget package tests #27

Merged
merged 3 commits into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,26 +52,26 @@ You can checkout this Github repository or you can use the NuGet package:

**Install using the command line from the Package Manager:**
```bash
Install-Package SoloX.CodeQuality.Prod -version 2.2.0
Install-Package SoloX.CodeQuality.Prod -version 2.2.1
or
Install-Package SoloX.CodeQuality.Test -version 2.2.0
Install-Package SoloX.CodeQuality.Test -version 2.2.1
```

**Install using the .Net CLI:**
```bash
dotnet add package SoloX.CodeQuality.Prod --version 2.2.0
dotnet add package SoloX.CodeQuality.Prod --version 2.2.1
or
dotnet add package SoloX.CodeQuality.Test --version 2.2.0
dotnet add package SoloX.CodeQuality.Test --version 2.2.1
```

**Install editing your project file (csproj):**
```xml
<PackageReference Include="SoloX.CodeQuality.Prod" Version="2.2.0">
<PackageReference Include="SoloX.CodeQuality.Prod" Version="2.2.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
or
<PackageReference Include="SoloX.CodeQuality.Test" Version="2.2.0">
<PackageReference Include="SoloX.CodeQuality.Test" Version="2.2.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
Expand Down Expand Up @@ -218,17 +218,17 @@ You can checkout this Github repository or use the NuGet package:

**Install using the command line from the Package Manager:**
```bash
Install-Package SoloX.CodeQuality.Playwright -version 2.2.0
Install-Package SoloX.CodeQuality.Playwright -version 2.2.1
```

**Install using the .Net CLI:**
```bash
dotnet add package SoloX.CodeQuality.Playwright --version 2.2.0
dotnet add package SoloX.CodeQuality.Playwright --version 2.2.1
```

**Install editing your project file (csproj):**
```xml
<PackageReference Include="SoloX.CodeQuality.Playwright" Version="2.2.0" />
<PackageReference Include="SoloX.CodeQuality.Playwright" Version="2.2.1" />
```

* * *
Expand Down Expand Up @@ -416,29 +416,29 @@ You can checkout this Github repository or you can use the NuGet package:

**Install using the command line from the Package Manager:**
```bash
Install-Package SoloX.CodeQuality.Test.Helpers -version 2.2.0
Install-Package SoloX.CodeQuality.Test.Helpers -version 2.2.1

Install-Package SoloX.CodeQuality.Test.Helpers.XUnit -version 2.2.0
Install-Package SoloX.CodeQuality.Test.Helpers.XUnit -version 2.2.1

Install-Package SoloX.CodeQuality.Test.Helpers.NUnit -version 2.2.0
Install-Package SoloX.CodeQuality.Test.Helpers.NUnit -version 2.2.1
```

**Install using the .Net CLI:**
```bash
dotnet add package SoloX.CodeQuality.Test.Helpers --version 2.2.0
dotnet add package SoloX.CodeQuality.Test.Helpers --version 2.2.1

dotnet add package SoloX.CodeQuality.Test.Helpers.XUnit --version 2.2.0
dotnet add package SoloX.CodeQuality.Test.Helpers.XUnit --version 2.2.1

dotnet add package SoloX.CodeQuality.Test.Helpers.NUnit --version 2.2.0
dotnet add package SoloX.CodeQuality.Test.Helpers.NUnit --version 2.2.1
```

**Install editing your project file (csproj):**
```xml
<PackageReference Include="SoloX.CodeQuality.Test.Helpers" Version="2.2.0" />
<PackageReference Include="SoloX.CodeQuality.Test.Helpers" Version="2.2.1" />

<PackageReference Include="SoloX.CodeQuality.Test.Helpers.XUnit" Version="2.2.0" />
<PackageReference Include="SoloX.CodeQuality.Test.Helpers.XUnit" Version="2.2.1" />

<PackageReference Include="SoloX.CodeQuality.Test.Helpers.NUnit" Version="2.2.0" />
<PackageReference Include="SoloX.CodeQuality.Test.Helpers.NUnit" Version="2.2.1" />
```

* * *
Expand Down
2 changes: 1 addition & 1 deletion src/SharedProperties.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>

<PropertyGroup>
<Version>2.2.0</Version>
<Version>2.2.1</Version>
<Authors>Xavier Solau</Authors>
<Copyright>Copyright © 2021 Xavier Solau</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
Expand Down
7 changes: 7 additions & 0 deletions src/libs/SoloX.CodeQuality.Playwright/IPlaywrightTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,12 @@ public interface IPlaywrightTest : IAsyncDisposable
/// <param name="pageSetupHandler">Page setup handler to initialize page environment before it is display (or null).</param>
/// <returns>async task.</returns>
Task GotoPageAsync(string relativePath, Func<IPage, Task> testHandler, string? traceName = null, Func<IPage, Task>? pageSetupHandler = null);

/// <summary>
/// Get Url used to bind Playwright and host to test.
/// </summary>
#pragma warning disable CA1056 // URI-like properties should not be strings
string Url { get; }
#pragma warning restore CA1056 // URI-like properties should not be strings
}
}
81 changes: 66 additions & 15 deletions src/libs/SoloX.CodeQuality.Playwright/PlaywrightDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public class PlaywrightDriver : IAsyncDisposable

private static readonly string[] INSTALL_ARGUMENTS = new[] { "install" };

private static readonly object InstallLock = new object();
private static readonly object LockSync = new object();
private static bool playwrightInstalled;

private readonly BrowserNewContextOptions? browserNewContextOptions;
private readonly TracingStartOptions? tracingStartOptions;
Expand Down Expand Up @@ -86,31 +87,78 @@ public async Task InitializeAsync(BrowserTypeLaunchOptions? browserTypeLaunchOpt
/// </summary>
private static void InstallPlaywright()
{
InstallPlaywrightDeps();
InstallPlaywrightBin();
lock (LockSync)
{
if (playwrightInstalled)
{
return;
}

var localApplicationData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "PlaywrightDriver");

if (!Directory.Exists(localApplicationData))
{
Directory.CreateDirectory(localApplicationData);
}

var lockFile = Path.Combine(localApplicationData, "PlaywrightInstallLock");

var timeout = 60;

while (!TryWriteLockFile(lockFile))
{
Thread.Sleep(1000);
timeout--;
if (timeout < 0)
{
throw new PlaywrightException($"Unable to lock for Playwright install (Timeout)");
}
}

try
{
InstallPlaywrightDeps();
InstallPlaywrightBin();
}
finally
{
playwrightInstalled = true;
File.Delete(lockFile);
}
}
}

private static bool TryWriteLockFile(string lockFile)
{
try
{
using var file = new FileStream(lockFile, FileMode.CreateNew, FileAccess.Write);
file.WriteByte(0);
file.Flush();
file.Close();
}
catch (IOException)
{
return false;
}
return true;
}

private static void InstallPlaywrightDeps()
{
lock (InstallLock)
var exitCode = Microsoft.Playwright.Program.Main(INSTALL_DEPS_ARGUMENTS);
if (exitCode != 0)
{
var exitCode = Microsoft.Playwright.Program.Main(INSTALL_DEPS_ARGUMENTS);
if (exitCode != 0)
{
throw new PlaywrightException($"Playwright exited with code {exitCode} on install-deps");
}
throw new PlaywrightException($"Playwright exited with code {exitCode} on install-deps");
}
}

private static void InstallPlaywrightBin()
{
lock (InstallLock)
var exitCode = Microsoft.Playwright.Program.Main(INSTALL_ARGUMENTS);
if (exitCode != 0)
{
var exitCode2 = Microsoft.Playwright.Program.Main(INSTALL_ARGUMENTS);
if (exitCode2 != 0)
{
throw new PlaywrightException($"Playwright exited with code {exitCode2} on install");
}
throw new PlaywrightException($"Playwright exited with code {exitCode} on install");
}
}

Expand Down Expand Up @@ -140,10 +188,13 @@ public async Task GotoPageAsync(string url, Func<IPage, Task> testHandler, Brows
catch (PlaywrightException)
{
retry--;

if (retry == 0)
{
throw;
}

await Task.Delay(1000).ConfigureAwait(false);
}
}
}
Expand Down
55 changes: 32 additions & 23 deletions src/libs/SoloX.CodeQuality.Playwright/PlaywrightTestBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ private sealed class PlaywrightTest : IPlaywrightTest

private bool isDisposed;

public string Url => this.url;

internal PlaywrightTest(
Browser browser,
string url,
Expand Down Expand Up @@ -358,28 +360,6 @@ private sealed class PortStore
{
private readonly HashSet<int> usedPorts = [];

/// <summary>
/// Setup port store and prob all TCP port already in use.
/// </summary>
public PortStore()
{
// Get used port with Netstat like command.
var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
var tcpListeners = ipGlobalProperties.GetActiveTcpListeners();

foreach (var tcpEndPoint in tcpListeners)
{
this.usedPorts.Add(tcpEndPoint.Port);
}

var tcpConnections = ipGlobalProperties.GetActiveTcpConnections();

foreach (var tcpConnection in tcpConnections)
{
this.usedPorts.Add(tcpConnection.LocalEndPoint.Port);
}
}

public int GetPort(PortRange portRange)
{
#pragma warning disable CA5394 // Do not use insecure randomness
Expand All @@ -388,14 +368,20 @@ public int GetPort(PortRange portRange)

lock (this.usedPorts)
{
while (!this.usedPorts.Add(port))
var systemPort = ProbUsedPorts();

var allUsedPorts = new HashSet<int>(systemPort.Union(this.usedPorts));

while (allUsedPorts.Contains(port))
{
port++;
if (port >= portRange.EndPort)
{
port = portRange.StartPort;
}
}

this.usedPorts.Add(port);
}
return port;
}
Expand All @@ -407,6 +393,29 @@ public void Release(int port)
this.usedPorts.Remove(port);
}
}

public static HashSet<int> ProbUsedPorts()
{
HashSet<int> usedSystemPorts = [];

// Get used port with Netstat like command.
var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
var tcpListeners = ipGlobalProperties.GetActiveTcpListeners();

foreach (var tcpEndPoint in tcpListeners)
{
usedSystemPorts.Add(tcpEndPoint.Port);
}

var tcpConnections = ipGlobalProperties.GetActiveTcpConnections();

foreach (var tcpConnection in tcpConnections)
{
usedSystemPorts.Add(tcpConnection.LocalEndPoint.Port);
}

return usedSystemPorts;
}
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/libs/SoloX.CodeQuality.Test.Helpers/DotnetHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public static class DotnetHelper
private const string BUILD = "build";
private const string PUBLISH = "publish";
private const string RUN = "run";
private const string TEST = "test";

public static bool Restore(string projectPath, out string stdout, out string stderr)
{
Expand All @@ -30,6 +31,11 @@ public static bool Build(string projectPath, out string stdout, out string stder
return ProcessHelper.Run(projectPath, DOTNET, BUILD, out stdout, out stderr) == 0;
}

public static bool Test(string projectPath, out string stdout, out string stderr)
{
return ProcessHelper.Run(projectPath, DOTNET, TEST, out stdout, out stderr) == 0;
}

public static bool Publish(string projectPath, out string stdout, out string stderr)
{
return ProcessHelper.Run(projectPath, DOTNET, PUBLISH, out stdout, out stderr) == 0;
Expand Down
Loading
Loading