/*
* Copyright (c) 2012 Diamond Light Source Ltd.
*
* 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
*/
package uk.ac.diamond.scisoft.analysis.processing.test;
import static org.junit.Assert.assertEquals;
import java.util.Collection;
import org.eclipse.dawnsci.analysis.api.processing.ExecutionType;
import org.eclipse.dawnsci.analysis.api.processing.IExecutionVisitor;
import org.eclipse.dawnsci.analysis.api.processing.IOperation;
import org.eclipse.dawnsci.analysis.api.processing.IOperationContext;
import org.eclipse.dawnsci.analysis.api.processing.IOperationService;
import org.eclipse.dawnsci.analysis.api.processing.OperationData;
import org.eclipse.dawnsci.analysis.api.processing.OperationException;
import org.eclipse.dawnsci.analysis.api.processing.model.ValueModel;
import org.eclipse.january.IMonitor;
import org.eclipse.january.dataset.Random;
import org.junit.BeforeClass;
import org.junit.Test;
import uk.ac.diamond.scisoft.analysis.processing.OperationServiceImpl;
import uk.ac.diamond.scisoft.analysis.processing.runner.OperationRunnerImpl;
import uk.ac.diamond.scisoft.analysis.processing.runner.SeriesRunner;
/**
* Works with ordinary junit but therefore does not test the extension points
*
* @author Matthew Gerring
*
*/
public class OperationsTest {
private static IOperationService service;
/**
* Manually creates the service so that no extension points have to be read.
*
* We do this use annotations
* @throws Exception
*/
@BeforeClass
public static void before() throws Exception {
service = new OperationServiceImpl();
// Just read all these operations.
service.createOperations(service.getClass().getClassLoader(), "uk.ac.diamond.scisoft.analysis.processing.operations");
OperationRunnerImpl.setRunner(ExecutionType.SERIES, new SeriesRunner());
OperationRunnerImpl.setRunner(ExecutionType.PARALLEL, new SeriesRunner());
}
@Test
public void testGetService() throws Exception {
if (service == null) throw new Exception("Cannot get the service!");
}
@Test
public void testServiceHasOperations() throws Exception {
final Collection<String> operations = service.getRegisteredOperations();
if (operations==null || operations.isEmpty()) throw new Exception("No operations were registered!");
}
@Test
public void testSimpleSubtract() throws Exception {
final IOperation subtract = service.create("uk.ac.diamond.scisoft.analysis.processing.subtractOperation");
subtract.setModel(new ValueModel(100));
final IOperationContext context = service.createContext();
context.setData(Random.rand(0.0, 10.0, 1024, 1024));
context.setDataDimensions(new int[]{0,1});
counter = 0;
context.setVisitor(new IExecutionVisitor.Stub() {
@Override
public void executed(OperationData result, IMonitor monitor) throws Exception {
++counter;
for (int i = 0; i < result.getData().getShape()[0]; i++) {
for (int j = 0; j < result.getData().getShape()[1]; j++) {
if ( result.getData().getDouble(i,j)>0 ) throw new Exception("Incorrect value found!");
}
}
}
});
context.setSeries(subtract);
service.execute(context);
if (counter!=1) throw new Exception("Unexpected execution amount "+counter);
}
@Test
public void testSimpleAddAndSubtractUsingFind() throws Exception {
final IOperation add = service.findFirst("add");
final IOperation subtract = service.findFirst("subtractOperation");
final IOperationContext context = service.createContext();
context.setData(Random.rand(0.0, 10.0, 1024, 1024));
context.setDataDimensions(new int[]{0,1});
subtract.setModel(new ValueModel(100));
add.setModel(new ValueModel(101));
counter = 0;
context.setVisitor(new IExecutionVisitor.Stub() {
@Override
public void executed(OperationData result, IMonitor monitor) throws Exception {
++counter;
for (int i = 0; i < result.getData().getShape()[0]; i++) {
for (int j = 0; j < result.getData().getShape()[1]; j++) {
if ( result.getData().getDouble(i,j)<0 ) throw new Exception("Incorrect value found! "+result.getData().getDouble(i,j));
}
}
}
});
context.setSeries(subtract, add);
service.execute(context);
if (counter!=1) throw new Exception("Unexpected execution amount "+counter);
}
private volatile int counter;
@Test
public void testSimpleAddAndSubtractOnStack() throws Exception {
final IOperation add = service.findFirst("add");
final IOperation subtract = service.findFirst("subtractOperation");
final IOperationContext context = service.createContext();
context.setData(Random.rand(0.0, 10.0, 24, 1024, 1024));
// context.setSlicing("all"); //
context.setDataDimensions(new int[]{1,2});
subtract.setModel(new ValueModel(100));
add.setModel(new ValueModel(101));
counter = 0;
context.setVisitor(new IExecutionVisitor.Stub() {
@Override
public void executed(OperationData result, IMonitor monitor) throws Exception {
System.out.println(result.getData().getName());
counter++;
for (int i = 0; i < result.getData().getShape()[0]; i++) {
for (int j = 0; j < result.getData().getShape()[1]; j++) {
if ( result.getData().getDouble(0,i,j)<0 ) throw new Exception("Incorrect value found!");
}
}
}
});
context.setSeries(subtract, add);
service.execute(context);
if ( counter != 24 ) throw new Exception("The counter is "+counter);
}
@Test
public void testSimpleAddAndSubtractOnStackParallel() throws Exception {
final IOperation add = service.findFirst("add");
final IOperation subtract = service.findFirst("subtractOperation");
final IOperationContext context = service.createContext();
context.setData(Random.rand(0.0, 10.0, 24, 1024, 1024));
// context.setSlicing("all"); //
context.setDataDimensions(new int[]{1,2});
subtract.setModel(new ValueModel(100));
add.setModel(new ValueModel(101));
counter = 0;
context.setParallelTimeout(Long.MAX_VALUE);
context.setExecutionType(ExecutionType.PARALLEL);
context.setVisitor(new IExecutionVisitor.Stub() {
@Override
public void executed(OperationData result, IMonitor monitor) throws Exception {
try {
// This sleep simply introduces some random behaviour
// on the parallel jobs so that we definitely get a different order.
final long time = Math.round(Math.random()*1000);
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
++counter;
for (int i = 0; i < result.getData().getShape()[0]; i++) {
for (int j = 0; j < result.getData().getShape()[1]; j++) {
if ( result.getData().getDouble(0,i,j)<0 ) throw new Exception("Incorrect value found!");
}
}
}
});
context.setSeries(subtract, add);
service.execute(context);
Thread.sleep(5000);
if ( counter < 23 ) throw new Exception("Not all jobs completed before timeout in parallel run! Loop count was : "+counter);
Thread.sleep(5000);
if ( counter != 24 ) throw new Exception("The counter is "+counter);
}
@Test
public void testParallelLongerThanDefault() throws Exception {
final IOperation add = service.findFirst("add");
final IOperation subtract = service.findFirst("subtractOperation");
final IOperationContext context = service.createContext();
context.setData(Random.rand(0.0, 10.0, 1024, 1024));
// context.setSlicing("all"); //
context.setDataDimensions(new int[]{1,2});
subtract.setModel(new ValueModel(100));
add.setModel(new ValueModel(101));
context.setExecutionType(ExecutionType.GRAPH);
context.setParallelTimeout(5000);
context.setPoolSize(Runtime.getRuntime().availableProcessors());
context.setVisitor(new IExecutionVisitor.Stub() {
@Override
public void executed(OperationData result, IMonitor monitor) throws Exception {
try {
// This sleep simply introduces some random behaviour
// on the parallel jobs so that we
final long time = Math.round(Math.random()*10000);
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < result.getData().getShape()[0]; i++) {
for (int j = 0; j < result.getData().getShape()[1]; j++) {
if ( result.getData().getDouble(i,j)<0 ) throw new Exception("Incorrect value found!");
}
}
}
});
context.setSeries(subtract, add);
try {
service.execute(context);
} catch (OperationException ne) {
return;
}
throw new Exception("The default wait time of 5000ms should have been reached!");
}
@Test
public void testParallelTimeout() throws Exception {
final IOperation add = service.findFirst("add");
final IOperation subtract = service.findFirst("subtractOperation");
final IOperationContext context = service.createContext();
context.setData(Random.rand(0.0, 10.0, 24, 1024, 1024));
// context.setSlicing("all"); //
context.setDataDimensions(new int[]{1,2});
subtract.setModel(new ValueModel(100));
add.setModel(new ValueModel(101));
counter = 0;
context.setParallelTimeout(Long.MAX_VALUE);
context.setVisitor(new IExecutionVisitor.Stub() {
@Override
public void executed(OperationData result, IMonitor monitor) throws Exception {
try {
// This sleep simply introduces some random behaviour
// on the parallel jobs so that we
final long time = Math.round(Math.random()*10000);
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
counter++;
for (int i = 0; i < result.getData().getShape()[0]; i++) {
for (int j = 0; j < result.getData().getShape()[1]; j++) {
if ( result.getData().getDouble(0,i,j)<0 ) throw new Exception("Incorrect value found!");
}
}
}
});
context.setSeries(subtract, add);
context.setExecutionType(ExecutionType.PARALLEL);
service.execute(context);
Thread.sleep(3000);
assertEquals("Not all jobs completed before timeout in parallel run! counter: " + counter + ", expected: 24", 24, counter);
}
}