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