Skip to content
Open
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
6 changes: 4 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,11 @@ jobs:
azure-credentials: ${{ secrets.AZURE_ACI_CREDENTIALS }}
tag: ServiceControl
- name: Run tests
run: ./tools/run-tests.ps1 -Projects $Env:TEST_PROJECTS -MaxParallel ${{ matrix.max-parallel || 1 }}
uses: Particular/run-tests-action@e49b48c5d8f05ce781825e9a50bcdf8c7dd56ba4

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will change to a tag once Particular/run-tests-action#16 merges.

with:
projects: ${{ steps.select.outputs.test-projects }}
max-parallel: ${{ matrix.max-parallel || 1 }}
env:
TEST_PROJECTS: ${{ steps.select.outputs.test-projects }}
ServiceControl_TESTS_FILTER: ${{ matrix.test-category }}
PARTICULARSOFTWARE_LICENSE: ${{ secrets.LICENSETEXT }}
AZURE_ACI_CREDENTIALS: ${{ secrets.AZURE_ACI_CREDENTIALS }}
Expand Down
43 changes: 30 additions & 13 deletions src/TestHelper/PortUtility.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TestHelper
namespace TestHelper
{
using System;
using System.Globalization;
Expand All @@ -8,25 +8,42 @@
public static class PortUtility
{
/// <summary>
/// The port an embedded server should bind, when the test runner has assigned one.
/// The 0-based index that <c>Particular/run-tests-action</c> assigns to each spawned
/// <c>dotnet test</c> process immediately before spawning it, so concurrent runs can derive
/// distinct per-run resources from it. The value is unique across all runs in the invocation;
/// in sequential mode (<c>max-parallel == 1</c>) it is always <c>0</c>. Defaults to <c>0</c>
/// when unset (e.g. local development outside the action).
/// </summary>
public const string AssignedPortVariableName = "ServiceControl_TESTS_RAVENDB_PORT";
public const string ParallelIndexVariableName = "PARTICULAR_RUN_TESTS_ACTION_PARALLEL_INDEX";

/// <summary>
/// Returns the port assigned by the test runner, or probes for a free one when running alone.
/// Spacing between per-run ports. Wide enough that a run's embedded server has room for any
/// additional listeners it opens alongside its main port.
/// </summary>
public const int ParallelPortSpacing = 10;

/// <summary>
/// Returns the port derived from the run-tests-action per-run parallel index.
/// </summary>
/// <remarks>
/// Concurrent test processes cannot each probe: <see cref="FindAvailablePort"/> only inspects
/// the listeners active at that instant, so processes starting together all see the same port
/// free and all but one then fail to bind.
/// <para>
/// The action sets <see cref="ParallelIndexVariableName"/> on every spawned <c>dotnet test</c>
/// process. Each run's port is computed as <c>startPort + (index * <see cref="ParallelPortSpacing"/>)</c>,
/// so concurrent runs bind distinct ports (the historic spacing of 10 is preserved). A sequential
/// run (index <c>0</c>) lands on <paramref name="startPort"/> -- the same base the historic probe
/// started from, so non-parallel behavior is unchanged.
/// </para>
/// <para>
/// When the index is unset (local development outside the action) it defaults to <c>0</c> and the
/// base <paramref name="startPort"/> is used directly. <see cref="FindAvailablePort"/> remains
/// available for callers that want to probe for a free port rather than derive a fixed one.
/// </para>
/// </remarks>
public static int GetAssignedOrAvailablePort(int startPort)
{
var assignedPort = Environment.GetEnvironmentVariable(AssignedPortVariableName);

return string.IsNullOrWhiteSpace(assignedPort)
? FindAvailablePort(startPort)
: int.Parse(assignedPort, CultureInfo.InvariantCulture);
var indexText = Environment.GetEnvironmentVariable(ParallelIndexVariableName);
var index = int.TryParse(indexText?.Trim(), NumberStyles.None, CultureInfo.InvariantCulture, out var i) ? i : 0;
return startPort + (Math.Max(0, index) * ParallelPortSpacing);
}

public static int FindAvailablePort(int startPort)
Expand All @@ -47,4 +64,4 @@ public static int FindAvailablePort(int startPort)
return startPort;
}
}
}
}
147 changes: 0 additions & 147 deletions tools/run-tests.ps1

This file was deleted.

2 changes: 1 addition & 1 deletion tools/select-test-projects.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#
# A category can span several test projects that share infrastructure, so that CI provisions its
# container once and compiles the union of their closures once. Their assemblies then run concurrently,
# via the -MaxParallel switch on run-tests.ps1.
# via the 'max-parallel' input on Particular/run-tests-action.
#
# Use -List to print every category and its projects without writing any files.

Expand Down