Skip to content

Commit 80597a6

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 3a985b8 commit 80597a6

File tree

6 files changed

+95
-40
lines changed

6 files changed

+95
-40
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/Framework/EndpointTests/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
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace Tests.Framework.Integration
5+
{
6+
public class CallUniqueValues : Dictionary<ClientMethod, string>
7+
{
8+
private string UniqueValue => "nest-" + Guid.NewGuid().ToString("N").Substring(0, 8);
9+
10+
private IDictionary<ClientMethod, IDictionary<string, object>> ExtendedValues { get; }
11+
= new Dictionary<ClientMethod, IDictionary<string, object>>();
12+
13+
public ClientMethod CurrentView { get; set; } = ClientMethod.Fluent;
14+
public ClientMethod[] Views { get; } = new[] { ClientMethod.Fluent, ClientMethod.FluentAsync, ClientMethod.Initializer, ClientMethod.InitializerAsync };
15+
16+
public string Value => this[CurrentView];
17+
public T ExtendedValue<T>(string key) where T : class => this.ExtendedValues[CurrentView][key] as T;
18+
public void ExtendedValue<T>(string key, T value) where T : class => this.ExtendedValues[CurrentView][key] = value;
19+
20+
public CallUniqueValues()
21+
{
22+
this.Add(ClientMethod.Fluent, this.UniqueValue);
23+
this.Add(ClientMethod.FluentAsync, this.UniqueValue);
24+
this.Add(ClientMethod.Initializer, this.UniqueValue);
25+
this.Add(ClientMethod.InitializerAsync, this.UniqueValue);
26+
27+
this.ExtendedValues.Add(ClientMethod.Fluent, new Dictionary<string, object>());
28+
this.ExtendedValues.Add(ClientMethod.FluentAsync, new Dictionary<string, object>());
29+
this.ExtendedValues.Add(ClientMethod.Initializer, new Dictionary<string, object>());
30+
this.ExtendedValues.Add(ClientMethod.InitializerAsync, new Dictionary<string, object>());
31+
}
32+
}
33+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace Tests.Framework.Integration
2+
{
3+
public enum ClientMethod
4+
{
5+
Fluent,
6+
FluentAsync,
7+
Initializer,
8+
InitializerAsync
9+
}
10+
}

src/Tests/tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# mode either u (unit test), i (integration test) or m (mixed mode)
2-
mode: m
2+
mode: u
33
# the elasticsearch version that should be started
44
# Can be a snapshot version of sonatype or "latest" to get the latest snapshot of sonatype
55
elasticsearch_version: 5.0.0-alpha3

0 commit comments

Comments
 (0)