Skip to content

Commit

Permalink
[TEST] share code between streamable/writeable/xcontent base test cla…
Browse files Browse the repository at this point in the history
…sses (#28785)

Today we have two test base classes that have a lot in common when it comes to testing wire and xcontent serialization: `AbstractSerializingTestCase` and `AbstractXContentStreamableTestCase`. There are subtle differences though between the two, in the way they work, what can be overridden and features that they support (e.g. insertion of random fields).

This commit introduces a new base class called `AbstractWireTestCase` which holds all of the serialization test code in common between `Streamable` and `Writeable`. It has two minimal subclasses called `AbstractWireSerializingTestCase` and `AbstractStreamableTestCase` which are specialized for `Writeable` and `Streamable`.

This commit also introduces a new test class called `AbstractXContentTestCase` for all of the xContent testing, which holds a testFromXContent method for parsing and rendering to xContent. This one can be delegated to from the existing `AbstractStreamableXContentTestCase` and `AbstractSerializingTestCase` so that we avoid code duplicate as much as possible and all these base classes offer the same functionalities in the same way. Having this last base class decoupled from the serialization testing may also help with the REST high-level client testing, as there are some classes where it's hard to implement equals/hashcode and this makes it possible to override `assertEqualInstances` for custom equality comparisons (also this base class doesn't require implementing equals/hashcode as it doesn't test such methods.
  • Loading branch information
javanna authored Feb 23, 2018
1 parent 3728c50 commit cd3d9c9
Show file tree
Hide file tree
Showing 27 changed files with 523 additions and 488 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.elasticsearch.common;

/**
* A {@link java.util.function.BiFunction}-like interface which allows throwing checked exceptions.
*/
@FunctionalInterface
public interface CheckedBiFunction<T, U, R, E extends Exception> {
R apply(T t, U u) throws E;
}
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,8 @@ public EnumSet<MetaData.XContentContext> context() {
return ALL_CONTEXTS;
}

public static PersistentTasksCustomMetaData fromXContent(XContentParser parser) throws IOException {
return PERSISTENT_TASKS_PARSER.parse(parser, null).build();
public static PersistentTasksCustomMetaData fromXContent(XContentParser parser) {
return PERSISTENT_TASKS_PARSER.apply(parser, null).build();
}

@SuppressWarnings("unchecked")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ public static StoredScriptSource parse(BytesReference content, XContentType xCon
* Note that the "source" parameter can also handle template parsing including from
* a complex JSON object.
*/
public static StoredScriptSource fromXContent(XContentParser parser) throws IOException {
public static StoredScriptSource fromXContent(XContentParser parser) {
return PARSER.apply(parser, null).build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,8 @@ public void writeTo(StreamOutput out) throws IOException {
}
}

public static CollapseBuilder fromXContent(XContentParser parser) throws IOException {
CollapseBuilder builder = PARSER.parse(parser, new CollapseBuilder(), null);
return builder;
public static CollapseBuilder fromXContent(XContentParser parser) {
return PARSER.apply(parser, null);
}

// for object parser only
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import org.elasticsearch.common.settings.Settings.Builder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
import org.elasticsearch.test.EqualsHashCodeTestUtils;

import java.util.List;
import java.util.Set;
Expand All @@ -39,23 +38,21 @@ protected ClusterUpdateSettingsResponse doParseInstance(XContentParser parser) {
}

@Override
protected EqualsHashCodeTestUtils.MutateFunction<ClusterUpdateSettingsResponse> getMutateFunction() {
return response -> {
int i = randomIntBetween(0, 2);
switch(i) {
case 0:
return new ClusterUpdateSettingsResponse(response.isAcknowledged() == false,
response.transientSettings, response.persistentSettings);
case 1:
return new ClusterUpdateSettingsResponse(response.isAcknowledged(), mutateSettings(response.transientSettings),
response.persistentSettings);
case 2:
return new ClusterUpdateSettingsResponse(response.isAcknowledged(), response.transientSettings,
mutateSettings(response.persistentSettings));
default:
throw new UnsupportedOperationException();
}
};
protected ClusterUpdateSettingsResponse mutateInstance(ClusterUpdateSettingsResponse response) {
int i = randomIntBetween(0, 2);
switch(i) {
case 0:
return new ClusterUpdateSettingsResponse(response.isAcknowledged() == false,
response.transientSettings, response.persistentSettings);
case 1:
return new ClusterUpdateSettingsResponse(response.isAcknowledged(), mutateSettings(response.transientSettings),
response.persistentSettings);
case 2:
return new ClusterUpdateSettingsResponse(response.isAcknowledged(), response.transientSettings,
mutateSettings(response.persistentSettings));
default:
throw new UnsupportedOperationException();
}
}

private static Settings mutateSettings(Settings settings) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
import org.elasticsearch.test.EqualsHashCodeTestUtils;

public class IndicesAliasesResponseTests extends AbstractStreamableXContentTestCase<IndicesAliasesResponse> {

Expand All @@ -41,7 +40,7 @@ protected IndicesAliasesResponse createBlankInstance() {
}

@Override
protected EqualsHashCodeTestUtils.MutateFunction<IndicesAliasesResponse> getMutateFunction() {
return response -> new IndicesAliasesResponse(response.isAcknowledged() == false);
protected IndicesAliasesResponse mutateInstance(IndicesAliasesResponse response) {
return new IndicesAliasesResponse(response.isAcknowledged() == false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
import org.elasticsearch.test.EqualsHashCodeTestUtils;

public class CloseIndexResponseTests extends AbstractStreamableXContentTestCase<CloseIndexResponse> {

Expand All @@ -41,7 +40,7 @@ protected CloseIndexResponse createBlankInstance() {
}

@Override
protected EqualsHashCodeTestUtils.MutateFunction<CloseIndexResponse> getMutateFunction() {
return response -> new CloseIndexResponse(response.isAcknowledged() == false);
protected CloseIndexResponse mutateInstance(CloseIndexResponse response) {
return new CloseIndexResponse(response.isAcknowledged() == false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
import org.elasticsearch.test.EqualsHashCodeTestUtils;

import java.io.IOException;

Expand All @@ -46,23 +45,21 @@ protected CreateIndexResponse createBlankInstance() {
}

@Override
protected EqualsHashCodeTestUtils.MutateFunction<CreateIndexResponse> getMutateFunction() {
return response -> {
protected CreateIndexResponse mutateInstance(CreateIndexResponse response) {
if (randomBoolean()) {
if (randomBoolean()) {
if (randomBoolean()) {
boolean acknowledged = response.isAcknowledged() == false;
boolean shardsAcknowledged = acknowledged && response.isShardsAcknowledged();
return new CreateIndexResponse(acknowledged, shardsAcknowledged, response.index());
} else {
boolean shardsAcknowledged = response.isShardsAcknowledged() == false;
boolean acknowledged = shardsAcknowledged || response.isAcknowledged();
return new CreateIndexResponse(acknowledged, shardsAcknowledged, response.index());
}
boolean acknowledged = response.isAcknowledged() == false;
boolean shardsAcknowledged = acknowledged && response.isShardsAcknowledged();
return new CreateIndexResponse(acknowledged, shardsAcknowledged, response.index());
} else {
return new CreateIndexResponse(response.isAcknowledged(), response.isShardsAcknowledged(),
response.index() + randomAlphaOfLengthBetween(2, 5));
boolean shardsAcknowledged = response.isShardsAcknowledged() == false;
boolean acknowledged = shardsAcknowledged || response.isAcknowledged();
return new CreateIndexResponse(acknowledged, shardsAcknowledged, response.index());
}
};
} else {
return new CreateIndexResponse(response.isAcknowledged(), response.isShardsAcknowledged(),
response.index() + randomAlphaOfLengthBetween(2, 5));
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
import org.elasticsearch.test.EqualsHashCodeTestUtils;

public class DeleteIndexResponseTests extends AbstractStreamableXContentTestCase<DeleteIndexResponse> {

Expand All @@ -48,7 +47,7 @@ protected DeleteIndexResponse createBlankInstance() {
}

@Override
protected EqualsHashCodeTestUtils.MutateFunction<DeleteIndexResponse> getMutateFunction() {
return response -> new DeleteIndexResponse(response.isAcknowledged() == false);
protected DeleteIndexResponse mutateInstance(DeleteIndexResponse response) {
return new DeleteIndexResponse(response.isAcknowledged() == false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
import org.elasticsearch.test.EqualsHashCodeTestUtils;

public class PutMappingResponseTests extends AbstractStreamableXContentTestCase<PutMappingResponse> {

Expand All @@ -48,7 +47,7 @@ protected PutMappingResponse createBlankInstance() {
}

@Override
protected EqualsHashCodeTestUtils.MutateFunction<PutMappingResponse> getMutateFunction() {
return response -> new PutMappingResponse(response.isAcknowledged() == false);
protected PutMappingResponse mutateInstance(PutMappingResponse response) {
return new PutMappingResponse(response.isAcknowledged() == false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
import org.elasticsearch.test.EqualsHashCodeTestUtils;

public class OpenIndexResponseTests extends AbstractStreamableXContentTestCase<OpenIndexResponse> {

Expand All @@ -43,17 +42,15 @@ protected OpenIndexResponse createBlankInstance() {
}

@Override
protected EqualsHashCodeTestUtils.MutateFunction<OpenIndexResponse> getMutateFunction() {
return response -> {
if (randomBoolean()) {
boolean acknowledged = response.isAcknowledged() == false;
boolean shardsAcknowledged = acknowledged && response.isShardsAcknowledged();
return new OpenIndexResponse(acknowledged, shardsAcknowledged);
} else {
boolean shardsAcknowledged = response.isShardsAcknowledged() == false;
boolean acknowledged = shardsAcknowledged || response.isAcknowledged();
return new OpenIndexResponse(acknowledged, shardsAcknowledged);
}
};
protected OpenIndexResponse mutateInstance(OpenIndexResponse response) {
if (randomBoolean()) {
boolean acknowledged = response.isAcknowledged() == false;
boolean shardsAcknowledged = acknowledged && response.isShardsAcknowledged();
return new OpenIndexResponse(acknowledged, shardsAcknowledged);
} else {
boolean shardsAcknowledged = response.isShardsAcknowledged() == false;
boolean acknowledged = shardsAcknowledged || response.isAcknowledged();
return new OpenIndexResponse(acknowledged, shardsAcknowledged);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
import org.elasticsearch.test.EqualsHashCodeTestUtils;

import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -75,58 +74,56 @@ protected Predicate<String> getRandomFieldsExcludeFilter() {
}

@Override
protected EqualsHashCodeTestUtils.MutateFunction<RolloverResponse> getMutateFunction() {
return response -> {
int i = randomIntBetween(0, 6);
switch(i) {
case 0:
return new RolloverResponse(response.getOldIndex() + randomAlphaOfLengthBetween(2, 5),
response.getNewIndex(), response.getConditionStatus(), response.isDryRun(), response.isRolledOver(),
response.isAcknowledged(), response.isShardsAcknowledged());
case 1:
return new RolloverResponse(response.getOldIndex(), response.getNewIndex() + randomAlphaOfLengthBetween(2, 5),
response.getConditionStatus(), response.isDryRun(), response.isRolledOver(),
response.isAcknowledged(), response.isShardsAcknowledged());
case 2:
Map<String, Boolean> results;
if (response.getConditionStatus().isEmpty()) {
results = randomResults(false);
} else {
results = new HashMap<>(response.getConditionStatus().size());
List<String> keys = randomSubsetOf(randomIntBetween(1, response.getConditionStatus().size()),
response.getConditionStatus().keySet());
for (Map.Entry<String, Boolean> entry : response.getConditionStatus().entrySet()) {
boolean value = keys.contains(entry.getKey()) ? entry.getValue() == false : entry.getValue();
results.put(entry.getKey(), value);
}
protected RolloverResponse mutateInstance(RolloverResponse response) {
int i = randomIntBetween(0, 6);
switch(i) {
case 0:
return new RolloverResponse(response.getOldIndex() + randomAlphaOfLengthBetween(2, 5),
response.getNewIndex(), response.getConditionStatus(), response.isDryRun(), response.isRolledOver(),
response.isAcknowledged(), response.isShardsAcknowledged());
case 1:
return new RolloverResponse(response.getOldIndex(), response.getNewIndex() + randomAlphaOfLengthBetween(2, 5),
response.getConditionStatus(), response.isDryRun(), response.isRolledOver(),
response.isAcknowledged(), response.isShardsAcknowledged());
case 2:
Map<String, Boolean> results;
if (response.getConditionStatus().isEmpty()) {
results = randomResults(false);
} else {
results = new HashMap<>(response.getConditionStatus().size());
List<String> keys = randomSubsetOf(randomIntBetween(1, response.getConditionStatus().size()),
response.getConditionStatus().keySet());
for (Map.Entry<String, Boolean> entry : response.getConditionStatus().entrySet()) {
boolean value = keys.contains(entry.getKey()) ? entry.getValue() == false : entry.getValue();
results.put(entry.getKey(), value);
}
return new RolloverResponse(response.getOldIndex(), response.getNewIndex(), results, response.isDryRun(),
response.isRolledOver(), response.isAcknowledged(), response.isShardsAcknowledged());
case 3:
return new RolloverResponse(response.getOldIndex(), response.getNewIndex(),
response.getConditionStatus(), response.isDryRun() == false, response.isRolledOver(),
response.isAcknowledged(), response.isShardsAcknowledged());
case 4:
return new RolloverResponse(response.getOldIndex(), response.getNewIndex(),
response.getConditionStatus(), response.isDryRun(), response.isRolledOver() == false,
response.isAcknowledged(), response.isShardsAcknowledged());
case 5: {
boolean acknowledged = response.isAcknowledged() == false;
boolean shardsAcknowledged = acknowledged && response.isShardsAcknowledged();
return new RolloverResponse(response.getOldIndex(), response.getNewIndex(),
response.getConditionStatus(), response.isDryRun(), response.isRolledOver(),
acknowledged, shardsAcknowledged);
}
case 6: {
boolean shardsAcknowledged = response.isShardsAcknowledged() == false;
boolean acknowledged = shardsAcknowledged || response.isAcknowledged();
return new RolloverResponse(response.getOldIndex(), response.getNewIndex(),
response.getConditionStatus(), response.isDryRun(), response.isRolledOver(),
acknowledged, shardsAcknowledged);
}
default:
throw new UnsupportedOperationException();
return new RolloverResponse(response.getOldIndex(), response.getNewIndex(), results, response.isDryRun(),
response.isRolledOver(), response.isAcknowledged(), response.isShardsAcknowledged());
case 3:
return new RolloverResponse(response.getOldIndex(), response.getNewIndex(),
response.getConditionStatus(), response.isDryRun() == false, response.isRolledOver(),
response.isAcknowledged(), response.isShardsAcknowledged());
case 4:
return new RolloverResponse(response.getOldIndex(), response.getNewIndex(),
response.getConditionStatus(), response.isDryRun(), response.isRolledOver() == false,
response.isAcknowledged(), response.isShardsAcknowledged());
case 5: {
boolean acknowledged = response.isAcknowledged() == false;
boolean shardsAcknowledged = acknowledged && response.isShardsAcknowledged();
return new RolloverResponse(response.getOldIndex(), response.getNewIndex(),
response.getConditionStatus(), response.isDryRun(), response.isRolledOver(),
acknowledged, shardsAcknowledged);
}
case 6: {
boolean shardsAcknowledged = response.isShardsAcknowledged() == false;
boolean acknowledged = shardsAcknowledged || response.isAcknowledged();
return new RolloverResponse(response.getOldIndex(), response.getNewIndex(),
response.getConditionStatus(), response.isDryRun(), response.isRolledOver(),
acknowledged, shardsAcknowledged);
}
};
default:
throw new UnsupportedOperationException();
}
}
}
Loading

0 comments on commit cd3d9c9

Please sign in to comment.