1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.lang3.concurrent;
18
19 import static org.hamcrest.CoreMatchers.instanceOf;
20 import static org.hamcrest.MatcherAssert.assertThat;
21 import static org.junit.jupiter.api.Assertions.assertFalse;
22 import static org.junit.jupiter.api.Assertions.assertSame;
23 import static org.junit.jupiter.api.Assertions.assertTrue;
24 import static org.junit.jupiter.api.Assertions.fail;
25
26 import java.io.IOException;
27 import java.lang.reflect.Field;
28
29 import org.apache.commons.lang3.function.FailableConsumer;
30 import org.apache.commons.lang3.function.FailableSupplier;
31 import org.junit.jupiter.api.BeforeEach;
32 import org.junit.jupiter.api.Test;
33
34
35
36
37 public class MultiBackgroundInitializerSupplierTest extends MultiBackgroundInitializerTest {
38
39
40
41
42
43 private static final class SupplierChildBackgroundInitializer extends AbstractChildBackgroundInitializer {
44
45 SupplierChildBackgroundInitializer() {
46 this((CloseableCounter cc) -> cc.close());
47 }
48
49 SupplierChildBackgroundInitializer(FailableConsumer<?, ?> consumer) {
50 try {
51
52 final FailableSupplier<?, ?> supplier = () -> initializeInternal();
53 final Field initializer = AbstractConcurrentInitializer.class.getDeclaredField("initializer");
54 initializer.setAccessible(true);
55 initializer.set(this, supplier);
56
57 final Field closer = AbstractConcurrentInitializer.class.getDeclaredField("closer");
58 closer.setAccessible(true);
59 closer.set(this, consumer);
60 } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
61 fail();
62 }
63 }
64 }
65 private NullPointerException npe;
66 private IOException ioException;
67 private FailableConsumer<?, ?> ioExceptionConsumer;
68
69 private FailableConsumer<?, ?> nullPointerExceptionConsumer;
70
71
72
73
74 @Override
75 protected AbstractChildBackgroundInitializer createChildBackgroundInitializer() {
76 return new SupplierChildBackgroundInitializer();
77 }
78
79 @BeforeEach
80 public void setUpException() throws Exception {
81 npe = new NullPointerException();
82 ioException = new IOException();
83 ioExceptionConsumer = (CloseableCounter cc) -> {
84 throw ioException;
85 };
86 nullPointerExceptionConsumer = (CloseableCounter cc) -> {
87 throw npe;
88 };
89 }
90
91
92
93
94
95
96 @Test
97 public void testClose()
98 throws ConcurrentException, InterruptedException {
99 final AbstractChildBackgroundInitializer childOne = createChildBackgroundInitializer();
100 final AbstractChildBackgroundInitializer childTwo = createChildBackgroundInitializer();
101
102 assertFalse(initializer.isInitialized(), "Initalized without having anything to initalize");
103
104 initializer.addInitializer("child one", childOne);
105 initializer.addInitializer("child two", childTwo);
106
107 assertFalse(childOne.getCloseableCounter().isClosed(), "child one closed() succeeded before start()");
108 assertFalse(childTwo.getCloseableCounter().isClosed(), "child two closed() succeeded before start()");
109
110 initializer.start();
111
112 long startTime = System.currentTimeMillis();
113 long waitTime = 3000;
114 long endTime = startTime + waitTime;
115
116 while (!childOne.isStarted() || !childTwo.isStarted()) {
117 if (System.currentTimeMillis() > endTime) {
118 fail("children never started");
119 Thread.sleep(PERIOD_MILLIS);
120 }
121 }
122
123 assertFalse(childOne.getCloseableCounter().isClosed(), "child one close() succeeded after start() but before close()");
124 assertFalse(childTwo.getCloseableCounter().isClosed(), "child two close() succeeded after start() but before close()");
125
126 childOne.get();
127 childTwo.get();
128
129 assertFalse(childOne.getCloseableCounter().isClosed(), "child one initializing succeeded after start() but before close()");
130 assertFalse(childTwo.getCloseableCounter().isClosed(), "child two initializing succeeded after start() but before close()");
131
132 try {
133 initializer.close();
134 } catch (Exception e) {
135 fail();
136 }
137
138 assertTrue(childOne.getCloseableCounter().isClosed(), "child one close() did not succeed");
139 assertTrue(childOne.getCloseableCounter().isClosed(), "child two close() did not succeed");
140 }
141
142
143
144
145
146
147 @Test
148 public void testCloseWithCheckedException() throws Exception {
149 final AbstractChildBackgroundInitializer childOne = new SupplierChildBackgroundInitializer(ioExceptionConsumer);
150
151 initializer.addInitializer("child one", childOne);
152 initializer.start();
153
154 long startTime = System.currentTimeMillis();
155 long waitTime = 3000;
156 long endTime = startTime + waitTime;
157
158 while (! childOne.isStarted()) {
159 if (System.currentTimeMillis() > endTime) {
160 fail("children never started");
161 Thread.sleep(PERIOD_MILLIS);
162 }
163 }
164
165 childOne.get();
166 try {
167 initializer.close();
168 fail();
169 } catch (Exception e) {
170 assertThat(e, instanceOf(ConcurrentException.class));
171 assertSame(ioException, e.getSuppressed()[0]);
172 }
173 }
174
175
176
177
178
179
180 @Test
181 public void testCloseWithRuntimeException() throws Exception {
182 final AbstractChildBackgroundInitializer childOne = new SupplierChildBackgroundInitializer(nullPointerExceptionConsumer);
183
184 initializer.addInitializer("child one", childOne);
185 initializer.start();
186
187 long startTime = System.currentTimeMillis();
188 long waitTime = 3000;
189 long endTime = startTime + waitTime;
190
191 while (! childOne.isStarted()) {
192 if (System.currentTimeMillis() > endTime) {
193 fail("children never started");
194 Thread.sleep(PERIOD_MILLIS);
195 }
196 }
197
198 childOne.get();
199 try {
200 initializer.close();
201 fail();
202 } catch (Exception e) {
203 assertThat(e, instanceOf(ConcurrentException.class));
204 assertSame(npe, e.getSuppressed()[0]);
205 }
206 }
207
208
209
210
211
212
213
214 @Test
215 public void testCloseWithTwoExceptions()
216 throws ConcurrentException, InterruptedException {
217
218 final AbstractChildBackgroundInitializer childOne = new SupplierChildBackgroundInitializer(ioExceptionConsumer);
219 final AbstractChildBackgroundInitializer childTwo = new SupplierChildBackgroundInitializer(nullPointerExceptionConsumer);
220
221 initializer.addInitializer("child one", childOne);
222 initializer.addInitializer("child two", childTwo);
223
224 initializer.start();
225
226 final long startTime = System.currentTimeMillis();
227 final long waitTime = 3000;
228 final long endTime = startTime + waitTime;
229
230 while (! childOne.isStarted() || ! childTwo.isStarted()) {
231 if (System.currentTimeMillis() > endTime) {
232 fail("children never started");
233 Thread.sleep(PERIOD_MILLIS);
234 }
235 }
236
237 childOne.get();
238 childTwo.get();
239
240 try {
241 initializer.close();
242 fail();
243 } catch (Exception e) {
244
245 boolean foundChildOneException = false;
246 boolean foundChildTwoException = false;
247
248 for (Throwable t : e.getSuppressed()) {
249 if (t.equals(ioException)) {
250 foundChildOneException = true;
251 }
252 if (t.equals(npe)) {
253 foundChildTwoException = true;
254 }
255 }
256
257 assertTrue(foundChildOneException);
258 assertTrue(foundChildTwoException);
259 }
260 }
261 }