diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/async/AsyncExecutionId.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/async/AsyncExecutionId.java index edd24297d4a..6c2f891ff95 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/async/AsyncExecutionId.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/async/AsyncExecutionId.java @@ -92,14 +92,20 @@ public final class AsyncExecutionId { * to retrieve the response of an async execution. */ public static AsyncExecutionId decode(String id) { + final ByteBuffer byteBuffer; + try { + byteBuffer = ByteBuffer.wrap(Base64.getUrlDecoder().decode(id)); + } catch (Exception e) { + throw new IllegalArgumentException("invalid id: [" + id + "]", e); + } final AsyncExecutionId searchId; - try (StreamInput in = new ByteBufferStreamInput(ByteBuffer.wrap(Base64.getUrlDecoder().decode(id)))) { + try (StreamInput in = new ByteBufferStreamInput(byteBuffer)) { searchId = new AsyncExecutionId(in.readString(), new TaskId(in.readString())); if (in.available() > 0) { - throw new IllegalArgumentException("invalid id:[" + id + "]"); + throw new IllegalArgumentException("invalid id: [" + id + "]"); } } catch (IOException e) { - throw new IllegalArgumentException("invalid id:[" + id + "]"); + throw new IllegalArgumentException("invalid id: [" + id + "]", e); } return searchId; } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/async/AsyncExecutionIdTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/async/AsyncExecutionIdTests.java index cff463f14aa..6b02edf0697 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/async/AsyncExecutionIdTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/async/AsyncExecutionIdTests.java @@ -7,25 +7,32 @@ package org.elasticsearch.xpack.core.async; import org.elasticsearch.common.UUIDs; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.tasks.TaskId; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.test.EqualsHashCodeTestUtils; + +import java.io.IOException; +import java.util.Base64; + +import static org.hamcrest.CoreMatchers.instanceOf; public class AsyncExecutionIdTests extends ESTestCase { - public void testEncode() { + public void testEncodeAndDecode() { for (int i = 0; i < 10; i++) { - AsyncExecutionId instance = new AsyncExecutionId(UUIDs.randomBase64UUID(), - new TaskId(randomAlphaOfLengthBetween(5, 20), randomNonNegativeLong())); + AsyncExecutionId instance = randomAsyncId(); String encoded = AsyncExecutionId.encode(instance.getDocId(), instance.getTaskId()); AsyncExecutionId same = AsyncExecutionId.decode(encoded); assertEquals(same, instance); - - AsyncExecutionId mutate = mutate(instance); - assertNotEquals(mutate, instance); - assertNotEquals(mutate, same); } } - private AsyncExecutionId mutate(AsyncExecutionId id) { + private static AsyncExecutionId randomAsyncId() { + return new AsyncExecutionId(UUIDs.randomBase64UUID(), new TaskId(randomAlphaOfLengthBetween(5, 20), randomNonNegativeLong())); + } + + private static AsyncExecutionId mutate(AsyncExecutionId id) { int rand = randomIntBetween(0, 1); switch (rand) { case 0: @@ -39,4 +46,35 @@ public class AsyncExecutionIdTests extends ESTestCase { throw new AssertionError(); } } + + public void testEqualsAndHashcode() { + EqualsHashCodeTestUtils.checkEqualsAndHashCode(randomAsyncId(), + instance -> new AsyncExecutionId(instance.getDocId(), instance.getTaskId()), + AsyncExecutionIdTests::mutate); + } + + public void testDecodeInvalidId() throws IOException { + { + IllegalArgumentException exc = expectThrows(IllegalArgumentException.class, () -> AsyncExecutionId.decode("wrong")); + assertEquals("invalid id: [wrong]", exc.getMessage()); + assertThat(exc.getCause(), instanceOf(IllegalArgumentException.class)); + } + { + IllegalArgumentException exc = expectThrows(IllegalArgumentException.class, + () -> AsyncExecutionId.decode("FmhEOGQtRWVpVGplSXRtOVZudXZCOVEaYjFVZjZNWndRa3V0VmJvNV8tQmRpZzoxMzM=?pretty")); + assertEquals("invalid id: [FmhEOGQtRWVpVGplSXRtOVZudXZCOVEaYjFVZjZNWndRa3V0VmJvNV8tQmRpZzoxMzM=?pretty]", exc.getMessage()); + assertThat(exc.getCause(), instanceOf(IllegalArgumentException.class)); + } + { + try (BytesStreamOutput out = new BytesStreamOutput()) { + out.writeString(randomAlphaOfLengthBetween(5, 10)); + out.writeString(new TaskId(randomAlphaOfLengthBetween(5, 10), randomLong()).toString()); + out.writeString("wrong"); + String encoded = Base64.getUrlEncoder().encodeToString(BytesReference.toBytes(out.bytes())); + IllegalArgumentException exc = expectThrows(IllegalArgumentException.class, () -> AsyncExecutionId.decode(encoded)); + assertEquals("invalid id: [" + encoded + "]", exc.getMessage()); + assertNull(exc.getCause()); + } + } + } }