blob: 80b44ebec13d8ce4c2088f88cd6463605ad6acb5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2015 Wind River Systems and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.tests.dsf.concurrent;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.concurrent.ExecutionException;
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.RequestCache;
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() {
@Override
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<>() {
@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();
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<>() {
@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);
assertEquals(NUM_CACHES, (int) q.get());
}
}