Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-12-24 23:30:26 +01:00
Add tests for EventTask#resumeWhenComplete and clarify Javadoc.
Dieser Commit ist enthalten in:
Ursprung
08f1b87267
Commit
1aaecfff08
@ -75,7 +75,7 @@ public interface EventTask {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an continuation based {@link EventTask} from the given {@link Consumer}. The task isn't
|
||||
* Creates a continuation based {@link EventTask} from the given {@link Consumer}. The task isn't
|
||||
* guaranteed to be executed asynchronously ({@link #requiresAsync()} always returns
|
||||
* {@code false}).
|
||||
*
|
||||
@ -99,8 +99,9 @@ public interface EventTask {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an continuation based {@link EventTask} for the given {@link CompletableFuture}. The
|
||||
* continuation will be notified once the given future is completed.
|
||||
* Creates a continuation based {@link EventTask} for the given {@link CompletableFuture}. The
|
||||
* continuation is resumed upon completion of the given {@code future}, whether it is completed
|
||||
* successfully or not.
|
||||
*
|
||||
* @param future The task to wait for
|
||||
* @return The event task
|
||||
|
118
proxy/src/test/java/com/velocitypowered/proxy/event/EventTaskTest.java
Normale Datei
118
proxy/src/test/java/com/velocitypowered/proxy/event/EventTaskTest.java
Normale Datei
@ -0,0 +1,118 @@
|
||||
package com.velocitypowered.proxy.event;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import com.velocitypowered.api.event.Continuation;
|
||||
import com.velocitypowered.api.event.EventTask;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
import java.util.function.Consumer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class EventTaskTest {
|
||||
|
||||
@Test
|
||||
public void testResumeWhenCompleteNormal() {
|
||||
WitnessContinuation continuation = new WitnessContinuation();
|
||||
CompletableFuture<Void> completed = CompletableFuture.completedFuture(null);
|
||||
EventTask.resumeWhenComplete(completed).execute(continuation);
|
||||
assertTrue(continuation.completedSuccessfully(), "Completed future did not "
|
||||
+ "complete successfully");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResumeWhenCompleteException() {
|
||||
WitnessContinuation continuation = new WitnessContinuation();
|
||||
CompletableFuture<Void> failed = CompletableFuture.failedFuture(new Throwable());
|
||||
EventTask.resumeWhenComplete(failed).execute(continuation);
|
||||
assertTrue(continuation.completedWithError(), "Failed future completed successfully");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResumeWhenCompleteFromOtherThread() throws InterruptedException {
|
||||
WitnessContinuation continuation = new WitnessContinuation();
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
continuation.onComplete = (ignored) -> latch.countDown();
|
||||
CompletableFuture<Void> async = CompletableFuture.supplyAsync(() -> null);
|
||||
EventTask.resumeWhenComplete(async).execute(continuation);
|
||||
latch.await();
|
||||
|
||||
assertTrue(continuation.completedSuccessfully(), "Completed future did not "
|
||||
+ "complete successfully");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResumeWhenFailFromOtherThread() throws InterruptedException {
|
||||
WitnessContinuation continuation = new WitnessContinuation();
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
continuation.onComplete = (ignored) -> latch.countDown();
|
||||
CompletableFuture<Void> async = CompletableFuture.supplyAsync(() -> {
|
||||
throw new RuntimeException();
|
||||
});
|
||||
EventTask.resumeWhenComplete(async).execute(continuation);
|
||||
latch.await();
|
||||
|
||||
assertTrue(continuation.completedWithError(), "Failed future completed successfully");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResumeWhenFailFromOtherThreadComplexChain() throws InterruptedException {
|
||||
WitnessContinuation continuation = new WitnessContinuation();
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
continuation.onComplete = (ignored) -> latch.countDown();
|
||||
CompletableFuture<Void> async = CompletableFuture.supplyAsync(() -> null)
|
||||
.thenAccept((v) -> {
|
||||
throw new RuntimeException();
|
||||
})
|
||||
.thenCompose((v) -> CompletableFuture.completedFuture(null));
|
||||
EventTask.resumeWhenComplete(async).execute(continuation);
|
||||
latch.await();
|
||||
|
||||
assertTrue(continuation.completedWithError(), "Failed future completed successfully");
|
||||
}
|
||||
|
||||
/**
|
||||
* An extremely simplified implementation of {@link Continuation} for verifying the completion
|
||||
* of an operation.
|
||||
*/
|
||||
private static class WitnessContinuation implements Continuation {
|
||||
|
||||
private static final AtomicIntegerFieldUpdater<WitnessContinuation> STATUS_UPDATER =
|
||||
AtomicIntegerFieldUpdater.newUpdater(WitnessContinuation.class, "status");
|
||||
|
||||
private static final int UNCOMPLETED = 0;
|
||||
private static final int COMPLETED = 1;
|
||||
private static final int COMPLETED_WITH_EXCEPTION = 2;
|
||||
|
||||
private volatile int status = UNCOMPLETED;
|
||||
private Consumer<Throwable> onComplete;
|
||||
|
||||
@Override
|
||||
public void resume() {
|
||||
if (!STATUS_UPDATER.compareAndSet(this, UNCOMPLETED, COMPLETED)) {
|
||||
throw new IllegalStateException("Continuation is already completed");
|
||||
}
|
||||
|
||||
this.onComplete.accept(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeWithException(Throwable exception) {
|
||||
if (!STATUS_UPDATER.compareAndSet(this, UNCOMPLETED, COMPLETED_WITH_EXCEPTION)) {
|
||||
throw new IllegalStateException("Continuation is already completed");
|
||||
}
|
||||
|
||||
this.onComplete.accept(exception);
|
||||
}
|
||||
|
||||
public boolean completedSuccessfully() {
|
||||
return STATUS_UPDATER.get(this) == COMPLETED;
|
||||
}
|
||||
|
||||
public boolean completedWithError() {
|
||||
return STATUS_UPDATER.get(this) == COMPLETED_WITH_EXCEPTION;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren