Skip to content

Commit

Permalink
C#: Make IT to manage redis. (#116)
Browse files Browse the repository at this point in the history
* Make IT to run redis.


Signed-off-by: Yury-Fridlyand <[email protected]>
  • Loading branch information
Yury-Fridlyand authored Mar 4, 2024
1 parent 4639a9b commit b382a3c
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 19 deletions.
9 changes: 5 additions & 4 deletions .github/workflows/csharp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ jobs:
working-directory: ./csharp
run: dotnet format --verify-no-changes --verbosity diagnostic

- name: Test dotnet ${{ matrix.dotnet }}
working-directory: ./csharp
run: dotnet test --framework net${{ matrix.dotnet }} "-l:html;LogFileName=TestReport.html" --results-directory . -warnaserror -- NUnit.WorkDirectory=$PWD

- uses: ./.github/workflows/test-benchmark
with:
language-flag: -csharp

- name: Test dotnet ${{ matrix.dotnet }}
working-directory: ./csharp
run: dotnet test --framework net${{ matrix.dotnet }} "-l:html;LogFileName=TestReport.html" --results-directory . -warnaserror

- name: Upload test reports
if: always()
continue-on-error: true
Expand All @@ -88,6 +88,7 @@ jobs:
path: |
csharp/TestReport.html
benchmarks/results/*
utils/clusters/**
lint-rust:
timeout-minutes: 10
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,12 @@
* Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
*/

namespace tests;
namespace tests.Integration;

using Glide;

