Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'tests/junit/plugins/infra/core/org.eclipse.papyrus.infra.core.tests/test/org/eclipse/papyrus/infra/core/utils/JobBasedFutureTest.java')
-rw-r--r--tests/junit/plugins/infra/core/org.eclipse.papyrus.infra.core.tests/test/org/eclipse/papyrus/infra/core/utils/JobBasedFutureTest.java331
1 files changed, 331 insertions, 0 deletions
diff --git a/tests/junit/plugins/infra/core/org.eclipse.papyrus.infra.core.tests/test/org/eclipse/papyrus/infra/core/utils/JobBasedFutureTest.java b/tests/junit/plugins/infra/core/org.eclipse.papyrus.infra.core.tests/test/org/eclipse/papyrus/infra/core/utils/JobBasedFutureTest.java
new file mode 100644
index 00000000000..5047dd18394
--- /dev/null
+++ b/tests/junit/plugins/infra/core/org.eclipse.papyrus.infra.core.tests/test/org/eclipse/papyrus/infra/core/utils/JobBasedFutureTest.java
@@ -0,0 +1,331 @@
+/*****************************************************************************
+ * Copyright (c) 2014 Christian W. Damus and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.core.utils;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.fail;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.papyrus.junit.framework.classification.tests.AbstractPapyrusTest;
+import org.eclipse.papyrus.junit.matchers.MoreMatchers;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+/**
+ * JUnit tests for the {@link JobBasedFuture} class.
+ */
+public class JobBasedFutureTest extends AbstractPapyrusTest {
+ private static final long FUTURE_DURATION = 3L;
+
+ private static final TimeUnit FUTURE_DURATION_UNIT = TimeUnit.SECONDS;
+
+ private static final int CONCURRENT_THREAD_COUNT = 3;
+
+ private static ExecutorService exec;
+
+ private long startedWhen;
+
+ public JobBasedFutureTest() {
+ super();
+ }
+
+ @Test
+ public void normalCompletion() {
+ runGetterThreads(Fixture.returning(true));
+ assertRunningTimeAtLeast(2L, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void normalCompletionWithSchedulingRule() {
+ runGetterThreads(Fixture.returning(true), new RuleSupplier());
+ assertRunningTimeAtLeast(2L, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void timeOut() {
+ runGetterThreads(Fixture.returning(true, 5L, TimeUnit.SECONDS), 2L, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void timeOutWithSchedulingRule() {
+ runGetterThreads(Fixture.returning(true, 5L, TimeUnit.SECONDS), 2L, TimeUnit.SECONDS, new RuleSupplier());
+ }
+
+ @Test
+ public void computeFails() {
+ runGetterThreads(Fixture.throwing(TestException.class), TestException.class);
+ assertRunningTimeAtLeast(2L, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void cancel() {
+ runGetterThreads(Fixture.returning(true), true);
+ }
+
+ @Test
+ public void listen_success() {
+ addListeners(Fixture.returning(true));
+ }
+
+ @Test
+ public void listen_failure() {
+ addListeners(Fixture.throwing(TestException.class), TestException.class);
+ }
+
+ //
+ // Test framework
+ //
+
+ @BeforeClass
+ public static void createExecutor() {
+ exec = Executors.newCachedThreadPool();
+ }
+
+ @AfterClass
+ public static void shutDownExecutor() {
+ exec.shutdown();
+ exec = null;
+ }
+
+ @Before
+ public void starting() {
+ startedWhen = System.currentTimeMillis();
+ }
+
+ void assertRunningTimeAtLeast(long time, TimeUnit unit) {
+ assertThat("Test running time too short", System.currentTimeMillis() - startedWhen, MoreMatchers.greaterThan(unit.toMillis(time)));
+ }
+
+ void runGetterThreads(final Fixture fixture) {
+ runGetterThreads(fixture, 0L, null, null, false, true, null);
+ }
+
+ void runGetterThreads(final Fixture fixture, Supplier<? extends ISchedulingRule> rule) {
+ runGetterThreads(fixture, 0L, null, rule, false, true, null);
+ }
+
+ void runGetterThreads(final Fixture fixture, long timeout, TimeUnit unit) {
+ runGetterThreads(fixture, timeout, unit, null, false, null, TimeoutException.class);
+ }
+
+ void runGetterThreads(final Fixture fixture, long timeout, TimeUnit unit, Supplier<? extends ISchedulingRule> rule) {
+ runGetterThreads(fixture, timeout, unit, rule, false, null, null);
+ }
+
+ void runGetterThreads(final Fixture fixture, Boolean expected) {
+ runGetterThreads(fixture, 0L, null, null, false, expected, null);
+ }
+
+ void runGetterThreads(final Fixture fixture, boolean cancel) {
+ runGetterThreads(fixture, 0L, null, null, true, null, null);
+ }
+
+ void runGetterThreads(final Fixture fixture, Class<? extends Throwable> expectedException) {
+ runGetterThreads(fixture, 0L, null, null, false, null, expectedException);
+ }
+
+ private void runGetterThreads(final Fixture fixture, final long timeout, final TimeUnit unit, final Supplier<? extends ISchedulingRule> rule, final boolean cancel, Boolean expected, Class<? extends Throwable> expectedException) {
+ final List<Boolean> results = Lists.newCopyOnWriteArrayList();
+ final List<Throwable> thrown = Lists.newCopyOnWriteArrayList();
+ final CountDownLatch latch = new CountDownLatch(CONCURRENT_THREAD_COUNT);
+
+ Runnable reader = new Runnable() {
+
+ public void run() {
+ ISchedulingRule rule_ = (rule == null) ? null : rule.get();
+
+ try {
+ if (rule_ != null) {
+ Job.getJobManager().beginRule(rule_, null);
+ }
+
+ if (cancel) {
+ fixture.cancel(true);
+ } else if (timeout <= 0L) {
+ results.add(fixture.get());
+ } else {
+ results.add(fixture.get(timeout, unit));
+ }
+ } catch (InterruptedException e) {
+ thrown.add(e);
+ } catch (TimeoutException e) {
+ thrown.add(e);
+ } catch (ExecutionException e) {
+ thrown.add(e.getCause());
+ } finally {
+ latch.countDown();
+
+ if (rule_ != null) {
+ Job.getJobManager().endRule(rule_);
+ }
+ }
+ }
+ };
+
+ for (int i = 0; i < CONCURRENT_THREAD_COUNT; i++) {
+ exec.submit(reader);
+ }
+
+ try {
+ assertThat("Test timed out", latch.await(10L, TimeUnit.MINUTES), is(true));
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ fail("Interrupted waiting for test threads");
+ }
+
+ assertThat(results, is((expected == null) ? Collections.<Boolean> emptyList() : Collections.nCopies(CONCURRENT_THREAD_COUNT, expected)));
+
+ if (expectedException != null) {
+ assertThat(Iterables.size(Iterables.filter(thrown, expectedException)), is(CONCURRENT_THREAD_COUNT));
+ }
+ }
+
+ void addListeners(final Fixture fixture) {
+ addListeners(fixture, true, null);
+ }
+
+ void addListeners(final Fixture fixture, Class<? extends Throwable> expectedException) {
+ addListeners(fixture, null, expectedException);
+ }
+
+ private void addListeners(final Fixture fixture, Boolean expected, Class<? extends Throwable> expectedException) {
+ final List<Boolean> results = Lists.newCopyOnWriteArrayList();
+ final List<Throwable> thrown = Lists.newCopyOnWriteArrayList();
+ final CountDownLatch latch = new CountDownLatch(CONCURRENT_THREAD_COUNT);
+
+ for (int i = 0; i < CONCURRENT_THREAD_COUNT; i++) {
+ Futures.addCallback(fixture, new FutureCallback<Boolean>() {
+ public void onSuccess(Boolean result) {
+ results.add(result);
+ latch.countDown();
+ }
+
+ public void onFailure(Throwable t) {
+ thrown.add(t);
+ latch.countDown();
+ }
+ });
+ }
+
+ try {
+ assertThat("Test timed out", latch.await(1L, TimeUnit.MINUTES), is(true));
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ fail("Interrupted waiting for test listeners");
+ }
+
+ assertThat(results, is((expected == null) ? Collections.<Boolean> emptyList() : Collections.nCopies(CONCURRENT_THREAD_COUNT, expected)));
+
+ if (expectedException != null) {
+ assertThat(Iterables.size(Iterables.filter(thrown, expectedException)), is(CONCURRENT_THREAD_COUNT));
+ }
+
+ }
+
+ private static class Fixture extends JobBasedFuture<Boolean> {
+ private final long delay;
+ private final TimeUnit delayUnit;
+
+ private boolean value = true;
+ private Class<? extends Throwable> exception;
+
+ Fixture(long delay, TimeUnit delayUnit) {
+ super("Test fixture");
+
+ this.delay = delay;
+ this.delayUnit = delayUnit;
+ }
+
+ @Override
+ protected Boolean compute(IProgressMonitor monitor) throws Exception {
+ if (delay > 0L) {
+ delayUnit.sleep(delay);
+ }
+
+ if (exception != null) {
+ if (Exception.class.isAssignableFrom(exception)) {
+ throw (Exception) exception.newInstance();
+ } else if (Error.class.isAssignableFrom(exception)) {
+ throw (Error) exception.newInstance();
+ }
+ }
+
+ return value;
+ }
+
+ static Fixture returning(boolean value) {
+ return returning(value, FUTURE_DURATION, FUTURE_DURATION_UNIT);
+ }
+
+ static Fixture returning(boolean value, long delay, TimeUnit unit) {
+ Fixture result = new Fixture(delay, unit);
+ result.value = value;
+ result.schedule();
+ return result;
+ }
+
+ static Fixture throwing(Class<? extends Throwable> exception) {
+ return throwing(exception, FUTURE_DURATION, FUTURE_DURATION_UNIT);
+ }
+
+ static Fixture throwing(Class<? extends Throwable> exception, long delay, TimeUnit unit) {
+ Fixture result = new Fixture(delay, unit);
+ result.exception = exception;
+ result.schedule();
+ return result;
+ }
+ }
+
+ static class TestException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public TestException() {
+ super();
+ }
+ }
+
+ static class RuleSupplier implements Supplier<ISchedulingRule> {
+ public ISchedulingRule get() {
+ return new ISchedulingRule() {
+ public boolean isConflicting(ISchedulingRule rule) {
+ return rule == this;
+ }
+
+ public boolean contains(ISchedulingRule rule) {
+ return rule == this;
+ }
+ };
+ }
+ }
+}

Back to the top