KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > cs > util > newjvm > IntegratedMasterSlaveTest


1 /*BEGIN_COPYRIGHT_BLOCK
2  *
3  * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/
4  * or http://sourceforge.net/projects/drjava/
5  *
6  * DrJava Open Source License
7  *
8  * Copyright (C) 2001-2005 JavaPLT group at Rice University (javaplt@rice.edu). All rights reserved.
9  *
10  * Developed by: Java Programming Languages Team, Rice University, http://www.cs.rice.edu/~javaplt/
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13  * documentation files (the "Software"), to deal with the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15  * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16  *
17  * - Redistributions of source code must retain the above copyright notice, this list of conditions and the
18  * following disclaimers.
19  * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
20  * following disclaimers in the documentation and/or other materials provided with the distribution.
21  * - Neither the names of DrJava, the JavaPLT, Rice University, nor the names of its contributors may be used to
22  * endorse or promote products derived from this Software without specific prior written permission.
23  * - Products derived from this software may not be called "DrJava" nor use the term "DrJava" as part of their
24  * names without prior written permission from the JavaPLT group. For permission, write to javaplt@rice.edu.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
27  * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28  * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * WITH THE SOFTWARE.
31  *
32  *END_COPYRIGHT_BLOCK*/

33
34 package edu.rice.cs.util.newjvm;
35
36 import edu.rice.cs.drjava.DrJavaTestCase;
37 import edu.rice.cs.drjava.config.FileOption;
38
39 import edu.rice.cs.util.Log;
40 import edu.rice.cs.util.swing.Utilities;
41
42 import java.rmi.RemoteException JavaDoc;
43
44 /** Test cases for the master/slave jvm control framework.
45  * @version $Id: IntegratedMasterSlaveTest.java 4031 2006-11-15 22:09:06Z rcartwright $
46  */

