Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
### Removed

### Fixed
- Fixed deserialization failure when OpenSearch returns shard failures without the `primary` field in error responses by upgrading version of `opensearch-api-specification`

### Security

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package org.opensearch.client.opensearch._types;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import jakarta.json.stream.JsonParser;
import java.io.StringReader;
import org.junit.Test;
import org.opensearch.client.json.JsonpMapper;
import org.opensearch.client.json.jackson.JacksonJsonpMapper;

public class ShardFailureTest {

private final JsonpMapper mapper = new JacksonJsonpMapper();

@Test
public void testShardFailureWithPrimaryField() {
String json = "{"
+ "\"shard\": 0,"
+ "\"index\": \"test-index\","
+ "\"node\": \"node-123\","
+ "\"primary\": true,"
+ "\"reason\": {"
+ " \"type\": \"query_shard_exception\","
+ " \"reason\": \"Failed to parse query\""
+ "}"
+ "}";

JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json));
ShardFailure shardFailure = ShardFailure._DESERIALIZER.deserialize(parser, mapper);

assertNotNull(shardFailure);
assertEquals(0, shardFailure.shard());
assertEquals("test-index", shardFailure.index());
assertEquals("node-123", shardFailure.node());
assertNotNull(shardFailure.primary());
assertTrue(shardFailure.primary());
assertNotNull(shardFailure.reason());
assertEquals("query_shard_exception", shardFailure.reason().type());
}

@Test
public void testShardFailureWithoutPrimaryField() {
// This is the real-world case that fails - OpenSearch often omits the "primary" field
String json = "{"
+ "\"shard\": 0,"
+ "\"index\": \"cases-p360\","
+ "\"node\": \"h88XL3ygSy2OxP0Ak-YIdA\","
+ "\"reason\": {"
+ " \"type\": \"query_shard_exception\","
+ " \"reason\": \"Failed to execute query\""
+ "}"
+ "}";

JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json));
ShardFailure shardFailure = ShardFailure._DESERIALIZER.deserialize(parser, mapper);

assertNotNull(shardFailure);
assertEquals(0, shardFailure.shard());
assertEquals("cases-p360", shardFailure.index());
assertEquals("h88XL3ygSy2OxP0Ak-YIdA", shardFailure.node());
// Primary field should be null when not present in JSON
assertNull(shardFailure.primary());
assertNotNull(shardFailure.reason());
assertEquals("query_shard_exception", shardFailure.reason().type());
}

@Test
public void testErrorCauseWithFailedShards() {
// Test a more complete error response with failed_shards array
// This verifies that ErrorCause can be deserialized when it contains
// a failed_shards array with ShardFailure objects missing the primary field
String json = "{"
+ "\"type\": \"search_phase_execution_exception\","
+ "\"reason\": \"all shards failed\","
+ "\"metadata\": {"
+ " \"failed_shards\": ["
+ " {"
+ " \"shard\": 0,"
+ " \"index\": \"test-index\","
+ " \"node\": \"node-1\","
+ " \"reason\": {"
+ " \"type\": \"query_shard_exception\","
+ " \"reason\": \"Parse error\""
+ " }"
+ " }"
+ " ]"
+ "}"
+ "}";

JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json));
ErrorCause errorCause = ErrorCause._DESERIALIZER.deserialize(parser, mapper);

// The main goal is to verify deserialization succeeds without throwing
assertNotNull(errorCause);
assertEquals("search_phase_execution_exception", errorCause.type());
assertEquals("all shards failed", errorCause.reason());
}
}
Loading