/*
* Copyright 2014 Red Hat, Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.vertx.test.core;
import io.vertx.core.Context;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author <a href="http://tfox.org">Tim Fox</a>
*/
public class ExecuteBlockingTest extends VertxTestBase {
@Test
public void testExecuteBlockingSuccess() {
vertx.executeBlocking(future -> {
try {
Thread.sleep(1000);
} catch (Exception ignore) {
}
future.complete("done!");
}, onSuccess(res -> {
assertEquals("done!", res);
testComplete();
}));
await();
}
@Test
public void testExecuteBlockingFailed() {
vertx.executeBlocking(future -> {
try {
Thread.sleep(1000);
} catch (Exception ignore) {
}
future.fail("failed!");
}, onFailure(t -> {
assertEquals("failed!", t.getMessage());
testComplete();
}));
await();
}
@Test
public void testExecuteBlockingThrowsRTE() {
vertx.executeBlocking(future -> {
throw new RuntimeException("rte");
}, onFailure(t -> {
assertEquals("rte", t.getMessage());
testComplete();
}));
await();
}
@Test
public void testExecuteBlockingContext() {
vertx.runOnContext(v -> {
Context ctx = vertx.getOrCreateContext();
assertTrue(ctx.isEventLoopContext());
vertx.executeBlocking(future -> {
assertSame(ctx, vertx.getOrCreateContext());
assertTrue(Thread.currentThread().getName().startsWith("vert.x-worker-thread"));
assertTrue(Context.isOnWorkerThread());
assertFalse(Context.isOnEventLoopThread());
try {
Thread.sleep(1000);
} catch (Exception ignore) {
}
vertx.runOnContext(v2 -> {
assertSame(ctx, vertx.getOrCreateContext());
assertTrue(Thread.currentThread().getName().startsWith("vert.x-eventloop-thread"));
assertFalse(Context.isOnWorkerThread());
assertTrue(Context.isOnEventLoopThread());
future.complete("done!");
});
}, onSuccess(res -> {
assertSame(ctx, vertx.getOrCreateContext());
assertTrue(Thread.currentThread().getName().startsWith("vert.x-eventloop-thread"));
assertFalse(Context.isOnWorkerThread());
assertTrue(Context.isOnEventLoopThread());
assertEquals("done!", res);
testComplete();
}));
});
await();
}
@Test
public void testExecuteBlockingTTCL() throws Exception {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
assertNotNull(cl);
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<ClassLoader> blockingTCCL = new AtomicReference<>();
vertx.<String>executeBlocking(future -> {
future.complete("whatever");
blockingTCCL.set(Thread.currentThread().getContextClassLoader());
}, ar -> {
assertTrue(ar.succeeded());
assertEquals("whatever", ar.result());
latch.countDown();
});
assertSame(cl, Thread.currentThread().getContextClassLoader());
awaitLatch(latch);
assertSame(cl, blockingTCCL.get());
}
@Test
public void testExecuteBlockingParallel() throws Exception {
long start = System.currentTimeMillis();
int numExecBlocking = 10;
long pause = 1000;
CountDownLatch latch = new CountDownLatch(numExecBlocking);
vertx.runOnContext(v -> {
Context ctx = vertx.getOrCreateContext();
assertTrue(ctx.isEventLoopContext());
for (int i = 0; i < numExecBlocking; i++) {
vertx.executeBlocking(future -> {
assertSame(ctx, vertx.getOrCreateContext());
assertTrue(Thread.currentThread().getName().startsWith("vert.x-worker-thread"));
assertTrue(Context.isOnWorkerThread());
assertFalse(Context.isOnEventLoopThread());
try {
Thread.sleep(pause);
} catch (Exception ignore) {
}
future.complete("done!");
}, false, onSuccess(res -> {
assertSame(ctx, vertx.getOrCreateContext());
assertTrue(Thread.currentThread().getName().startsWith("vert.x-eventloop-thread"));
assertFalse(Context.isOnWorkerThread());
assertTrue(Context.isOnEventLoopThread());
assertEquals("done!", res);
latch.countDown();
}));
}
});
awaitLatch(latch);
long now = System.currentTimeMillis();
long leeway = 1000;
assertTrue(now - start < pause + leeway);
}
}