/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.ok2c.lightnio.concurrent;
import java.nio.channels.IllegalSelectorException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.Assert;
import org.junit.Test;
/**
* Unit tests for {@link BasicFuture}.
*/
public class TestBasicFuture {
static class FutureResult<T> implements FutureCallback<T> {
private volatile boolean completed;
private volatile boolean failed;
private volatile boolean cancelled;
public void completed(final T result) {
if (this.completed) {
return;
}
this.completed = true;
}
public void cancelled() {
if (this.completed) {
return;
}
this.completed = true;
this.cancelled = true;
}
public void failed(final Exception ex) {
if (this.completed) {
return;
}
this.completed = true;
this.failed = true;
}
public boolean isCompleted() {
return this.completed;
}
public boolean isFailed() {
return this.failed;
}
public boolean isCancelled() {
return this.cancelled;
}
}
@Test
public void testFutureCompleted() throws Exception {
FutureResult<String> result = new FutureResult<String>();
BasicFuture<String> future = new BasicFuture<String>(result);
future.completed("done");
Assert.assertTrue(result.isCompleted());
Assert.assertFalse(result.isCancelled());
Assert.assertFalse(result.isFailed());
String s = future.get();
Assert.assertEquals("done", s);
Assert.assertTrue(future.isDone());
Assert.assertFalse(future.isCancelled());
}
@Test
public void testFutureCancelled() throws Exception {
FutureResult<String> result = new FutureResult<String>();
BasicFuture<String> future = new BasicFuture<String>(result);
future.cancel(true);
Assert.assertTrue(result.isCompleted());
Assert.assertTrue(result.isCancelled());
Assert.assertFalse(result.isFailed());
String s = future.get();
Assert.assertNull(s);
Assert.assertTrue(future.isDone());
Assert.assertTrue(future.isCancelled());
}
@Test(expected=ExecutionException.class)
public void testFutureFailed() throws Exception {
FutureResult<String> result = new FutureResult<String>();
BasicFuture<String> future = new BasicFuture<String>(result);
future.failed(new IllegalStateException());
Assert.assertTrue(result.isCompleted());
Assert.assertFalse(result.isCancelled());
Assert.assertTrue(result.isFailed());
String s = future.get();
Assert.assertNull(s);
}
@Test
public void testFutureCompletedThreaded() throws Exception {
final FutureResult<String> result = new FutureResult<String>();
final BasicFuture<String> future = new BasicFuture<String>(result);
Thread t = new Thread() {
@Override
public void run() {
try {
Thread.sleep(250);
future.completed("done");
} catch (InterruptedException ex) {
}
}
};
t.start();
String s = future.get();
t.join();
Assert.assertEquals("done", s);
Assert.assertTrue(future.isDone());
Assert.assertFalse(future.isCancelled());
Assert.assertTrue(result.isCompleted());
Assert.assertFalse(result.isCancelled());
Assert.assertFalse(result.isFailed());
}
@Test
public void testFutureCancelledThreaded() throws Exception {
final FutureResult<String> result = new FutureResult<String>();
final BasicFuture<String> future = new BasicFuture<String>(result);
Thread t = new Thread() {
@Override
public void run() {
try {
Thread.sleep(250);
future.cancel(true);
} catch (InterruptedException ex) {
}
}
};
t.start();
String s = future.get();
t.join();
Assert.assertTrue(result.isCompleted());
Assert.assertTrue(result.isCancelled());
Assert.assertFalse(result.isFailed());
Assert.assertNull(s);
Assert.assertTrue(future.isDone());
Assert.assertTrue(future.isCancelled());
}
@Test(expected=ExecutionException.class)
public void testFutureFailedThreaded() throws Exception {
final FutureResult<String> result = new FutureResult<String>();
final BasicFuture<String> future = new BasicFuture<String>(result);
Thread t = new Thread() {
@Override
public void run() {
try {
Thread.sleep(250);
future.failed(new IllegalSelectorException());
} catch (InterruptedException ex) {
}
}
};
t.start();
future.get();
}
@Test
public void testFutureTimeout() throws Exception {
final FutureResult<String> result = new FutureResult<String>();
final BasicFuture<String> future = new BasicFuture<String>(result);
Thread t = new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000);
future.completed("done");
} catch (InterruptedException ex) {
}
}
};
t.start();
try {
future.get(250, TimeUnit.MILLISECONDS);
} catch (TimeoutException expected) {
}
try {
future.get(250, TimeUnit.MILLISECONDS);
} catch (TimeoutException expected) {
}
String s = future.get();
Assert.assertEquals("done", s);
Assert.assertTrue(future.isDone());
Assert.assertFalse(future.isCancelled());
Assert.assertTrue(result.isCompleted());
Assert.assertFalse(result.isCancelled());
Assert.assertFalse(result.isFailed());
}
}