// TODO - need to start a new redis server for each test?
public class AsyncClientTests
public class GetAndSet
{
[OneTimeSetUp]
public void Setup()
{
Glide.Logger.SetLoggerConfig(Glide.Level.Info);
}

private async Task GetAndSetRandomValues(AsyncClient client)
{
var key = Guid.NewGuid().ToString();
Expand All @@ -27,7 +20,7 @@ private async Task GetAndSetRandomValues(AsyncClient client)
[Test]
public async Task GetReturnsLastSet()
{
using (var client = new AsyncClient("localhost", 6379, false))
using (var client = new AsyncClient("localhost", IntegrationTestBase.STANDALONE_PORTS[0], false))
{
await GetAndSetRandomValues(client);
}
Expand All @@ -36,7 +29,7 @@ public async Task GetReturnsLastSet()
[Test]
public async Task GetAndSetCanHandleNonASCIIUnicode()
{
using (var client = new AsyncClient("localhost", 6379, false))
using (var client = new AsyncClient("localhost", IntegrationTestBase.STANDALONE_PORTS[0], false))
{
var key = Guid.NewGuid().ToString();
var value = "שלום hello 汉字";
Expand All @@ -49,7 +42,7 @@ public async Task GetAndSetCanHandleNonASCIIUnicode()
[Test]
public async Task GetReturnsNull()
{
using (var client = new AsyncClient("localhost", 6379, false))
using (var client = new AsyncClient("localhost", IntegrationTestBase.STANDALONE_PORTS[0], false))
{
var result = await client.GetAsync(Guid.NewGuid().ToString());
Assert.That(result, Is.EqualTo(null));
Expand All @@ -59,7 +52,7 @@ public async Task GetReturnsNull()
[Test]
public async Task GetReturnsEmptyString()
{
using (var client = new AsyncClient("localhost", 6379, false))
using (var client = new AsyncClient("localhost", IntegrationTestBase.STANDALONE_PORTS[0], false))
{
var key = Guid.NewGuid().ToString();
var value = "";
Expand All @@ -72,7 +65,7 @@ public async Task GetReturnsEmptyString()
[Test]
public async Task HandleVeryLargeInput()
{
using (var client = new AsyncClient("localhost", 6379, false))
using (var client = new AsyncClient("localhost", IntegrationTestBase.STANDALONE_PORTS[0], false))
{
var key = Guid.NewGuid().ToString();
var value = Guid.NewGuid().ToString();
Expand All @@ -92,7 +85,7 @@ public async Task HandleVeryLargeInput()
[Test]
public void ConcurrentOperationsWork()
{
using (var client = new AsyncClient("localhost", 6379, false))
using (var client = new AsyncClient("localhost", IntegrationTestBase.STANDALONE_PORTS[0], false))
{
var operations = new List<Task>();

Expand Down
135 changes: 135 additions & 0 deletions csharp/tests/Integration/IntegrationTestBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/**
* Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
*/

using System.Diagnostics;

// Note: All IT should be in the same namespace
namespace tests.Integration;

[SetUpFixture]
public class IntegrationTestBase
{
[OneTimeSetUp]
public void SetUp()
{
// Stop all if weren't stopped on previous test run
StopRedis(false);

// Delete dirs if stop failed due to https://github.com/aws/glide-for-redis/issues/849
Directory.Delete(Path.Combine(scriptDir, "clusters"), true);

// Start cluster
CLUSTER_PORTS = StartRedis(true);
// Start standalone
STANDALONE_PORTS = StartRedis(false);

// Get redis version
REDIS_VERSION = GetRedisVersion();

TestContext.Progress.WriteLine($"Cluster ports = {string.Join(',', CLUSTER_PORTS)}");
TestContext.Progress.WriteLine($"Standalone ports = {string.Join(',', STANDALONE_PORTS)}");
TestContext.Progress.WriteLine($"Redis version = {REDIS_VERSION}");
}

[OneTimeTearDown]
public void TearDown()
{
// Stop all
StopRedis(true);
}

public static List<uint> STANDALONE_PORTS { get; private set; } = new();
public static List<uint> CLUSTER_PORTS { get; private set; } = new();
public static Version REDIS_VERSION { get; private set; } = new();

private readonly string scriptDir;

// Nunit requires a public default constructor. These variables would be set in SetUp method.
public IntegrationTestBase()
{
STANDALONE_PORTS = new();
CLUSTER_PORTS = new();
REDIS_VERSION = new();

string path = TestContext.CurrentContext.WorkDirectory;
if (Path.GetFileName(path) != "csharp")
throw new FileNotFoundException("`WorkDirectory` is incorrect or not defined. Please ensure the WorkDirectory was set by passing `-- NUnit.WorkDirectory=<path>` to the `dotnet test` command.");

scriptDir = Path.Combine(path, "..", "utils");
}


public List<uint> StartRedis(bool cluster, bool tls = false, string? name = null)
{
var cmd = $"start {(cluster ? "--cluster-mode" : "-r 0")} {(tls ? " --tls" : "")} {(name != null ? " --prefix " + name : "")}";
return ParsePortsFromOutput(RunClusterManager(cmd, false));
}

/// <summary>
/// Stop <b>all</b> instances on the given <paramref name="name"/>.
/// </summary>
public void StopRedis(bool keepLogs, string? name = null)
{
var cmd = $"stop --prefix {name ?? "redis-cluster"} {(keepLogs ? "--keep-folder" : "")}";
RunClusterManager(cmd, true);
}


private string RunClusterManager(string cmd, bool ignoreExitCode)
{
var info = new ProcessStartInfo
{
WorkingDirectory = scriptDir,
FileName = "python3",
Arguments = "cluster_manager.py " + cmd,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
};
var script = Process.Start(info);
script?.WaitForExit();
var error = script?.StandardError.ReadToEnd();
var output = script?.StandardOutput.ReadToEnd();
var exit_code = script?.ExitCode;

TestContext.Progress.WriteLine($"cluster_manager.py stdout\n====\n{output}\n====\ncluster_manager.py stderr\n====\n{error}\n====\n");

if (!ignoreExitCode && exit_code != 0)
throw new ApplicationException($"cluster_manager.py script failed: exit code {exit_code}.");

return output ?? "";
}

private List<uint> ParsePortsFromOutput(string output)
{
var ports = new List<uint>();
foreach (var line in output.Split("\n"))
{
if (!line.StartsWith("CLUSTER_NODES="))
continue;

var addresses = line.Split("=")[1].Split(",");
foreach (var address in addresses)
ports.Add(uint.Parse(address.Split(":")[1]));
}
return ports;
}

private Version GetRedisVersion()
{
var info = new ProcessStartInfo
{
FileName = "redis-server",
Arguments = "-v",
UseShellExecute = false,
RedirectStandardOutput = true,
};
var proc = Process.Start(info);
proc?.WaitForExit();
var output = proc?.StandardOutput.ReadToEnd() ?? "";

// Redis server v=7.2.3 sha=00000000:0 malloc=jemalloc-5.3.0 bits=64 build=7504b1fedf883f2
return new Version(output.Split(" ")[2].Split("=")[1]);
}
}
9 changes: 9 additions & 0 deletions csharp/tests/Unit/Placeholder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
*/

namespace tests.Unit;

using Glide;

// John Travolta is looking for tests

0 comments on commit b382a3c

Please sign in to comment.