KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > junit > JUnitMessageQueue


1 /*
2  * Copyright 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package com.google.gwt.junit;
17
18 import com.google.gwt.junit.client.TestResults;
19
20 import java.util.ArrayList JavaDoc;
21 import java.util.Collection JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Map JavaDoc;
26
27 /**
28  * A message queue to pass data between {@link JUnitShell} and {@link
29  * com.google.gwt.junit.server.JUnitHostImpl} in a thread-safe manner.
30  *
31  * <p>
32  * The public methods are called by the servlet to find out what test to execute
33  * next, and to report the results of the last test to run.
34  * </p>
35  *
36  * <p>
37  * The protected methods are called by the shell to fetch test results and drive
38  * the next test the client should run.
39  * </p>
40  */

41 public class JUnitMessageQueue {
42
43   /**
44    * Tracks which test each client is requesting.
45    *
46    * Key = client-id (e.g. agent+host) Value = the index of the current
47    * requested test
48    */

49   private Map JavaDoc/* <String,Integer> */clientTestRequests = new HashMap JavaDoc/* <String,Integer> */();
50
51   /**
52    * The index of the current test being executed.
53    */

54   private int currentTestIndex = -1;
55
56   /**
57    * The number of TestCase clients executing in parallel.
58    */

59   private int numClients = 1;
60
61   /**
62    * The lock used to synchronize access around testMethod, clientTestRequests,
63    * and currentTestIndex.
64    */

65   private Object JavaDoc readTestLock = new Object JavaDoc();
66
67   /**
68    * The lock used to synchronize access around testResults.
69    */

70   private Object JavaDoc resultsLock = new Object JavaDoc();
71
72   /**
73    * The name of the test class to execute.
74    */

75   private String JavaDoc testClass;
76
77   /**
78    * The name of the test method to execute.
79    */

80   private String JavaDoc testMethod;
81
82   /**
83    * The results for the current test method.
84    */

85   private List JavaDoc/* <TestResults> */testResults = new ArrayList JavaDoc/* <TestResults> */();
86
87   /**
88    * Creates a message queue with one client.
89    *
90    * @see JUnitMessageQueue#JUnitMessageQueue(int)
91    */

92   JUnitMessageQueue() {
93   }
94
95   /**
96    * Only instantiatable within this package.
97    *
98    * @param numClients The number of parallel clients being served by this
99    * queue.
100    */

101   JUnitMessageQueue(int numClients) {
102     this.numClients = numClients;
103   }
104
105   /**
106    * Called by the servlet to query for for the next method to test.
107    *
108    * @param testClassName The name of the test class.
109    * @param timeout How long to wait for an answer.
110    * @return The next test to run, or <code>null</code> if
111    * <code>timeout</code> is exceeded or the next test does not match
112    * <code>testClassName</code>.
113    */

114   public String JavaDoc getNextTestName(String JavaDoc clientId, String JavaDoc testClassName,
115       long timeout) {
116     synchronized (readTestLock) {
117       long stopTime = System.currentTimeMillis() + timeout;
118       while (!testIsAvailableFor(clientId, testClassName)) {
119         long timeToWait = stopTime - System.currentTimeMillis();
120         if (timeToWait < 1) {
121           return null;
122         }
123         try {
124           readTestLock.wait(timeToWait);
125         } catch (InterruptedException JavaDoc e) {
126           // just abort
127
return null;
128         }
129       }
130
131       if (!testClassName.equals(testClass)) {
132         // it's an old client that is now done
133
return null;
134       }
135
136       bumpClientTestRequest(clientId);
137       return testMethod;
138     }
139   }
140
141   /**
142    * Called by the servlet to report the results of the last test to run.
143    *
144    * @param testClassName The name of the test class.
145    * @param results The result of running the test.
146    */

147   public void reportResults(String JavaDoc testClassName, TestResults results) {
148     synchronized (resultsLock) {
149       if (!testClassName.equals(testClass)) {
150         // an old client is trying to report results, do nothing
151
return;
152       }
153       testResults.add(results);
154     }
155   }
156
157   /**
158    * Fetches the results of a completed test.
159    *
160    * @param testClassName The name of the test class.
161    * @return An getException thrown from a failed test, or <code>null</code>
162    * if the test completed without error.
163    */

164   List JavaDoc/* <TestResults> */getResults(String JavaDoc testClassName) {
165     assert (testClassName.equals(testClass));
166     return testResults;
167   }
168
169   /**
170    * Called by the shell to see if the currently-running test has completed.
171    *
172    * @param testClassName The name of the test class.
173    * @return If the test has completed, <code>true</code>, otherwise
174    * <code>false</code>.
175    */

176   boolean hasResult(String JavaDoc testClassName) {
177     synchronized (resultsLock) {
178       assert (testClassName.equals(testClass));
179       return testResults.size() == numClients;
180     }
181   }
182
183   /**
184    * Returns <code>true</code> if all clients have requested the
185    * currently-running test.
186    */

187   boolean haveAllClientsRetrievedCurrentTest() {
188     synchronized (readTestLock) {
189       // If a client hasn't yet contacted, it will have no entry
190
Collection JavaDoc clientIndices = clientTestRequests.values();
191       if (clientIndices.size() < numClients) {
192         return false;
193       }
194       // Every client must have been bumped PAST the current test index
195
for (Iterator JavaDoc it = clientIndices.iterator(); it.hasNext();) {
196         Integer JavaDoc value = (Integer JavaDoc) it.next();
197         if (value.intValue() <= currentTestIndex) {
198           return false;
199         }
200       }
201       return true;
202     }
203   }
204
205   /**
206    * Called by the shell to set the name of the next method to run for this test
207    * class.
208    *
209    * @param testClassName The name of the test class.
210    * @param testName The name of the method to run.
211    */

212   void setNextTestName(String JavaDoc testClassName, String JavaDoc testName) {
213     synchronized (readTestLock) {
214       testClass = testClassName;
215       testMethod = testName;
216       ++currentTestIndex;
217       testResults = new ArrayList JavaDoc/* <TestResults> */(numClients);
218       readTestLock.notifyAll();
219     }
220   }
221
222   /**
223    * Sets the number of clients that will be executing the JUnit tests in
224    * parallel.
225    *
226    * @param numClients must be > 0
227    */

228   void setNumClients(int numClients) {
229     this.numClients = numClients;
230   }
231
232   // This method requires that readTestLock is being held for the duration.
233
private void bumpClientTestRequest(String JavaDoc clientId) {
234     Integer JavaDoc index = (Integer JavaDoc) clientTestRequests.get(clientId);
235     clientTestRequests.put(clientId, new Integer JavaDoc(index.intValue() + 1));
236   }
237
238   // This method requires that readTestLock is being held for the duration.
239
private boolean testIsAvailableFor(String JavaDoc clientId, String JavaDoc testClassName) {
240     if (!testClassName.equals(testClass)) {
241       // the "null" test is always available for an old client
242
return true;
243     }
244     Integer JavaDoc index = (Integer JavaDoc) clientTestRequests.get(clientId);
245     if (index == null) {
246       index = new Integer JavaDoc(0);
247       clientTestRequests.put(clientId, index);
248     }
249     return index.intValue() == currentTestIndex;
250   }
251 }
252
Popular Tags