blob: 763894a2de7b25ef84ad5de184ad34bb295304a1 [file] [log] [blame]
// DiseaseModelScenarioTest.java
package org.eclipse.stem.diseasemodels.standard.tests;
/*******************************************************************************
* Copyright (c) 2006 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;
import junit.framework.TestCase;
import org.eclipse.emf.common.util.URI;
import org.eclipse.stem.core.graph.Graph;
import org.eclipse.stem.core.graph.LabelValue;
import org.eclipse.stem.core.graph.NodeLabel;
import org.eclipse.stem.core.model.Decorator;
import org.eclipse.stem.core.model.Model;
import org.eclipse.stem.core.model.NodeDecorator;
import org.eclipse.stem.core.scenario.Scenario;
import org.eclipse.stem.core.scenario.tests.ScenarioTest;
import org.eclipse.stem.definitions.nodes.Region;
import org.eclipse.stem.diseasemodels.standard.DiseaseModel;
import org.eclipse.stem.diseasemodels.standard.DiseaseModelLabel;
import org.eclipse.stem.diseasemodels.standard.DiseaseModelLabelValue;
/**
* This class is the top-level class for all test of disease models in a
* particular scenario.
*/
public abstract class DiseaseModelScenarioTest extends TestCase {
protected static final String DIRECTORY = "temp";
/**
* The key for scenario 1x1
*/
public static final String TEST_SCENARIO1x1_KEY = "1x1";
/**
* The key for scenario 1x2
*/
public static final String TEST_SCENARIO1x2_KEY = "1x2";
/**
* The key for scenario 1x3
*/
public static final String TEST_SCENARIO1x3_KEY = "1x3";
/**
* The key for scenario 2x2
*/
public static final String TEST_SCENARIO2x2_KEY = "2x2";
/**
* The key for scenario 3x3
*/
public static final String TEST_SCENARIO3x3_KEY = "3x3";
// TODO implement the disease model test scenarios
// You need to un-comment the testSpecifications and then in each of the
// test implementations you're going to need to figure out the valid disease
// model label values. see StochasticSEIRScenarioTest.java etc.
protected static TestSpec[] testSpecifications = new TestSpec[] { new TestSpec(
1, 1, TEST_SCENARIO1x1_KEY)
/*
* new TestSpec(1, 1, TEST_SCENARIO1x1_KEY), new TestSpec(1, 2,
* TEST_SCENARIO1x2_KEY), new TestSpec(1, 3, TEST_SCENARIO1x3_KEY), new
* TestSpec(2, 2, TEST_SCENARIO2x2_KEY), new TestSpec(3, 3,
* TEST_SCENARIO3x3_KEY)
*/
};
/**
* @param expectedLabelValues
* the expected label values for the test
* @return how many labels are expected to be updated by a disease model for
* each test.
*/
protected static int computeExpectedNumberOfLabels(
final LabelValue[][][] expectedLabelValues) {
return expectedLabelValues[0].length * expectedLabelValues[0][0].length;
} // computeExpectedNumberOfLabels
/**
* @param numRows
* the number of rows in the lattice
* @param numColumns
* the number of columns in the lattice
* @return a scenario with nodes in a lattice with a disease model.
*/
public Scenario createFixture(final int numRows, final int numColumns) {
final Collection<NodeDecorator> DISEASE_MODELS = new ArrayList<NodeDecorator>();
DISEASE_MODELS.addAll(getDiseaseModelsToTest());
final Model model = DiseaseModelTestUtil.createLatticeModel(
DISEASE_MODELS, numRows, numColumns,
DiseaseModelTestUtil.TEST_POPULATION_COUNT,
DiseaseModelTestUtil.TEST_AREA);
final Scenario retValue = DiseaseModelTestUtil.createLatticeScenario(
getScenarioDecorators(model), model);
assert retValue.sane();
return retValue;
} // createFixture
/**
* Execute all of the tests specified in testSpecifications
*/
public void testDoAllTests() {
for (final TestSpec testSpec : testSpecifications) {
doTest(testSpec);
}
} // testDoAllTests
/**
* Test serializing and de-serializing scenarios
*/
public void testSerializeDeserializeScenario() {
final int[][] rowColumns = new int[][] { { 1, 1 }, { 1, 2 }, { 3, 3 } };
for (final int[] rowColumn : rowColumns) {
final Scenario fixture = createFixture(rowColumn[0], rowColumn[1]);
final URI uri = createSerializationURI(fixture);
ScenarioTest.serializeDeserializeScenario(fixture, uri);
}
} // testSerializeDeserializeScenario
/**
* @param testSpec
* a test specification
*/
private void doTest(final TestSpec testSpec) {
doTest(createFixture(testSpec.numRows, testSpec.numColumns),
testSpec.scenarioDiseaseKey);
} // doTest
/**
* @param scenario
* the scenario to test
* @param scenarioDiseaseKey
* the unique identifier of the scenario test
*/
private void doTest(final Scenario scenario, final String scenarioDiseaseKey) {
final int numSteps = getNumberOfSteps(scenarioDiseaseKey);
// Step through the disease computation by using the actual scenario
// step method
for (int step = 0; step < numSteps; step++) {
// Make one step...
scenario.step();
// ... and make sure everything looks ok
assertTrue(scenario.sane());
// Now validate the computed values for each disease model in the
// scenario...
for (final DiseaseModel diseaseModel : getDiseaseModels(scenario)) {
// Really only need to check this once...
if (step == 0) {
assertTrue(
"Disease model \""
+ diseaseModel.getDublinCore().getTitle()
+ "\" \""
+ scenario.getDublinCore().getTitle()
+ "\" \"" + scenarioDiseaseKey,
diseaseModel.getLabelsToUpdate().size() == getExpectedNumberOfLabelsToUpdate(scenarioDiseaseKey));
} // if
assertTrue(validateDiseaseModelState(scenario,
scenarioDiseaseKey, step, diseaseModel,
getExpectedDiseaseModelState(scenarioDiseaseKey, step)));
} // for each disease model
} // for each step
} // doTest
/**
* @param scenario
* the scenario whose state is to be verified
* @param scenarioDiseaseKey
* the unique identifier of the scenario test
* @param step
* the step number in the test being verified
* @param expectedDiseaseModelState
* the disease model label values that should be present
*/
private boolean validateDiseaseModelState(final Scenario scenario,
final String scenarioDiseaseKey, final int step,
final DiseaseModel diseaseModel,
final LabelValue[][] expectedDiseaseModelState) {
final boolean retValue = true;
final Graph canonicalGraph = scenario.getCanonicalGraph();
for (int row = 0; row < expectedDiseaseModelState.length; row++) {
for (int column = 0; column < expectedDiseaseModelState[row].length; column++) {
final Region region = DiseaseModelTestUtil.getRegion(
canonicalGraph, row, column);
final LabelValue labelValue = expectedDiseaseModelState[row][column];
final LabelValue dmLabelValue = getCurrentDiseaseModelLabelValue(
region, diseaseModel);
assertTrue("Disease model \""
+ diseaseModel.getDublinCore().getTitle() + "\" ("
+ scenarioDiseaseKey + ") step: " + step + " [" + row
+ ", " + column + "] Got \"" + dmLabelValue.toString()
+ "\", expected \"" + labelValue.toString() + "\"",
compareLabelValues(labelValue, dmLabelValue));
} // for column
} // for row
return retValue;
} // validateDiseaseModelState
/**
* @param labelValue
* @param dmLabelValue
* @return <code>true</code> if the labels are "equal". We do a "fuzzy"
* compare on the double values. We declare them "equal" if they
* differ by less than a specified tolerance.
*/
protected boolean compareLabelValues(final LabelValue lableValue1,
final LabelValue lableValue2) {
boolean retValue = true;
final DiseaseModelLabelValue dmLV1 = (DiseaseModelLabelValue) lableValue1;
final DiseaseModelLabelValue dmLV2 = (DiseaseModelLabelValue) lableValue2;
retValue = retValue
&& DiseaseModelTestUtil.closeEnough(dmLV1.getDiseaseDeaths(),
dmLV2.getDiseaseDeaths());
return retValue;
} // compareLabelValues
/**
* @param fixture
* the scenario to test
* @return the URI to use to serialize and then de-serialize the scenario
* under test
*/
private URI createSerializationURI(final Scenario fixture) {
final URI uri = URI
.createURI(DIRECTORY + "/" + getDiseaseURIPrefix()
+ encodeTitle(fixture.getDublinCore().getTitle())
+ ".scenario");
return uri;
} // createSerializationURI
/**
* @param title
* the title of a scenario
* @return the title with all whitespace removed
*/
private String encodeTitle(final String title) {
final StringBuilder sb = new StringBuilder();
final StringTokenizer st = new StringTokenizer(title, ",.[] ");
while (st.hasMoreTokens()) {
sb.append(st.nextToken());
} // while
return sb.toString();
} // encodeTitle
/**
* @param region
* the region node to search for a label updated by the disease
* model
* @param diseaseModel
* the disease model
* @return the current value of the label on the node updated by the disease
* model
*/
private LabelValue getCurrentDiseaseModelLabelValue(final Region region,
final DiseaseModel diseaseModel) {
LabelValue retValue = null;
for (final Object element : region.getLabels()) {
final NodeLabel nodeLabel = (NodeLabel) element;
if (nodeLabel instanceof DiseaseModelLabel) {
final DiseaseModelLabel diseaseModelLabel = (DiseaseModelLabel) nodeLabel;
// Is this label updated by the disease model?
if (diseaseModel.getLabelsToUpdate()
.contains(diseaseModelLabel)) {
// Yes
retValue = diseaseModelLabel.getCurrentValue();
break;
}
} // if
} // for each node label
return retValue;
} // getCurrentDiseaseModelLabelValue
/**
*
* @param scenario
* a scenario
* @return all of the disease models in the scenario.
*/
protected List<DiseaseModel> getDiseaseModels(final Scenario scenario) {
final List<DiseaseModel> retValue = new ArrayList<DiseaseModel>();
for (final Object element : scenario.getCanonicalGraph()
.getDecorators()) {
final Decorator decorator = (Decorator) element;
if (decorator instanceof DiseaseModel) {
retValue.add((DiseaseModel) decorator);
}
} // for each decorator in the canonical graph
return retValue;
} // getDiseaseModel
/**
* @param diseaseScenarioKey
* the key identifying the test
* @return the number of disease model computations to execute for the test.
*/
protected abstract int getNumberOfSteps(final String diseaseScenarioKey);
/**
* @param diseaseScenarioKey
* the key identifying the test
* @return the expected number of labels a disease model will update
*/
protected abstract int getExpectedNumberOfLabelsToUpdate(
final String diseaseScenarioKey);
/**
* @param diseaseScenarioKey
* identifier that uniquely identifies the combination of disease
* and scenario.
* @param step
* the simulation step that has been completed.
* @return an array of disease model label values that are the expected
* values after the given step of the simulation.
*/
protected abstract LabelValue[][] getExpectedDiseaseModelState(
final String diseaseScenarioKey, final int step);
/**
* @return the disease models to be tested
*/
public abstract List<NodeDecorator> getDiseaseModelsToTest();
/**
* @param model
* the model to generate scenario decorators for
* @return the scenario decorators to include in a fixture
*/
public abstract Collection<Decorator> getScenarioDecorators(Model model);
/**
* @return a string to be used in a URI to prefix the scenario files being
* serialized for a particular disease under test.
*/
protected abstract String getDiseaseURIPrefix();
/**
* This class represents the parameters for the specification of a test
*/
protected static final class TestSpec {
/**
* The number of rows in the lattice graph
*/
public int numRows = 0;
/**
* The number of columns in the lattice graph
*/
public int numColumns = 0;
/**
* The scenario/disease key of the test.
*/
public String scenarioDiseaseKey = "";
/**
* @param numRows
* @param numColumns
* @param scenarioDiseaseKey
*/
protected TestSpec(final int numRows, final int numColumns,
final String scenarioDiseaseKey) {
super();
this.numRows = numRows;
this.numColumns = numColumns;
this.scenarioDiseaseKey = scenarioDiseaseKey;
}
} // TestSpec
} // DiseaseModelScenarioTest