Skip to content

Commit c1f307c

Browse files
Make unit test more deterministic
1 parent 9517e67 commit c1f307c

File tree

1 file changed

+48
-37
lines changed

1 file changed

+48
-37
lines changed

rxjava-contrib/rxjava-swing/src/main/java/rx/concurrency/SwingScheduler.java

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
*/
1616
package rx.concurrency;
1717

18-
import static org.junit.Assert.assertTrue;
18+
import static org.junit.Assert.*;
1919
import static org.mockito.Mockito.*;
2020

2121
import java.awt.EventQueue;
2222
import java.awt.event.ActionEvent;
2323
import java.awt.event.ActionListener;
24+
import java.util.concurrent.CountDownLatch;
2425
import java.util.concurrent.TimeUnit;
2526
import java.util.concurrent.atomic.AtomicReference;
2627

@@ -41,7 +42,7 @@
4142
import rx.util.functions.Func2;
4243

4344
/**
44-
* Executes work on the Swing UI thread.
45+
* Executes work on the Swing UI thread.
4546
* This scheduler should only be used with actions that execute quickly.
4647
*/
4748
public final class SwingScheduler extends Scheduler {
@@ -77,33 +78,33 @@ public void call() {
7778
@Override
7879
public <T> Subscription schedule(final T state, final Func2<Scheduler, T, Subscription> action, long dueTime, TimeUnit unit) {
7980
final AtomicReference<Subscription> sub = new AtomicReference<Subscription>();
80-
long delay = unit.toMillis(dueTime);
81+
long delay = unit.toMillis(dueTime);
8182
assertThatTheDelayIsValidForTheSwingTimer(delay);
82-
83+
8384
class ExecuteOnceAction implements ActionListener {
8485
private Timer timer;
85-
86+
8687
private void setTimer(Timer timer) {
8788
this.timer = timer;
8889
}
89-
90+
9091
@Override
9192
public void actionPerformed(ActionEvent e) {
9293
timer.stop();
9394
sub.set(action.call(SwingScheduler.this, state));
9495
}
9596
}
96-
97+
9798
ExecuteOnceAction executeOnce = new ExecuteOnceAction();
9899
final Timer timer = new Timer((int) delay, executeOnce);
99100
executeOnce.setTimer(timer);
100101
timer.start();
101-
102+
102103
return Subscriptions.create(new Action0() {
103104
@Override
104105
public void call() {
105106
timer.stop();
106-
107+
107108
Subscription subscription = sub.get();
108109
if (subscription != null) {
109110
subscription.unsubscribe();
@@ -115,28 +116,28 @@ public void call() {
115116
@Override
116117
public <T> Subscription schedulePeriodically(T state, final Func2<Scheduler, T, Subscription> action, long initialDelay, long period, TimeUnit unit) {
117118
final AtomicReference<Timer> timer = new AtomicReference<Timer>();
118-
119-
final long delay = unit.toMillis(period);
119+
120+
final long delay = unit.toMillis(period);
120121
assertThatTheDelayIsValidForTheSwingTimer(delay);
121-
122+
122123
final CompositeSubscription subscriptions = new CompositeSubscription();
123124
final Func2<Scheduler, T, Subscription> initialAction = new Func2<Scheduler, T, Subscription>() {
124-
@Override
125-
public Subscription call(final Scheduler scheduler, final T state0) {
126-
// start timer for periodic execution, collect subscriptions
127-
timer.set(new Timer((int) delay, new ActionListener() {
128-
@Override
129-
public void actionPerformed(ActionEvent e) {
130-
subscriptions.add(action.call(scheduler, state0));
131-
}
132-
}));
133-
timer.get().start();
134-
135-
return action.call(scheduler, state0);
136-
}
125+
@Override
126+
public Subscription call(final Scheduler scheduler, final T state0) {
127+
// start timer for periodic execution, collect subscriptions
128+
timer.set(new Timer((int) delay, new ActionListener() {
129+
@Override
130+
public void actionPerformed(ActionEvent e) {
131+
subscriptions.add(action.call(scheduler, state0));
132+
}
133+
}));
134+
timer.get().start();
135+
136+
return action.call(scheduler, state0);
137+
}
137138
};
138139
subscriptions.add(schedule(state, initialAction, initialDelay, unit));
139-
140+
140141
subscriptions.add(Subscriptions.create(new Action0() {
141142
@Override
142143
public void call() {
@@ -147,7 +148,7 @@ public void call() {
147148
}
148149
}
149150
}));
150-
151+
151152
return subscriptions;
152153
}
153154

@@ -156,11 +157,11 @@ private static void assertThatTheDelayIsValidForTheSwingTimer(long delay) {
156157
throw new IllegalArgumentException(String.format("The swing timer only accepts non-negative delays up to %d milliseconds.", Integer.MAX_VALUE));
157158
}
158159
}
159-
160+
160161
public static class UnitTest {
161162
@Rule
162163
public ExpectedException exception = ExpectedException.none();
163-
164+
164165
@Test
165166
public void testInvalidDelayValues() {
166167
final SwingScheduler scheduler = new SwingScheduler();
@@ -174,34 +175,44 @@ public void testInvalidDelayValues() {
174175

175176
exception.expect(IllegalArgumentException.class);
176177
scheduler.schedulePeriodically(action, 1L + Integer.MAX_VALUE, 100L, TimeUnit.MILLISECONDS);
177-
178+
178179
exception.expect(IllegalArgumentException.class);
179180
scheduler.schedulePeriodically(action, 100L, 1L + Integer.MAX_VALUE / 1000, TimeUnit.SECONDS);
180181
}
181-
182+
182183
@Test
183184
public void testPeriodicScheduling() throws Exception {
184185
final SwingScheduler scheduler = new SwingScheduler();
185186

187+
final CountDownLatch latch = new CountDownLatch(4);
188+
186189
final Action0 innerAction = mock(Action0.class);
187190
final Action0 unsubscribe = mock(Action0.class);
188191
final Func0<Subscription> action = new Func0<Subscription>() {
189192
@Override
190193
public Subscription call() {
191-
innerAction.call();
192-
assertTrue(SwingUtilities.isEventDispatchThread());
193-
return Subscriptions.create(unsubscribe);
194+
try {
195+
innerAction.call();
196+
assertTrue(SwingUtilities.isEventDispatchThread());
197+
return Subscriptions.create(unsubscribe);
198+
} finally {
199+
latch.countDown();
200+
}
194201
}
195202
};
196-
203+
197204
Subscription sub = scheduler.schedulePeriodically(action, 50, 200, TimeUnit.MILLISECONDS);
198-
Thread.sleep(840);
205+
206+
if (!latch.await(5000, TimeUnit.MILLISECONDS)) {
207+
fail("timed out waiting for tasks to execute");
208+
}
209+
199210
sub.unsubscribe();
200211
waitForEmptyEventQueue();
201212
verify(innerAction, times(4)).call();
202213
verify(unsubscribe, times(4)).call();
203214
}
204-
215+
205216
@Test
206217
public void testNestedActions() throws Exception {
207218
final SwingScheduler scheduler = new SwingScheduler();

0 commit comments

Comments
 (0)