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