|
13 | 13 |
|
14 | 14 | package com.rabbitmq.stream.impl;
|
15 | 15 |
|
| 16 | +import static com.rabbitmq.stream.impl.TestUtils.latchAssert; |
| 17 | +import static org.assertj.core.api.Assertions.assertThat; |
| 18 | +import static org.assertj.core.api.Assertions.assertThatThrownBy; |
16 | 19 | import static org.mockito.ArgumentMatchers.any;
|
17 | 20 | import static org.mockito.Mockito.*;
|
18 | 21 |
|
19 | 22 | import com.rabbitmq.stream.BackOffDelayPolicy;
|
| 23 | +import com.rabbitmq.stream.StreamException; |
20 | 24 | import com.rabbitmq.stream.impl.Client.ClientParameters;
|
| 25 | +import com.rabbitmq.stream.impl.StreamEnvironment.LocatorNotAvailableException; |
21 | 26 | import io.netty.buffer.ByteBufAllocator;
|
22 | 27 | import java.net.URI;
|
23 | 28 | import java.time.Duration;
|
24 | 29 | import java.util.Arrays;
|
25 | 30 | import java.util.Collections;
|
| 31 | +import java.util.concurrent.CountDownLatch; |
26 | 32 | import java.util.concurrent.Executors;
|
27 | 33 | import java.util.concurrent.ScheduledExecutorService;
|
| 34 | +import java.util.concurrent.atomic.AtomicInteger; |
28 | 35 | import java.util.concurrent.atomic.AtomicReference;
|
29 | 36 | import java.util.function.Function;
|
30 | 37 | import org.junit.jupiter.api.AfterEach;
|
@@ -173,4 +180,92 @@ void shouldNotOpenConnectionWhenLazyInitIsEnabled(
|
173 | 180 | cf);
|
174 | 181 | verify(cf, times(expectedConnectionCreation)).apply(any(Client.ClientParameters.class));
|
175 | 182 | }
|
| 183 | + |
| 184 | + @Test |
| 185 | + void locatorOperationShouldReturnOperationResultIfNoProblem() { |
| 186 | + AtomicInteger counter = new AtomicInteger(); |
| 187 | + int result = |
| 188 | + StreamEnvironment.locatorOperation( |
| 189 | + c -> counter.incrementAndGet(), () -> null, BackOffDelayPolicy.fixed(Duration.ZERO)); |
| 190 | + assertThat(result).isEqualTo(1); |
| 191 | + } |
| 192 | + |
| 193 | + @Test |
| 194 | + void locatorOperationShouldRetryAndReturnResultIfLocatorException() { |
| 195 | + AtomicInteger counter = new AtomicInteger(); |
| 196 | + int result = |
| 197 | + StreamEnvironment.locatorOperation( |
| 198 | + c -> { |
| 199 | + if (counter.incrementAndGet() < 2) { |
| 200 | + throw new LocatorNotAvailableException(); |
| 201 | + } else { |
| 202 | + return counter.get(); |
| 203 | + } |
| 204 | + }, |
| 205 | + () -> null, |
| 206 | + BackOffDelayPolicy.fixed(Duration.ofMillis(10))); |
| 207 | + assertThat(result).isEqualTo(2); |
| 208 | + } |
| 209 | + |
| 210 | + @Test |
| 211 | + void locatorOperationShouldThrowLocatorExceptionWhenRetryExhausts() { |
| 212 | + AtomicInteger counter = new AtomicInteger(); |
| 213 | + assertThatThrownBy( |
| 214 | + () -> |
| 215 | + StreamEnvironment.locatorOperation( |
| 216 | + c -> { |
| 217 | + counter.incrementAndGet(); |
| 218 | + throw new LocatorNotAvailableException(); |
| 219 | + }, |
| 220 | + () -> null, |
| 221 | + BackOffDelayPolicy.fixed(Duration.ofMillis(10)))) |
| 222 | + .isInstanceOf(LocatorNotAvailableException.class); |
| 223 | + assertThat(counter).hasValue(3); |
| 224 | + } |
| 225 | + |
| 226 | + @Test |
| 227 | + void locatorOperationShouldThrowInterruptedExceptionAsCauseIfInterrupted() |
| 228 | + throws InterruptedException { |
| 229 | + CountDownLatch latch = new CountDownLatch(1); |
| 230 | + AtomicReference<Exception> exception = new AtomicReference<>(); |
| 231 | + Thread thread = |
| 232 | + new Thread( |
| 233 | + () -> { |
| 234 | + try { |
| 235 | + StreamEnvironment.locatorOperation( |
| 236 | + c -> { |
| 237 | + latch.countDown(); |
| 238 | + throw new LocatorNotAvailableException(); |
| 239 | + }, |
| 240 | + () -> null, |
| 241 | + BackOffDelayPolicy.fixed(Duration.ofMinutes(10))); |
| 242 | + } catch (StreamException e) { |
| 243 | + exception.set(e); |
| 244 | + } |
| 245 | + }); |
| 246 | + thread.start(); |
| 247 | + latchAssert(latch).completes(); |
| 248 | + Thread.sleep(100); |
| 249 | + thread.interrupt(); |
| 250 | + Thread.sleep(100); |
| 251 | + assertThat(exception.get()) |
| 252 | + .isInstanceOf(StreamException.class) |
| 253 | + .hasCauseInstanceOf(InterruptedException.class); |
| 254 | + } |
| 255 | + |
| 256 | + @Test |
| 257 | + void locatorOperationShouldNotRetryAndReThrowUnexpectedException() { |
| 258 | + AtomicInteger counter = new AtomicInteger(); |
| 259 | + assertThatThrownBy( |
| 260 | + () -> |
| 261 | + StreamEnvironment.locatorOperation( |
| 262 | + c -> { |
| 263 | + counter.incrementAndGet(); |
| 264 | + throw new RuntimeException(); |
| 265 | + }, |
| 266 | + () -> null, |
| 267 | + BackOffDelayPolicy.fixed(Duration.ofMillis(10)))) |
| 268 | + .isInstanceOf(RuntimeException.class); |
| 269 | + assertThat(counter).hasValue(1); |
| 270 | + } |
176 | 271 | }
|
0 commit comments