Skip to content

Commit 7cfd502

Browse files
committed
Added helper methods to ESRestTestCase for checking warnings in mixed and current-version-only clusters.
This is supported by a new VersionSpecificWarningsHandler class with associated unit test. Closes #36251
1 parent c3a6d19 commit 7cfd502

File tree

3 files changed

+149
-3
lines changed

3 files changed

+149
-3
lines changed

client/rest-high-level/src/test/java/org/elasticsearch/client/ESRestHighLevelClientTestCase.java

+11-3
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,22 @@ protected static RestHighLevelClient highLevelClient() {
7575
*/
7676
protected static <Req, Resp> Resp execute(Req request, SyncMethod<Req, Resp> syncMethod,
7777
AsyncMethod<Req, Resp> asyncMethod) throws IOException {
78+
return execute(request, syncMethod, asyncMethod, RequestOptions.DEFAULT);
79+
}
80+
81+
/**
82+
* Executes the provided request using either the sync method or its async variant, both provided as functions
83+
*/
84+
protected static <Req, Resp> Resp execute(Req request, SyncMethod<Req, Resp> syncMethod,
85+
AsyncMethod<Req, Resp> asyncMethod, RequestOptions options) throws IOException {
7886
if (randomBoolean()) {
79-
return syncMethod.execute(request, RequestOptions.DEFAULT);
87+
return syncMethod.execute(request, options);
8088
} else {
8189
PlainActionFuture<Resp> future = PlainActionFuture.newFuture();
82-
asyncMethod.execute(request, RequestOptions.DEFAULT, future);
90+
asyncMethod.execute(request, options, future);
8391
return future.actionGet();
8492
}
85-
}
93+
}
8694

8795
/**
8896
* Executes the provided request using either the sync method or its async

test/framework/src/main/java/org/elasticsearch/test/rest/ESRestTestCase.java

+67
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@
3030
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksAction;
3131
import org.elasticsearch.client.Request;
3232
import org.elasticsearch.client.RequestOptions;
33+
import org.elasticsearch.client.RequestOptions.Builder;
3334
import org.elasticsearch.client.Response;
3435
import org.elasticsearch.client.ResponseException;
3536
import org.elasticsearch.client.RestClient;
3637
import org.elasticsearch.client.RestClientBuilder;
38+
import org.elasticsearch.client.WarningsHandler;
3739
import org.elasticsearch.common.CheckedRunnable;
3840
import org.elasticsearch.common.Strings;
3941
import org.elasticsearch.common.io.PathUtils;
@@ -69,12 +71,14 @@
6971
import java.security.NoSuchAlgorithmException;
7072
import java.security.cert.CertificateException;
7173
import java.util.ArrayList;
74+
import java.util.Arrays;
7275
import java.util.HashSet;
7376
import java.util.List;
7477
import java.util.Map;
7578
import java.util.Set;
7679
import java.util.TreeSet;
7780
import java.util.concurrent.TimeUnit;
81+
import java.util.function.Consumer;
7882
import java.util.function.Predicate;
7983

8084
import static java.util.Collections.sort;
@@ -177,6 +181,69 @@ public void initClient() throws IOException {
177181
assert hasXPack != null;
178182
assert nodeVersions != null;
179183
}
184+
185+
// Helper class to check warnings in REST responses with sensitivity to versions
186+
// used in the target cluster.
187+
public static class VersionSensitiveWarningsHandler implements WarningsHandler {
188+
Set<String> requiredSameVersionClusterWarnings = new HashSet<>();
189+
Set<String> allowedWarnings = new HashSet<>();
190+
final Set<Version> testNodeVersions;
191+
192+
public VersionSensitiveWarningsHandler(Set<Version> nodeVersions) {
193+
this.testNodeVersions = nodeVersions;
194+
}
195+
196+
/**
197+
* Adds to the set of warnings that are all required in responses if the cluster
198+
* is formed from nodes all running the exact same version as the client.
199+
* @param requiredWarnings a set of required warnings
200+
*/
201+
public void current(String... requiredWarnings) {
202+
requiredSameVersionClusterWarnings.addAll(Arrays.asList(requiredWarnings));
203+
}
204+
205+
/**
206+
* Adds to the set of warnings that are permissible (but not required) when running
207+
* in mixed-version clusters or those that differ in version from the test client.
208+
* @param allowedWarnings optional warnings that will be ignored if received
209+
*/
210+
public void compatible(String... allowedWarnings) {
211+
this.allowedWarnings.addAll(Arrays.asList(allowedWarnings));
212+
}
213+
214+
@Override
215+
public boolean warningsShouldFailRequest(List<String> warnings) {
216+
if (isExclusivelyTargetingCurrentVersionCluster()) {
217+
// absolute equality required in expected and actual.
218+
Set<String> actual = new HashSet<>(warnings);
219+
return false == requiredSameVersionClusterWarnings.equals(actual);
220+
} else {
221+
// Some known warnings can safely be ignored
222+
for (String actualWarning : warnings) {
223+
if (false == allowedWarnings.contains(actualWarning) &&
224+
false == requiredSameVersionClusterWarnings.contains(actualWarning)) {
225+
return true;
226+
}
227+
}
228+
return false;
229+
}
230+
}
231+
232+
private boolean isExclusivelyTargetingCurrentVersionCluster() {
233+
assertFalse("Node versions running in the cluster are missing", testNodeVersions.isEmpty());
234+
return testNodeVersions.size() == 1 &&
235+
testNodeVersions.iterator().next().equals(Version.CURRENT);
236+
}
237+
238+
}
239+
240+
public static RequestOptions expectVersionSpecificWarnings(Consumer<VersionSensitiveWarningsHandler> expectationsSetter) {
241+
Builder builder = RequestOptions.DEFAULT.toBuilder();
242+
VersionSensitiveWarningsHandler warningsHandler = new VersionSensitiveWarningsHandler(nodeVersions);
243+
expectationsSetter.accept(warningsHandler);
244+
builder.setWarningsHandler(warningsHandler);
245+
return builder.build();
246+
}
180247

