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
39
40
41
42
43
44 package org.eclipse.jgit.lib;
45
46 import static org.junit.Assert.assertEquals;
47 import static org.junit.Assert.assertFalse;
48 import static org.junit.Assert.assertNull;
49 import static org.junit.Assert.assertTrue;
50 import static org.junit.Assert.fail;
51
52 import java.util.concurrent.CountDownLatch;
53 import java.util.concurrent.TimeUnit;
54
55 import org.junit.Test;
56
57 public class ThreadSafeProgressMonitorTest {
58 @Test
59 public void testFailsMethodsOnBackgroundThread()
60 throws InterruptedException {
61 final MockProgressMonitor mock = new MockProgressMonitor();
62 final ThreadSafeProgressMonitor pm = new ThreadSafeProgressMonitor(mock);
63
64 runOnThread(new Runnable() {
65 @Override
66 public void run() {
67 try {
68 pm.start(1);
69 fail("start did not fail on background thread");
70 } catch (IllegalStateException notMainThread) {
71
72 }
73
74 try {
75 pm.beginTask("title", 1);
76 fail("beginTask did not fail on background thread");
77 } catch (IllegalStateException notMainThread) {
78
79 }
80
81 try {
82 pm.endTask();
83 fail("endTask did not fail on background thread");
84 } catch (IllegalStateException notMainThread) {
85
86 }
87 }
88 });
89
90
91 assertNull(mock.taskTitle);
92 assertEquals(0, mock.value);
93 }
94
95 @Test
96 public void testMethodsOkOnMainThread() {
97 final MockProgressMonitor mock = new MockProgressMonitor();
98 final ThreadSafeProgressMonitor pm = new ThreadSafeProgressMonitor(mock);
99
100 pm.start(1);
101 assertEquals(1, mock.value);
102
103 pm.beginTask("title", 42);
104 assertEquals("title", mock.taskTitle);
105 assertEquals(42, mock.value);
106
107 pm.update(1);
108 pm.pollForUpdates();
109 assertEquals(43, mock.value);
110
111 pm.update(2);
112 pm.pollForUpdates();
113 assertEquals(45, mock.value);
114
115 pm.endTask();
116 assertNull(mock.taskTitle);
117 assertEquals(0, mock.value);
118 }
119
120 @Test
121 public void testUpdateOnBackgroundThreads() throws InterruptedException {
122 final MockProgressMonitor mock = new MockProgressMonitor();
123 final ThreadSafeProgressMonitor pm = new ThreadSafeProgressMonitor(mock);
124
125 pm.startWorker();
126
127 final CountDownLatch doUpdate = new CountDownLatch(1);
128 final CountDownLatch didUpdate = new CountDownLatch(1);
129 final CountDownLatch doEndWorker = new CountDownLatch(1);
130
131 final Thread bg = new Thread() {
132 @Override
133 public void run() {
134 assertFalse(pm.isCancelled());
135
136 await(doUpdate);
137 pm.update(2);
138 didUpdate.countDown();
139
140 await(doEndWorker);
141 pm.update(1);
142 pm.endWorker();
143 }
144 };
145 bg.start();
146
147 pm.pollForUpdates();
148 assertEquals(0, mock.value);
149 doUpdate.countDown();
150
151 await(didUpdate);
152 pm.pollForUpdates();
153 assertEquals(2, mock.value);
154
155 doEndWorker.countDown();
156 pm.waitForCompletion();
157 assertEquals(3, mock.value);
158 }
159
160 private static void await(CountDownLatch cdl) {
161 try {
162 assertTrue("latch released", cdl.await(1000, TimeUnit.MILLISECONDS));
163 } catch (InterruptedException ie) {
164 fail("Did not expect to be interrupted");
165 }
166 }
167
168 private static void runOnThread(Runnable task) throws InterruptedException {
169 Thread t = new Thread(task);
170 t.start();
171 t.join(1000);
172 assertFalse("thread has stopped", t.isAlive());
173 }
174
175 private static class MockProgressMonitor implements ProgressMonitor {
176 String taskTitle;
177
178 int value;
179
180 @Override
181 public void update(int completed) {
182 value += completed;
183 }
184
185 @Override
186 public void start(int totalTasks) {
187 value = totalTasks;
188 }
189
190 @Override
191 public void beginTask(String title, int totalWork) {
192 taskTitle = title;
193 value = totalWork;
194 }
195
196 @Override
197 public void endTask() {
198 taskTitle = null;
199 value = 0;
200 }
201
202 @Override
203 public boolean isCancelled() {
204 return false;
205 }
206 }
207 }