From 8567b14d17fa24f884125bdd8f41b6c2151b2713 Mon Sep 17 00:00:00 2001 From: Joshua Adams Date: Wed, 13 Aug 2025 10:28:18 +0100 Subject: [PATCH 1/3] Add ClusterBalanceStats Serialization Tests Adds serialization tests for `ClusterBalanceStats.MetricStats` and `ClusterBalanceStats.TierBalanceStats` --- .../allocator/MetricStatsTests.java | 67 ++++++++++ .../allocator/TierBalanceStatsTests.java | 125 ++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100644 server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/MetricStatsTests.java create mode 100644 server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/TierBalanceStatsTests.java diff --git a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/MetricStatsTests.java b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/MetricStatsTests.java new file mode 100644 index 0000000000000..1f88b76607ee0 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/MetricStatsTests.java @@ -0,0 +1,67 @@ +/* + * 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.cluster.routing.allocation.allocator; + +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.io.stream.Writeable; +import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.test.AbstractWireSerializingTestCase; +import org.elasticsearch.xcontent.ToXContent; +import org.elasticsearch.xcontent.XContentBuilder; +import org.elasticsearch.xcontent.XContentFactory; + +import java.io.IOException; +import java.util.Map; + +import static org.hamcrest.Matchers.equalTo; + +public class MetricStatsTests extends AbstractWireSerializingTestCase { + + @Override + protected Writeable.Reader instanceReader() { + return ClusterBalanceStats.MetricStats::readFrom; + } + + @Override + protected ClusterBalanceStats.MetricStats createTestInstance() { + return createRandomMetricStats(); + } + + public static ClusterBalanceStats.MetricStats createRandomMetricStats() { + return new ClusterBalanceStats.MetricStats(randomDouble(), randomDouble(), randomDouble(), randomDouble(), randomDouble()); + } + + @Override + protected ClusterBalanceStats.MetricStats mutateInstance(ClusterBalanceStats.MetricStats instance) throws IOException { + return createTestInstance(); + } + + public void testToXContent() throws IOException { + // Given + double total = randomDouble(); + double min = randomDouble(); + double max = randomDouble(); + double average = randomDouble(); + double stdDev = randomDouble(); + ClusterBalanceStats.MetricStats stats = new ClusterBalanceStats.MetricStats(total, min, max, average, stdDev); + + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder = stats.toXContent(builder, ToXContent.EMPTY_PARAMS); + // Convert to map for easy assertions + Map map = XContentHelper.convertToMap(BytesReference.bytes(builder), false, builder.contentType()).v2(); + + // Then + assertThat(map.get("total"), equalTo(total)); + assertThat(map.get("min"), equalTo(min)); + assertThat(map.get("max"), equalTo(max)); + assertThat(map.get("average"), equalTo(average)); + assertThat(map.get("std_dev"), equalTo(stdDev)); + } +} diff --git a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/TierBalanceStatsTests.java b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/TierBalanceStatsTests.java new file mode 100644 index 0000000000000..e9a3513ea93fa --- /dev/null +++ b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/TierBalanceStatsTests.java @@ -0,0 +1,125 @@ +/* + * 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.cluster.routing.allocation.allocator; + +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.io.stream.Writeable; +import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.test.AbstractWireSerializingTestCase; +import org.elasticsearch.xcontent.ToXContent; +import org.elasticsearch.xcontent.XContentBuilder; +import org.elasticsearch.xcontent.XContentFactory; + +import java.io.IOException; +import java.util.Map; + +import static org.elasticsearch.cluster.routing.allocation.allocator.MetricStatsTests.createRandomMetricStats; +import static org.hamcrest.Matchers.containsInAnyOrder; + +public class TierBalanceStatsTests extends AbstractWireSerializingTestCase { + + @Override + protected Writeable.Reader instanceReader() { + return ClusterBalanceStats.TierBalanceStats::readFrom; + } + + @Override + protected ClusterBalanceStats.TierBalanceStats createTestInstance() { + return createRandomTierBalanceStats(); + } + + private ClusterBalanceStats.TierBalanceStats createRandomTierBalanceStats() { + return new ClusterBalanceStats.TierBalanceStats( + createRandomMetricStats(), + createRandomMetricStats(), + createRandomMetricStats(), + createRandomMetricStats(), + createRandomMetricStats() + ); + } + + @Override + protected ClusterBalanceStats.TierBalanceStats mutateInstance(ClusterBalanceStats.TierBalanceStats instance) throws IOException { + return createTestInstance(); + } + + @SuppressWarnings("unchecked") + public void testToXContent() throws IOException { + // Given + ClusterBalanceStats.MetricStats shardCount = createRandomMetricStats(); + ClusterBalanceStats.MetricStats undesiredShardAllocations = createRandomMetricStats(); + ClusterBalanceStats.MetricStats forecastWriteLoad = createRandomMetricStats(); + ClusterBalanceStats.MetricStats forecastDiskUsage = createRandomMetricStats(); + ClusterBalanceStats.MetricStats actualDiskUsage = createRandomMetricStats(); + ClusterBalanceStats.TierBalanceStats tierBalanceStats = new ClusterBalanceStats.TierBalanceStats( + shardCount, + undesiredShardAllocations, + forecastWriteLoad, + forecastDiskUsage, + actualDiskUsage + ); + + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder = tierBalanceStats.toXContent(builder, ToXContent.EMPTY_PARAMS); + // Convert to map for easy assertions + Map map = XContentHelper.convertToMap(BytesReference.bytes(builder), false, builder.contentType()).v2(); + + assertThat( + map.keySet(), + containsInAnyOrder( + "shard_count", + "undesired_shard_allocation_count", + "forecast_write_load", + "forecast_disk_usage", + "actual_disk_usage" + ) + ); + + Map shardCountStats = (Map) map.get("shard_count"); + assertThat(shardCountStats.keySet(), containsInAnyOrder("total", "average", "min", "max", "std_dev")); + assertEquals(shardCountStats.get("total"), shardCount.total()); + assertEquals(shardCountStats.get("average"), shardCount.average()); + assertEquals(shardCountStats.get("min"), shardCount.min()); + assertEquals(shardCountStats.get("max"), shardCount.max()); + assertEquals(shardCountStats.get("std_dev"), shardCount.stdDev()); + + Map undesiredShardAllocationCountStats = (Map) map.get("undesired_shard_allocation_count"); + assertThat(undesiredShardAllocationCountStats.keySet(), containsInAnyOrder("total", "average", "min", "max", "std_dev")); + assertEquals(undesiredShardAllocationCountStats.get("total"), undesiredShardAllocations.total()); + assertEquals(undesiredShardAllocationCountStats.get("average"), undesiredShardAllocations.average()); + assertEquals(undesiredShardAllocationCountStats.get("min"), undesiredShardAllocations.min()); + assertEquals(undesiredShardAllocationCountStats.get("max"), undesiredShardAllocations.max()); + assertEquals(undesiredShardAllocationCountStats.get("std_dev"), undesiredShardAllocations.stdDev()); + + Map forecastWriteLoadStats = (Map) map.get("forecast_write_load"); + assertThat(forecastWriteLoadStats.keySet(), containsInAnyOrder("total", "average", "min", "max", "std_dev")); + assertEquals(forecastWriteLoadStats.get("total"), forecastWriteLoad.total()); + assertEquals(forecastWriteLoadStats.get("average"), forecastWriteLoad.average()); + assertEquals(forecastWriteLoadStats.get("min"), forecastWriteLoad.min()); + assertEquals(forecastWriteLoadStats.get("max"), forecastWriteLoad.max()); + assertEquals(forecastWriteLoadStats.get("std_dev"), forecastWriteLoad.stdDev()); + + Map forecastDiskUsageStats = (Map) map.get("forecast_disk_usage"); + assertThat(forecastDiskUsageStats.keySet(), containsInAnyOrder("total", "average", "min", "max", "std_dev")); + assertEquals(forecastDiskUsageStats.get("total"), forecastDiskUsage.total()); + assertEquals(forecastDiskUsageStats.get("average"), forecastDiskUsage.average()); + assertEquals(forecastDiskUsageStats.get("min"), forecastDiskUsage.min()); + assertEquals(forecastDiskUsageStats.get("max"), forecastDiskUsage.max()); + assertEquals(forecastDiskUsageStats.get("std_dev"), forecastDiskUsage.stdDev()); + + Map actualDiskUsageStats = (Map) map.get("actual_disk_usage"); + assertThat(actualDiskUsageStats.keySet(), containsInAnyOrder("total", "average", "min", "max", "std_dev")); + assertEquals(actualDiskUsageStats.get("total"), actualDiskUsage.total()); + assertEquals(actualDiskUsageStats.get("average"), actualDiskUsage.average()); + assertEquals(actualDiskUsageStats.get("min"), actualDiskUsage.min()); + assertEquals(actualDiskUsageStats.get("max"), actualDiskUsage.max()); + assertEquals(actualDiskUsageStats.get("std_dev"), actualDiskUsage.stdDev()); + } +} From 6ad7be01e8c17169c9bb58fac45958829845d745 Mon Sep 17 00:00:00 2001 From: Joshua Adams Date: Mon, 18 Aug 2025 12:19:20 +0100 Subject: [PATCH 2/3] Remove unnecessary comments --- .../cluster/routing/allocation/allocator/MetricStatsTests.java | 2 -- .../routing/allocation/allocator/TierBalanceStatsTests.java | 1 - 2 files changed, 3 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/MetricStatsTests.java b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/MetricStatsTests.java index 1f88b76607ee0..b26787bd7e40f 100644 --- a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/MetricStatsTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/MetricStatsTests.java @@ -44,7 +44,6 @@ protected ClusterBalanceStats.MetricStats mutateInstance(ClusterBalanceStats.Met } public void testToXContent() throws IOException { - // Given double total = randomDouble(); double min = randomDouble(); double max = randomDouble(); @@ -57,7 +56,6 @@ public void testToXContent() throws IOException { // Convert to map for easy assertions Map map = XContentHelper.convertToMap(BytesReference.bytes(builder), false, builder.contentType()).v2(); - // Then assertThat(map.get("total"), equalTo(total)); assertThat(map.get("min"), equalTo(min)); assertThat(map.get("max"), equalTo(max)); diff --git a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/TierBalanceStatsTests.java b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/TierBalanceStatsTests.java index e9a3513ea93fa..cba1d5685b981 100644 --- a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/TierBalanceStatsTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/TierBalanceStatsTests.java @@ -52,7 +52,6 @@ protected ClusterBalanceStats.TierBalanceStats mutateInstance(ClusterBalanceStat @SuppressWarnings("unchecked") public void testToXContent() throws IOException { - // Given ClusterBalanceStats.MetricStats shardCount = createRandomMetricStats(); ClusterBalanceStats.MetricStats undesiredShardAllocations = createRandomMetricStats(); ClusterBalanceStats.MetricStats forecastWriteLoad = createRandomMetricStats(); From 3d5bde7d1017648441bbfec29ade8ace4e655c72 Mon Sep 17 00:00:00 2001 From: Joshua Adams Date: Thu, 21 Aug 2025 09:28:15 +0100 Subject: [PATCH 3/3] Addresses nit comments --- .../allocator/MetricStatsTests.java | 17 ++--- .../allocator/TierBalanceStatsTests.java | 63 ++++++++----------- 2 files changed, 32 insertions(+), 48 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/MetricStatsTests.java b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/MetricStatsTests.java index b26787bd7e40f..74090c55cb11f 100644 --- a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/MetricStatsTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/MetricStatsTests.java @@ -44,22 +44,17 @@ protected ClusterBalanceStats.MetricStats mutateInstance(ClusterBalanceStats.Met } public void testToXContent() throws IOException { - double total = randomDouble(); - double min = randomDouble(); - double max = randomDouble(); - double average = randomDouble(); - double stdDev = randomDouble(); - ClusterBalanceStats.MetricStats stats = new ClusterBalanceStats.MetricStats(total, min, max, average, stdDev); + ClusterBalanceStats.MetricStats stats = createRandomMetricStats(); XContentBuilder builder = XContentFactory.jsonBuilder(); builder = stats.toXContent(builder, ToXContent.EMPTY_PARAMS); // Convert to map for easy assertions Map map = XContentHelper.convertToMap(BytesReference.bytes(builder), false, builder.contentType()).v2(); - assertThat(map.get("total"), equalTo(total)); - assertThat(map.get("min"), equalTo(min)); - assertThat(map.get("max"), equalTo(max)); - assertThat(map.get("average"), equalTo(average)); - assertThat(map.get("std_dev"), equalTo(stdDev)); + assertThat(map.get("total"), equalTo(stats.total())); + assertThat(map.get("min"), equalTo(stats.min())); + assertThat(map.get("max"), equalTo(stats.max())); + assertThat(map.get("average"), equalTo(stats.average())); + assertThat(map.get("std_dev"), equalTo(stats.stdDev())); } } diff --git a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/TierBalanceStatsTests.java b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/TierBalanceStatsTests.java index cba1d5685b981..201494839103f 100644 --- a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/TierBalanceStatsTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/TierBalanceStatsTests.java @@ -52,18 +52,7 @@ protected ClusterBalanceStats.TierBalanceStats mutateInstance(ClusterBalanceStat @SuppressWarnings("unchecked") public void testToXContent() throws IOException { - ClusterBalanceStats.MetricStats shardCount = createRandomMetricStats(); - ClusterBalanceStats.MetricStats undesiredShardAllocations = createRandomMetricStats(); - ClusterBalanceStats.MetricStats forecastWriteLoad = createRandomMetricStats(); - ClusterBalanceStats.MetricStats forecastDiskUsage = createRandomMetricStats(); - ClusterBalanceStats.MetricStats actualDiskUsage = createRandomMetricStats(); - ClusterBalanceStats.TierBalanceStats tierBalanceStats = new ClusterBalanceStats.TierBalanceStats( - shardCount, - undesiredShardAllocations, - forecastWriteLoad, - forecastDiskUsage, - actualDiskUsage - ); + ClusterBalanceStats.TierBalanceStats tierBalanceStats = createRandomTierBalanceStats(); XContentBuilder builder = XContentFactory.jsonBuilder(); builder = tierBalanceStats.toXContent(builder, ToXContent.EMPTY_PARAMS); @@ -83,42 +72,42 @@ public void testToXContent() throws IOException { Map shardCountStats = (Map) map.get("shard_count"); assertThat(shardCountStats.keySet(), containsInAnyOrder("total", "average", "min", "max", "std_dev")); - assertEquals(shardCountStats.get("total"), shardCount.total()); - assertEquals(shardCountStats.get("average"), shardCount.average()); - assertEquals(shardCountStats.get("min"), shardCount.min()); - assertEquals(shardCountStats.get("max"), shardCount.max()); - assertEquals(shardCountStats.get("std_dev"), shardCount.stdDev()); + assertEquals(shardCountStats.get("total"), tierBalanceStats.shardCount().total()); + assertEquals(shardCountStats.get("average"), tierBalanceStats.shardCount().average()); + assertEquals(shardCountStats.get("min"), tierBalanceStats.shardCount().min()); + assertEquals(shardCountStats.get("max"), tierBalanceStats.shardCount().max()); + assertEquals(shardCountStats.get("std_dev"), tierBalanceStats.shardCount().stdDev()); Map undesiredShardAllocationCountStats = (Map) map.get("undesired_shard_allocation_count"); assertThat(undesiredShardAllocationCountStats.keySet(), containsInAnyOrder("total", "average", "min", "max", "std_dev")); - assertEquals(undesiredShardAllocationCountStats.get("total"), undesiredShardAllocations.total()); - assertEquals(undesiredShardAllocationCountStats.get("average"), undesiredShardAllocations.average()); - assertEquals(undesiredShardAllocationCountStats.get("min"), undesiredShardAllocations.min()); - assertEquals(undesiredShardAllocationCountStats.get("max"), undesiredShardAllocations.max()); - assertEquals(undesiredShardAllocationCountStats.get("std_dev"), undesiredShardAllocations.stdDev()); + assertEquals(undesiredShardAllocationCountStats.get("total"), tierBalanceStats.undesiredShardAllocations().total()); + assertEquals(undesiredShardAllocationCountStats.get("average"), tierBalanceStats.undesiredShardAllocations().average()); + assertEquals(undesiredShardAllocationCountStats.get("min"), tierBalanceStats.undesiredShardAllocations().min()); + assertEquals(undesiredShardAllocationCountStats.get("max"), tierBalanceStats.undesiredShardAllocations().max()); + assertEquals(undesiredShardAllocationCountStats.get("std_dev"), tierBalanceStats.undesiredShardAllocations().stdDev()); Map forecastWriteLoadStats = (Map) map.get("forecast_write_load"); assertThat(forecastWriteLoadStats.keySet(), containsInAnyOrder("total", "average", "min", "max", "std_dev")); - assertEquals(forecastWriteLoadStats.get("total"), forecastWriteLoad.total()); - assertEquals(forecastWriteLoadStats.get("average"), forecastWriteLoad.average()); - assertEquals(forecastWriteLoadStats.get("min"), forecastWriteLoad.min()); - assertEquals(forecastWriteLoadStats.get("max"), forecastWriteLoad.max()); - assertEquals(forecastWriteLoadStats.get("std_dev"), forecastWriteLoad.stdDev()); + assertEquals(forecastWriteLoadStats.get("total"), tierBalanceStats.forecastWriteLoad().total()); + assertEquals(forecastWriteLoadStats.get("average"), tierBalanceStats.forecastWriteLoad().average()); + assertEquals(forecastWriteLoadStats.get("min"), tierBalanceStats.forecastWriteLoad().min()); + assertEquals(forecastWriteLoadStats.get("max"), tierBalanceStats.forecastWriteLoad().max()); + assertEquals(forecastWriteLoadStats.get("std_dev"), tierBalanceStats.forecastWriteLoad().stdDev()); Map forecastDiskUsageStats = (Map) map.get("forecast_disk_usage"); assertThat(forecastDiskUsageStats.keySet(), containsInAnyOrder("total", "average", "min", "max", "std_dev")); - assertEquals(forecastDiskUsageStats.get("total"), forecastDiskUsage.total()); - assertEquals(forecastDiskUsageStats.get("average"), forecastDiskUsage.average()); - assertEquals(forecastDiskUsageStats.get("min"), forecastDiskUsage.min()); - assertEquals(forecastDiskUsageStats.get("max"), forecastDiskUsage.max()); - assertEquals(forecastDiskUsageStats.get("std_dev"), forecastDiskUsage.stdDev()); + assertEquals(forecastDiskUsageStats.get("total"), tierBalanceStats.forecastShardSize().total()); + assertEquals(forecastDiskUsageStats.get("average"), tierBalanceStats.forecastShardSize().average()); + assertEquals(forecastDiskUsageStats.get("min"), tierBalanceStats.forecastShardSize().min()); + assertEquals(forecastDiskUsageStats.get("max"), tierBalanceStats.forecastShardSize().max()); + assertEquals(forecastDiskUsageStats.get("std_dev"), tierBalanceStats.forecastShardSize().stdDev()); Map actualDiskUsageStats = (Map) map.get("actual_disk_usage"); assertThat(actualDiskUsageStats.keySet(), containsInAnyOrder("total", "average", "min", "max", "std_dev")); - assertEquals(actualDiskUsageStats.get("total"), actualDiskUsage.total()); - assertEquals(actualDiskUsageStats.get("average"), actualDiskUsage.average()); - assertEquals(actualDiskUsageStats.get("min"), actualDiskUsage.min()); - assertEquals(actualDiskUsageStats.get("max"), actualDiskUsage.max()); - assertEquals(actualDiskUsageStats.get("std_dev"), actualDiskUsage.stdDev()); + assertEquals(actualDiskUsageStats.get("total"), tierBalanceStats.actualShardSize().total()); + assertEquals(actualDiskUsageStats.get("average"), tierBalanceStats.actualShardSize().average()); + assertEquals(actualDiskUsageStats.get("min"), tierBalanceStats.actualShardSize().min()); + assertEquals(actualDiskUsageStats.get("max"), tierBalanceStats.actualShardSize().max()); + assertEquals(actualDiskUsageStats.get("std_dev"), tierBalanceStats.actualShardSize().stdDev()); } }