package org.baderlab.csplugins.enrichmentmap.integration; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import javax.inject.Inject; import org.cytoscape.model.CyColumn; import org.cytoscape.model.CyNetwork; import org.cytoscape.model.CyNetworkManager; import org.cytoscape.model.CyRow; import org.cytoscape.model.CyTable; import org.cytoscape.model.subnetwork.CyRootNetwork; import org.cytoscape.task.read.LoadNetworkFileTaskFactory; import org.cytoscape.work.TaskIterator; import org.junit.runner.RunWith; import org.ops4j.pax.exam.junit.PaxExam; import com.google.common.collect.ImmutableSet; /** * Most of this was copied from the gui-distribution/integration-test project. */ @RunWith(PaxExam.class) public abstract class BaseIntegrationTest extends PaxExamConfiguration { @Inject private LoadNetworkFileTaskFactory loadNetworkFileTaskFactory; @Inject private CyNetworkManager networkManager; protected CyNetwork importNetworkFromFile(String path, String fileName) throws IOException { Set<CyNetwork> existingNetworks = networkManager.getNetworkSet(); // import the network File file = TestUtils.createTempFile(path, fileName); TaskIterator taskIterator = loadNetworkFileTaskFactory.createTaskIterator(file); SerialTestTaskManager taskManager = new SerialTestTaskManager(); taskManager.execute(taskIterator); // get a reference to the imported network Set<CyNetwork> networksAfterImport = networkManager.getNetworkSet(); networksAfterImport.removeAll(existingNetworks); assertEquals(1, networksAfterImport.size()); return networksAfterImport.iterator().next(); } /** * If there is only one network it will be returned, otherwise the test will fail. */ protected CyNetwork assertAndGetOnlyNetwork() { Set<CyNetwork> networks = networkManager.getNetworkSet(); assertEquals(1, networks.size()); return networks.iterator().next(); } public void assertNetworksEqual(CyNetwork expectedNetwork, CyNetwork actualNetwork, Set<String> columnsToIgnore) { columnsToIgnore = columnsToIgnore == null ? Collections.emptySet() : columnsToIgnore; assertTablesEqual(expectedNetwork.getDefaultNodeTable(), actualNetwork.getDefaultNodeTable(), false, columnsToIgnore); assertTablesEqual(expectedNetwork.getDefaultEdgeTable(), actualNetwork.getDefaultEdgeTable(), true, columnsToIgnore); } public void assertTablesEqual(CyTable expectedTable, CyTable actualTable, boolean edgeTable, Set<String> columnsToIgnore) { List<CyColumn> expectedColumns = new ArrayList<>(expectedTable.getColumns()); // Remove columns to ignore expectedColumns = expectedColumns.stream() .filter(c -> !columnsToIgnore.contains(c.getName())) .filter(c -> !CyNetwork.SUID.equals(c.getName())) .collect(Collectors.toList()); // Note if the two networks are in the same collection they will probably have the same columns. // Test columns are the same for(CyColumn expectedColumn : expectedColumns) { String name = expectedColumn.getName(); // if(!CyNetwork.SUID.equals(name)) { CyColumn actualColumn = actualTable.getColumn(name); assertNotNull("Column '" + name + "' does not exist", actualColumn); assertEquals ("Column '" + name + "' is wrong type", expectedColumn.getType(), actualColumn.getType()); // } } List<CyRow> expectedRows = expectedTable.getAllRows(); List<CyRow> actualRows = actualTable.getAllRows(); assertEquals("Tables are not the same size", expectedRows.size(), actualRows.size()); if(edgeTable) { assertEdgeTableRowsEqual(expectedColumns, expectedRows, actualRows); } else { // node table or other table // need to sort both Lists sort(expectedColumns, expectedRows); sort(expectedColumns, actualRows); for(int i = 0; i < expectedRows.size(); i++) { CyRow expectedRow = expectedRows.get(i); CyRow actualRow = actualRows.get(i); assertAttributesEqual(expectedColumns, expectedRow, actualRow); } } } /** * For edges we need to ignore the directionality. */ private void assertEdgeTableRowsEqual(List<CyColumn> expectedColumns, List<CyRow> expectedRows, List<CyRow> actualRows) { Set<String> columnsToIgnore = ImmutableSet.of(CyNetwork.NAME, CyRootNetwork.SHARED_NAME); List<CyColumn> columnsToTest = expectedColumns.stream().filter(c->!columnsToIgnore.contains(c.getName())).collect(Collectors.toList()); Map<SimilarityKey, CyRow> expectedRowsByKey = new HashMap<>(); for(CyRow row : expectedRows) { SimilarityKey key = SimilarityKey.parse(row.get(CyNetwork.NAME, String.class)); expectedRowsByKey.put(key, row); } for(CyRow actual : actualRows) { SimilarityKey key = SimilarityKey.parse(actual.get(CyNetwork.NAME, String.class)); CyRow expected = expectedRowsByKey.remove(key); assertNotNull(key.toString(), expected); assertAttributesEqual(columnsToTest, expected, actual); } assertTrue(expectedRowsByKey.isEmpty()); } private void assertAttributesEqual(List<CyColumn> columnsToTest, CyRow expected, CyRow actual) { for(CyColumn column : columnsToTest) { String name = column.getName(); Class<?> type = column.getType(); // if(!CyNetwork.SUID.equals(name)) { Object expectedValue = expected.get(name, type); Object actualValue = actual.get(name, type); String message = "Col: " + name + ","; if(type.equals(List.class)) { // because CyListImpl doesn't implement equals() assertArrayEquals(message, ((List<?>)expectedValue).toArray(), ((List<?>)actualValue).toArray() ); } else { assertEquals(message, expectedValue, actualValue); } // } } } /** * I don't need to actually sort the rows in a meaningful way, just make it deterministic. */ public void sort(List<CyColumn> columns, List<CyRow> rows) { Comparator<CyRow> rowComparator = null; for(CyColumn column : columns) { // if(!CyNetwork.SUID.equals(column.getName())) { Comparator<CyRow> c = Comparator.comparing((CyRow row) -> row.get(column.getName(), column.getType()).toString()); rowComparator = rowComparator == null ? c : rowComparator.thenComparing(c); // } } Collections.sort(rows, rowComparator); } /** * This method exists because: * - The JUnit 4.11 version of assertArrayEquals actually has a bug in it. * - Need to sort the arrays. */ private static void assertArrayEquals(String message, Object[] expected, Object[] actual) { Arrays.sort(expected); Arrays.sort(actual); assertTrue(message, Arrays.equals(expected, actual)); } public void printList(List<CyRow> xs) { xs.stream().limit(20).forEach(row -> System.out.println(row.getAllValues())); } }