/* The contents of this file are subject to the license and copyright terms * detailed in the license directory at the root of the source tree (also * available online at http://fedora-commons.org/license/). */ package fedora.server.journal.readerwriter.multicast.rmi; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Date; import java.util.HashMap; import java.util.Map; import javax.xml.namespace.QName; import javax.xml.stream.XMLEventFactory; import javax.xml.stream.XMLStreamException; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import fedora.server.journal.JournalException; import fedora.server.journal.MockServerForJournalTesting; import fedora.server.journal.readerwriter.multicast.MockMulticastJournalWriter; import fedora.server.management.MockManagementDelegate; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.fail; /** * NOTE: The tests which require a functioning RMI receiver do not work in all * environments, and have been disabled with the "Ignore" annotation. At this * time, I don't know where the problem lies. * * @author Jim Blake */ public class TestRmiTransport { // Supports legacy test runners public static junit.framework.Test suite() { return new junit.framework.JUnit4TestAdapter(TestRmiTransport.class); } private Process rmiRegistryProcess; private StringWriter rmiRegistryProcessOutput; // immaterial to the test - required by the constructor. private static final boolean CRUCIAL = true; private Map<String, String> parameters; private MockMulticastJournalWriter parent; @Before public void initalizeBasicParameters() throws UnknownHostException { parameters = new HashMap<String, String>(); parameters.put(RmiTransport.PARAMETER_HOST_NAME, InetAddress .getLocalHost().getHostName()); parameters.put(RmiTransport.PARAMETER_SERVICE_NAME, "RmiJournalReceiver"); } @Before public void initializeTransportParent() throws JournalException { MockServerForJournalTesting server = new MockServerForJournalTesting(new MockManagementDelegate(), "myHashValue"); parent = new MockMulticastJournalWriter(new HashMap<String, String>(), null, server); } @After public void stopRmiRegistry() throws InterruptedException { if (rmiRegistryProcess != null) { rmiRegistryProcess.destroy(); rmiRegistryProcess.waitFor(); rmiRegistryProcess = null; Thread.sleep(3000); } } @Test(expected = JournalException.class) public void testNoHostParameter() throws JournalException { parameters.remove(RmiTransport.PARAMETER_HOST_NAME); new RmiTransport(parameters, CRUCIAL, parent); } @Test(expected = JournalException.class) public void testInvalidHostParameter() throws JournalException { parameters.put(RmiTransport.PARAMETER_HOST_NAME, "BogusHost"); new RmiTransport(parameters, CRUCIAL, parent); } @Test(expected = JournalException.class) public void testInvalidPortParameter() throws JournalException { parameters.put(RmiTransport.PARAMETER_PORT_NUMBER, "BogusPort"); new RmiTransport(parameters, CRUCIAL, parent); } @Test(expected = JournalException.class) public void testNoServiceNameParameter() throws JournalException { parameters.remove(RmiTransport.PARAMETER_SERVICE_NAME); new RmiTransport(parameters, CRUCIAL, parent); } @Test(expected = JournalException.class) public void testNoRegistry() throws JournalException { new RmiTransport(parameters, CRUCIAL, parent); } @Ignore @Test(expected = JournalException.class) public void testNoSuchService() throws JournalException, IOException { startMockRmiJournalReceiver(); parameters.put(RmiTransport.PARAMETER_SERVICE_NAME, "BogusService"); new RmiTransport(parameters, CRUCIAL, parent); } @Ignore @Test public void testSuccessfulConnection() throws JournalException, IOException { startMockRmiJournalReceiver(); new RmiTransport(parameters, CRUCIAL, parent); } @Ignore @Test public void testOpenCloseShutdownSequence() throws JournalException, IOException { startMockRmiJournalReceiver(); RmiTransport transport = new RmiTransport(parameters, CRUCIAL, parent); transport.openFile("someHash", "aFileName", new Date()); assertCorrectNumberOfCalls(1, 0, 0); transport.closeFile(); assertCorrectNumberOfCalls(1, 1, 1); transport.shutdown(); assertCorrectNumberOfCalls(1, 1, 1); } @Ignore @Test public void testWritesWithSmallBuffer() throws JournalException, IOException, XMLStreamException { startMockRmiJournalReceiver(); parameters.put(RmiTransport.PARAMETER_BUFFER_SIZE, "100"); RmiTransport transport = new RmiTransport(parameters, CRUCIAL, parent); transport.openFile("someHash", "aFileName", new Date()); assertCorrectNumberOfCalls(1, 1, 0); XMLEventFactory factory = XMLEventFactory.newInstance(); QName name1 = new QName("junkyElement1"); QName name2 = new QName("junkyElement12"); transport.getWriter() .add(factory.createStartElement(name1, null, null)); transport.getWriter().add(factory.createEndElement(name1, null)); assertCorrectNumberOfCalls(1, 1, 0); transport.getWriter() .add(factory.createStartElement(name2, null, null)); transport.getWriter().add(factory.createEndElement(name2, null)); transport.closeFile(); assertCorrectNumberOfCalls(1, 3, 1); transport.shutdown(); assertCorrectNumberOfCalls(1, 3, 1); } @Ignore @Test(expected = JournalException.class) public void testReceiverThrowsException() throws IOException, JournalException { startMockRmiJournalReceiver(true); RmiTransport transport = new RmiTransport(parameters, CRUCIAL, parent); transport.openFile("someHash", "aFileName", new Date()); fail("Expected an exception."); } private void startMockRmiJournalReceiver() throws IOException { startMockRmiJournalReceiver(false); } private void startMockRmiJournalReceiver(boolean throwException) throws IOException { String exceptionOption = throwException ? "throwException" : "dontThrow"; ProcessBuilder pb = new ProcessBuilder("java", MockRmiJournalReceiver.class .getName(), exceptionOption); pb.environment() .put("CLASSPATH", System.getProperty("java.class.path")); pb.redirectErrorStream(true); rmiRegistryProcess = pb.start(); StreamEater outputEater = new StreamEater(rmiRegistryProcess.getInputStream()); rmiRegistryProcessOutput = outputEater.getOutput(); } private void assertCorrectNumberOfCalls(int i, int j, int k) { // Give the output a chance to catch up with the registry process. try { Thread.sleep(100); } catch (InterruptedException e) { // ignore an exception } String outputString = rmiRegistryProcessOutput.toString(); String[] split1 = outputString.split("openFile\\("); assertEquals("wrong number of openFile() calls", i, split1.length - 1); String[] split2 = outputString.split("writeText\\("); assertEquals("wrong number of writeText() calls", j, split2.length - 1); String[] split3 = outputString.split("closeFile\\("); assertEquals("wrong number of closeFile() calls", k, split3.length - 1); } private static class StreamEater extends Thread { private final InputStream stream; private final StringWriter output = new StringWriter(); private final byte[] buffer = new byte[4096]; public StreamEater(InputStream stream) { this.stream = stream; start(); } @Override public void run() { try { int howMany = 0; while (true) { howMany = stream.read(buffer); if (howMany > 0) { output.write(new String(buffer, 0, howMany)); } else if (howMany == 0) { Thread.yield(); } else { break; } } } catch (IOException e) { e.printStackTrace(); } finally { try { stream.close(); } catch (IOException e) { e.printStackTrace(); } } } public StringWriter getOutput() { return output; } } }