From b9827a47b58c977980c72b5c4a0d02c989dc6a58 Mon Sep 17 00:00:00 2001 From: Reuben Bond <203839+ReubenBond@users.noreply.github.com> Date: Mon, 10 Feb 2025 11:45:31 -0800 Subject: [PATCH] Enable GitHub Actions test logger (#9331) --- .github/workflows/ci.yml | 184 +++++++-- Directory.Build.props | 4 +- Directory.Packages.props | 1 + .../TestClusterPortAllocator.cs | 386 +++++++++--------- .../StatelessWorkerTests.cs | 62 ++- test/Directory.Build.props | 1 + .../Reminder/ReminderTests_AzureTable.cs | 2 +- .../IPersistenceTestGrains.cs | 2 +- .../IStatelessWorkerWithMayInterleaveGrain.cs | 10 +- .../StatelessWorkerWithMayInterleaveGrain.cs | 15 +- .../PersistenceTestGrains.cs | 113 +++-- .../OrleansTaskSchedulerAdvancedTests_Set2.cs | 2 +- .../EventSourcingTests/ChatGrainTests.cs | 4 +- .../UpgradeTests/UpgradeTestsBase.cs | 3 +- test/Tester/LocalhostSiloTests.cs | 6 + .../StorageTests/PersistenceGrainTests.cs | 4 +- 16 files changed, 504 insertions(+), 295 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7638ff20ec..82d6dba52e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,18 +14,19 @@ jobs: build: name: Build runs-on: ${{ matrix.os }} + continue-on-error: true strategy: matrix: - os: [ubuntu-latest, windows-latest] + os: [ubuntu-latest, windows-latest, macos-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: | 8.0.x - name: Build - run: dotnet build + run: dotnet build -bl - uses: actions/upload-artifact@v4 with: name: build_log_${{ matrix.os }} @@ -35,9 +36,11 @@ jobs: test-redis: name: Redis provider tests runs-on: ubuntu-latest + continue-on-error: true strategy: matrix: provider: ["Redis"] + framework: [net8.0] services: redis: image: redis @@ -49,21 +52,27 @@ jobs: --health-timeout 5s --health-retries 5 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: | 8.0.x - name: Test - run: dotnet test --framework net8.0 --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" --blame-hang-timeout 10m --logger "trx" -- -parallel none -noshadow + run: dotnet test + --framework ${{ matrix.framework }} + --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" + --blame-hang-timeout 10m + --logger "trx;LogFileName=test_results_${{ matrix.provider }}_${{ matrix.framework }}.trx" + --logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true;summary.includeNotFoundTests=false" + -- -parallel none -noshadow env: ORLEANSREDISCONNECTIONSTRING: "localhost:6379,ssl=False,abortConnect=False" - name: Archive Test Results if: always() uses: actions/upload-artifact@v4 with: - name: test_output_${{ github.job }} + name: test_output_${{ github.job }}_${{ matrix.framework }} retention-days: 1 path: | **/TestResults/* @@ -71,26 +80,34 @@ jobs: test-cassandra: name: Cassandra provider tests runs-on: ubuntu-latest + continue-on-error: true strategy: matrix: provider: ["Cassandra"] dbversion: ["3.11", "4.0", "4.1", "5.0"] + framework: [net8.0] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: | 8.0.x - name: Test - run: dotnet test --framework net8.0 --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Clustering)" --blame-hang-timeout 10m --logger "trx" -- -parallel none -noshadow + run: dotnet test + --framework ${{ matrix.framework }} + --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Clustering)" + --blame-hang-timeout 10m + --logger "trx;LogFileName=test_results_${{ matrix.provider }}_${{ matrix.dbversion }}_${{ matrix.framework }}.trx" + --logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true;summary.includeNotFoundTests=false" + -- -parallel none -noshadow env: CASSANDRAVERSION: ${{ matrix.dbversion }} - name: Archive Test Results if: always() uses: actions/upload-artifact@v4 with: - name: test_output_${{ github.job }}_${{ matrix.dbversion }} + name: test_output_${{ github.job }}_${{ matrix.dbversion }}_${{ matrix.framework }} retention-days: 1 path: | **/TestResults/* @@ -98,9 +115,11 @@ jobs: test-postgres: name: PostgreSQL provider tests runs-on: ubuntu-latest + continue-on-error: true strategy: matrix: provider: ["PostgreSql"] + framework: [net8.0] services: postgres: image: postgres @@ -115,14 +134,20 @@ jobs: --health-timeout 5s --health-retries 5 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: | 8.0.x - name: Test - run: dotnet test --framework net8.0 --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" --blame-hang-timeout 10m --logger "trx" -- -parallel none -noshadow + run: dotnet test + --framework ${{ matrix.framework }} + --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" + --blame-hang-timeout 10m + --logger "trx;LogFileName=test_results_${{ matrix.provider }}_${{ matrix.framework }}.trx" + --logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true;summary.includeNotFoundTests=false" + -- -parallel none -noshadow env: # [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="False positive")] ORLEANSPOSTGRESCONNECTIONSTRING: "Server=127.0.0.1;Port=5432;Pooling=false;User Id=postgres;Password=postgres;SSL Mode=Disable" @@ -130,7 +155,7 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: test_output_${{ github.job }} + name: test_output_${{ github.job }}_${{ matrix.framework }} retention-days: 1 path: | **/TestResults/* @@ -138,9 +163,11 @@ jobs: test-mariadb: name: MariaDB/MySQL provider tests runs-on: ubuntu-latest + continue-on-error: true strategy: matrix: provider: ["MySql"] + framework: [net8.0] services: mariadb: image: mariadb:10.6 @@ -150,14 +177,20 @@ jobs: # [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="False positive")] MARIADB_ROOT_PASSWORD: "mariadb" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: | 8.0.x - name: Test - run: dotnet test --framework net8.0 --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" --blame-hang-timeout 10m --logger "trx" -- -parallel none -noshadow + run: dotnet test + --framework ${{ matrix.framework }} + --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" + --blame-hang-timeout 10m + --logger "trx;LogFileName=test_results_${{ matrix.provider }}_${{ matrix.framework }}.trx" + --logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true;summary.includeNotFoundTests=false" + -- -parallel none -noshadow env: # [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Not a secret")] ORLEANSMYSQLCONNECTIONSTRING: "Server=127.0.0.1;Port=3306;UId=root;Pwd=mariadb;" @@ -165,7 +198,7 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: test_output_${{ github.job }} + name: test_output_${{ github.job }}_${{ matrix.framework }} retention-days: 1 path: | **/TestResults/* @@ -173,9 +206,11 @@ jobs: test-sqlserver: name: Microsoft SQL Server provider tests runs-on: ubuntu-latest + continue-on-error: true strategy: matrix: provider: ["SqlServer"] + framework: [net8.0] services: mssql: image: mcr.microsoft.com/mssql/server:latest @@ -187,14 +222,20 @@ jobs: # [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="False positive")] SA_PASSWORD: "yourWeak(!)Password" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: | 8.0.x - name: Test - run: dotnet test --framework net8.0 --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" --blame-hang-timeout 10m --logger "trx" -- -parallel none -noshadow + run: dotnet test + --framework ${{ matrix.framework }} + --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" + --blame-hang-timeout 10m + --logger "trx;LogFileName=test_results_${{ matrix.provider }}_${{ matrix.framework }}.trx" + --logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true;summary.includeNotFoundTests=false" + -- -parallel none -noshadow env: # [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Not a secret")] ORLEANSMSSQLCONNECTIONSTRING: "Server=127.0.0.1,1433;User Id=SA;Password=yourWeak(!)Password;" @@ -202,7 +243,7 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: test_output_${{ github.job }} + name: test_output_${{ github.job }}_${{ matrix.framework }} retention-days: 1 path: | **/TestResults/* @@ -210,9 +251,9 @@ jobs: test-azure-storage: name: Azure Storage provider tests runs-on: ubuntu-latest + continue-on-error: true strategy: matrix: - suite: ["BVT", "SlowBVT", "Functional"] framework: ["net8.0"] provider: ["AzureStorage"] services: @@ -223,14 +264,20 @@ jobs: - 10001:10001 - 10002:10002 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: | 8.0.x - name: Test - run: dotnet test --filter "Category=${{ matrix.provider }}&Category=${{ matrix.suite }}" --framework ${{ matrix.framework }} --blame-hang-timeout 10m --logger "trx" -- -parallel none -noshadow + run: dotnet test + --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" + --framework ${{ matrix.framework }} + --blame-hang-timeout 10m + --logger "trx;LogFileName=test_results_${{ matrix.provider }}_${{ matrix.framework }}.trx" + --logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true;summary.includeNotFoundTests=false" + -- -parallel none -noshadow env: # [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Not a secret")] # [SuppressMessage("Microsoft.Security", "CSCAN0090:ConfigFile", Justification="Not a secret")] @@ -240,7 +287,7 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: test_output_${{ github.job }}_${{ matrix.suite }} + name: test_output_${{ github.job }}_${{ matrix.framework }} retention-days: 1 path: | **/TestResults/* @@ -249,16 +296,18 @@ jobs: if: ${{ false }} name: Azure Cosmos DB provider tests runs-on: windows-latest + continue-on-error: true strategy: matrix: framework: ["net8.0"] provider: ["Cosmos"] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v3 with: - include-prerelease: true + dotnet-version: | + 8.0.x # - name: Install emulator certificate # run: | # sleep 90s @@ -276,7 +325,13 @@ jobs: $IPAddress = "127.0.0.1" #(Get-NetIPAddress -AddressFamily IPV4 -AddressState Preferred -PrefixOrigin Manual | Select-Object IPAddress -First 1).IPAddress ?? "127.0.0.1" Add-Content -Path $env:GITHUB_ENV -Value "ORLEANSCOSMOSDBACCOUNTENDPOINT=https://$($IPAddress):8081/" - name: Test - run: dotnet test --framework net8.0 --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" --framework ${{ matrix.framework }} --blame-hang-timeout 10m --logger "trx" -- -parallel none -noshadow + run: dotnet test + --framework ${{ matrix.framework }} + --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" + --blame-hang-timeout 10m + --logger "trx;LogFileName=test_results_${{ matrix.provider }}_${{ matrix.framework }}.trx" + --logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true;summary.includeNotFoundTests=false" + -- -parallel none -noshadow env: # [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Not a secret")] #ORLEANSCOSMOSDBACCOUNTENDPOINT: "https://127.0.0.1:8081/" @@ -286,7 +341,7 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: test_output_${{ github.job }} + name: test_output_${{ github.job }}_${{ matrix.framework }} retention-days: 1 path: | **/TestResults/* @@ -294,9 +349,11 @@ jobs: test-consul: name: Consul provider tests runs-on: ubuntu-latest + continue-on-error: true strategy: matrix: provider: ["Consul"] + framework: [net8.0] services: consul: image: hashicorp/consul @@ -305,14 +362,20 @@ jobs: - 8600:8600/tcp - 8600:8600/udp steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: | 8.0.x - name: Test - run: dotnet test --framework net8.0 --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" --blame-hang-timeout 10m --logger "trx" -- -parallel none -noshadow + run: dotnet test + --framework ${{ matrix.framework }} + --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" + --blame-hang-timeout 10m + --logger "trx;LogFileName=test_results_${{ matrix.provider }}_${{ matrix.framework }}.trx" + --logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true;summary.includeNotFoundTests=false" + -- -parallel none -noshadow env: # [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Not a secret")] # [SuppressMessage("Microsoft.Security", "CSCAN0090:ConfigFile", Justification="Not a secret")] @@ -322,7 +385,7 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: test_output_${{ github.job }} + name: test_output_${{ github.job }}_${{ matrix.framework }} retention-days: 1 path: | **/TestResults/* @@ -330,9 +393,11 @@ jobs: test-zookeeper: name: ZooKeeper provider tests runs-on: ubuntu-latest + continue-on-error: true strategy: matrix: provider: ["ZooKeeper"] + framework: [net8.0] services: consul: image: bitnami/zookeeper @@ -341,21 +406,27 @@ jobs: env: ALLOW_ANONYMOUS_LOGIN: "yes" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: | 8.0.x - name: Test - run: dotnet test --framework net8.0 --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" --blame-hang-timeout 10m --logger "trx" -- -parallel none -noshadow + run: dotnet test + --framework ${{ matrix.framework }} + --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" + --blame-hang-timeout 10m + --logger "trx;LogFileName=test_results_${{ matrix.provider }}_${{ matrix.framework }}.trx" + --logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true;summary.includeNotFoundTests=false" + -- -parallel none -noshadow env: ORLEANSZOOKEEPERCONNECTIONSTRING: "localhost:2181" - name: Archive Test Results if: always() uses: actions/upload-artifact@v4 with: - name: test_output_${{ github.job }} + name: test_output_${{ github.job }}_${{ matrix.framework }} retention-days: 1 path: | **/TestResults/* @@ -363,9 +434,11 @@ jobs: test-dynamodb: name: AWS DynamoDB provider tests runs-on: ubuntu-latest + continue-on-error: true strategy: matrix: provider: ["DynamoDB"] + framework: [net8.0] services: dynamodb: image: amazon/dynamodb-local:latest @@ -378,14 +451,20 @@ jobs: AWS_SECRET_ACCESS_KEY: pass AWS_REGION: us-east-1 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: | 8.0.x - name: Test - run: dotnet test --framework net8.0 --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" --blame-hang-timeout 10m --logger "trx" -- -parallel none -noshadow + run: dotnet test + --framework ${{ matrix.framework }} + --filter "Category=${{ matrix.provider }}&(Category=BVT|Category=SlowBVT|Category=Functional)" + --blame-hang-timeout 10m + --logger "trx;LogFileName=test_results_${{ matrix.provider }}_${{ matrix.framework }}.trx" + --logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true;summary.includeNotFoundTests=false" + -- -parallel none -noshadow env: ORLEANSDYNAMODBSERVICE: "http://127.0.0.1:8000" # [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Not a secret")] @@ -396,7 +475,42 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: test_output_${{ github.job }} + name: test_output_${{ github.job }}_${{ matrix.framework }} + retention-days: 1 + path: | + **/TestResults/* + **/logs/* + test: + name: Test + runs-on: ${{ matrix.os }} + continue-on-error: true + strategy: + matrix: + suite: [BVT, SlowBVT, Functional] + os: [ubuntu-latest, windows-latest, macos-latest] + framework: [net8.0] + steps: + - uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: | + 8.0.x + - name: Build + run: dotnet build + - name: Test + run: dotnet test + --framework ${{ matrix.framework }} + --filter "Category=${{ matrix.suite }}" + --blame-hang-timeout 10m + --logger "trx;LogFileName=test_results_${{ matrix.suite }}_${{ matrix.framework }}.trx" + --logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true;summary.includeNotFoundTests=false" + -- -parallel none -noshadow + - name: Archive Test Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: test_output_${{ github.job }}_${{ matrix.suite }}_${{ matrix.os }}_${{ matrix.framework }} retention-days: 1 path: | **/TestResults/* diff --git a/Directory.Build.props b/Directory.Build.props index 2ccdfed7fe..1160f6d671 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -51,7 +51,7 @@ 9.0.0.0 - 9.0.0 + 9.1.0 @@ -103,4 +103,4 @@ - + \ No newline at end of file diff --git a/Directory.Packages.props b/Directory.Packages.props index 450486392d..a3879d31ae 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -114,6 +114,7 @@ + diff --git a/src/Orleans.TestingHost/TestClusterPortAllocator.cs b/src/Orleans.TestingHost/TestClusterPortAllocator.cs index a54e2c035c..153f3d24c1 100644 --- a/src/Orleans.TestingHost/TestClusterPortAllocator.cs +++ b/src/Orleans.TestingHost/TestClusterPortAllocator.cs @@ -5,264 +5,282 @@ using System.Linq; using System.Net; using System.Net.NetworkInformation; +using System.Net.Sockets; using System.Threading; -namespace Orleans.TestingHost +namespace Orleans.TestingHost; + +/// +/// Default implementation, which tries to allocate unused ports. +/// +public class TestClusterPortAllocator : ITestClusterPortAllocator { - /// - /// Default implementation, which tries to allocate unused ports. - /// - public class TestClusterPortAllocator : ITestClusterPortAllocator + private bool _disposed; + private readonly object _lockObj = new(); + private readonly Dictionary _allocatedPorts = []; + + /// + public (int, int) AllocateConsecutivePortPairs(int numPorts = 5) { - private bool disposed; - private readonly object lockObj = new object(); - private readonly Dictionary allocatedPorts = new Dictionary(); + // Evaluate current system tcp connections + var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); + var tcpConnInfoArray = ipGlobalProperties.GetActiveTcpListeners(); - /// - public (int, int) AllocateConsecutivePortPairs(int numPorts = 5) - { - // Evaluate current system tcp connections - IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); - IPEndPoint[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpListeners(); + // each returned port in the pair will have to have at least this amount of available ports following it - // each returned port in the pair will have to have at least this amount of available ports following it + return (GetAvailableConsecutiveServerPorts(tcpConnInfoArray, 22300, 30000, numPorts), + GetAvailableConsecutiveServerPorts(tcpConnInfoArray, 40000, 50000, numPorts)); + } - return (GetAvailableConsecutiveServerPorts(tcpConnInfoArray, 22300, 30000, numPorts), - GetAvailableConsecutiveServerPorts(tcpConnInfoArray, 40000, 50000, numPorts)); - } + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } - /// - public void Dispose() + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// to release both managed and unmanaged resources; to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + if (_disposed) { - Dispose(true); - GC.SuppressFinalize(this); + return; } - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// to release both managed and unmanaged resources; to release only unmanaged resources. - protected virtual void Dispose(bool disposing) + lock (_lockObj) { - if (disposed) + if (_disposed) { return; } - lock (lockObj) + foreach (var pair in _allocatedPorts) { - if (disposed) - { - return; - } - - foreach (var pair in allocatedPorts) - { - MutexManager.Instance.SignalRelease(pair.Value); - } - - allocatedPorts.Clear(); - disposed = true; + MutexManager.Instance.SignalRelease(pair.Value); } - } - /// - /// Finalizes an instance of the class. - /// - ~TestClusterPortAllocator() - { - Dispose(false); + _allocatedPorts.Clear(); + _disposed = true; } + } - private int GetAvailableConsecutiveServerPorts(IPEndPoint[] tcpConnInfoArray, int portStartRange, int portEndRange, int consecutivePortsToCheck) - { - const int MaxAttempts = 100; + /// + /// Finalizes an instance of the class. + /// + ~TestClusterPortAllocator() + { + Dispose(false); + } - var allocations = new List<(int Port, string Mutex)>(); + private int GetAvailableConsecutiveServerPorts(IPEndPoint[] tcpConnInfoArray, int portStartRange, int portEndRange, int consecutivePortsToCheck) + { + const int MaxAttempts = 100; - for (int attempts = 0; attempts < MaxAttempts; attempts++) - { - int basePort = Random.Shared.Next(portStartRange, portEndRange); + var allocations = new List<(int Port, string Mutex)>(); + + for (var attempts = 0; attempts < MaxAttempts; attempts++) + { + var basePort = Random.Shared.Next(portStartRange, portEndRange); - // get ports in buckets, so we don't interfere with parallel runs of this same function - basePort = basePort - (basePort % consecutivePortsToCheck); - int endPort = basePort + consecutivePortsToCheck; + // get ports in buckets, so we don't interfere with parallel runs of this same function + basePort = basePort - basePort % consecutivePortsToCheck; + var endPort = basePort + consecutivePortsToCheck; - // make sure none of the ports in the sub range are in use - if (tcpConnInfoArray.All(endpoint => endpoint.Port < basePort || endpoint.Port >= endPort)) + // make sure none of the ports in the sub range are in use + if (tcpConnInfoArray.All(endpoint => endpoint.Port < basePort || endpoint.Port >= endPort)) + { + var portsAvailable = true; + for (var i = 0; i < consecutivePortsToCheck; i++) { - for (var i = 0; i < consecutivePortsToCheck; i++) + var port = basePort + i; + try { - var port = basePort + i; - var name = $"Global.TestCluster.{port.ToString(CultureInfo.InvariantCulture)}"; - if (MutexManager.Instance.Acquire(name)) - { - allocations.Add((port, name)); - } - else - { - foreach (var allocation in allocations) - { - MutexManager.Instance.SignalRelease(allocation.Mutex); - } - - allocations.Clear(); - break; - } + using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + socket.Bind(new IPEndPoint(IPAddress.Loopback, port)); } - - if (allocations.Count == 0) + catch (SocketException) { - // Try a different range. - continue; + portsAvailable = false; + break; } + } - lock (lockObj) + if (!portsAvailable) + { + continue; + } + + for (var i = 0; i < consecutivePortsToCheck; i++) + { + var port = basePort + i; + var name = $"Global.TestCluster.{port.ToString(CultureInfo.InvariantCulture)}"; + if (MutexManager.Instance.Acquire(name)) + { + allocations.Add((port, name)); + } + else { foreach (var allocation in allocations) { - allocatedPorts[allocation.Port] = allocation.Mutex; + MutexManager.Instance.SignalRelease(allocation.Mutex); } + + allocations.Clear(); + break; } + } - return basePort; + if (allocations.Count == 0) + { + // Try a different range. + continue; + } + + lock (_lockObj) + { + foreach (var allocation in allocations) + { + _allocatedPorts[allocation.Port] = allocation.Mutex; + } } - } - throw new InvalidOperationException("Cannot find enough free ports to spin up a cluster"); + return basePort; + } } - private class MutexManager - { - private readonly Dictionary _mutexes = new Dictionary(); - private readonly BlockingCollection _workItems = new BlockingCollection(); - private readonly Thread _thread; + throw new InvalidOperationException("Cannot find enough free ports to spin up a cluster"); + } - public static MutexManager Instance { get; } = new MutexManager(); + private class MutexManager + { + private readonly Dictionary _mutexes = []; + private readonly BlockingCollection _workItems = []; + private readonly Thread _thread; - private MutexManager() - { - _thread = new Thread(Run) - { - Name = "MutexManager.Worker", - IsBackground = true, - }; - _thread.Start(); - AppDomain.CurrentDomain.DomainUnload += this.OnAppDomainUnload; - } + public static MutexManager Instance { get; } = new MutexManager(); - private void OnAppDomainUnload(object sender, EventArgs e) + private MutexManager() + { + _thread = new Thread(Run) { - Shutdown(); - } + Name = "MutexManager.Worker", + IsBackground = true, + }; + _thread.Start(); + AppDomain.CurrentDomain.DomainUnload += this.OnAppDomainUnload; + } - private void Shutdown() - { - _workItems.CompleteAdding(); - _thread.Join(); - } + private void OnAppDomainUnload(object sender, EventArgs e) => Shutdown(); + + private void Shutdown() + { + _workItems.CompleteAdding(); + _thread.Join(); + } - public bool Acquire(string name) + public bool Acquire(string name) + { + var result = new [] { 0 }; + var signal = new ManualResetEventSlim(initialState: false); + _workItems.Add(() => { - var result = new [] { 0 }; - var signal = new ManualResetEventSlim(initialState: false); - _workItems.Add(() => + try { - try + if (!_mutexes.TryGetValue(name, out var mutex)) { - if (!_mutexes.TryGetValue(name, out var mutex)) + mutex = new Mutex(false, name); + if (mutex.WaitOne(500)) { - mutex = new Mutex(false, name); - if (mutex.WaitOne(500)) - { - // Acquired - _mutexes[name] = mutex; - Interlocked.Increment(ref result[0]); - return; - } - - // Failed to acquire: the mutex is already held by another process. - try - { - mutex.ReleaseMutex(); - } - finally - { - mutex.Close(); - } + // Acquired + _mutexes[name] = mutex; + Interlocked.Increment(ref result[0]); + return; } - // Failed to acquire: the mutex is already held by this process. - } - finally - { - signal.Set(); + // Failed to acquire: the mutex is already held by another process. + try + { + mutex.ReleaseMutex(); + } + finally + { + mutex.Close(); + } } - }); - if (!signal.Wait(TimeSpan.FromSeconds(10))) + // Failed to acquire: the mutex is already held by this process. + } + finally { - throw new TimeoutException("Timed out while waiting for MutexManager to acquire mutex."); + signal.Set(); } + }); - return result[0] == 1; + if (!signal.Wait(TimeSpan.FromSeconds(10))) + { + throw new TimeoutException("Timed out while waiting for MutexManager to acquire mutex."); } - public void SignalRelease(string name) - { - if (_workItems.IsAddingCompleted) return; + return result[0] == 1; + } - try + public void SignalRelease(string name) + { + if (_workItems.IsAddingCompleted) return; + + try + { + _workItems.Add(() => { - _workItems.Add(() => + if (_mutexes.Remove(name, out var value)) { - if (_mutexes.Remove(name, out var value)) - { - value.ReleaseMutex(); - value.Close(); - } - }); - } - catch - { - } + value.ReleaseMutex(); + value.Close(); + } + }); } + catch + { + } + } - private void Run() + private void Run() + { + try { - try + foreach (var action in _workItems.GetConsumingEnumerable()) { - foreach (var action in _workItems.GetConsumingEnumerable()) + try + { + action(); + } + catch { - try - { - action(); - } - catch - { - } } } - catch - { - } - finally + } + catch + { + } + finally + { + foreach (var mutex in _mutexes.Values) { - foreach (var mutex in _mutexes.Values) + try { - try - { - mutex.ReleaseMutex(); - } - catch { } - finally - { - mutex.Close(); - } + mutex.ReleaseMutex(); + } + catch { } + finally + { + mutex.Close(); } - - _mutexes.Clear(); } + + _mutexes.Clear(); } } } diff --git a/test/DefaultCluster.Tests/StatelessWorkerTests.cs b/test/DefaultCluster.Tests/StatelessWorkerTests.cs index 620434f9b7..651c502a73 100644 --- a/test/DefaultCluster.Tests/StatelessWorkerTests.cs +++ b/test/DefaultCluster.Tests/StatelessWorkerTests.cs @@ -26,7 +26,7 @@ public async Task StatelessWorkerThrowExceptionConstructor() { var grain = this.GrainFactory.GetGrain(0); - for (int i=0; i<100; i++) + for (int i = 0; i < 100; i++) { var ex = await Assert.ThrowsAsync(() => grain.Ping()); Assert.Equal("oops", ex.Message); @@ -39,14 +39,14 @@ public async Task StatelessWorkerActivationsPerSiloDoNotExceedMaxLocalWorkersCou var gatewayOptions = this.Fixture.Client.ServiceProvider.GetRequiredService>(); var gatewaysCount = gatewayOptions.Value.Gateways.Count; // do extra calls to trigger activation of ExpectedMaxLocalActivations local activations - int numberOfCalls = ExpectedMaxLocalActivations * 3 * gatewaysCount; + int numberOfCalls = ExpectedMaxLocalActivations * 3 * gatewaysCount; IStatelessWorkerGrain grain = this.GrainFactory.GetGrain(GetRandomGrainId()); List promises = new List(); // warmup for (int i = 0; i < gatewaysCount; i++) - promises.Add(grain.LongCall()); + promises.Add(grain.LongCall()); await Task.WhenAll(promises); await Task.Delay(2000); @@ -100,7 +100,7 @@ public async Task ManyConcurrentInvocationsOnActivationLimitedStatelessWorkerDoe // message forwards. When the issue occurs, this test will throw an exception. // We are trying to trigger a race condition and need more than 1 attempt to reliably reproduce the issue. - for (var attempt = 0; attempt < 100; attempt ++) + for (var attempt = 0; attempt < 100; attempt++) { var grain = this.GrainFactory.GetGrain(attempt); await Task.WhenAll(Enumerable.Range(0, 10).Select(_ => grain.DummyCall())); @@ -123,7 +123,7 @@ public async Task StatelessWorkerFastActivationsDontFailInMultiSiloDeployment() IStatelessWorkerGrain grain = this.GrainFactory.GetGrain(GetRandomGrainId()); List promises = new List(); - + for (int i = 0; i < numberOfCalls; i++) promises.Add(grain.LongCall()); await Task.WhenAll(promises); @@ -135,9 +135,12 @@ public async Task StatelessWorkerFastActivationsDontFailInMultiSiloDeployment() public async Task StatelessWorker_DoesNotThrow_IfMarkedWithMayInterleave() { var grain = GrainFactory.GetGrain(0); - var exception = await Record.ExceptionAsync(grain.GoFast); - - Assert.Null(exception); + var observer = new CallbackObserver(); + var reference = GrainFactory.CreateObjectReference(observer); + var task = grain.GoFast(reference); + await observer.OnCallback.WaitAsync(TimeSpan.FromSeconds(10)); + observer.Signal(); + await task; } [Fact, TestCategory("SlowBVT"), TestCategory("StatelessWorker")] @@ -145,29 +148,46 @@ public async Task StatelessWorker_ShouldNotInterleaveCalls_IfMayInterleavePredic { var grain = GrainFactory.GetGrain(0); - var delay = TimeSpan.FromSeconds(1); - await grain.SetDelay(delay); - - var stopwatch = Stopwatch.StartNew(); - await Task.WhenAll(grain.GoSlow(), grain.GoSlow(), grain.GoSlow()); - stopwatch.Stop(); + List callbacks = [new(), new(), new()]; + var callbackReferences = callbacks.Select(c => GrainFactory.CreateObjectReference(c)).ToList(); + List completions = [grain.GoSlow(callbackReferences[0]), grain.GoSlow(callbackReferences[1]), grain.GoSlow(callbackReferences[2])]; + var callbackSignals = callbacks.Select(c => c.OnCallback).ToList(); - Assert.InRange(stopwatch.Elapsed.TotalSeconds, 2.85, 3.15); // theoretically it should be 3.0 + var triggered = await Task.WhenAny(callbackSignals).WaitAsync(TimeSpan.FromSeconds(10)); + callbackSignals.Remove(triggered); + await Assert.ThrowsAsync(async () => await Task.WhenAny(callbackSignals).WaitAsync(TimeSpan.FromSeconds(5))); + callbacks.ForEach(c => c.Signal()); + await Task.WhenAll(completions).WaitAsync(TimeSpan.FromSeconds(10)); } [Fact, TestCategory("SlowBVT"), TestCategory("StatelessWorker")] public async Task StatelessWorker_ShouldInterleaveCalls_IfMayInterleavePredicatedMatches() { + using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10)); var grain = GrainFactory.GetGrain(0); - var delay = TimeSpan.FromSeconds(1); - await grain.SetDelay(delay); + List callbacks = [new(), new(), new()]; + var callbackReferences = callbacks.Select(c => GrainFactory.CreateObjectReference(c)).ToList(); + var completion = Task.WhenAll(grain.GoFast(callbackReferences[0]), grain.GoFast(callbackReferences[1]), grain.GoFast(callbackReferences[2])); - var stopwatch = Stopwatch.StartNew(); - await Task.WhenAll(grain.GoFast(), grain.GoFast(), grain.GoFast()); - stopwatch.Stop(); + // Wait for all callbacks to be triggered simultaneously, giving up if they don't signal before the timeout. + await Task.WhenAll(callbacks.Select(c => c.OnCallback)).WaitAsync(cts.Token); + callbacks.ForEach(c => c.Signal()); + + await completion; + } - Assert.InRange(stopwatch.Elapsed.TotalSeconds, 0.85, 1.15); // theoretically it should be 1.0 + private sealed class CallbackObserver : ICallbackGrainObserver + { + private readonly TaskCompletionSource _waitAsyncTcs = new(TaskCreationOptions.RunContinuationsAsynchronously); + private readonly TaskCompletionSource _wasCalledTcs = new(TaskCreationOptions.RunContinuationsAsynchronously); + public void Signal() => _waitAsyncTcs.TrySetResult(); + public Task OnCallback => _wasCalledTcs.Task; + async Task ICallbackGrainObserver.WaitAsync() + { + _wasCalledTcs.TrySetResult(); + await _waitAsyncTcs.Task; + } } } } \ No newline at end of file diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 1c9de31807..51dce53156 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -27,6 +27,7 @@ + diff --git a/test/Extensions/TesterAzureUtils/Reminder/ReminderTests_AzureTable.cs b/test/Extensions/TesterAzureUtils/Reminder/ReminderTests_AzureTable.cs index 26fd8394e3..8556c01197 100644 --- a/test/Extensions/TesterAzureUtils/Reminder/ReminderTests_AzureTable.cs +++ b/test/Extensions/TesterAzureUtils/Reminder/ReminderTests_AzureTable.cs @@ -46,7 +46,7 @@ public async Task Rem_Azure_Basic_StopByRef() await Test_Reminders_Basic_StopByRef(); } - [SkippableFact, TestCategory("Functional")] + [SkippableFact(Skip = "https://github.com/dotnet/orleans/issues/9337"), TestCategory("Functional")] public async Task Rem_Azure_Basic_ListOps() { await Test_Reminders_Basic_ListOps(); diff --git a/test/Grains/TestGrainInterfaces/IPersistenceTestGrains.cs b/test/Grains/TestGrainInterfaces/IPersistenceTestGrains.cs index 41d51fec95..5f51aff733 100644 --- a/test/Grains/TestGrainInterfaces/IPersistenceTestGrains.cs +++ b/test/Grains/TestGrainInterfaces/IPersistenceTestGrains.cs @@ -185,7 +185,7 @@ public interface IReentrentGrainWithState : IGrainWithGuidKey Task Task_Delay(bool doStart); } - public interface INonReentrentStressGrainWithoutState : IGrainWithGuidKey + public interface INonReentrantStressGrainWithoutState : IGrainWithGuidKey { Task Test1(); Task Task_Delay(bool doStart); diff --git a/test/Grains/TestGrainInterfaces/IStatelessWorkerWithMayInterleaveGrain.cs b/test/Grains/TestGrainInterfaces/IStatelessWorkerWithMayInterleaveGrain.cs index 43ef894fac..37b1b01992 100644 --- a/test/Grains/TestGrainInterfaces/IStatelessWorkerWithMayInterleaveGrain.cs +++ b/test/Grains/TestGrainInterfaces/IStatelessWorkerWithMayInterleaveGrain.cs @@ -2,7 +2,11 @@ namespace UnitTests.GrainInterfaces; public interface IStatelessWorkerWithMayInterleaveGrain : IGrainWithIntegerKey { - Task SetDelay(TimeSpan delay); - Task GoSlow(); - Task GoFast(); + Task GoSlow(ICallbackGrainObserver callback); + Task GoFast(ICallbackGrainObserver callback); +} + +public interface ICallbackGrainObserver : IGrainObserver +{ + Task WaitAsync(); } \ No newline at end of file diff --git a/test/Grains/TestGrains/StatelessWorkerWithMayInterleaveGrain.cs b/test/Grains/TestGrains/StatelessWorkerWithMayInterleaveGrain.cs index 7c63c9ece0..e46b230948 100644 --- a/test/Grains/TestGrains/StatelessWorkerWithMayInterleaveGrain.cs +++ b/test/Grains/TestGrains/StatelessWorkerWithMayInterleaveGrain.cs @@ -8,16 +8,15 @@ namespace UnitTests.Grains; [MayInterleave(nameof(MayInterleaveMethod))] public class StatelessWorkerWithMayInterleaveGrain : Grain, IStatelessWorkerWithMayInterleaveGrain { - private TimeSpan _delay = TimeSpan.FromMilliseconds(1); - public static bool MayInterleaveMethod(IInvokable req) => req.GetMethodName() == nameof(GoFast); - public Task SetDelay(TimeSpan delay) + public async Task GoSlow(ICallbackGrainObserver callback) { - _delay = delay; - return Task.CompletedTask; + await callback.WaitAsync(); } - public Task GoSlow() => Task.Delay(_delay); - public Task GoFast() => Task.Delay(_delay); -} \ No newline at end of file + public async Task GoFast(ICallbackGrainObserver callback) + { + await callback.WaitAsync(); + } +} diff --git a/test/Grains/TestInternalGrains/PersistenceTestGrains.cs b/test/Grains/TestInternalGrains/PersistenceTestGrains.cs index 73c17b6655..494bcdaa74 100644 --- a/test/Grains/TestInternalGrains/PersistenceTestGrains.cs +++ b/test/Grains/TestInternalGrains/PersistenceTestGrains.cs @@ -880,7 +880,7 @@ private void CheckRuntimeEnvironment() } } - internal class NonReentrentStressGrainWithoutState : Grain, INonReentrentStressGrainWithoutState + internal class NonReentrantStressGrainWithoutState : Grain, INonReentrantStressGrainWithoutState { private const int Multiple = 100; private ILogger logger; @@ -897,64 +897,113 @@ public override Task OnActivateAsync(CancellationToken cancellationToken) //if grain created outside a cluster if (loggerFactory == null) loggerFactory = NullLoggerFactory.Instance; - logger = loggerFactory.CreateLogger($"NonReentrentStressGrainWithoutState-{_id}"); + logger = loggerFactory.CreateLogger($"NonReentrantStressGrainWithoutState-{_id}"); executing = false; - logger.LogInformation("--> OnActivateAsync"); - logger.LogInformation("<-- OnActivateAsync"); + logger.LogDebug("--> OnActivateAsync"); + logger.LogDebug("<-- OnActivateAsync"); return base.OnActivateAsync(cancellationToken); } private async Task SetOne(int iter, int level) { - logger.LogInformation("---> SetOne {Iteration}-{Level}_0", iter, level); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug("---> SetOne {Iteration}-{Level}_0", iter, level); + } + CheckRuntimeEnvironment("SetOne"); if (level > 0) { - logger.LogInformation("SetOne {Iteration}-{Level}_1. Before await Task.Done.", iter, level); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug("SetOne {Iteration}-{Level}_1. Before await Task.Done.", iter, level); + } + await Task.CompletedTask; - logger.LogInformation("SetOne {Iteration}-{Level}_2. After await Task.Done.", iter, level); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug("SetOne {Iteration}-{Level}_2. After await Task.Done.", iter, level); + } + CheckRuntimeEnvironment($"SetOne {iter}-{level}_3"); - logger.LogInformation("SetOne {Iteration}-{Level}_4. Before await Task.Delay.", iter, level); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug("SetOne {Iteration}-{Level}_4. Before await Task.Delay.", iter, level); + } + await Task.Delay(TimeSpan.FromMilliseconds(10)); - logger.LogInformation("SetOne {Iteration}-{Level}_5. After await Task.Delay.", iter, level); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug("SetOne {Iteration}-{Level}_5. After await Task.Delay.", iter, level); + } + CheckRuntimeEnvironment($"SetOne {iter}-{level}_6"); var nextLevel = level - 1; await SetOne(iter, nextLevel); - logger.LogInformation( - "SetOne {Iteration}-{Level}_7 => {2}. After await SetOne call.", - iter, - level, - nextLevel); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug( + "SetOne {Iteration}-{Level}_7 => {NextLevel}. After await SetOne call.", + iter, + level, + nextLevel); + } + CheckRuntimeEnvironment($"SetOne {iter}-{level}_8"); - logger.LogInformation("SetOne {Iteration}-{Level}_9. Finished SetOne.", iter, level); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug("SetOne {Iteration}-{Level}_9. Finished SetOne.", iter, level); + } } CheckRuntimeEnvironment($"SetOne {iter}-{level}_10"); - logger.LogInformation("<--- SetOne {Iteration}-{Level}_11", iter, level); + logger.LogDebug("<--- SetOne {Iteration}-{Level}_11", iter, level); } public async Task Test1() { - logger.LogInformation("Test1.Start"); - CheckRuntimeEnvironment("Test1.BeforeLoop"); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug("Test1.Start"); + } + var tasks = new List(); for (var i = 0; i < Multiple; i++) { - logger.LogInformation("Test1_ ------> {CallNum}", i); CheckRuntimeEnvironment($"Test1_{i}_0"); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug("Test1_ ------> {CallNum}", i); + } + var task = SetOne(i, LEVEL); - logger.LogInformation("After SetOne call {CallNum}", i); CheckRuntimeEnvironment($"Test1_{i}_1"); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug("After SetOne call {CallNum}", i); + } + tasks.Add(task); CheckRuntimeEnvironment($"Test1_{i}_2"); - logger.LogInformation("Test1_ <------ {CallNum}", i); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug("Test1_ <------ {CallNum}", i); + } } CheckRuntimeEnvironment("Test1.AfterLoop"); - logger.LogInformation("Test1_About to WhenAll"); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug("Test1_About to WhenAll"); + } + await Task.WhenAll(tasks); - logger.LogInformation("Test1.Finish"); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug("Test1.Finish"); + } + CheckRuntimeEnvironment("Test1.Finish-CheckRuntimeEnvironment"); //#if DEBUG // // HACK for testing @@ -966,11 +1015,11 @@ public async Task Task_Delay(bool doStart) { var wrapper = new Task(async () => { - logger.LogInformation("Before Task.Delay #1 TaskScheduler.Current={TaskScheduler}", TaskScheduler.Current); + logger.LogDebug("Before Task.Delay #1 TaskScheduler.Current={TaskScheduler}", TaskScheduler.Current); await DoDelay(1); - logger.LogInformation("After Task.Delay #1 TaskScheduler.Current={TaskScheduler}", TaskScheduler.Current); + logger.LogDebug("After Task.Delay #1 TaskScheduler.Current={TaskScheduler}", TaskScheduler.Current); await DoDelay(2); - logger.LogInformation("After Task.Delay #2 TaskScheduler.Current={TaskScheduler}", TaskScheduler.Current); + logger.LogDebug("After Task.Delay #2 TaskScheduler.Current={TaskScheduler}", TaskScheduler.Current); }); if (doStart) @@ -983,15 +1032,14 @@ public async Task Task_Delay(bool doStart) private async Task DoDelay(int i) { - logger.LogInformation("Before Task.Delay #{Num} TaskScheduler.Current={TaskScheduler}", i, TaskScheduler.Current); + logger.LogDebug("Before Task.Delay #{Num} TaskScheduler.Current={TaskScheduler}", i, TaskScheduler.Current); await Task.Delay(1); - logger.LogInformation("After Task.Delay #{Num} TaskScheduler.Current={TaskScheduler}", i, TaskScheduler.Current); + logger.LogDebug("After Task.Delay #{Num} TaskScheduler.Current={TaskScheduler}", i, TaskScheduler.Current); } private void CheckRuntimeEnvironment(string str) { var callStack = new StackTrace(); - //Log("CheckRuntimeEnvironment - {0} Executing={1}", str, executing); if (executing) { var errorMsg = string.Format( @@ -1002,15 +1050,12 @@ private void CheckRuntimeEnvironment(string str) TestRuntimeEnvironmentUtility.CaptureRuntimeEnvironment(), callStack); this.logger.LogError(1, "{Message}", "\n\n\n\n" + errorMsg + "\n\n\n\n"); - //Environment.Exit(1); - throw new Exception(errorMsg); + throw new InvalidOperationException(errorMsg); } - //Assert.IsFalse(executing, "Found out that this grain is already in the middle of execution. Single threaded-ness violation!"); + executing = true; - //Log("CheckRuntimeEnvironment - Start sleep " + str); Thread.Sleep(10); executing = false; - //Log("CheckRuntimeEnvironment - End sleep " + str); } } diff --git a/test/NonSilo.Tests/SchedulerTests/OrleansTaskSchedulerAdvancedTests_Set2.cs b/test/NonSilo.Tests/SchedulerTests/OrleansTaskSchedulerAdvancedTests_Set2.cs index 226a7db02c..10e32d7d79 100644 --- a/test/NonSilo.Tests/SchedulerTests/OrleansTaskSchedulerAdvancedTests_Set2.cs +++ b/test/NonSilo.Tests/SchedulerTests/OrleansTaskSchedulerAdvancedTests_Set2.cs @@ -635,7 +635,7 @@ internal async Task Run_ActivationSched_Test1(TaskScheduler scheduler, bool boun { SiloAddress = SiloAddressUtils.NewLocalSiloAddress(23) }; - var grain = new NonReentrentStressGrainWithoutState(); + var grain = new NonReentrantStressGrainWithoutState(); await Task.Factory.StartNew(() => grain.OnActivateAsync(CancellationToken.None), CancellationToken.None, TaskCreationOptions.None, scheduler).Unwrap(); diff --git a/test/Tester/EventSourcingTests/ChatGrainTests.cs b/test/Tester/EventSourcingTests/ChatGrainTests.cs index e54fe3f274..db38df6f4e 100644 --- a/test/Tester/EventSourcingTests/ChatGrainTests.cs +++ b/test/Tester/EventSourcingTests/ChatGrainTests.cs @@ -22,8 +22,8 @@ public async Task Init() var content = (await chat.GetChat()).ToString(); - var expectedprefix = "\r\n\r\n "; - var expectedsuffix = "\r\n \r\n"; + var expectedprefix = $"{Environment.NewLine}{Environment.NewLine} "; + var expectedsuffix = $"{Environment.NewLine} {Environment.NewLine}"; Assert.StartsWith(expectedprefix, content); Assert.EndsWith(expectedsuffix, content); diff --git a/test/Tester/HeterogeneousSilosTests/UpgradeTests/UpgradeTestsBase.cs b/test/Tester/HeterogeneousSilosTests/UpgradeTests/UpgradeTestsBase.cs index 50079198fe..f751921d58 100644 --- a/test/Tester/HeterogeneousSilosTests/UpgradeTests/UpgradeTestsBase.cs +++ b/test/Tester/HeterogeneousSilosTests/UpgradeTests/UpgradeTestsBase.cs @@ -3,6 +3,7 @@ using Orleans.Configuration; using Orleans.Runtime; using Orleans.TestingHost; +using System.Runtime.InteropServices; using TestExtensions; using TestVersionGrainInterfaces; using TestVersionGrains; @@ -28,7 +29,7 @@ public abstract class UpgradeTestsBase : IDisposable, IAsyncLifetime private const string VersionsProjectDirectory = "Grains"; private const string GrainsV1ProjectName = "TestVersionGrains"; private const string GrainsV2ProjectName = "TestVersionGrains2"; - private const string VersionTestBinaryName = "TestVersionGrains.exe"; + private static readonly string VersionTestBinaryName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "TestVersionGrains.exe" : "TestVersionGrains"; private readonly FileInfo assemblyGrainsV1; private readonly FileInfo assemblyGrainsV2; diff --git a/test/Tester/LocalhostSiloTests.cs b/test/Tester/LocalhostSiloTests.cs index ee479b895d..7dd70d5e63 100644 --- a/test/Tester/LocalhostSiloTests.cs +++ b/test/Tester/LocalhostSiloTests.cs @@ -61,6 +61,9 @@ public async Task LocalhostClusterTest() siloBuilder .AddMemoryGrainStorage("MemoryStore") .UseLocalhostClustering(baseSiloPort, baseGatewayPort); +#pragma warning disable ORLEANSEXP003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + siloBuilder.AddDistributedGrainDirectory(); +#pragma warning restore ORLEANSEXP003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. }).Build(); var silo2 = new HostBuilder().UseOrleans((ctx, siloBuilder) => @@ -68,6 +71,9 @@ public async Task LocalhostClusterTest() siloBuilder .AddMemoryGrainStorage("MemoryStore") .UseLocalhostClustering(baseSiloPort + 1, baseGatewayPort + 1, new IPEndPoint(IPAddress.Loopback, baseSiloPort)); +#pragma warning disable ORLEANSEXP003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + siloBuilder.AddDistributedGrainDirectory(); +#pragma warning restore ORLEANSEXP003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. }).Build(); var clientHost = new HostBuilder().UseOrleansClient((ctx, clientBuilder) => diff --git a/test/TesterInternal/StorageTests/PersistenceGrainTests.cs b/test/TesterInternal/StorageTests/PersistenceGrainTests.cs index 39ac0fdf3e..982eba4b9c 100644 --- a/test/TesterInternal/StorageTests/PersistenceGrainTests.cs +++ b/test/TesterInternal/StorageTests/PersistenceGrainTests.cs @@ -1130,7 +1130,7 @@ public async Task ReentrentGrainWithState() public async Task NonReentrentStressGrainWithoutState() { Guid id1 = Guid.NewGuid(); - INonReentrentStressGrainWithoutState grain1 = this.HostedCluster.GrainFactory.GetGrain(id1); + INonReentrantStressGrainWithoutState grain1 = this.HostedCluster.GrainFactory.GetGrain(id1); await grain1.Test1(); } @@ -1149,7 +1149,7 @@ public async Task ReentrentGrain_Task_Delay() public async Task NonReentrentGrain_Task_Delay() { Guid id1 = Guid.NewGuid(); - INonReentrentStressGrainWithoutState grain1 = this.HostedCluster.GrainFactory.GetGrain(id1); + INonReentrantStressGrainWithoutState grain1 = this.HostedCluster.GrainFactory.GetGrain(id1); await grain1.Task_Delay(DoStart); }