1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.lib;
12
13 import static org.junit.Assert.assertEquals;
14 import static org.junit.Assert.assertFalse;
15 import static org.junit.Assert.assertNull;
16 import static org.junit.Assert.assertTrue;
17 import static org.junit.Assert.fail;
18
19 import java.util.concurrent.CountDownLatch;
20 import java.util.concurrent.TimeUnit;
21
22 import org.junit.Test;
23
24 public class ThreadSafeProgressMonitorTest {
25 @Test
26 public void testFailsMethodsOnBackgroundThread()
27 throws InterruptedException {
28 final MockProgressMonitor mock = new MockProgressMonitor();
29 final ThreadSafeProgressMonitor pm = new ThreadSafeProgressMonitor(mock);
30
31 runOnThread(() -> {
32 try {
33 pm.start(1);
34 fail("start did not fail on background thread");
35 } catch (IllegalStateException notMainThread) {
36
37 }
38
39 try {
40 pm.beginTask("title", 1);
41 fail("beginTask did not fail on background thread");
42 } catch (IllegalStateException notMainThread) {
43
44 }
45
46 try {
47 pm.endTask();
48 fail("endTask did not fail on background thread");
49 } catch (IllegalStateException notMainThread) {
50
51 }
52 });
53
54
55 assertNull(mock.taskTitle);
56 assertEquals(0, mock.value);
57 }
58
59 @Test
60 public void testMethodsOkOnMainThread() {
61 final MockProgressMonitor mock = new MockProgressMonitor();
62 final ThreadSafeProgressMonitor pm = new ThreadSafeProgressMonitor(mock);
63
64 pm.start(1);
65 assertEquals(1, mock.value);
66
67 pm.beginTask("title", 42);
68 assertEquals("title", mock.taskTitle);
69 assertEquals(42, mock.value);
70
71 pm.update(1);
72 pm.pollForUpdates();
73 assertEquals(43, mock.value);
74
75 pm.update(2);
76 pm.pollForUpdates();
77 assertEquals(45, mock.value);
78
79 pm.endTask();
80 assertNull(mock.taskTitle);
81 assertEquals(0, mock.value);
82 }
83
84 @Test
85 public void testUpdateOnBackgroundThreads() throws InterruptedException {
86 final MockProgressMonitor mock = new MockProgressMonitor();
87 final ThreadSafeProgressMonitor pm = new ThreadSafeProgressMonitor(mock);
88
89 pm.startWorker();
90
91 final CountDownLatch doUpdate = new CountDownLatch(1);
92 final CountDownLatch didUpdate = new CountDownLatch(1);
93 final CountDownLatch doEndWorker = new CountDownLatch(1);
94
95 final Thread bg = new Thread() {
96 @Override
97 public void run() {
98 assertFalse(pm.isCancelled());
99
100 await(doUpdate);
101 pm.update(2);
102 didUpdate.countDown();
103
104 await(doEndWorker);
105 pm.update(1);
106 pm.endWorker();
107 }
108 };
109 bg.start();
110
111 pm.pollForUpdates();
112 assertEquals(0, mock.value);
113 doUpdate.countDown();
114
115 await(didUpdate);
116 pm.pollForUpdates();
117 assertEquals(2, mock.value);
118
119 doEndWorker.countDown();
120 pm.waitForCompletion();
121 assertEquals(3, mock.value);
122 }
123
124 private static void await(CountDownLatch cdl) {
125 try {
126 assertTrue("latch released", cdl.await(1000, TimeUnit.MILLISECONDS));
127 } catch (InterruptedException ie) {
128 fail("Did not expect to be interrupted");
129 }
130 }
131
132 private static void runOnThread(Runnable task) throws InterruptedException {
133 Thread t = new Thread(task);
134 t.start();
135 t.join(1000);
136 assertFalse("thread has stopped", t.isAlive());
137 }
138
139 private static class MockProgressMonitor implements ProgressMonitor {
140 String taskTitle;
141
142 int value;
143
144 @Override
145 public void update(int completed) {
146 value += completed;
147 }
148
149 @Override
150 public void start(int totalTasks) {
151 value = totalTasks;
152 }
153
154 @Override
155 public void beginTask(String title, int totalWork) {
156 taskTitle = title;
157 value = totalWork;
158 }
159
160 @Override
161 public void endTask() {
162 taskTitle = null;
163 value = 0;
164 }
165
166 @Override
167 public boolean isCancelled() {
168 return false;
169 }
170 }
171 }