47 public class IntegratedMasterSlaveTest extends DrJavaTestCase {
48   
49   private static Log _log = new Log("MasterSlave.txt", false);
50   
51   final TestMasterJVM _testMaster = new TestMasterJVM(); // JUnit ensures separate copy for each test
52

53   public void tearDown() throws Exception JavaDoc {
54     _testMaster.dispose();
55     super.tearDown();
56   }
57  
58   public void testItAll() throws Exception JavaDoc {
59     // run a couple of times. each one forks its own jvm so not
60
// too many! we run multiple times to prove that the master
61
// can invoke multiple slaves (only one active at a time though)
62
for (int i = 0; i < 2; i++) _testMaster.runTestSequence();
63     _log.log("testItAll completed");
64   }
65
66   public void testImmediateQuit() throws Exception JavaDoc {
67     for (int i = 0; i < 5; i++) _testMaster.runImmediateQuitTest();
68     _log.log("testImmediateQuit completed");
69   }
70  
71   
72   private class TestMasterJVM extends AbstractMasterJVM implements TestMasterRemote {
73         
74     /** Field and lock used to signal slave quit events. */
75     private volatile boolean _justQuit; // true after slave quits
76
private final Object JavaDoc _quitLock = new Object JavaDoc();
77     
78     /** Field and lock used to signal slave connected events. */
79     private volatile boolean _connected; // true when slave is connected
80
private final Object JavaDoc _connectedLock = new Object JavaDoc();
81     
82     /** Field and lock used to signal letter change events. */
83     private volatile char _letter;
84     private final Object JavaDoc _letterLock = new Object JavaDoc();
85     
86     private volatile String JavaDoc _currentTest = "";
87
88     public TestMasterJVM() { super(CounterSlave.class.getName()); }
89
90     /** In util-20020414-0647, if quitSlave were called between the time the slave was invoked and the time it
91      * registered, an IllegalStateException was thrown. The correct behavior, which we test for here, is for the
92      * slave to quit as soon as it is started up.
93      */

94     public void runImmediateQuitTest() throws Exception JavaDoc {
95       
96 // Utilities.show("ImmediateQuitTest started");
97

98       _currentTest = "runImmediateQuitTest";
99       _justQuit = false;
100       _connected = false;
101       _letter = 'a'; // this needs to be reset because the slave is going to check it!
102

103       invokeSlave(new String JavaDoc[0], FileOption.NULL_FILE);
104
105 // Utilities.show("slave invoked");
106

107       // Immediately call quit, which should not throw an exception. It should return without waiting.
108
quitSlave();
109                      
110 // Utilities.show("slave quit");
111

112       // now we just wait for the quit to process
113
synchronized(_quitLock) { while (! _justQuit) _quitLock.wait(); }
114       
115       _currentTest = ""; // If we get here, it worked as expected.
116

117                      
118 // Utilities.show("ImmediateQuitTest finished");
119
_log.log("Ran immediateQuitTest");
120       
121       // (All of the post-quit invariants are checked in handleSlaveQuit.
122
}
123
124     public void runTestSequence() throws Exception JavaDoc {
125       
126       _currentTest = "runTestSequence";
127       _justQuit = false;
128       _connected = false;
129       _letter = 'a';
130
131       invokeSlave(new String JavaDoc[0], FileOption.NULL_FILE);
132
133       synchronized(_connectedLock) { while (! _connected) _connectedLock.wait(); }
134
135       ((TestSlaveRemote)getSlave()).startLetterTest();
136       
137       _log.log("letter test started");
138
139       // now, wait until five getletter calls passed; after fifth call letter is 'f' due to the ++
140
synchronized(_letterLock) { while (_letter != 'f') { _letterLock.wait(); } }
141       
142       _log.log("letter test finished");
143
144       for (int i = 0; i < 7; i++) {
145         int value = ((TestSlaveRemote) getSlave()).getNumber();
146         assertEquals("value returned by slave", i, value);
147       }
148       
149       _log.log("number test finished");
150
151       quitSlave();
152       synchronized(_quitLock) { while (! _justQuit) _quitLock.wait(); } // for quit to finish
153
_currentTest = "";
154       _log.log("Ran runTestSequence");
155     }
156
157     public char getLetter() {
158       synchronized(_letterLock) {
159         char ret = _letter;
160         _letter++;
161         _letterLock.notify();
162         return ret;
163       }
164     }
165
166     protected void handleSlaveConnected() {
167       TestSlaveRemote slave = (TestSlaveRemote) getSlave();
168       assertTrue("slave is set", slave != null);
169       assertTrue("startUp not in progress", ! isStartupInProgress());
170       // getLetter should have never been called.
171
assertEquals("letter value", 'a', _letter);
172       synchronized(_connectedLock) {
173         _connected = true;
174         _connectedLock.notify();
175       }
176       _log.log("_handleSlaveConnected() finished");
177     }
178
179     protected void handleSlaveQuit(int status) {
180       assertEquals("slave result code", 0, status);
181       if (_currentTest.equals("runTestSequence")) {
182         // 5 letter calls must have occurred, so 'f' should be next
183
assertEquals("last letter returned", 'f', _letter);
184       }
185       assertTrue("slave is not set", getSlave() == null);
186       assertTrue("startUp not in progress", ! isStartupInProgress());
187
188       // alert test method that quit occurred.
189
synchronized(_quitLock) {
190         _justQuit = true;
191         _quitLock.notify();
192       }
193     }
194
195     /** Called if the slave JVM dies before it is able to register.
196      * @param cause The Throwable which caused the slave to die.
197      */

198     public void errorStartingSlave(Throwable JavaDoc cause) throws RemoteException JavaDoc {
199       fail("There was an error starting the slave JVM: " + cause);
200     }
201   }
202
203   /** The slave will exit with error codes in the case of problems, since there is no other thing it can do!
204    * <DL>
205    * <DT>1</DT><DD>MasterRemote class cast exception.</DD>
206    * <DT>2</DT><DD>Incorect value from getLetter</DD>
207    * <DT>3</DT><DD>RemoteException caught</DD>
208    * <DT>4</DT><DD>Timeout waiting for master JVM to call</DD>
209    * <DT>5</DT><DD>Interrupted while waiting for master JVM to call</DD>
210    * </DL>
211    */

212   public static class CounterSlave extends AbstractSlaveJVM implements TestSlaveRemote {
213     
214     public static final CounterSlave ONLY = new CounterSlave();
215     
216     private volatile int _counter = 0;
217     private volatile TestMasterRemote _master = null;
218     
219     private CounterSlave() { }
220
221     public synchronized int getNumber() { return _counter++; }
222
223     protected void handleStart(MasterRemote m) { _master = (TestMasterRemote) m; }
224
225     public void startLetterTest() throws RemoteException JavaDoc {
226       // Run this part of the test in a new thread, so this call will immediately return
227
Thread JavaDoc thread = new Thread JavaDoc() {
228         public void run() {
229           try {
230             for (char c = 'a'; c <= 'e'; c++) {
231               char got = _master.getLetter();
232               if (c != got) System.exit(2);
233             }
234
235             // OK, now wait up till 15 seconds for master jvm to call
236
Thread.sleep(15000);
237             System.exit(4);
238           }
239           catch (InterruptedException JavaDoc e) { System.exit(5); }
240           catch (RemoteException JavaDoc re) {
241             javax.swing.JOptionPane.showMessageDialog(null, re.toString());
242             System.exit(3);
243           }
244           catch (ClassCastException JavaDoc cce) { System.exit(1); }
245         }
246       };
247       thread.start();
248     }
249   }
250
251   public interface TestSlaveRemote extends SlaveRemote {
252     public int getNumber() throws RemoteException JavaDoc;
253     public void startLetterTest() throws RemoteException JavaDoc;
254   }
255
256   public interface TestMasterRemote/*<SlaveType extends SlaveRemote>*/ extends MasterRemote/*<SlaveType>*/ {
257     public char getLetter() throws RemoteException JavaDoc;
258   }
259 }
260
Popular Tags