Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPawel Piech2010-10-18 16:50:06 +0000
committerPawel Piech2010-10-18 16:50:06 +0000
commitc6e0fac759022c8f0a9d138e11b3c87971325ab5 (patch)
treedffb56adbce52d688bc94a9a91fc56fb50106fa1 /dsf/org.eclipse.cdt.tests.dsf
parent400a4127fdd2fab3aac96c07f279b3f1492c6497 (diff)
downloadorg.eclipse.cdt-c6e0fac759022c8f0a9d138e11b3c87971325ab5.tar.gz
org.eclipse.cdt-c6e0fac759022c8f0a9d138e11b3c87971325ab5.tar.xz
org.eclipse.cdt-c6e0fac759022c8f0a9d138e11b3c87971325ab5.zip
Bug 310345 - [concurrent] Asynchronous Cache Programming Model (ACPM) utilities for DSF
Diffstat (limited to 'dsf/org.eclipse.cdt.tests.dsf')
-rw-r--r--dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/concurrent/CacheTests.java721
-rw-r--r--dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/concurrent/TransactionTests.java178
2 files changed, 899 insertions, 0 deletions
diff --git a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/concurrent/CacheTests.java b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/concurrent/CacheTests.java
new file mode 100644
index 00000000000..b6455fd62dd
--- /dev/null
+++ b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/concurrent/CacheTests.java
@@ -0,0 +1,721 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.tests.dsf.concurrent;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+
+import junit.framework.Assert;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
+import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
+import org.eclipse.cdt.dsf.concurrent.ImmediateInDsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.Query;
+import org.eclipse.cdt.dsf.concurrent.RequestCache;
+import org.eclipse.cdt.tests.dsf.TestDsfExecutor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests that exercise the DataCache object.
+ */
+public class CacheTests {
+
+ TestDsfExecutor fExecutor;
+ TestCache fTestCache;
+ DataRequestMonitor<Integer> fRetrieveRm;
+
+ class TestCache extends RequestCache<Integer> {
+
+ public TestCache() {
+ super(new ImmediateInDsfExecutor(fExecutor));
+ }
+
+ @Override
+ protected void retrieve(DataRequestMonitor<Integer> rm) {
+ synchronized(CacheTests.this) {
+ fRetrieveRm = rm;
+ CacheTests.this.notifyAll();
+ }
+ }
+
+ @Override
+ protected void reset() {
+ super.reset();
+ }
+
+ @Override
+ public void reset(Integer data, IStatus status) {
+ super.reset(data, status);
+ }
+
+ @Override
+ public void disable() {
+ super.disable();
+ }
+
+ @Override
+ public void set(Integer data, IStatus status) {
+ super.set(data, status);
+ }
+
+ }
+
+ /**
+ * There's no rule on how quickly the cache has to start data retrieval
+ * after it has been requested. It could do it immediately, or it could
+ * wait a dispatch cycle, etc..
+ */
+ private void waitForRetrieveRm() {
+ synchronized(this) {
+ while (fRetrieveRm == null) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ return;
+ }
+ }
+ }
+ }
+
+ @Before
+ public void startExecutor() throws ExecutionException, InterruptedException {
+ fExecutor = new TestDsfExecutor();
+ fTestCache = new TestCache();
+ }
+
+ @After
+ public void shutdownExecutor() throws ExecutionException, InterruptedException {
+ fExecutor.submit(new DsfRunnable() { public void run() {
+ fExecutor.shutdown();
+ }}).get();
+ if (fExecutor.exceptionsCaught()) {
+ Throwable[] exceptions = fExecutor.getExceptions();
+ throw new ExecutionException(exceptions[0]);
+ }
+ fRetrieveRm = null;
+ fTestCache = null;
+ fExecutor = null;
+ }
+
+ private void assertCacheValidWithData(Object data) {
+ Assert.assertTrue(fTestCache.isValid());
+ Assert.assertEquals(data, fTestCache.getData());
+ Assert.assertTrue(fTestCache.getStatus().isOK());
+ }
+
+ private void assertCacheResetWithoutData() {
+ Assert.assertFalse(fTestCache.isValid());
+ Assert.assertEquals(null, fTestCache.getData());
+ Assert.assertFalse(fTestCache.getStatus().isOK());
+ Assert.assertEquals(fTestCache.getStatus().getCode(), IDsfStatusConstants.INVALID_STATE);
+ }
+
+ private void assertCacheDisabledWithoutData() {
+ Assert.assertTrue(fTestCache.isValid());
+ Assert.assertEquals(null, fTestCache.getData());
+ Assert.assertFalse(fTestCache.getStatus().isOK());
+ Assert.assertEquals(fTestCache.getStatus().getCode(), IDsfStatusConstants.INVALID_STATE);
+ }
+
+ private void assertCacheWaiting() {
+ Assert.assertFalse(fTestCache.isValid());
+ Assert.assertEquals(null, fTestCache.getData());
+ Assert.assertFalse(fTestCache.getStatus().isOK());
+ Assert.assertEquals(fTestCache.getStatus().getCode(), IDsfStatusConstants.INVALID_STATE);
+ Assert.assertFalse(fRetrieveRm.isCanceled());
+ }
+
+ private void assertCacheCanceled() {
+ Assert.assertFalse(fTestCache.isValid());
+ Assert.assertEquals(null, fTestCache.getData());
+ Assert.assertFalse(fTestCache.getStatus().isOK());
+ Assert.assertEquals(fTestCache.getStatus().getCode(), IDsfStatusConstants.INVALID_STATE);
+ Assert.assertTrue(fRetrieveRm.isCanceled());
+ }
+
+ @Test
+ public void getWithCompletionInDsfThreadTest() throws InterruptedException, ExecutionException {
+ // Request data from cache
+ Query<Integer> q = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ // Check initial state
+ Assert.assertFalse(fTestCache.isValid());
+ Assert.assertFalse(fTestCache.getStatus().isOK());
+ Assert.assertEquals(fTestCache.getStatus().getCode(), IDsfStatusConstants.INVALID_STATE);
+
+ fExecutor.execute(q);
+
+ // Wait until the cache requests the data.
+ waitForRetrieveRm();
+
+ // Check state while waiting for data
+ Assert.assertFalse(fTestCache.isValid());
+
+ // Complete the cache's retrieve data request.
+ fExecutor.submit(new Callable<Object>() { public Object call() {
+ fRetrieveRm.setData(1);
+ fRetrieveRm.done();
+
+ // Check that the data is available in the cache immediately
+ // (in the same dispatch cycle).
+ Assert.assertEquals(1, (int)fTestCache.getData());
+ Assert.assertTrue(fTestCache.isValid());
+
+ return null;
+ }}).get();
+
+ Assert.assertEquals(1, (int)q.get());
+
+ // Re-check final state
+ assertCacheValidWithData(1);
+ }
+
+ @Test
+ public void getTest() throws InterruptedException, ExecutionException {
+ // Check initial state
+ Assert.assertFalse(fTestCache.isValid());
+
+ // Request data from cache
+ Query<Integer> q = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ fExecutor.execute(q);
+
+ // Wait until the cache starts data retrieval.
+ waitForRetrieveRm();
+
+ // Check state while waiting for data
+ Assert.assertFalse(fTestCache.isValid());
+
+ // Set the data without using an executor.
+ fRetrieveRm.setData(1);
+ fRetrieveRm.done();
+
+ Assert.assertEquals(1, (int)q.get());
+
+ // Check final state
+ assertCacheValidWithData(1);
+ }
+
+ @Test
+ public void getTestWithTwoClients() throws InterruptedException, ExecutionException {
+ // Check initial state
+ Assert.assertFalse(fTestCache.isValid());
+
+ // Request data from cache
+ Query<Integer> q1 = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ fExecutor.execute(q1);
+
+ // Request data from cache again
+ Query<Integer> q2 = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ fExecutor.execute(q2);
+
+ // Wait until the cache starts data retrieval.
+ waitForRetrieveRm();
+
+ // Check state while waiting for data
+ Assert.assertFalse(fTestCache.isValid());
+
+ // Set the data without using an executor.
+ fRetrieveRm.setData(1);
+ fRetrieveRm.done();
+
+ Assert.assertEquals(1, (int)q1.get());
+ Assert.assertEquals(1, (int)q2.get());
+
+ // Check final state
+ assertCacheValidWithData(1);
+ }
+
+ @Test
+ public void getTestWithManyClients() throws InterruptedException, ExecutionException {
+ // Check initial state
+ Assert.assertFalse(fTestCache.isValid());
+
+ // Request data from cache
+ List<Query<Integer>> qList = new ArrayList<Query<Integer>>();
+ for (int i = 0; i < 10; i++) {
+ Query<Integer> q = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ fExecutor.execute(q);
+ qList.add(q);
+ }
+ // Wait until the cache starts data retrieval.
+ waitForRetrieveRm();
+
+ // Check state while waiting for data
+ Assert.assertFalse(fTestCache.isValid());
+
+ // Set the data without using an executor.
+ fRetrieveRm.setData(1);
+ fRetrieveRm.done();
+
+ for (Query<Integer> q : qList) {
+ Assert.assertEquals(1, (int)q.get());
+ }
+
+ // Check final state
+ assertCacheValidWithData(1);
+ }
+
+ @Test
+ public void disableBeforeRequestTest() throws InterruptedException, ExecutionException {
+ // Disable the cache with a given value
+ fExecutor.submit(new DsfRunnable() {
+ public void run() {
+ fTestCache.disable();
+ }
+ }).get();
+
+ assertCacheDisabledWithoutData();
+
+ // Try to request data from cache
+ Query<Integer> q = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ fExecutor.execute(q);
+
+ Thread.sleep(100);
+
+ // Retrieval should never have been made.
+ Assert.assertEquals(null, fRetrieveRm);
+
+ try {
+ Assert.assertEquals(null, q.get());
+ } catch (ExecutionException e) {
+ // expected the exception
+ return;
+ }
+ Assert.fail("expected an exeption");
+ }
+
+ @Test
+ public void disableWhilePendingTest() throws InterruptedException, ExecutionException {
+ // Request data from cache
+ Query<Integer> q = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ fExecutor.execute(q);
+
+ // Disable the cache with a given value
+ fExecutor.submit(new DsfRunnable() {
+ public void run() {
+ fTestCache.disable();
+ }
+ }).get();
+
+ assertCacheDisabledWithoutData();
+
+ // Completed the retrieve RM
+ fExecutor.submit(new DsfRunnable() {
+ public void run() {
+ fRetrieveRm.setData(1);
+ fRetrieveRm.done();
+ }
+ }).get();
+
+ // Validate that cache is still disabled without data.
+ assertCacheDisabledWithoutData();
+ }
+
+ @Test
+ public void disableWhileValidTest() throws InterruptedException, ExecutionException {
+ // Request data from cache
+ Query<Integer> q = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ fExecutor.execute(q);
+
+ // Wait until the cache starts data retrieval.
+ waitForRetrieveRm();
+
+ // Complete the request
+ fRetrieveRm.setData(1);
+ fRetrieveRm.done();
+
+ q.get();
+
+ // Disable cache
+ fExecutor.submit(new DsfRunnable() {
+ public void run() {
+ fTestCache.disable();
+ }
+ }).get();
+
+ // Check final state
+ assertCacheValidWithData(1);
+ }
+
+ @Test
+ public void disableWithValueTest() throws InterruptedException, ExecutionException {
+ // Disable the cache with a given value
+ fExecutor.submit(new DsfRunnable() {
+ public void run() {
+ fTestCache.set(2, Status.OK_STATUS);
+ }
+ }).get();
+
+ // Validate that cache is disabled without data.
+ assertCacheValidWithData(2);
+ }
+
+
+ @Test
+ public void resetBeforeRequestTest() throws InterruptedException, ExecutionException {
+ // Disable the cache with a given value
+ fExecutor.submit(new DsfRunnable() {
+ public void run() {
+ fTestCache.reset();
+ }
+ }).get();
+
+ assertCacheResetWithoutData();
+
+ // Try to request data from cache (check that cache still works normally)
+ Query<Integer> q = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ fExecutor.execute(q);
+
+ // Wait until the cache starts data retrieval.
+ waitForRetrieveRm();
+
+ // Complete the request
+ fRetrieveRm.setData(1);
+ fRetrieveRm.done();
+
+ // Check result
+ Assert.assertEquals(1, (int)q.get());
+
+ assertCacheValidWithData(1);
+ }
+
+ @Test
+ public void resetWhilePendingTest() throws InterruptedException, ExecutionException {
+ // Request data from cache
+ Query<Integer> q = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ fExecutor.execute(q);
+
+ // Wait until the cache starts data retrieval.
+ waitForRetrieveRm();
+
+ // Disable the cache with a given value
+ fExecutor.submit(new DsfRunnable() {
+ public void run() {
+ fTestCache.reset();
+ }
+ }).get();
+
+ assertCacheResetWithoutData();
+
+ // Completed the retrieve RM
+ fExecutor.submit(new DsfRunnable() {
+ public void run() {
+ fRetrieveRm.setData(1);
+ fRetrieveRm.done();
+ }
+ }).get();
+
+ // Validate that cache is still disabled without data.
+ assertCacheResetWithoutData();
+ }
+
+ @Test
+ public void cancelWhilePendingTest() throws InterruptedException, ExecutionException {
+ // Request data from cache
+ Query<Integer> q = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ fExecutor.execute(q);
+
+ // Wait until the cache starts data retrieval.
+ waitForRetrieveRm();
+
+ // Cancel the client request
+ q.cancel(true);
+ try {
+ q.get();
+ Assert.fail("Expected a cancellation exception");
+ } catch (CancellationException e) {} // Expected exception;
+
+ assertCacheCanceled();
+
+ // Completed the retrieve RM
+ fExecutor.submit(new DsfRunnable() {
+ public void run() {
+ fRetrieveRm.setData(1);
+ fRetrieveRm.done();
+ }
+ }).get();
+
+ // Validate that cache accepts the canceled request data
+ assertCacheValidWithData(1);
+ }
+
+ @Test
+ public void cancelWhilePendingWithoutClientNotificationTest() throws InterruptedException, ExecutionException {
+ // Request data from cache
+ Query<Integer> q = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(new DataRequestMonitor<Integer>(ImmediateExecutor.getInstance(), rm) {
+ @Override
+ public synchronized void addCancelListener(ICanceledListener listener) {
+ // Do not add the cancel listener so that the cancel request is not
+ // propagated to the cache.
+ }
+ });
+ }
+ };
+ fExecutor.execute(q);
+
+ // Wait until the cache starts data retrieval.
+ waitForRetrieveRm();
+
+ // Cancel the client request
+ q.cancel(true);
+
+ assertCacheCanceled();
+
+ try {
+ q.get();
+ Assert.fail("Expected a cancellation exception");
+ } catch (CancellationException e) {} // Expected exception;
+
+ // Completed the retrieve RM
+ fExecutor.submit(new DsfRunnable() {
+ public void run() {
+ fRetrieveRm.setData(1);
+ fRetrieveRm.done();
+ }
+ }).get();
+
+ // Validate that cache accepts the canceled request data
+ assertCacheValidWithData(1);
+ }
+
+ @Test
+ public void cancelWhilePendingWithTwoClientsTest() throws InterruptedException, ExecutionException {
+ // Request data from cache
+ Query<Integer> q1 = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ fExecutor.execute(q1);
+
+ // Request data from cache again
+ Query<Integer> q2 = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ fExecutor.execute(q2);
+
+
+ // Wait until the cache starts data retrieval.
+ waitForRetrieveRm();
+
+ // Cancel the first client request
+ q1.cancel(true);
+ try {
+ q1.get();
+ Assert.fail("Expected a cancellation exception");
+ } catch (CancellationException e) {} // Expected exception;
+ assertCacheWaiting();
+
+ // Cancel the second request
+ q2.cancel(true);
+ try {
+ q2.get();
+ Assert.fail("Expected a cancellation exception");
+ } catch (CancellationException e) {} // Expected exception;
+
+ assertCacheCanceled();
+
+ // Completed the retrieve RM
+ fExecutor.submit(new DsfRunnable() {
+ public void run() {
+ fRetrieveRm.setData(1);
+ fRetrieveRm.done();
+ }
+ }).get();
+
+ // Validate that cache accepts the canceled request data
+ assertCacheValidWithData(1);
+ }
+
+ @Test
+ public void cancelWhilePendingWithManyClientsTest() throws InterruptedException, ExecutionException {
+ // Request data from cache
+ List<Query<Integer>> qList = new ArrayList<Query<Integer>>();
+ for (int i = 0; i < 10; i++) {
+ Query<Integer> q = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ fExecutor.execute(q);
+ qList.add(q);
+ }
+
+ // Wait until the cache starts data retrieval.
+ waitForRetrieveRm();
+
+ // Cancel some client requests
+ int[] toCancel = new int[] { 0, 2, 5, 9};
+ for (int i = 0; i < toCancel.length; i++) {
+
+ // Cancel request and verify that its canceled
+ Query<Integer> q = qList.get(toCancel[i]);
+ q.cancel(true);
+ try {
+ q.get();
+ Assert.fail("Expected a cancellation exception");
+ } catch (CancellationException e) {} // Expected exception;
+ qList.set(toCancel[i], null);
+
+ assertCacheWaiting();
+ }
+
+ // Replace canceled requests with new ones
+ for (int i = 0; i < toCancel.length; i++) {
+ Query<Integer> q = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ fExecutor.execute(q);
+ qList.set(toCancel[i], q);
+ assertCacheWaiting();
+ }
+
+ // Now cancel all requests
+ for (int i = 0; i < (qList.size() - 1); i++) {
+ // Validate that cache is still waiting and is not canceled
+ assertCacheWaiting();
+ qList.get(i).cancel(true);
+ }
+ qList.get(qList.size() - 1).cancel(true);
+ assertCacheCanceled();
+
+ // Completed the retrieve RM
+ fExecutor.submit(new DsfRunnable() {
+ public void run() {
+ fRetrieveRm.setData(1);
+ fRetrieveRm.done();
+ }
+ }).get();
+
+ // Validate that cache accepts the canceled request data
+ assertCacheValidWithData(1);
+ }
+
+ @Test
+ public void resetWhileValidTest() throws InterruptedException, ExecutionException {
+ // Request data from cache
+ Query<Integer> q = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ fTestCache.request(rm);
+ }
+ };
+ fExecutor.execute(q);
+
+ // Wait until the cache starts data retrieval.
+ waitForRetrieveRm();
+
+ // Complete the request
+ fRetrieveRm.setData(1);
+ fRetrieveRm.done();
+
+ q.get();
+
+ // Disable cache
+ fExecutor.submit(new DsfRunnable() {
+ public void run() {
+ fTestCache.reset();
+ }
+ }).get();
+
+ // Check final state
+ assertCacheResetWithoutData();
+ }
+
+ @Test
+ public void resetWithValueTest() throws InterruptedException, ExecutionException {
+ // Disable the cache with a given value
+ fExecutor.submit(new DsfRunnable() {
+ public void run() {
+ fTestCache.reset(2, Status.OK_STATUS);
+ }
+ }).get();
+
+ // Validate that cache is disabled without data.
+ Assert.assertFalse(fTestCache.isValid());
+ Assert.assertEquals(2, (int)fTestCache.getData());
+ Assert.assertTrue(fTestCache.getStatus().isOK());
+ }
+}
diff --git a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/concurrent/TransactionTests.java b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/concurrent/TransactionTests.java
new file mode 100644
index 00000000000..1b53c51bc30
--- /dev/null
+++ b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/concurrent/TransactionTests.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.tests.dsf.concurrent;
+
+import java.util.Arrays;
+import java.util.concurrent.ExecutionException;
+
+import junit.framework.Assert;
+
+import org.eclipse.cdt.dsf.concurrent.RequestCache;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.ImmediateInDsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.Query;
+import org.eclipse.cdt.dsf.concurrent.Transaction;
+import org.eclipse.cdt.tests.dsf.TestDsfExecutor;
+import org.eclipse.core.runtime.CoreException;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests that exercise the Transaction object.
+ */
+public class TransactionTests {
+ final static private int NUM_CACHES = 5;
+
+ TestDsfExecutor fExecutor;
+ TestCache[] fTestCaches = new TestCache[NUM_CACHES];
+ DataRequestMonitor<?>[] fRetrieveRms = new DataRequestMonitor<?>[NUM_CACHES];
+
+ class TestCache extends RequestCache<Integer> {
+
+ final private int fIndex;
+
+ public TestCache(int index) {
+ super(new ImmediateInDsfExecutor(fExecutor));
+ fIndex = index;
+ }
+
+ @Override
+ protected void retrieve(DataRequestMonitor<Integer> rm) {
+ synchronized(TransactionTests.this) {
+ fRetrieveRms[fIndex] = rm;
+ TransactionTests.this.notifyAll();
+ }
+ }
+
+ }
+
+ class TestSingleTransaction extends Transaction<Integer> {
+
+ @Override
+ protected Integer process() throws InvalidCacheException, CoreException {
+ validate(fTestCaches[0]);
+ return fTestCaches[0].getData();
+ }
+ }
+
+ class TestSumTransaction extends Transaction<Integer> {
+ @Override
+ protected Integer process() throws InvalidCacheException, CoreException {
+ validate(fTestCaches);
+
+ int sum = 0;
+ for (RequestCache<Integer> cache : fTestCaches) {
+ sum += cache.getData();
+ }
+ return sum;
+ }
+ }
+
+ /**
+ * There's no rule on how quickly the cache has to start data retrieval
+ * after it has been requested. It could do it immediately, or it could
+ * wait a dispatch cycle, etc..
+ */
+ private void waitForRetrieveRm(boolean all) {
+ synchronized(this) {
+ if (all) {
+ while (Arrays.asList(fRetrieveRms).contains(null)) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ return;
+ }
+ }
+ } else {
+ while (fRetrieveRms[0] == null) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ @Before
+ public void startExecutor() throws ExecutionException, InterruptedException {
+ fExecutor = new TestDsfExecutor();
+ for (int i = 0; i < fTestCaches.length; i++) {
+ fTestCaches[i] = new TestCache(i);
+ }
+ }
+
+ @After
+ public void shutdownExecutor() throws ExecutionException, InterruptedException {
+ fExecutor.submit(new DsfRunnable() { public void run() {
+ fExecutor.shutdown();
+ }}).get();
+ if (fExecutor.exceptionsCaught()) {
+ Throwable[] exceptions = fExecutor.getExceptions();
+ throw new ExecutionException(exceptions[0]);
+ }
+ fRetrieveRms = new DataRequestMonitor<?>[NUM_CACHES];
+ fTestCaches = new TestCache[NUM_CACHES];
+ fExecutor = null;
+ }
+
+ @Test
+ public void singleTransactionTest() throws InterruptedException, ExecutionException {
+ final TestSingleTransaction testTransaction = new TestSingleTransaction();
+ // Request data from cache
+ Query<Integer> q = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ testTransaction.request(rm);
+ }
+ };
+ fExecutor.execute(q);
+
+ // Wait until the cache starts data retrieval.
+ waitForRetrieveRm(false);
+
+ // Set the data without using an executor.
+ ((DataRequestMonitor<Integer>)fRetrieveRms[0]).setData(1);
+ fRetrieveRms[0].done();
+
+ Assert.assertEquals(1, (int)q.get());
+ }
+
+ @Test
+ public void sumTransactionTest() throws InterruptedException, ExecutionException {
+
+ final TestSumTransaction testTransaction = new TestSumTransaction();
+ // Request data from cache
+ Query<Integer> q = new Query<Integer>() {
+ @Override
+ protected void execute(DataRequestMonitor<Integer> rm) {
+ testTransaction.request(rm);
+ }
+ };
+ fExecutor.execute(q);
+
+ // Wait until the cache starts data retrieval.
+ waitForRetrieveRm(true);
+
+ // Set the data without using an executor.
+ for (DataRequestMonitor<?> rm : fRetrieveRms) {
+ ((DataRequestMonitor<Integer>)rm).setData(1);
+ rm.done();
+ }
+
+ fExecutor.execute(q);
+ Assert.assertEquals(NUM_CACHES, (int)q.get());
+ }
+
+}

Back to the top