edu.cmu.tetradapp.test.TestSessionNode Maven / Gradle / Ivy
///////////////////////////////////////////////////////////////////////////////
// For information as to what this class does, see the Javadoc, below. //
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, //
// 2007, 2008, 2009, 2010, 2014, 2015, 2022 by Peter Spirtes, Richard //
// Scheines, Joseph Ramsey, and Clark Glymour. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program; if not, write to the Free Software //
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //
///////////////////////////////////////////////////////////////////////////////
package edu.cmu.tetradapp.test;
import edu.cmu.tetrad.util.Parameters;
import edu.cmu.tetradapp.session.*;
import org.junit.Test;
import java.rmi.MarshalledObject;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import static org.junit.Assert.*;
/**
* Tests the operation of the session node. The session node needs to be able
* to:> 0
*
* - Add and remove parents or children without violating the constraint that the set of models for the
* parents of a node at any time should be a subset of the set of objects needed to constuct an object of the given
* model class for some constructor of the model class. Note that in adding parents or children, the lists of parents or
* children of other nodes need to be adjusted and kept in sync.
*
- Create a new model given the parents of the node,
* provided the models of the node's parents can be mapped unambiguously onto the objects required for some constructor
* of the model class.
*
- Fire events to listeners when any of the following happens: (a) parents are added or removed;
* (b) models are created or destroyed. The adding and removing of listeners must also be tested.
*
*
* @author josephramsey
*/
public class TestSessionNode {
/**
* A string field to help debug events.
*/
private String eventId;
/**
* Tests the existsConstructor
method, which determines
* whether a constructor exists in the model class that accepts objects of the given classes as arguments.> 0
*/
@Test
public void testExistsConstructor() {
SessionNode node = new SessionNode(Type1.class);
Class[] testSet1 = {Type1.class};
Class[] testSet2 = {Type2.class};
Class[] testSet3 = {Type3.class};
Class[] testSet4 = {Type2.class, Type3.class};
Class[] testSet5 = {Type3.class, Type4.class};
Class[] testSet6 = {Type2.class, Type2.class};
assertFalse(node.existsConstructor(Type1.class, testSet1));
assertTrue(node.existsConstructor(Type1.class, testSet2));
assertTrue(node.existsConstructor(Type1.class, testSet3));
assertTrue(node.existsConstructor(Type1.class, testSet4));
assertFalse(node.existsConstructor(Type1.class, testSet5));
assertFalse(node.existsConstructor(Type1.class, testSet6));
}
/**
* Tests whether the getValueCombination method is working. This method is used to generate combinations of parent
* model classes.
*/
@Test
public void testGetValueCombination() {
SessionNode node = new SessionNode(Type1.class);
int[] numValues = {2, 3, 4};
assertEquals(24, node.getProduct(numValues));
assertTrue(isTheSame(node.getValueCombination(0, numValues), 0, 0, 0));
assertTrue(isTheSame(node.getValueCombination(5, numValues), 0, 1, 1));
assertTrue(isTheSame(node.getValueCombination(10, numValues), 0, 2, 2));
assertTrue(isTheSame(node.getValueCombination(15, numValues), 1, 0, 3));
assertTrue(isTheSame(node.getValueCombination(19, numValues), 1, 1, 3));
assertTrue(isTheSame(node.getValueCombination(23, numValues), 1, 2, 3));
}
/**
* Helper method for testGetValueCombination to test whether the given array has the given three values in it.
*/
private boolean isTheSame(int[] arr, int n1, int n2, int n3) {
return (arr[0] == n1) && (arr[1] == n2) && (arr[2] == n3);
}
/**
*
Tests the assignParameters
method for the case where each
* model contains exactly one model type. Must test the following:> 0
*
- The order of the classes of the returned argument array
* must be the same as the order of the classes in the parameterTypes array.
*
- If one of the classes in the parameterTypes array is null, null
* should be returned.
- If an object of some type required by the
* parameterTypes array does not exist in the object array, null should be
* returned.
- If there are more objects in the object array than are
* required by the parameterTypes array, null should be returned.
*
*/
@Test
public void testAssignParameters1() {
// Set up a dummy session node to access the assign parameters
// method.
SessionNode node = new SessionNode(Type1.class);
// Set up a list of objects to get parameters from.
Type2 object1 = new Type2(new Parameters());
Type3 object2 = new Type3(object1, new Parameters());
List objects = new ArrayList();
objects.add(object1);
objects.add(object2);
// Try it with the correct parameter types...
Class[] parameterTypes1 = {Type2.class, Type3.class};
Object[] arguments1 = node.assignParameters(parameterTypes1, objects);
assertNotNull(arguments1);
for (int i = 0; i < parameterTypes1.length; i++) {
assertEquals(arguments1[i].getClass(), parameterTypes1[i]);
}
// Try it with the wrong set...
Class[] parameterTypes2 = {Type1.class, Type3.class};
Object[] arguments2 = node.assignParameters(parameterTypes2, objects);
assertNull(arguments2);
// Try it with the right set but with a null inserted.
try {
Class[] parameterTypes3 =
{Type2.class, Type3.class, null};
node.assignParameters(parameterTypes3, objects);
fail("Should not have been able to assign parameters with a null " +
"parameter in the list.");
} catch (NullPointerException e) {
// What we wanted.
}
// Try it with too many types...
Class[] parameterTypes4 =
{Type2.class, Type3.class, Type4.class};
Object[] arguments4 = node.assignParameters(parameterTypes4, objects);
assertNull(arguments4);
}
/**
* Tests whether model classes can identified correctly as consistent.
*/
// @Test
public void testIsConsistentModelClass() {
// Test single model classes.
SessionNode node1 = new SessionNode(Type1.class);
SessionNode node2 = new SessionNode(Type2.class);
SessionNode node3 = new SessionNode(Type3.class);
SessionNode node4 =
new SessionNode(new Class[]{Type1.class, Type2.class});
SessionNode node6 = new SessionNode(
new Class[]{Type1.class, Type2.class, Type3.class});
SessionNode node7 =
new SessionNode(new Class[]{Type1.class, Type4.class});
List parents = new ArrayList();
// An empty set of parents should always be consistent.s
//assertTrue(node1.isConsistentModelClass(Type1.class, parents));
parents.add(node1);
//assertTrue(!node1.isConsistentModelClass(Type1.class, parents));
parents.add(node2);
//assertTrue(!node1.isConsistentModelClass(Type1.class, parents));
parents.add(node3);
//assertTrue(!node1.isConsistentModelClass(Type1.class, parents));
parents.remove(node1);
//assertTrue(node1.isConsistentModelClass(Type1.class, parents));
parents.remove(node2);
//assertTrue(node1.isConsistentModelClass(Type1.class, parents));
parents.remove(node3);
// Type 1 requires 2 & 3; node 4 has a type 2 in it, so this
// is consistent. We could go on to add, say, node6, which has
// a type 3 in it, and that would be great. At that point we
// could construct the model.
parents.add(node4);
assertTrue(node1.isConsistentModelClass(Type1.class, parents, false));
parents.add(node6);
assertTrue(node1.isConsistentModelClass(Type1.class, parents, false));
// If we remove node6 now and add node7, which doesn't contain
// a 3, it should fail.
parents.remove(node6);
parents.add(node7);
assertFalse(node1.isConsistentModelClass(Type1.class, parents, false));
}
/**
* Tests whether ClassA x = y for some ClassA in a list where x is of type ClassA and y is of type ClassB.
*/
@Test
public void testGetAssignableClass() {
SessionNode node1 = new SessionNode("???", "Node1", Type1.class);
List list = new ArrayList();
list.add(List.class);
list.add(Map.class);
list.add(String.class);
assertNotNull(node1.getAssignableClass(list, ArrayList.class));
assertNotNull(node1.getAssignableClass(list, SortedMap.class));
assertNull(node1.getAssignableClass(list, Object.class));
}
/**
* Tests whether parent nodes can be added and removed correctly.
*/
// @Test
public void testAddRemoveParents() {
SessionNode node1 = new SessionNode("???", "Node1", Type1.class);
SessionNode node2 = new SessionNode("???", "Node2", Type2.class);
SessionNode node3 = new SessionNode("???", "Node2", Type3.class);
SessionNode node4 = new SessionNode("???", "Node4", Type4.class);
assertTrue(node1.addParent(node2));
assertEquals(1, node2.getNumChildren());
assertEquals(1, node1.getNumParents());
assertFalse(node1.addParent(node4));
assertTrue(node1.addParent(node3));
assertFalse(node1.removeParent(node4));
assertTrue(node1.removeParent(node2));
assertEquals(1, node1.getNumParents());
assertTrue(node1.removeParent(node3));
assertEquals(0, node1.getNumParents());
}
/**
* Tests whether children nodes can be added and removed correctly.
*/
// @Test
public void testAddRemoveChildren() {
SessionNode node1 = new SessionNode("???", "Node1", Type1.class);
SessionNode node2 = new SessionNode("???", "Node2", Type2.class);
SessionNode node3 = new SessionNode("???", "Node3", Type3.class);
SessionNode node4 = new SessionNode("???", "Node4", Type4.class);
assertTrue(node2.addChild(node1));
assertEquals(1, node2.getNumChildren());
assertEquals(1, node1.getNumParents());
assertFalse(node4.addChild(node1));
assertTrue(node3.addChild(node1));
assertFalse(node4.removeChild(node1));
assertEquals(1, node2.getNumChildren());
assertEquals(1, node3.getNumChildren());
assertTrue(node2.removeChild(node1));
assertTrue(node3.removeChild(node1));
assertEquals(0, node3.getNumChildren());
}
/**
* Tests whether the consistent model classes are calculated correctly. Note that this method should not return
* anything but null unless all of the parent classes have models in them.
*
* @throws Exception if something goes wrong.
*/
// @Test
public void testGetConsistentModelClasses() throws Exception {
final boolean simulation = true;
SessionNode node1 = new SessionNode(new Class[]{Type1.class});
SessionNode node2 = new SessionNode(new Class[]{Type2.class});
SessionNode node3 = new SessionNode(new Class[]{Type3.class});
assertTrue(node1.addParent(node2));
assertTrue(node1.addParent(node3));
assertTrue(node3.addParent(node2));
Class[] classes = node1.getConsistentModelClasses(false);
assertNull(classes);
try {
node2.createModel(Type2.class, simulation);
node3.createModel(Type3.class, simulation);
} catch (RuntimeException e) {
fail("Model not created.");
}
classes = node1.getConsistentModelClasses(false);
assertNotNull(classes);
assertEquals(classes[0], Type1.class);
}
/**
* Tests whether a model can be created correctly.
*/
// @Test
public void testCreateModel() {
final boolean simulation = true;
SessionNode node1 = new SessionNode(Type1.class);
SessionNode node2 = new SessionNode(Type2.class);
SessionNode node3 = new SessionNode(Type3.class);
node3.addParent(node2);
node1.addParent(node2);
node1.addParent(node3);
try {
node2.createModel(Type2.class, simulation);
node3.createModel(Type3.class, simulation);
node1.createModel(Type1.class, simulation);
} catch (Exception e) {
e.printStackTrace();
fail("Model not created.");
}
node1.destroyModel();
assertNull(node1.getModel());
}
/**
* Tests to make sure events are sent and received properly.
*/
// @Test
public void testEvents() {
final boolean simulation = true;
SessionListener listener = new SessionListener() {
/**
* This method is called when a node is added.
*/
public void nodeAdded(SessionEvent event) {
setEventId("nodeAdded");
}
/**
* This method is called when a node is removed.
*/
public void nodeRemoved(SessionEvent event) {
setEventId("nodeRemoved");
}
/**
* This method is called when a parent is added.
*/
public void parentAdded(SessionEvent event) {
setEventId("parentAdded");
}
/**
* This method is called when a parent is removed.
*/
public void parentRemoved(SessionEvent event) {
setEventId("parentRemoved");
}
/**
* This method is called when a model is created for a node.
*/
public void modelCreated(SessionEvent event) {
setEventId("modelCreated");
}
/**
* This method is called when a model is destroyed for a node.
*/
public void modelDestroyed(SessionEvent event) {
setEventId("modelDestroyed");
}
/**
* This method is called when a model is destroyed for a node.
*/
public void modelUnclear(SessionEvent event) {
setEventId("modelUnclear");
}
/**
* This method is called when a node is executed manually.
*/
public void executionStarted(SessionEvent event) {
setEventId("executionBegun");
}
/**
* This method is called when a node is executed manually.
*/
public void repetitionChanged(SessionEvent event) {
setEventId("repetitionChanged");
}
/**
* This method is called when a node is executed manually.
*/
public void addingEdge(SessionEvent event) {
setEventId("addingEdge");
}
};
// Create up some nodes.
SessionNode node1 = new SessionNode("???", "Node1", Type1.class);
SessionNode node2 = new SessionNode("???", "Node2", Type2.class);
SessionNode node3 = new SessionNode("???", "Node3", Type3.class);
// Listen to node1.
node1.addSessionListener(listener);
// Test adding and removing parents and children.
try {
setEventId(null);
node1.addParent(node2);
assertEquals("parentAdded", getEventId());
setEventId(null);
node1.removeParent(node2);
assertEquals("parentRemoved", getEventId());
setEventId(null);
node2.addChild(node1);
assertEquals("parentAdded", getEventId());
setEventId(null);
node2.removeChild(node1);
assertEquals("parentRemoved", getEventId());
// Test model created.
node1.addParent(node2);
node1.addParent(node3);
node3.addParent(node2);
node2.createModel(Type2.class, simulation);
node3.createModel(Type3.class, simulation);
setEventId(null);
node1.createModel(Type1.class, simulation);
assertEquals("modelCreated", getEventId());
setEventId(null);
node1.destroyModel();
assertEquals("modelDestroyed", getEventId());
// Test reassess model.
node1.createModel(Type1.class, simulation);
assertNotNull(node1.getModel());
node2.destroyModel();
assertNull(node1.getModel());
} catch (Exception e) {
fail(e.getMessage());
}
}
private String getEventId() {
return this.eventId;
}
private void setEventId(String eventId) {
this.eventId = eventId;
}
/**
* Tests the isStructurallyIdentical
method.
*/
// @Test
public void testStructuralIdentity() {
final boolean simulation = true;
SessionNode node1 = new SessionNode(Type1.class);
SessionNode node2 = new SessionNode(Type2.class);
SessionNode node3 = new SessionNode(Type3.class);
try {
node1.addParent(node2);
node1.addParent(node3);
node3.addParent(node2);
node2.createModel(Type2.class, simulation);
node3.createModel(Type3.class, simulation);
node1.createModel(Type1.class, simulation);
assertTrue(node1.isStructurallyIdentical(node1));
assertFalse(node1.isStructurallyIdentical(node2));
} catch (Exception e) {
fail(e.getMessage());
}
}
/**
* Tests whether the session can be serialized and reconstructed correctly. This only tests the skeletal form of the
* serialization--serialization of each specific model has to be tested separately in those models, since the
* session class itself is not supposed to have any knowledge of specific models. (For the test, we just make up a
* few classes and try serializing those.)
*/
// @Test
public void testSerialization() {
final boolean simulation = true;
SessionNode node1 = new SessionNode(Type1.class);
SessionNode node2 = new SessionNode(Type2.class);
SessionNode node3 = new SessionNode(Type3.class);
node1.addParent(node2);
node1.addParent(node3);
node3.addParent(node2);
try {
node2.createModel(Type2.class, simulation);
node3.createModel(Type3.class, simulation);
node1.createModel(Type1.class, simulation);
} catch (Exception e) {
fail("Model not created.");
}
SessionNode node1Copy = null;
try {
node1Copy = (SessionNode) new MarshalledObject(node1).get();
} catch (Exception e) {
fail("Serialization failed.");
}
assertTrue(node1.isStructurallyIdentical(node1Copy));
}
/**
* Tests whether parameters can be added correctly.
*/
// @Test
public void testParameterization() {
final boolean simulation = true;
SessionNode node1 = new SessionNode(Type1.class);
SessionNode node2 = new SessionNode(Type2.class);
SessionNode node3 = new SessionNode(Type3.class);
Type2 param = new Type2(new Parameters());
node1.putParam(Type1.class, new Parameters());
node1.addParent(node3);
node3.addParent(node2);
try {
node2.createModel(Type2.class, simulation);
node3.createModel(Type3.class, simulation);
// node1.createModel(Type1.class, simulation);
} catch (Exception e) {
e.printStackTrace();
fail("Model not created.");
}
node1.destroyModel();
try {
node1.createModel(simulation);
} catch (Exception e) {
fail("Model not created.");
}
}
/**
* Tests whether the name of the node is set correctly.
*/
@Test
public void testSetName() {
final String name = "Test";
SessionNode node1 = new SessionNode("???", name, Type1.class);
assertEquals(name, node1.getDisplayName());
}
}