1
1
package com .flowingcode .vaadin .addons .gridexporter .test ;
2
2
3
3
import static org .apache .commons .io .output .NullOutputStream .NULL_OUTPUT_STREAM ;
4
+ import static org .hamcrest .CoreMatchers .instanceOf ;
4
5
import static org .hamcrest .MatcherAssert .assertThat ;
5
6
import static org .hamcrest .Matchers .equalTo ;
6
7
import static org .hamcrest .Matchers .nullValue ;
8
+ import static org .junit .Assert .assertFalse ;
7
9
import static org .junit .Assert .assertTrue ;
8
10
import com .flowingcode .vaadin .addons .gridexporter .ConfigurableConcurrentStreamResourceWriter ;
9
11
import com .flowingcode .vaadin .addons .gridexporter .GridExporter ;
12
+ import com .vaadin .flow .component .UI ;
10
13
import com .vaadin .flow .server .StreamResourceWriter ;
11
14
import com .vaadin .flow .server .VaadinService ;
12
15
import com .vaadin .flow .server .VaadinServletService ;
15
18
import java .nio .channels .InterruptedByTimeoutException ;
16
19
import java .util .ArrayList ;
17
20
import java .util .List ;
21
+ import java .util .concurrent .BrokenBarrierException ;
18
22
import java .util .concurrent .CountDownLatch ;
19
23
import java .util .concurrent .CyclicBarrier ;
20
24
import java .util .concurrent .Exchanger ;
@@ -76,6 +80,7 @@ private void initializeCyclicBarrier(int parties) {
76
80
77
81
@ Before
78
82
public void before () {
83
+ GridExporter .setFailOnUiChange (false );
79
84
barrier = null ;
80
85
if (!lock .tryLock ()) {
81
86
throw new IllegalStateException (
@@ -100,17 +105,30 @@ private interface MockDownload {
100
105
101
106
MockDownload withCost (float cost );
102
107
108
+ void detach ();
109
+
103
110
Throwable get () throws InterruptedException ;
104
111
105
112
MockDownload await () throws InterruptedException ;
106
113
107
114
MockDownload start ();
108
115
109
116
boolean wasInterruptedByTimeout ();
117
+
118
+ boolean isFinished ();
119
+
120
+ boolean isAccepted ();
121
+ }
122
+
123
+ private Thread newThread (Runnable target ) {
124
+ Thread thread = new Thread (target );
125
+ threads .add (thread );
126
+ return thread ;
110
127
}
111
128
112
129
private MockDownload newDownload () {
113
130
131
+ CyclicBarrier barrier = this .barrier ;
114
132
CountDownLatch latch = new CountDownLatch (1 );
115
133
116
134
ConcurrentStreamResourceWriter writer =
@@ -119,6 +137,7 @@ private MockDownload newDownload() {
119
137
await (barrier );
120
138
});
121
139
140
+ writer .setUi (new UI ());
122
141
Exchanger <Throwable > exchanger = new Exchanger <>();
123
142
124
143
Thread thread = newThread (() -> {
@@ -138,8 +157,6 @@ private MockDownload newDownload() {
138
157
}
139
158
});
140
159
141
- threads .add (thread );
142
-
143
160
return new MockDownload () {
144
161
@ Override
145
162
public Throwable get () throws InterruptedException {
@@ -185,10 +202,25 @@ public MockDownload withCost(float cost) {
185
202
return this ;
186
203
}
187
204
205
+ @ Override
206
+ public void detach () {
207
+ writer .setUi (null );
208
+ }
209
+
188
210
@ Override
189
211
public boolean wasInterruptedByTimeout () {
190
212
return writer .interruptedByTimeout ;
191
213
}
214
+
215
+ @ Override
216
+ public boolean isAccepted () {
217
+ return writer .accepted ;
218
+ }
219
+
220
+ @ Override
221
+ public boolean isFinished () {
222
+ return writer .finished ;
223
+ }
192
224
};
193
225
}
194
226
@@ -329,4 +361,49 @@ public void testInterruptedByTimeout3()
329
361
assertThat (q3 .get (), throwsInterruptedByTimeout ());
330
362
}
331
363
364
+
365
+ @ Test (timeout = TEST_TIMEOUT )
366
+ public void testAcceptFinish () throws InterruptedException {
367
+ ConcurrentStreamResourceWriter .setLimit (2 );
368
+ initializeCyclicBarrier (2 );
369
+ var q1 = newDownload ().await ();
370
+ assertTrue ("Download has not been accepted" , q1 .isAccepted ());
371
+ assertFalse ("Download has finished too early" , q1 .isFinished ());
372
+ var q2 = newDownload ().await ();
373
+ assertTrue ("Download has not been accepted" , q2 .isAccepted ());
374
+ assertThat (q1 .get (), nullValue ());
375
+ assertThat (q2 .get (), nullValue ());
376
+ assertTrue ("Download has not finished" , q1 .isFinished ());
377
+ assertTrue ("Download has not finished" , q2 .isFinished ());
378
+ }
379
+
380
+ @ Test (timeout = TEST_TIMEOUT )
381
+ public void testFailOnUiClose () throws InterruptedException , BrokenBarrierException {
382
+ GridExporter .setFailOnUiChange (true );
383
+ ConcurrentStreamResourceWriter .setLimit (1 );
384
+
385
+ initializeCyclicBarrier (2 );
386
+ CyclicBarrier b1 = barrier ;
387
+ var q1 = newDownload ().await ();
388
+ assertTrue ("Download has not been accepted" , q1 .isAccepted ());
389
+ assertFalse ("Download has finished too early" , q1 .isFinished ());
390
+
391
+ initializeCyclicBarrier (2 );
392
+ var q2 = newDownload ().withTimeout (TEST_TIMEOUT ).start ();
393
+ assertTrue ("Download has not been accepted" , q1 .isAccepted ());
394
+ assertFalse ("Download has finished too early" , q1 .isFinished ());
395
+
396
+ // detach while the semaphore is held by q1
397
+ q2 .detach ();
398
+
399
+ // await on b1 so that q1 releases the semaphore
400
+ b1 .await ();
401
+ assertThat (q1 .get (), nullValue ());
402
+
403
+ // with "FailOnUiChange" the other thread never arrives at the barrier
404
+ assertThat (barrier .getNumberWaiting (), equalTo (0 ));
405
+ assertThat (q2 .get (), instanceOf (IOException .class ));
406
+
407
+ }
408
+
332
409
}
0 commit comments