181248
/**
182249
* Construct an HttpHost from the given host and port
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.test.rest;
21+
22+
import org.elasticsearch.Version;
23+
import org.elasticsearch.client.WarningsHandler;
24+
import org.elasticsearch.test.ESTestCase;
25+
import org.elasticsearch.test.rest.ESRestTestCase.VersionSensitiveWarningsHandler;
26+
27+
import java.io.IOException;
28+
import java.util.Arrays;
29+
import java.util.Collections;
30+
import java.util.HashSet;
31+
import java.util.Set;
32+
import java.util.function.Consumer;
33+
34+
public class VersionSensitiveWarningsHandlerTests extends ESTestCase {
35+
36+
public void testSameVersionCluster() throws IOException {
37+
Set<Version> nodeVersions= new HashSet<>();
38+
nodeVersions.add(Version.CURRENT);
39+
WarningsHandler handler = expectVersionSpecificWarnings(nodeVersions, (v)->{
40+
v.current("expectedCurrent1");
41+
});
42+
assertFalse(handler.warningsShouldFailRequest(Arrays.asList("expectedCurrent1")));
43+
assertTrue(handler.warningsShouldFailRequest(Arrays.asList("expectedCurrent1", "unexpected")));
44+
assertTrue(handler.warningsShouldFailRequest(Collections.emptyList()));
45+
46+
}
47+
public void testMixedVersionCluster() throws IOException {
48+
Set<Version> nodeVersions= new HashSet<>();
49+
nodeVersions.add(Version.CURRENT);
50+
nodeVersions.add(Version.CURRENT.minimumIndexCompatibilityVersion());
51+
WarningsHandler handler = expectVersionSpecificWarnings(nodeVersions, (v)->{
52+
v.current("expectedCurrent1");
53+
v.compatible("Expected legacy warning");
54+
});
55+
assertFalse(handler.warningsShouldFailRequest(Arrays.asList("expectedCurrent1")));
56+
assertFalse(handler.warningsShouldFailRequest(Arrays.asList("Expected legacy warning")));
57+
assertFalse(handler.warningsShouldFailRequest(Arrays.asList("expectedCurrent1", "Expected legacy warning")));
58+
assertFalse(handler.warningsShouldFailRequest(Arrays.asList("Expected legacy warning")));
59+
assertTrue(handler.warningsShouldFailRequest(Arrays.asList("expectedCurrent1", "Unexpected legacy warning")));
60+
assertTrue(handler.warningsShouldFailRequest(Arrays.asList("Unexpected legacy warning")));
61+
assertFalse(handler.warningsShouldFailRequest(Collections.emptyList()));
62+
}
63+
64+
private static WarningsHandler expectVersionSpecificWarnings(Set<Version> nodeVersions,
65+
Consumer<VersionSensitiveWarningsHandler> expectationsSetter) {
66+
//Based on EsRestTestCase.expectVersionSpecificWarnings helper method but without ESRestTestCase dependency
67+
VersionSensitiveWarningsHandler warningsHandler = new VersionSensitiveWarningsHandler(nodeVersions);
68+
expectationsSetter.accept(warningsHandler);
69+
return warningsHandler;
70+
}
71+
}

0 commit comments

Comments
 (0)