From 1fb5d4f96e884c650fa7a0a0b1fe565dd1b6811a Mon Sep 17 00:00:00 2001
From: Cesar Munoz <56847527+LikeTheSalad@users.noreply.github.com>
Date: Wed, 18 Jun 2025 09:34:26 +0200
Subject: [PATCH 01/24] Creating WebSocket contract
---
.../websocket/OkHttpWebSocket.java | 67 +++++++++++++++++++
.../connectivity/websocket/WebSocket.java | 14 ++++
.../websocket/WebSocketListener.java | 16 +++++
3 files changed, 97 insertions(+)
create mode 100644 opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/OkHttpWebSocket.java
create mode 100644 opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocket.java
create mode 100644 opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocketListener.java
diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/OkHttpWebSocket.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/OkHttpWebSocket.java
new file mode 100644
index 000000000..e156389ab
--- /dev/null
+++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/OkHttpWebSocket.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.opamp.client.internal.connectivity.websocket;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Response;
+import okio.ByteString;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class OkHttpWebSocket extends okhttp3.WebSocketListener implements WebSocket {
+ private final OkHttpClient client;
+ private final String url;
+ private WebSocketListener listener;
+ private okhttp3.WebSocket webSocket;
+
+ public static OkHttpWebSocket create(String url) {
+ OkHttpClient client = new OkHttpClient();
+ return new OkHttpWebSocket(client, url);
+ }
+
+ public OkHttpWebSocket(OkHttpClient client, String url) {
+ this.client = client;
+ this.url = url;
+ }
+
+ @Override
+ public void start(WebSocketListener listener) {
+ this.listener = listener;
+ okhttp3.Request request = new okhttp3.Request.Builder().url(url).build();
+ webSocket = client.newWebSocket(request, this);
+ }
+
+ @Override
+ public void send(byte[] request) {
+ webSocket.send(ByteString.of(request));
+ }
+
+ @Override
+ public void stop() {
+ webSocket.cancel();
+ }
+
+ @Override
+ public void onOpen(@NotNull okhttp3.WebSocket webSocket, @NotNull Response response) {
+ listener.onOpened(this);
+ }
+
+ @Override
+ public void onClosed(@NotNull okhttp3.WebSocket webSocket, int code, @NotNull String reason) {
+ listener.onClosed(this);
+ }
+
+ @Override
+ public void onFailure(
+ @NotNull okhttp3.WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) {
+ listener.onFailure(this, t);
+ }
+
+ @Override
+ public void onMessage(@NotNull okhttp3.WebSocket webSocket, @NotNull ByteString bytes) {
+ listener.onMessage(this, bytes.toByteArray());
+ }
+}
diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocket.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocket.java
new file mode 100644
index 000000000..00bc3878e
--- /dev/null
+++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocket.java
@@ -0,0 +1,14 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.opamp.client.internal.connectivity.websocket;
+
+public interface WebSocket {
+ void start(WebSocketListener listener);
+
+ void send(byte[] request);
+
+ void stop();
+}
diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocketListener.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocketListener.java
new file mode 100644
index 000000000..ce81d3dd4
--- /dev/null
+++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocketListener.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.opamp.client.internal.connectivity.websocket;
+
+public interface WebSocketListener {
+ void onOpened(WebSocket webSocket);
+
+ void onClosed(WebSocket webSocket);
+
+ void onMessage(WebSocket webSocket, byte[] data);
+
+ void onFailure(WebSocket webSocket, Throwable t);
+}
From 52476f75d0690bbaf4e742189225a80c73bb3802 Mon Sep 17 00:00:00 2001
From: Cesar Munoz <56847527+LikeTheSalad@users.noreply.github.com>
Date: Thu, 19 Jun 2025 17:03:38 +0200
Subject: [PATCH 02/24] Updating tests to reuse tools and adding javadocs
---
.../connectivity/websocket/WebSocket.java | 58 ++++-
.../websocket/WebSocketListener.java | 16 --
.../service/WebSocketRequestService.java | 210 ++++++++++++++++++
.../service/HttpRequestServiceTest.java | 128 ++---------
.../request/service/TestScheduler.java | 115 ++++++++++
5 files changed, 401 insertions(+), 126 deletions(-)
delete mode 100644 opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocketListener.java
create mode 100644 opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java
create mode 100644 opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/TestScheduler.java
diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocket.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocket.java
index 00bc3878e..b40409f98 100644
--- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocket.java
+++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocket.java
@@ -5,10 +5,62 @@
package io.opentelemetry.opamp.client.internal.connectivity.websocket;
+import javax.annotation.Nullable;
+
public interface WebSocket {
- void start(WebSocketListener listener);
+ /**
+ * Starts the websocket connection if it's not yet started or if it has been closed.
+ *
+ * @param listener Will receive events from the websocket connection.
+ */
+ void open(Listener listener);
+
+ /**
+ * Stops the websocket connection if running. Nothing will happen if it's already stopped.
+ *
+ * @param code Status code as defined by Section 7.4 of RFC 6455
+ * @param reason Reason for shutting down, as explained in Section 5.5.1 of RFC
+ * 6455
+ */
+ void close(int code, @Nullable String reason);
+
+ /**
+ * Sends a message via the websocket connection.
+ *
+ * @param request The message payload.
+ * @return {@link Boolean#FALSE} If the message can't get dispatched for any reason, whether the
+ * websocket isn't running, or the connection isn't established, or it's terminated. {@link
+ * Boolean#TRUE} if the message can get sent. Returning {@link Boolean#TRUE} doesn't guarantee
+ * that the message will arrive at the remote peer.
+ */
+ boolean send(byte[] request);
+
+ interface Listener {
+
+ /**
+ * Called when the websocket connection is successfully established with the remote peer and may
+ * start sending messages.
+ */
+ void onOpen();
+
+ /** Called when the connection is terminated and no further messages can get transmitted. */
+ void onClosed();
- void send(byte[] request);
+ /**
+ * Called when receiving a message from the remote peer.
+ *
+ * @param data The payload sent by the remote peer.
+ */
+ void onMessage(byte[] data);
- void stop();
+ /**
+ * Called when the connection is closed or cannot be established due to an error. No messages
+ * can get transmitted after this method is called.
+ *
+ * @param t The error.
+ */
+ void onFailure(Throwable t);
+ }
}
diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocketListener.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocketListener.java
deleted file mode 100644
index ce81d3dd4..000000000
--- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/WebSocketListener.java
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.opamp.client.internal.connectivity.websocket;
-
-public interface WebSocketListener {
- void onOpened(WebSocket webSocket);
-
- void onClosed(WebSocket webSocket);
-
- void onMessage(WebSocket webSocket, byte[] data);
-
- void onFailure(WebSocket webSocket, Throwable t);
-}
diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java
new file mode 100644
index 000000000..18fc9ba13
--- /dev/null
+++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java
@@ -0,0 +1,210 @@
+package io.opentelemetry.opamp.client.internal.request.service;
+
+import com.google.protobuf.CodedInputStream;
+import com.google.protobuf.CodedOutputStream;
+import io.opentelemetry.opamp.client.internal.connectivity.websocket.WebSocket;
+import io.opentelemetry.opamp.client.internal.request.Request;
+import io.opentelemetry.opamp.client.internal.request.delay.AcceptsDelaySuggestion;
+import io.opentelemetry.opamp.client.internal.request.delay.PeriodicDelay;
+import io.opentelemetry.opamp.client.internal.response.OpampServerResponseError;
+import io.opentelemetry.opamp.client.internal.response.Response;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.time.Duration;
+import java.util.Objects;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import opamp.proto.ServerErrorResponse;
+import opamp.proto.ServerErrorResponseType;
+import opamp.proto.ServerToAgent;
+
+public final class WebSocketRequestService implements RequestService, WebSocket.Listener {
+ private final WebSocket webSocket;
+ private final PeriodicDelay periodicRetryDelay;
+ private final AtomicBoolean retryingConnection = new AtomicBoolean(false);
+ private final AtomicBoolean nextRetryScheduled = new AtomicBoolean(false);
+ private final AtomicBoolean hasPendingRequest = new AtomicBoolean(false);
+ private final AtomicBoolean closed = new AtomicBoolean(false);
+ private final ScheduledExecutorService executorService;
+ public static final PeriodicDelay DEFAULT_DELAY_BETWEEN_RETRIES =
+ PeriodicDelay.ofFixedDuration(Duration.ofSeconds(30));
+ @Nullable private Callback callback;
+ @Nullable private Supplier requestSupplier;
+
+ /**
+ * Creates an {@link WebSocketRequestService}.
+ *
+ * @param webSocket The WebSocket implementation.
+ */
+ public static WebSocketRequestService create(WebSocket webSocket) {
+ return create(webSocket, DEFAULT_DELAY_BETWEEN_RETRIES);
+ }
+
+ /**
+ * Creates an {@link WebSocketRequestService}.
+ *
+ * @param webSocket The WebSocket implementation.
+ * @param periodicRetryDelay The time to wait between retries.
+ */
+ public static WebSocketRequestService create(
+ WebSocket webSocket, PeriodicDelay periodicRetryDelay) {
+ return new WebSocketRequestService(
+ webSocket, periodicRetryDelay, Executors.newSingleThreadScheduledExecutor());
+ }
+
+ WebSocketRequestService(
+ WebSocket webSocket,
+ PeriodicDelay periodicRetryDelay,
+ ScheduledExecutorService executorService) {
+ this.webSocket = webSocket;
+ this.periodicRetryDelay = periodicRetryDelay;
+ this.executorService = executorService;
+ }
+
+ @Override
+ public void start(Callback callback, Supplier requestSupplier) {
+ if (closed.get()) {
+ throw new IllegalStateException("This service is already closed");
+ }
+ this.callback = callback;
+ this.requestSupplier = requestSupplier;
+ startConnection();
+ }
+
+ private void startConnection() {
+ webSocket.open(this);
+ }
+
+ @Override
+ public void sendRequest() {
+ try {
+ if (!trySendRequest()) {
+ hasPendingRequest.set(true);
+ }
+ } catch (IOException e) {
+ getCallback().onRequestFailed(e);
+ }
+ }
+
+ private boolean trySendRequest() throws IOException {
+ try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(outputStream);
+ codedOutput.writeUInt64NoTag(0);
+ byte[] payload = getRequest().getAgentToServer().encode();
+ codedOutput.write(payload, 0, payload.length);
+ codedOutput.flush();
+ return webSocket.send(outputStream.toByteArray());
+ }
+ }
+
+ @Nonnull
+ private Request getRequest() {
+ return Objects.requireNonNull(requestSupplier).get();
+ }
+
+ @Override
+ public void stop() {
+ if (closed.compareAndSet(false, true)) {
+ sendRequest();
+ webSocket.close(1000, null);
+ }
+ }
+
+ @Override
+ public void onOpen() {
+ retryingConnection.set(false);
+ getCallback().onConnectionSuccess();
+ if (hasPendingRequest.compareAndSet(true, false)) {
+ sendRequest();
+ }
+ }
+
+ @Override
+ public void onMessage(byte[] data) {
+ try {
+ ServerToAgent serverToAgent = readServerToAgent(data);
+
+ if (serverToAgent.error_response != null) {
+ handleServerError(serverToAgent.error_response);
+ getCallback()
+ .onRequestFailed(
+ new OpampServerResponseError(serverToAgent.error_response.error_message));
+ return;
+ }
+
+ getCallback().onRequestSuccess(Response.create(serverToAgent));
+ } catch (IOException e) {
+ getCallback().onRequestFailed(e);
+ }
+ }
+
+ private static ServerToAgent readServerToAgent(byte[] data) throws IOException {
+ CodedInputStream codedInputStream = CodedInputStream.newInstance(data);
+ codedInputStream.readRawVarint64(); // It moves the read position to the end of the header.
+ int totalBytesRead = codedInputStream.getTotalBytesRead();
+ int payloadSize = data.length - totalBytesRead;
+ byte[] payload = new byte[payloadSize];
+ System.arraycopy(data, totalBytesRead, payload, 0, payloadSize);
+ return ServerToAgent.ADAPTER.decode(payload);
+ }
+
+ private void handleServerError(ServerErrorResponse errorResponse) {
+ if (serverIsUnavailable(errorResponse)) {
+ Duration retryAfter = null;
+
+ if (errorResponse.retry_info != null) {
+ retryAfter = Duration.ofNanos(errorResponse.retry_info.retry_after_nanoseconds);
+ }
+
+ webSocket.close(1000, null);
+ scheduleConnectionRetry(retryAfter);
+ }
+ }
+
+ private static boolean serverIsUnavailable(ServerErrorResponse errorResponse) {
+ return errorResponse.type.equals(ServerErrorResponseType.ServerErrorResponseType_Unavailable);
+ }
+
+ @SuppressWarnings("FutureReturnValueIgnored")
+ private void scheduleConnectionRetry(@Nullable Duration retryAfter) {
+ if (retryingConnection.compareAndSet(false, true)) {
+ periodicRetryDelay.reset();
+ if (retryAfter != null && periodicRetryDelay instanceof AcceptsDelaySuggestion) {
+ ((AcceptsDelaySuggestion) periodicRetryDelay).suggestDelay(retryAfter);
+ }
+ }
+ if (nextRetryScheduled.compareAndSet(false, true)) {
+ executorService.schedule(
+ this::retryConnection, periodicRetryDelay.getNextDelay().toNanos(), TimeUnit.NANOSECONDS);
+ }
+ }
+
+ private void retryConnection() {
+ nextRetryScheduled.set(false);
+ startConnection();
+ }
+
+ @Override
+ public void onClosed() {
+ if (!closed.get()) {
+ // The service isn't closed so we should retry connecting.
+ scheduleConnectionRetry(null);
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ getCallback().onConnectionFailed(t);
+ scheduleConnectionRetry(null);
+ }
+
+ @Nonnull
+ private Callback getCallback() {
+ return Objects.requireNonNull(callback);
+ }
+}
diff --git a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java
index 63439e8c6..9e0125943 100644
--- a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java
+++ b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java
@@ -8,10 +8,8 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -33,10 +31,7 @@
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import opamp.proto.AgentToServer;
@@ -44,7 +39,6 @@
import opamp.proto.ServerErrorResponse;
import opamp.proto.ServerErrorResponseType;
import opamp.proto.ServerToAgent;
-import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -61,8 +55,7 @@ class HttpRequestServiceTest {
private static final Duration RETRY_DELAY = Duration.ofSeconds(5);
@Mock private RequestService.Callback callback;
- private final List scheduledTasks = new ArrayList<>();
- private ScheduledExecutorService executorService;
+ private TestScheduler scheduler;
private TestHttpSender requestSender;
private PeriodicDelay periodicRequestDelay;
private PeriodicDelayWithSuggestion periodicRetryDelay;
@@ -74,11 +67,11 @@ void setUp() {
requestSender = new TestHttpSender();
periodicRequestDelay = createPeriodicDelay(REGULAR_DELAY);
periodicRetryDelay = createPeriodicDelayWithSuggestionSupport(RETRY_DELAY);
- executorService = createTestScheduleExecutorService();
+ scheduler = new TestScheduler();
httpRequestService =
new HttpRequestService(
requestSender,
- executorService,
+ scheduler.getMockService(),
periodicRequestDelay,
periodicRetryDelay,
RetryAfterParser.getInstance());
@@ -88,28 +81,26 @@ void setUp() {
@AfterEach
void tearDown() {
httpRequestService.stop();
- scheduledTasks.clear();
- verify(executorService).shutdown();
+ verify(scheduler.getMockService()).shutdown();
}
@Test
void verifyStart_scheduledFirstTask() {
- assertThat(scheduledTasks).hasSize(1);
- ScheduledTask firstTask = scheduledTasks.get(0);
- assertThat(firstTask.delay).isEqualTo(REGULAR_DELAY);
+ TestScheduler.Task firstTask = assertAndGetSingleCurrentTask();
+ assertThat(firstTask.getDelay()).isEqualTo(REGULAR_DELAY);
// Verify initial task creates next one
- scheduledTasks.clear();
+ scheduler.clearTasks();
requestSender.enqueueResponse(createSuccessfulResponse(new ServerToAgent.Builder().build()));
firstTask.run();
- assertThat(scheduledTasks).hasSize(1);
+ assertThat(scheduler.getScheduledTasks()).hasSize(1);
// Check on-demand requests don't create subsequent tasks
requestSender.enqueueResponse(createSuccessfulResponse(new ServerToAgent.Builder().build()));
httpRequestService.sendRequest();
- assertThat(scheduledTasks).hasSize(1);
+ assertThat(scheduler.getScheduledTasks()).hasSize(1);
}
@Test
@@ -128,14 +119,14 @@ void verifySendingRequest_happyPath() {
@Test
void verifyWhenSendingOnDemandRequest_andDelayChanges() {
// Initial state
- assertThat(assertAndGetSingleCurrentTask().delay).isEqualTo(REGULAR_DELAY);
+ assertThat(assertAndGetSingleCurrentTask().getDelay()).isEqualTo(REGULAR_DELAY);
// Trigger delay strategy change
requestSender.enqueueResponse(createFailedResponse(503));
httpRequestService.sendRequest();
// Expected state
- assertThat(assertAndGetSingleCurrentTask().delay).isEqualTo(RETRY_DELAY);
+ assertThat(assertAndGetSingleCurrentTask().getDelay()).isEqualTo(RETRY_DELAY);
}
@Test
@@ -252,30 +243,30 @@ void verifySendingRequest_duringRegularMode() {
private void verifyRetryDelayOnError(
HttpSender.Response errorResponse, Duration expectedRetryDelay) {
requestSender.enqueueResponse(errorResponse);
- ScheduledTask previousTask = assertAndGetSingleCurrentTask();
+ TestScheduler.Task previousTask = assertAndGetSingleCurrentTask();
previousTask.run();
verifySingleRequestSent();
verify(periodicRetryDelay).reset();
verify(callback).onRequestFailed(any());
- ScheduledTask retryTask = assertAndGetSingleCurrentTask();
- assertThat(retryTask.delay).isEqualTo(expectedRetryDelay);
+ TestScheduler.Task retryTask = assertAndGetSingleCurrentTask();
+ assertThat(retryTask.getDelay()).isEqualTo(expectedRetryDelay);
// Retry with another error
clearInvocations(callback);
- scheduledTasks.clear();
+ scheduler.clearTasks();
requestSender.enqueueResponse(createFailedResponse(500));
retryTask.run();
verifySingleRequestSent();
verify(callback).onRequestFailed(any());
- ScheduledTask retryTask2 = assertAndGetSingleCurrentTask();
- assertThat(retryTask2.delay).isEqualTo(expectedRetryDelay);
+ TestScheduler.Task retryTask2 = assertAndGetSingleCurrentTask();
+ assertThat(retryTask2.getDelay()).isEqualTo(expectedRetryDelay);
// Retry with a success
clearInvocations(callback);
- scheduledTasks.clear();
+ scheduler.clearTasks();
ServerToAgent serverToAgent = new ServerToAgent.Builder().build();
requestSender.enqueueResponse(createSuccessfulResponse(serverToAgent));
retryTask2.run();
@@ -283,7 +274,7 @@ private void verifyRetryDelayOnError(
verify(periodicRequestDelay).reset();
verifySingleRequestSent();
verifyRequestSuccessCallback(serverToAgent);
- assertThat(assertAndGetSingleCurrentTask().delay).isEqualTo(REGULAR_DELAY);
+ assertThat(assertAndGetSingleCurrentTask().getDelay()).isEqualTo(REGULAR_DELAY);
}
private Request createRequestSupplier() {
@@ -292,7 +283,8 @@ private Request createRequestSupplier() {
return Request.create(agentToServer);
}
- private ScheduledTask assertAndGetSingleCurrentTask() {
+ private TestScheduler.Task assertAndGetSingleCurrentTask() {
+ List scheduledTasks = scheduler.getScheduledTasks();
assertThat(scheduledTasks).hasSize(1);
return scheduledTasks.get(0);
}
@@ -313,33 +305,6 @@ private void verifyRequestFailedCallback(int errorCode) {
assertThat(captor.getValue().getMessage()).isEqualTo("Error message");
}
- private ScheduledExecutorService createTestScheduleExecutorService() {
- ScheduledExecutorService service = mock();
-
- lenient()
- .doAnswer(
- invocation -> {
- Runnable runnable = invocation.getArgument(0);
- runnable.run();
- return null;
- })
- .when(service)
- .execute(any());
-
- when(service.schedule(any(Runnable.class), anyLong(), any(TimeUnit.class)))
- .thenAnswer(
- invocation -> {
- ScheduledTask task =
- new ScheduledTask(invocation.getArgument(0), invocation.getArgument(1));
-
- scheduledTasks.add(task);
-
- return task;
- });
-
- return service;
- }
-
private static HttpSender.Response createSuccessfulResponse(ServerToAgent serverToAgent) {
return createSuccessfulResponse(serverToAgent.encodeByteString().toByteArray());
}
@@ -438,55 +403,4 @@ private RequestParams(int contentLength) {
}
}
}
-
- private class ScheduledTask implements ScheduledFuture