Skip to content

Commit 2366f1c

Browse files
committed
add TargetEnvironmentAttribute and FaultInjectorClient
1 parent 7dcd6d2 commit 2366f1c

File tree

3 files changed

+154
-9
lines changed

3 files changed

+154
-9
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using Xunit;
2+
3+
namespace NRedisStack.Tests;
4+
public class TargetEnvironmentAttribute : SkipIfRedisAttribute
5+
{
6+
private string targetEnv;
7+
public TargetEnvironmentAttribute(string targetEnv) : base(Comparison.LessThan, "0.0.0")
8+
{
9+
this.targetEnv = targetEnv;
10+
}
11+
12+
public TargetEnvironmentAttribute(string targetEnv, Is environment, Comparison comparison = Comparison.LessThan,
13+
string targetVersion = "0.0.0") : base(environment, comparison, targetVersion)
14+
{
15+
this.targetEnv = targetEnv;
16+
}
17+
18+
public TargetEnvironmentAttribute(string targetEnv, Is environment1, Is environment2, Comparison comparison = Comparison.LessThan,
19+
string targetVersion = "0.0.0") : base(environment1, environment2, comparison, targetVersion)
20+
{
21+
this.targetEnv = targetEnv;
22+
}
23+
24+
public override string? Skip
25+
{
26+
get
27+
{
28+
if (!new RedisFixture().IsTargetConnectionExist(targetEnv))
29+
{
30+
return "Test skipped, because: target environment not found.";
31+
}
32+
return base.Skip;
33+
}
34+
}
35+
}

tests/NRedisStack.Tests/TokenBasedAuthentication/AuthenticationTests.cs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,28 @@
66

77
namespace NRedisStack.Tests.TokenBasedAuthentication
88
{
9-
public class AuthenticationTests
9+
public class AuthenticationTests : AbstractNRedisStackTest
1010
{
1111
static readonly string key = "myKey";
1212
static readonly string value = "myValue";
1313
static readonly string index = "myIndex";
1414
static readonly string field = "myField";
1515
static readonly string alias = "myAlias";
16+
public AuthenticationTests(RedisFixture redisFixture) : base(redisFixture) { }
1617

17-
string env0Host = "localhost:6379";
18-
19-
[Fact]
18+
[TargetEnvironment("standalone-entraid-acl")]
2019
public void TestTokenBasedAuthentication()
2120
{
22-
21+
Assert.True(new FaultInjectorClient().TriggerActionAsync("enable_entraid", new Dictionary<string, object>()).Wait(5000),"Entraid could not be enabled this time!!!");
2322
// NOTE: ConnectionMultiplexer instances should be as long-lived as possible. Ideally a single ConnectionMultiplexer per cache is reused over the lifetime of the client application process.
2423
ConnectionMultiplexer? connectionMultiplexer = null;
25-
StringWriter connectionLog = new();
24+
// StringWriter connectionLog = new();
2625

27-
var configurationOptions = ConfigurationOptions.Parse($"{env0Host}").ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential()).Result!;
26+
var configurationOptions = new ConfigurationOptions().ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential()).Result!;
2827
configurationOptions.Ssl = false;
2928
configurationOptions.AbortOnConnectFail = true; // Fail fast for the purposes of this sample. In production code, this should remain false to retry connections on startup
3029

31-
connectionMultiplexer = ConnectionMultiplexer.ConnectAsync(configurationOptions, connectionLog).Result;
30+
connectionMultiplexer = redisFixture.GetConnectionById(configurationOptions, "standalone-entraid-acl");
3231

3332
IDatabase db = connectionMultiplexer.GetDatabase();
3433

@@ -53,7 +52,6 @@ public void TestTokenBasedAuthentication()
5352
SearchResult res1 = ft.Search(alias, new Query("*").ReturnFields(field));
5453
Assert.Equal(1, res1.TotalResults);
5554
Assert.Equal(value, res1.Documents[0][field]);
56-
5755
}
5856
}
5957
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
using System.Text;
2+
using System.Text.Json;
3+
4+
public class FaultInjectorClient
5+
{
6+
private static readonly string BASE_URL;
7+
8+
static FaultInjectorClient()
9+
{
10+
BASE_URL = Environment.GetEnvironmentVariable("FAULT_INJECTION_API_URL") ?? "http://127.0.0.1:20324";
11+
}
12+
13+
public class TriggerActionResponse
14+
{
15+
public string ActionId { get; }
16+
private DateTime? LastRequestTime { get; set; }
17+
private DateTime? CompletedAt { get; set; }
18+
private DateTime? FirstRequestAt { get; set; }
19+
20+
public TriggerActionResponse(string actionId)
21+
{
22+
ActionId = actionId;
23+
}
24+
25+
public async Task<bool> IsCompletedAsync(TimeSpan checkInterval, TimeSpan delayAfter, TimeSpan timeout)
26+
{
27+
if (CompletedAt.HasValue)
28+
{
29+
return DateTime.UtcNow - CompletedAt.Value >= delayAfter;
30+
}
31+
32+
if (FirstRequestAt.HasValue && DateTime.UtcNow - FirstRequestAt.Value >= timeout)
33+
{
34+
throw new TimeoutException("Timeout");
35+
}
36+
37+
if (!LastRequestTime.HasValue || DateTime.UtcNow - LastRequestTime.Value >= checkInterval)
38+
{
39+
LastRequestTime = DateTime.UtcNow;
40+
41+
if (!FirstRequestAt.HasValue)
42+
{
43+
FirstRequestAt = LastRequestTime;
44+
}
45+
46+
using var httpClient = GetHttpClient();
47+
var request = new HttpRequestMessage(HttpMethod.Get, $"{BASE_URL}/action/{ActionId}");
48+
49+
try
50+
{
51+
var response = await httpClient.SendAsync(request);
52+
var result = await response.Content.ReadAsStringAsync();
53+
54+
55+
if (result.Contains("success"))
56+
{
57+
CompletedAt = DateTime.UtcNow;
58+
return DateTime.UtcNow - CompletedAt.Value >= delayAfter;
59+
}
60+
}
61+
catch (HttpRequestException e)
62+
{
63+
throw new Exception("Fault injection proxy error", e);
64+
}
65+
}
66+
return false;
67+
}
68+
}
69+
70+
private static HttpClient GetHttpClient()
71+
{
72+
var httpClient = new HttpClient
73+
{
74+
Timeout = TimeSpan.FromMilliseconds(5000)
75+
};
76+
return httpClient;
77+
}
78+
79+
public async Task<TriggerActionResponse> TriggerActionAsync(string actionType, Dictionary<string, object> parameters)
80+
{
81+
var payload = new Dictionary<string, object>
82+
{
83+
{ "type", actionType },
84+
{ "parameters", parameters }
85+
};
86+
87+
var jsonString = JsonSerializer.Serialize(payload, new JsonSerializerOptions
88+
{
89+
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
90+
});
91+
92+
using var httpClient = GetHttpClient();
93+
var request = new HttpRequestMessage(HttpMethod.Post, $"{BASE_URL}/action")
94+
{
95+
Content = new StringContent(jsonString, Encoding.UTF8, "application/json")
96+
};
97+
98+
try
99+
{
100+
var response = await httpClient.SendAsync(request);
101+
var result = await response.Content.ReadAsStringAsync();
102+
return JsonSerializer.Deserialize<TriggerActionResponse>(result, new JsonSerializerOptions
103+
{
104+
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
105+
});
106+
}
107+
catch (HttpRequestException e)
108+
{
109+
throw;
110+
}
111+
}
112+
}

0 commit comments

Comments
 (0)