1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package com.gargoylesoftware.base.gui;
39
40 import java.util.Arrays;
41 import java.util.ArrayList;
42 import java.util.Collections;
43 import java.util.List;
44 import java.util.Locale;
45 import javax.swing.SwingUtilities;
46 import junit.framework.TestCase;
47
48 /***
49 * Tests for AbstractUIController
50 *
51 * @version $Revision: 1.9 $
52 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
53 */
54 public final class AbstractUIControllerTest extends TestCase {
55
56 private static final String TASK_COMPLETE = "taskComplete";
57 private static final String TASK_ERROR_THROWN = "taskErrorThrown";
58 private static final String TASK_EXCEPTION_THROWN = "taskExceptionThrown";
59 private static final String TASK_SUCCESSFUL = "taskSuccessful";
60
61 private Locale originalLocale_;
62
63
64 /***
65 * Create an instance of the test
66 *
67 * @param name The name of the test.
68 */
69 public AbstractUIControllerTest( final String name ) {
70 super( name );
71 }
72
73
74
75 /***
76 * The JUnit setup method
77 */
78 public void setUp() {
79 originalLocale_ = Locale.getDefault();
80
81
82
83 new javax.swing.JLabel();
84 }
85
86
87 /***
88 * The teardown method for JUnit
89 */
90 public void tearDown() {
91 Locale.setDefault( originalLocale_ );
92 }
93
94
95 /***
96 * Test the startTask() method
97 *
98 * @throws Exception When the test fails
99 */
100 public void testStartTask()
101 throws Exception {
102 final String workerString = "worker";
103 final String uiString = "ui";
104
105 final List list = Collections.synchronizedList( new ArrayList() );
106
107 /*** A task for testing */
108 class TestStartTask extends WorkerTask {
109 public String failMessage = null;
110
111 /*** Code that will run on the worker thread */
112 public void runOnWorkerThread() {
113 if( SwingUtilities.isEventDispatchThread() == true ) {
114 failMessage = "runOnWorkerThread() was called from the UI thread";
115 }
116 list.add( workerString );
117 }
118
119 /*** Code that will run on the ui thread */
120 public void runOnUIThread() {
121 list.add( uiString );
122 if( SwingUtilities.isEventDispatchThread() == false ) {
123 failMessage = "runOnUIThread() was not called from the UI thread";
124 }
125 }
126 }
127
128 final TestStartTask task = new TestStartTask();
129 final LoggingUIController controller = new LoggingUIController();
130
131 controller.testTask( task );
132
133 if( task.failMessage != null ) {
134 fail( task.failMessage );
135 }
136
137 final List expectedStatusMessages = Arrays.asList( new String[]{
138 TASK_SUCCESSFUL, TASK_COMPLETE } );
139 assertEquals( expectedStatusMessages, controller.getList() );
140
141 assertEquals( "list size", 2, list.size() );
142 assertEquals( "worker element", workerString, list.get( 0 ) );
143 assertEquals( "UI element", uiString, list.get( 1 ) );
144 }
145
146
147 /***
148 * Test successful completion of a task
149 *
150 * @throws Exception If an error occurs
151 */
152 public void testTaskSuccessful()
153 throws Exception {
154 final LoggingUIController controller = new LoggingUIController();
155 controller.testTask( new ThrowableTask( null, null ) );
156
157 final List expectedResult = new ArrayList();
158 expectedResult.add( TASK_SUCCESSFUL );
159 expectedResult.add( TASK_COMPLETE );
160 assertListsSame( expectedResult, controller.getList() );
161 }
162
163
164 /***
165 * Test a task that throws an exception from the worker thread
166 *
167 * @throws Exception If an error occurs
168 */
169 public void testTaskException_WorkerThread()
170 throws Exception {
171 final LoggingUIController controller = new LoggingUIController();
172 final IllegalStateException e = new IllegalStateException();
173 controller.testTask( new ThrowableTask( e, null ) );
174
175 final List expectedResult = new ArrayList();
176 expectedResult.add( TASK_EXCEPTION_THROWN );
177 expectedResult.add( e );
178 expectedResult.add( TASK_COMPLETE );
179 assertListsSame( expectedResult, controller.getList() );
180 }
181
182
183 /***
184 * Test a task that throws an exception from the ui thread
185 *
186 * @throws Exception If an error occurs
187 */
188 public void testTaskException_UiThread()
189 throws Exception {
190 final LoggingUIController controller = new LoggingUIController();
191 final IllegalStateException e = new IllegalStateException();
192 controller.testTask( new ThrowableTask( null, e ) );
193
194 final List expectedResult = new ArrayList();
195 expectedResult.add( TASK_EXCEPTION_THROWN );
196 expectedResult.add( e );
197 expectedResult.add( TASK_COMPLETE );
198 assertListsSame( expectedResult, controller.getList() );
199 }
200
201
202 /***
203 * Test a task that throws an error from the worker thread
204 *
205 * @throws Exception If an error occurs
206 */
207 public void testTaskError_WorkerThread()
208 throws Exception {
209 final LoggingUIController controller = new LoggingUIController();
210 final Error e = new OutOfMemoryError();
211 controller.testTask( new ThrowableTask( e, null ) );
212
213 final List expectedResult = new ArrayList();
214 expectedResult.add( TASK_ERROR_THROWN );
215 expectedResult.add( e );
216 expectedResult.add( TASK_COMPLETE );
217 assertListsSame( expectedResult, controller.getList() );
218 }
219
220
221 /***
222 * Test a task that throws an error from the ui thread
223 *
224 * @throws Exception If an error occurs
225 */
226 public void testTaskError_UiThread()
227 throws Exception {
228 final LoggingUIController controller = new LoggingUIController();
229 final Error e = new OutOfMemoryError();
230 controller.testTask( new ThrowableTask( null, e ) );
231
232 final List expectedResult = new ArrayList();
233 expectedResult.add( TASK_ERROR_THROWN );
234 expectedResult.add( e );
235 expectedResult.add( TASK_COMPLETE );
236 assertListsSame( expectedResult, controller.getList() );
237 }
238
239
240 /***
241 * Test changing the locale
242 */
243 public void testLocaleChanged() {
244 final List list = new ArrayList();
245
246 /*** Dummy controller for testing */
247 class MyController extends AbstractUIController {
248 /*** @param locale The new locale */
249 protected final void localeChanged( final Locale locale ) {
250 assertEquals( "locale == getLocale()", locale, getLocale() );
251 list.add( locale );
252 }
253
254 /*** The code to run */
255 protected final void runImpl() {
256 }
257 }
258 Locale.setDefault( Locale.GERMAN );
259 final MyController controller = new MyController();
260
261 assertEquals( "before run()", 0, list.size() );
262 controller.run();
263
264 assertEquals( "localeChanged on construction", 1, list.size() );
265 assertEquals( "locale at construction", Locale.GERMAN, list.get( 0 ) );
266
267 controller.setLocale( Locale.FRENCH );
268 assertEquals( "localeChanged on setLocale", 2, list.size() );
269 assertEquals( "locale at construction", Locale.FRENCH, list.get( 1 ) );
270 }
271
272
273 /***
274 * Test setLocale() with a null locale
275 */
276 public void testSetLocale_Null() {
277 final AbstractUIController controller =
278 new AbstractUIController() {
279 protected void localeChanged( final Locale locale ) {
280 }
281
282
283 protected void runImpl() {
284 }
285 };
286
287 try {
288 controller.setLocale( null );
289 fail( "Expected exception" );
290 }
291 catch( final NullPointerException e ) {
292
293 }
294 }
295
296
297 private void assertListsSame( final List expected, final List actual ) {
298 final int max = Math.min( expected.size(), actual.size() );
299
300 int i;
301 for( i = 0; i < max; i++ ) {
302 assertEquals( "list[" + i + "]", expected.get( i ), actual.get( i ) );
303 }
304 assertEquals( "list.size", expected.size(), actual.size() );
305 }
306
307
308 private class LoggingUIController extends AbstractUIController {
309 private List list_ = Collections.synchronizedList( new ArrayList() );
310
311 /*** @return An immutable copy of the logged information */
312 public List getList() {
313 return Collections.unmodifiableList( list_ );
314 }
315
316 /*** @inheritDoc AbstractUIController#taskComplete(WorkerTask) */
317 public void taskComplete( final WorkerTask task ) {
318 list_.add( TASK_COMPLETE );
319 checkIsOnUIThread();
320 synchronized( this ) {
321 this.notifyAll();
322 }
323 }
324
325 /*** @inheritDoc AbstractUIController#taskSuccessful(WorkerTask) */
326 public void taskSuccessful( final WorkerTask task ) {
327 list_.add( TASK_SUCCESSFUL );
328 checkIsOnUIThread();
329 }
330
331 /*** @inheritDoc AbstractUIController#taskErrorThrown(WorkerTask,Throwable) */
332 public void taskErrorThrown( final WorkerTask task, final Throwable t ) {
333 list_.add( TASK_ERROR_THROWN );
334 checkIsOnUIThread();
335 list_.add( t );
336 }
337
338 /*** @inheritDoc AbstractUIController#taskExceptionThrown(WorkerTask,Exception) */
339 public void taskExceptionThrown( final WorkerTask task, final Exception e ) {
340 list_.add( TASK_EXCEPTION_THROWN );
341 checkIsOnUIThread();
342 list_.add( e );
343 }
344
345 /***
346 * Perform testing of this task
347 * @param task The task to test
348 * @throws InterruptedException If the thread is interrupted
349 */
350 public synchronized void testTask( final WorkerTask task )
351 throws InterruptedException {
352 startTask( task );
353 this.wait( 5000 );
354 }
355
356
357 protected void localeChanged( final Locale locale ) {
358 }
359
360
361 protected void runImpl() {
362 }
363
364
365 private void checkIsOnUIThread() {
366 if( SwingUtilities.isEventDispatchThread() == false ) {
367 list_.add( "Not on UI thread!" );
368 }
369 }
370 }
371
372
373 private class ThrowableTask extends WorkerTask {
374 private Throwable workerThrowable_;
375 private Throwable uiThrowable_;
376
377
378 /***
379 * Create an instance of {1}
380 *
381 * @param workerThrowable
382 * @param uiThrowable
383 */
384 public ThrowableTask( final Throwable workerThrowable, final Throwable uiThrowable ) {
385 workerThrowable_ = workerThrowable;
386 uiThrowable_ = uiThrowable;
387 }
388
389 /*** @inheritDoc AbstractUIController#runOnWorkerThread() */
390 public void runOnWorkerThread()
391 throws Exception {
392 throwIfNeeded( workerThrowable_ );
393 }
394
395 /*** @inheritDoc AbstractUIController#runOnUIThread() */
396 public void runOnUIThread()
397 throws Exception {
398 throwIfNeeded( uiThrowable_ );
399 }
400
401
402 private void throwIfNeeded( final Throwable t )
403 throws Exception {
404 if( t != null ) {
405 if( t instanceof Exception ) {
406 throw ( Exception )t;
407 }
408
409 throw ( Error )t;
410 }
411 }
412 }
413 }
414