
org.elasticsearch.test.EnumSerializationTestUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of framework Show documentation
Show all versions of framework Show documentation
Elasticsearch subproject :test:framework
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
package org.elasticsearch.test;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import java.io.IOException;
import static org.elasticsearch.test.ESTestCase.assertEquals;
/**
* Enum serialization via {@link StreamOutput#writeEnum} and {@link StreamInput#readEnum(Class)} uses the enum value's ordinal on the wire.
* Reordering the values in an enum, or adding a new value, will change the ordinals and is therefore a wire protocol change, but it's easy
* to miss this fact in the context of a larger commit. To protect against this trap, any enums that we send over the wire should have a
* test that uses {@link #assertEnumSerialization} to assert a fixed mapping between ordinals and values. That way, a change to the ordinals
* will require a test change, and thus some thought about BwC.
*/
public class EnumSerializationTestUtils {
private EnumSerializationTestUtils() {/* no instances */}
/**
* Assert that the enum constants of the given class are exactly the ones passed in explicitly as arguments, which fixes its wire
* protocol when using {@link StreamOutput#writeEnum} and {@link StreamInput#readEnum(Class)}.
*
* @param value0 The enum constant with ordinal {@code 0}, passed as a separate argument to avoid prevent callers just lazily using
* {@code EnumClass.values()} to pass the values of the enum, which would negate the point of this test.
* @param values The remaining enum constants, in ordinal order.
*/
@SafeVarargs
public static > void assertEnumSerialization(Class clazz, E value0, E... values) {
final var enumConstants = clazz.getEnumConstants();
assertEquals(clazz.getCanonicalName(), enumConstants.length, values.length + 1);
for (var ordinal = 0; ordinal < values.length + 1; ordinal++) {
final var enumValue = ordinal == 0 ? value0 : values[ordinal - 1];
final var description = clazz.getCanonicalName() + "[" + ordinal + "]";
assertEquals(description, enumConstants[ordinal], enumValue);
try (var out = new BytesStreamOutput(1)) {
out.writeEnum(enumValue);
try (var in = out.bytes().streamInput()) {
assertEquals(description, ordinal, in.readVInt());
}
} catch (IOException e) {
ESTestCase.fail(e);
}
try (var out = new BytesStreamOutput(1)) {
out.writeVInt(ordinal);
try (var in = out.bytes().streamInput()) {
assertEquals(description, enumValue, in.readEnum(clazz));
}
} catch (IOException e) {
ESTestCase.fail(e);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy