001package edu.pdx.cs.joy.family; 002 003import org.junit.jupiter.api.AfterEach; 004import org.junit.jupiter.api.Assertions; 005import org.junit.jupiter.api.BeforeEach; 006import org.junit.jupiter.api.io.TempDir; 007 008import java.io.File; 009import java.io.PrintWriter; 010import java.io.StringWriter; 011import java.rmi.RemoteException; 012import java.rmi.registry.LocateRegistry; 013import java.rmi.registry.Registry; 014import java.util.Calendar; 015import java.util.Date; 016 017import static org.junit.jupiter.api.Assertions.assertNotNull; 018 019 020/** 021 * This is the abstract superclass for all of the remote family 022 * tree tests. 023 */ 024public abstract class RemoteTestCase { 025 026 /** The port on which the RMI registry runs */ 027 private static final int RMI_PORT = 028 Integer.getInteger("RMI_PORT", 1999).intValue(); 029 030 /** An RMI Registry that is co-located in the VM in which the test 031 * runs */ 032 private static Registry registry; 033 034 /** The name of this test */ 035 private String name = "RemoteTestCase" + System.currentTimeMillis(); 036 037 /** 038 * Creates an empty <code>RemoteFamilyTree</code> and binds it into 039 * the RMI namespace. 040 */ 041 @BeforeEach 042 public void setUp(@TempDir File tempDir) { 043 try { 044 File file = new File(tempDir, "familyTree.xml"); 045 file.delete(); 046 file.deleteOnExit(); 047 RemoteFamilyTree tree = new XmlRemoteFamilyTree(file); 048 this.bind(tree); 049 050 } catch (Exception ex) { 051 fail("While getting creating remote family tree", ex); 052 } 053 } 054 055 /** 056 * Unbinds the remote family tree from the RMI namespace 057 */ 058 @AfterEach 059 public void tearDown() { 060 this.unbind(); 061 } 062 063 /** 064 * Returns the name that the <code>RemoteFamilyTree</code> is bound 065 * into in the RMI namespace. 066 */ 067 protected String getFamilyName() { 068 return "RemoteTestCase"; 069 } 070 071 /** 072 * Returns an RMI registry that is co-located in this VM. If one 073 * doesn't exist, it is started on {@link #RMI_PORT} 074 */ 075 private Registry getRegistry() { 076 if (registry != null) { 077 return registry; 078 } 079 080 synchronized (RemoteTestCase.class) { 081 if (registry != null) { 082 return registry; 083 } 084 085 try { 086 registry = LocateRegistry.createRegistry(RMI_PORT); 087 088 } catch (RemoteException ex) { 089 try { 090 registry = LocateRegistry.createRegistry(RMI_PORT); 091 092 } catch (RemoteException ex1) { 093 fail("Couldn't create local registry", ex); 094 } 095 } 096 097 assertNotNull(registry); 098 return registry; 099 } 100 } 101 102 /** 103 * Returns the <code>RemoteFamilyTree</code> used by this test 104 */ 105 protected RemoteFamilyTree getTree() { 106// if (System.getSecurityManager() == null) { 107// System.setSecurityManager(new RMISecurityManager()); 108// } 109 110 Registry registry = getRegistry(); 111 try { 112 return (RemoteFamilyTree) registry.lookup(this.getName()); 113 114 } catch (Exception ex) { 115 fail("While getting remote family tree on " + this.getName(), ex); 116 return null; 117 } 118 } 119 120 /** 121 * Convenience method that binds a given 122 * <code>RemoteFamilyTree</code> into the RMI namespace. 123 */ 124 protected void bind(RemoteFamilyTree tree) { 125// if (System.getSecurityManager() == null) { 126// System.setSecurityManager(new RMISecurityManager()); 127// } 128 129 Registry registry = getRegistry(); 130 try { 131 registry.rebind(this.getName(), tree); 132 System.out.println("Successfully bound RemoteFamilyTree"); 133 134 } catch (Exception ex) { 135 fail("While getting remote family tree on " + this.getName(), ex); 136 } 137 } 138 139 /** 140 * Convenience method that unbinds and shuts down the remote family 141 * tree from the RMI namespace. 142 */ 143 protected void unbind() { 144// if (System.getSecurityManager() == null) { 145// System.setSecurityManager(new RMISecurityManager()); 146// } 147 148 Registry registry = getRegistry(); 149 try { 150 RemoteFamilyTree tree = 151 (RemoteFamilyTree) registry.lookup(this.getName()); 152 tree.shutdown(); 153 registry.unbind(this.getName()); 154 System.out.println("Successfully unbound RemoteFamilyTree"); 155 156 } catch (Exception ex) { 157 fail("While getting remote family tree on " + this.getName(), ex); 158 } 159 } 160 161 private String getName() 162 { 163 return name; 164 } 165 166 /** 167 * Asserts the equality of two dates. Only takes the month, day, 168 * and year into account. 169 */ 170 protected void assertEquals(Date d1, Date d2) { 171 Calendar cal1 = Calendar.getInstance(); 172 cal1.setTime(d1); 173 174 Calendar cal2 = Calendar.getInstance(); 175 cal1.setTime(d2); 176 177 Assertions.assertEquals(cal1.get(Calendar.DAY_OF_YEAR), 178 cal2.get(Calendar.DAY_OF_YEAR)); 179 Assertions.assertEquals(cal1.get(Calendar.YEAR), cal2.get(Calendar.YEAR)); 180 } 181 182 /** 183 * A JUnit failure that is caused by an exception. This method 184 * provides us with a nice strack trace for the failure. 185 * 186 * @since Winter 2004 187 */ 188 public static void fail(String message, Throwable cause) { 189 StringWriter sw = new StringWriter(); 190 sw.write(message); 191 sw.write("\nCaused by: "); 192 193 PrintWriter pw = new PrintWriter(sw, true); 194 cause.printStackTrace(pw); 195 Assertions.fail(sw.toString()); 196 } 197 198}