Skip to content

Commit 7ad57b4

Browse files
committed
The task cancel API test was a bit flakey,
It was setting additional values in the integration setup on the class itself but this setup is run once for possibly multiple classes e.g EndpointUsage x; new TestClass(x).Test1(); new TestClass(x).Test2(); new TestClass(x).Test3(); new TestClass(x).Test4(); new TestClass(x).Test5(); integration setup is an override per TestClass but only one of them will be called per instance of `x`. So if the callback defines setting variables on the `TestClass` instance using `this` other TestClass instances won't see this. This PR makes CallIsolatedValues a class of its own that allows you to register extended values that can be shared amongst all TestClass instances.
1 parent 193355f commit 7ad57b4

File tree

30 files changed

+137
-96
lines changed

30 files changed

+137
-96
lines changed

src/Tests/Cat/CatRepositories/CatRepositoriesApiTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ public class CatRepositoriesApiTests : ApiIntegrationTestBase<ICatResponse<CatRe
1717

1818
public CatRepositoriesApiTests(IndexingCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
1919

20-
protected override void BeforeAllCalls(IElasticClient client, IDictionary<ClientMethod, string> values)
20+
protected override void IntegrationSetup(IElasticClient client, CallUniqueValues values)
2121
{
2222
if (!TestClient.Configuration.RunIntegrationTests) return;
23-
var repositoryLocation = Path.Combine(this._cluster.Node.RepositoryPath, RandomString());
23+
var repositoryLocation = Path.Combine(this.Cluster.Node.RepositoryPath, RandomString());
2424

2525
var create = this.Client.CreateRepository(RepositoryName, cr => cr
2626
.FileSystem(fs => fs

src/Tests/Cat/CatSnapshots/CatSnapshotsApiTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ public class CatSnapshotsApiTests : ApiIntegrationTestBase<ICatResponse<CatSnaps
1919

2020
public CatSnapshotsApiTests(IndexingCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
2121

22-
protected override void BeforeAllCalls(IElasticClient client, IDictionary<ClientMethod, string> values)
22+
protected override void IntegrationSetup(IElasticClient client, CallUniqueValues values)
2323
{
2424
if (!TestClient.Configuration.RunIntegrationTests) return;
25-
var repositoryLocation = Path.Combine(this._cluster.Node.RepositoryPath, RandomString());
25+
var repositoryLocation = Path.Combine(this.Cluster.Node.RepositoryPath, RandomString());
2626

2727
var create = this.Client.CreateRepository(RepositoryName, cr => cr
2828
.FileSystem(fs => fs

src/Tests/Cluster/TaskManagement/TasksCancel/TasksCancelApiTests.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,31 @@
1010

1111
namespace Tests.Cluster.TaskManagement.TasksCancel
1212
{
13-
// TODO Unit tests will fail in mixed mode because SetupTaskIds isn't setup
1413
[Collection(IntegrationContext.OwnIndex)]
1514
public class TasksCancelApiTests : ApiIntegrationTestBase<ITasksCancelResponse, ITasksCancelRequest, TasksCancelDescriptor, TasksCancelRequest>
1615
{
17-
public class Test
16+
private TaskId TaskId => this.RanIntegrationSetup ? this.ExtendedValue<TaskId>("taskId") : "foo:1";
17+
18+
private class Test
1819
{
1920
public long Id { get; set; }
2021
public string Flag { get; set; }
2122
}
2223

2324
public TasksCancelApiTests(OwnIndexCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
2425

25-
protected IDictionary<string, TaskId> SetupTaskIds { get; } = new Dictionary<string, TaskId>();
26-
27-
protected override void BeforeAllCalls(IElasticClient client, IDictionary<ClientMethod, string> values)
26+
protected override void IntegrationSetup(IElasticClient client, CallUniqueValues values)
2827
{
2928
foreach (var index in values.Values)
3029
{
3130
client.IndexMany(Enumerable.Range(0, 10000).Select(i => new Test { Id = i + 1, Flag = "bar" }), index);
3231
client.Refresh(index);
3332
}
34-
foreach (var index in values.Values)
33+
foreach (var view in values.Views)
3534
{
35+
values.CurrentView = view;
36+
var index = values.Value;
37+
3638
var reindex = client.ReindexOnServer(r => r
3739
.Source(s => s.Index(index))
3840
.Destination(s => s.Index($"{index}-clone"))
@@ -42,7 +44,7 @@ protected override void BeforeAllCalls(IElasticClient client, IDictionary<Client
4244
var taskId = reindex.Task;
4345
var taskInfo = client.TasksList(new TasksListRequest(taskId));
4446
taskInfo.IsValid.Should().BeTrue();
45-
this.SetupTaskIds[index] = taskId;
47+
values.ExtendedValue("taskId", taskId);
4648
}
4749
}
4850
protected override LazyResponses ClientUsage() => Calls(
@@ -58,20 +60,18 @@ protected override LazyResponses ClientUsage() => Calls(
5860
protected override string UrlPath => $"/_tasks/{Uri.EscapeDataString(this.TaskId.ToString())}/_cancel";
5961
protected override bool SupportsDeserialization => false;
6062

61-
private TaskId TaskId => TestClient.Configuration.RunIntegrationTests ? this.SetupTaskIds[CallIsolatedValue] : "foo:1";
6263

6364
protected override Func<TasksCancelDescriptor, ITasksCancelRequest> Fluent => d => d
6465
.TaskId(this.TaskId);
6566

6667
protected override TasksCancelRequest Initializer => new TasksCancelRequest(this.TaskId);
6768

68-
// TODO this test is flaky, sometimes SetupTaskIds is empty
6969
protected override void ExpectResponse(ITasksCancelResponse response)
7070
{
7171
response.NodeFailures.Should().BeNullOrEmpty();
7272
response.Nodes.Should().NotBeEmpty();
7373
var tasks = response.Nodes.First().Value.Tasks;
74-
tasks.Should().NotBeEmpty().And.ContainKey(this.SetupTaskIds[CallIsolatedValue]);
74+
tasks.Should().NotBeEmpty().And.ContainKey(this.TaskId);
7575
}
7676
}
7777
}

src/Tests/Document/Multiple/DeleteByQuery/DeleteByQueryApiTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class DeleteByQueryApiTests : ApiIntegrationTestBase<IDeleteByQueryRespon
1717
{
1818
public DeleteByQueryApiTests(OwnIndexCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
1919

20-
protected override void BeforeAllCalls(IElasticClient client, IDictionary<ClientMethod, string> values)
20+
protected override void IntegrationSetup(IElasticClient client, CallUniqueValues values)
2121
{
2222
foreach (var index in values.Values)
2323
{
@@ -44,7 +44,7 @@ protected override LazyResponses ClientUsage() => Calls(
4444

4545
protected override bool SupportsDeserialization => false;
4646

47-
protected override object ExpectJson { get; } = new
47+
protected override object ExpectJson { get; } = new
4848
{
4949
query = new
5050
{
@@ -66,7 +66,7 @@ protected override LazyResponses ClientUsage() => Calls(
6666
.Values(Project.Projects.First().Name, "x")
6767
)
6868
);
69-
69+
7070
protected override DeleteByQueryRequest Initializer => new DeleteByQueryRequest(this.Indices)
7171
{
7272
IgnoreUnavailable = true,

src/Tests/Document/Multiple/ReindexOnServer/ReindexOnServerApiTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class Test
2323

2424
public ReindexOnServerApiTests(OwnIndexCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
2525

26-
protected override void BeforeAllCalls(IElasticClient client, IDictionary<ClientMethod, string> values)
26+
protected override void IntegrationSetup(IElasticClient client, CallUniqueValues values)
2727
{
2828
foreach (var index in values.Values)
2929
{

src/Tests/Document/Multiple/UpdateByQuery/UpdateByQueryApiTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class Test
2323

2424
public UpdateByQueryApiTests(OwnIndexCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
2525

26-
protected override void BeforeAllCalls(IElasticClient client, IDictionary<ClientMethod, string> values)
26+
protected override void IntegrationSetup(IElasticClient client, CallUniqueValues values)
2727
{
2828
foreach (var index in values.Values)
2929
{
@@ -131,7 +131,7 @@ public class UpdateByQueryWithFailuresApiTests : UpdateByQueryApiTests
131131
{
132132
public UpdateByQueryWithFailuresApiTests(OwnIndexCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
133133

134-
protected override void BeforeAllCalls(IElasticClient client, IDictionary<ClientMethod, string> values)
134+
protected override void IntegrationSetup(IElasticClient client, CallUniqueValues values)
135135
{
136136
foreach (var index in values.Values)
137137
{

src/Tests/Document/Single/Delete/DeleteApiTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class DeleteApiTests : ApiIntegrationTestBase<IDeleteResponse, IDeleteReq
1414
{
1515
public DeleteApiTests(IndexingCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
1616

17-
protected override void BeforeAllCalls(IElasticClient client, IDictionary<ClientMethod, string> values)
17+
protected override void IntegrationSetup(IElasticClient client, CallUniqueValues values)
1818
{
1919
foreach (var id in values.Values)
2020
this.Client.Index(Project.Instance, i=>i.Id(id));

src/Tests/Document/Single/Exists/DocumentExistsApiTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class DocumentExistsApiTests : ApiIntegrationTestBase<IExistsResponse, ID
1414
{
1515
public DocumentExistsApiTests(IndexingCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
1616

17-
protected override void BeforeAllCalls(IElasticClient client, IDictionary<ClientMethod, string> values)
17+
protected override void IntegrationSetup(IElasticClient client, CallUniqueValues values)
1818
{
1919
foreach (var id in values.Values)
2020
this.Client.Index(Project.Instance, i=>i.Id(id));

src/Tests/Document/Single/Update/UpdateApiTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class UpdateApiTests : ApiIntegrationTestBase<IUpdateResponse<Project>, I
1414
{
1515
public UpdateApiTests(IndexingCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
1616

17-
protected override void BeforeAllCalls(IElasticClient client, IDictionary<ClientMethod, string> values)
17+
protected override void IntegrationSetup(IElasticClient client, CallUniqueValues values)
1818
{
1919
foreach (var id in values.Values)
2020
this.Client.Index(Project.Instance, i=>i.Id(id));

src/Tests/Document/Single/Update/UpdateWithSourceApiTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class UpdateWithSourceApiTests : ApiIntegrationTestBase<IUpdateResponse<P
1818
{
1919
public UpdateWithSourceApiTests(IndexingCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
2020

21-
protected override void BeforeAllCalls(IElasticClient client, IDictionary<ClientMethod, string> values)
21+
protected override void IntegrationSetup(IElasticClient client, CallUniqueValues values)
2222
{
2323
foreach (var id in values.Values)
2424
this.Client.Index(Project.Instance, i=>i.Id(id));

src/Tests/Framework/ApiIntegrationTestBase.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
namespace Tests.Framework
1010
{
11-
public abstract class ApiIntegrationTestBase<TResponse, TInterface, TDescriptor, TInitializer>
11+
public abstract class ApiIntegrationTestBase<TResponse, TInterface, TDescriptor, TInitializer>
1212
: ApiTestBase<TResponse, TInterface, TDescriptor, TInitializer>
1313
where TResponse : class, IResponse
1414
where TDescriptor : class, TInterface
@@ -29,8 +29,7 @@ [I] protected async Task HandlesStatusCode() =>
2929
[I] protected async Task ReturnsExpectedIsValid() =>
3030
await this.AssertOnAllResponses(r=>r.IsValid.Should().Be(this.ExpectIsValid));
3131

32-
[I] protected async Task ReturnsExpectedResponse() =>
33-
await this.AssertOnAllResponses(r => ExpectResponse(r));
32+
[I] protected async Task ReturnsExpectedResponse() => await this.AssertOnAllResponses(ExpectResponse);
3433

3534
protected override Task AssertOnAllResponses(Action<TResponse> assert)
3635
{

src/Tests/Framework/ApiTestBase.cs

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,87 +16,110 @@ public abstract class ApiTestBase<TResponse, TInterface, TDescriptor, TInitializ
1616
where TInitializer : class, TInterface
1717
where TInterface : class
1818
{
19-
protected readonly IIntegrationCluster _cluster;
19+
private readonly EndpointUsage _usage;
2020
private readonly LazyResponses _responses;
21+
private readonly int _port;
22+
private readonly CallUniqueValues _uniqueValues;
2123

2224
protected static string RandomString() => Guid.NewGuid().ToString("N").Substring(0, 8);
23-
protected virtual ConnectionSettings GetConnectionSettings(ConnectionSettings settings) => settings;
24-
protected virtual IElasticClient Client => this._cluster.Client(GetConnectionSettings);
25+
protected bool RanIntegrationSetup => this._usage?.CalledSetup ?? false;
26+
27+
protected IIntegrationCluster Cluster { get; }
2528

26-
protected IDictionary<Integration.ClientMethod, string> UniqueValues { get; }
27-
protected string CallIsolatedValue { get; private set; }
29+
protected string CallIsolatedValue => _uniqueValues.Value;
30+
protected T ExtendedValue<T>(string key) where T : class => this._uniqueValues.ExtendedValue<T>(key);
2831

29-
protected virtual void BeforeAllCalls(IElasticClient client, IDictionary<Integration.ClientMethod, string> values) { }
32+
protected virtual void IntegrationSetup(IElasticClient client, CallUniqueValues values) { }
3033
protected virtual void OnBeforeCall(IElasticClient client) { }
3134
protected virtual void OnAfterCall(IElasticClient client) { }
3235

33-
protected virtual int Port { get; set; } = 9200;
36+
protected IElasticClient Client => this.Cluster.Client(GetConnectionSettings);
37+
protected virtual ConnectionSettings GetConnectionSettings(ConnectionSettings settings) => settings;
3438

35-
protected virtual TInitializer Initializer { get; }
39+
protected virtual TDescriptor NewDescriptor() => Activator.CreateInstance<TDescriptor>();
3640
protected virtual Func<TDescriptor, TInterface> Fluent { get; }
41+
protected virtual TInitializer Initializer { get; }
3742

38-
protected virtual TDescriptor ClientDoesThisInternally(TDescriptor d) => d;
3943
protected abstract LazyResponses ClientUsage();
4044

41-
protected virtual TDescriptor NewDescriptor() => Activator.CreateInstance<TDescriptor>();
42-
4345
protected abstract string UrlPath { get; }
4446
protected abstract HttpMethod HttpMethod { get; }
4547

4648
protected ApiTestBase(IIntegrationCluster cluster, EndpointUsage usage)
4749
{
48-
this._cluster = cluster;
50+
this._usage = usage;
51+
this.Cluster = cluster;
52+
4953
this._responses = usage.CallOnce(this.ClientUsage);
50-
this.Port = cluster.Node.Port;
51-
this.UniqueValues = usage.CallUniqueValues;
52-
this.CallIsolatedValue = UniqueValues[Integration.ClientMethod.Fluent];
54+
this._port = cluster.Node.Port;
55+
this._uniqueValues = usage.CallUniqueValues;
5356
this.SetupSerialization();
5457
}
5558

56-
protected virtual LazyResponses Calls(
59+
[U] protected async Task HitsTheCorrectUrl() =>
60+
await this.AssertOnAllResponses(r => this.AssertUrl(r.ApiCall.Uri));
61+
62+
[U] protected async Task UsesCorrectHttpMethod() =>
63+
await this.AssertOnAllResponses(r => r.CallDetails.HttpMethod.Should().Be(this.HttpMethod));
64+
65+
[U] protected void SerializesInitializer() =>
66+
this.AssertSerializesAndRoundTrips<TInterface>(this.Initializer);
67+
68+
[U] protected void SerializesFluent() =>
69+
this.AssertSerializesAndRoundTrips(this.Fluent?.Invoke(NewDescriptor()));
70+
71+
protected LazyResponses Calls(
5772
Func<IElasticClient, Func<TDescriptor, TInterface>, TResponse> fluent,
5873
Func<IElasticClient, Func<TDescriptor, TInterface>, Task<TResponse>> fluentAsync,
5974
Func<IElasticClient, TInitializer, TResponse> request,
6075
Func<IElasticClient, TInitializer, Task<TResponse>> requestAsync
6176
)
6277
{
78+
//this client is outside the lambda so that the callstack is one where we can get the method name
79+
//of the current running test and send that as a header, great for e.g fiddler to relate requests with the test that sent it
6380
var client = this.Client;
6481
return new LazyResponses(async () =>
6582
{
66-
this.BeforeAllCalls(client, UniqueValues);
83+
if (TestClient.Configuration.RunIntegrationTests)
84+
{
85+
this.IntegrationSetup(client, _uniqueValues);
86+
}
87+
88+
this._usage.CalledSetup = true;
6789

6890
var dict = new Dictionary<ClientMethod, IResponse>();
69-
this.CallIsolatedValue = UniqueValues[ClientMethod.Fluent];
91+
_uniqueValues.CurrentView = ClientMethod.Fluent;
92+
7093
OnBeforeCall(client);
7194
dict.Add(ClientMethod.Fluent, fluent(client, this.Fluent));
7295
OnAfterCall(client);
7396

74-
this.CallIsolatedValue = UniqueValues[ClientMethod.FluentAsync];
97+
_uniqueValues.CurrentView = ClientMethod.FluentAsync;
7598
OnBeforeCall(client);
7699
dict.Add(ClientMethod.FluentAsync, await fluentAsync(client, this.Fluent));
77100
OnAfterCall(client);
78101

79-
this.CallIsolatedValue = UniqueValues[ClientMethod.Initializer];
102+
_uniqueValues.CurrentView = ClientMethod.Initializer;
80103
OnBeforeCall(client);
81104
dict.Add(ClientMethod.Initializer, request(client, this.Initializer));
82105
OnAfterCall(client);
83106

84-
this.CallIsolatedValue = UniqueValues[ClientMethod.InitializerAsync];
107+
_uniqueValues.CurrentView = ClientMethod.InitializerAsync;
85108
OnBeforeCall(client);
86109
dict.Add(ClientMethod.InitializerAsync, await requestAsync(client, this.Initializer));
87110
OnAfterCall(client);
88111
return dict;
89112
});
90113
}
91114

92-
protected virtual void AssertUrl(Uri u)
115+
private void AssertUrl(Uri u)
93116
{
94117
var paths = (this.UrlPath ?? "").Split(new[] { '?' }, 2);
95118
string path = paths.First(), query = string.Empty;
96119
if (paths.Length > 1)
97120
query = paths.Last();
98121

99-
var expectedUri = new UriBuilder("http", "localhost", Port, path, "?" + query).Uri;
122+
var expectedUri = new UriBuilder("http", "localhost", this._port, path, "?" + query).Uri;
100123

101124
u.AbsolutePath.Should().Be(expectedUri.AbsolutePath);
102125
u = new UriBuilder(u.Scheme, u.Host, u.Port, u.AbsolutePath, u.Query.Replace("pretty=true&", "").Replace("pretty=true", "")).Uri;
@@ -131,7 +154,7 @@ protected virtual async Task AssertOnAllResponses(Action<TResponse> assert)
131154
var response = kv.Value as TResponse;
132155
try
133156
{
134-
this.CallIsolatedValue = UniqueValues[kv.Key];
157+
this._uniqueValues.CurrentView = kv.Key;
135158
assert(response);
136159
}
137160
#pragma warning disable 7095 //enable this if you expect a single overload to act up
@@ -143,16 +166,5 @@ protected virtual async Task AssertOnAllResponses(Action<TResponse> assert)
143166
}
144167
}
145168

146-
[U] protected async Task HitsTheCorrectUrl() =>
147-
await this.AssertOnAllResponses(r => this.AssertUrl(r.ApiCall.Uri));
148-
149-
[U] protected async Task UsesCorrectHttpMethod() =>
150-
await this.AssertOnAllResponses(r => r.CallDetails.HttpMethod.Should().Be(this.HttpMethod));
151-
152-
[U] protected void SerializesInitializer() =>
153-
this.AssertSerializesAndRoundTrips<TInterface>(this.Initializer);
154-
155-
[U] protected void SerializesFluent() =>
156-
this.AssertSerializesAndRoundTrips(this.Fluent?.Invoke(this.ClientDoesThisInternally(NewDescriptor())));
157169
}
158170
}

src/Tests/Framework/AsyncLazy.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,4 @@ public LazyResponses(Func<Dictionary<Integration.ClientMethod, IResponse>> facto
6161

6262
public LazyResponses(Func<Task<Dictionary<Integration.ClientMethod, IResponse>>> factory) : base(factory) { }
6363
}
64-
}
64+
}

0 commit comments

Comments
 (0)