1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.commons.function;
18
19 import static org.junit.jupiter.api.Assertions.*;
20
21 import java.util.concurrent.atomic.AtomicInteger;
22
23 import org.apache.juneau.*;
24 import org.junit.jupiter.api.*;
25
26 class ResettableSupplier_Test extends TestBase {
27
28
29
30
31 @Test void a01_basic() {
32 var callCount = new AtomicInteger();
33 ResettableSupplier<String> supplier = new ResettableSupplier<>(() -> {
34 callCount.incrementAndGet();
35 return "result";
36 });
37
38
39 assertEquals("result", supplier.get());
40 assertEquals(1, callCount.get());
41
42
43 assertEquals("result", supplier.get());
44 assertEquals(1, callCount.get());
45 }
46
47 @Test void a02_returnsNull() {
48 var callCount = new AtomicInteger();
49 ResettableSupplier<String> supplier = new ResettableSupplier<>(() -> {
50 callCount.incrementAndGet();
51 return null;
52 });
53
54
55 assertNull(supplier.get());
56 assertEquals(1, callCount.get());
57
58
59 assertNull(supplier.get());
60 assertEquals(1, callCount.get());
61 }
62
63 @Test void a03_reset() {
64 var callCount = new AtomicInteger();
65 ResettableSupplier<String> supplier = new ResettableSupplier<>(() -> {
66 callCount.incrementAndGet();
67 return "result" + callCount.get();
68 });
69
70
71 assertEquals("result1", supplier.get());
72 assertEquals(1, callCount.get());
73
74
75 assertEquals("result1", supplier.get());
76 assertEquals(1, callCount.get());
77
78
79 supplier.reset();
80
81
82 assertEquals("result2", supplier.get());
83 assertEquals(2, callCount.get());
84
85
86 assertEquals("result2", supplier.get());
87 assertEquals(2, callCount.get());
88 }
89
90 @Test void a04_multipleResets() {
91 var callCount = new AtomicInteger();
92 ResettableSupplier<Integer> supplier = new ResettableSupplier<>(() -> {
93 callCount.incrementAndGet();
94 return callCount.get();
95 });
96
97 assertEquals(1, supplier.get());
98 supplier.reset();
99 assertEquals(2, supplier.get());
100 supplier.reset();
101 assertEquals(3, supplier.get());
102 supplier.reset();
103 assertEquals(4, supplier.get());
104 assertEquals(4, callCount.get());
105 }
106
107 @Test void a05_resetBeforeFirstCall() {
108 var callCount = new AtomicInteger();
109 ResettableSupplier<String> supplier = new ResettableSupplier<>(() -> {
110 callCount.incrementAndGet();
111 return "result";
112 });
113
114
115 supplier.reset();
116
117
118 assertEquals("result", supplier.get());
119 assertEquals(1, callCount.get());
120 }
121
122 @Test void a06_threadSafety_raceCondition() throws InterruptedException {
123 var callCount = new AtomicInteger();
124 ResettableSupplier<String> supplier = new ResettableSupplier<>(() -> {
125 callCount.incrementAndGet();
126
127 try {
128 Thread.sleep(10);
129 } catch (InterruptedException e) {
130 Thread.currentThread().interrupt();
131 }
132 return "result" + callCount.get();
133 });
134
135
136 var threads = new Thread[10];
137 var results = new String[10];
138 for (int i = 0; i < 10; i++) {
139 final int index = i;
140 threads[i] = new Thread(() -> {
141 results[index] = supplier.get();
142 });
143 }
144
145
146 for (var thread : threads) {
147 thread.start();
148 }
149
150
151 for (var thread : threads) {
152 thread.join();
153 }
154
155
156 var firstResult = results[0];
157 for (var result : results) {
158 assertEquals(firstResult, result);
159 }
160
161
162
163 assertTrue(callCount.get() >= 1);
164 }
165
166 @Test void a07_resetAndGetConcurrently() throws InterruptedException {
167 var callCount = new AtomicInteger();
168 ResettableSupplier<Integer> supplier = new ResettableSupplier<>(() -> {
169 callCount.incrementAndGet();
170 return callCount.get();
171 });
172
173 var resetThread = new Thread(() -> {
174 for (int i = 0; i < 10; i++) {
175 supplier.reset();
176 try {
177 Thread.sleep(5);
178 } catch (InterruptedException e) {
179 Thread.currentThread().interrupt();
180 }
181 }
182 });
183
184 var getThread = new Thread(() -> {
185 for (int i = 0; i < 100; i++) {
186 supplier.get();
187 try {
188 Thread.sleep(1);
189 } catch (InterruptedException e) {
190 Thread.currentThread().interrupt();
191 }
192 }
193 });
194
195 resetThread.start();
196 getThread.start();
197
198 resetThread.join();
199 getThread.join();
200
201
202
203
204 assertTrue(callCount.get() >= 1, "Supplier should have been called at least once");
205 }
206
207 @Test void a08_set() {
208 var callCount = new AtomicInteger();
209 ResettableSupplier<String> supplier = new ResettableSupplier<>(() -> {
210 callCount.incrementAndGet();
211 return "computed";
212 });
213
214
215 supplier.set("injected");
216 assertEquals("injected", supplier.get());
217 assertEquals(0, callCount.get());
218
219
220 assertEquals("injected", supplier.get());
221 assertEquals(0, callCount.get());
222
223
224 supplier.set("newValue");
225 assertEquals("newValue", supplier.get());
226 assertEquals(0, callCount.get());
227
228
229 supplier.reset();
230 assertEquals("computed", supplier.get());
231 assertEquals(1, callCount.get());
232
233
234 supplier.set("overridden");
235 assertEquals("overridden", supplier.get());
236 assertEquals(1, callCount.get());
237 }
238
239 @Test void a09_setNull() {
240 var callCount = new AtomicInteger();
241 ResettableSupplier<String> supplier = new ResettableSupplier<>(() -> {
242 callCount.incrementAndGet();
243 return "computed";
244 });
245
246
247 supplier.set(null);
248 assertNull(supplier.get());
249 assertEquals(0, callCount.get());
250
251
252 assertNull(supplier.get());
253 assertEquals(0, callCount.get());
254
255
256 supplier.reset();
257 assertEquals("computed", supplier.get());
258 assertEquals(1, callCount.get());
259 }
260
261
262
263
264 @Test void b01_isSupplied_notCalled() {
265 var supplier = new ResettableSupplier<>(() -> "value");
266 assertTrue(supplier.isSupplied());
267 }
268
269 @Test void b02_isSupplied_afterGet() {
270 var supplier = new ResettableSupplier<>(() -> "value");
271 supplier.get();
272 assertFalse(supplier.isSupplied());
273 }
274
275 @Test void b03_isSupplied_afterReset() {
276 var supplier = new ResettableSupplier<>(() -> "value");
277 supplier.get();
278 supplier.reset();
279 assertTrue(supplier.isSupplied());
280 }
281
282 @Test void b04_isSupplied_afterSet() {
283 var supplier = new ResettableSupplier<>(() -> "value");
284 supplier.set("injected");
285 assertFalse(supplier.isSupplied());
286 }
287
288
289
290
291 @Test void c01_copy_notCalled() {
292 var callCount = new AtomicInteger();
293 var supplier = new ResettableSupplier<>(() -> {
294 callCount.incrementAndGet();
295 return "value" + callCount.get();
296 });
297 var copy = supplier.copy();
298
299
300 assertEquals("value1", copy.get());
301 assertEquals(1, callCount.get());
302 }
303
304 @Test void c02_copy_afterGet() {
305 var callCount = new AtomicInteger();
306 var supplier = new ResettableSupplier<>(() -> {
307 callCount.incrementAndGet();
308 return "value" + callCount.get();
309 });
310 supplier.get();
311 var copy = supplier.copy();
312
313
314 assertEquals("value1", copy.get());
315 assertEquals(1, callCount.get());
316 }
317
318 @Test void c03_copy_independent() {
319 var supplier = new ResettableSupplier<>(() -> "value");
320 var copy = supplier.copy();
321
322
323 supplier.reset();
324 assertEquals("value", copy.get());
325 }
326
327
328
329
330 @Test void d01_map_present() {
331 var supplier = new ResettableSupplier<>(() -> "hello");
332 var mapped = supplier.map(String::length);
333 assertEquals(5, mapped.get());
334 }
335
336 @Test void d02_map_empty() {
337 @SuppressWarnings("cast")
338 var supplier = new ResettableSupplier<>(() -> (String)null);
339 var mapped = supplier.map(String::length);
340 assertNull(mapped.get());
341 }
342
343 @Test void d03_map_cached() {
344 var callCount = new AtomicInteger();
345 var supplier = new ResettableSupplier<>(() -> {
346 callCount.incrementAndGet();
347 return "hello";
348 });
349 var mapped = supplier.map(String::length);
350
351
352 assertEquals(5, mapped.get());
353 assertEquals(1, callCount.get());
354
355
356 assertEquals(5, mapped.get());
357 assertEquals(1, callCount.get());
358 }
359
360 @Test void d04_map_independent() {
361 var supplier = new ResettableSupplier<>(() -> "hello");
362 var mapped = supplier.map(String::length);
363
364
365 supplier.reset();
366
367 assertEquals(5, mapped.get());
368 }
369
370
371
372
373 @Test void e01_filter_matches() {
374 var supplier = new ResettableSupplier<>(() -> "hello");
375 var filtered = supplier.filter(s -> s.length() > 3);
376 assertEquals("hello", filtered.get());
377 }
378
379 @Test void e02_filter_noMatch() {
380 var supplier = new ResettableSupplier<>(() -> "hi");
381 var filtered = supplier.filter(s -> s.length() > 3);
382 assertNull(filtered.get());
383 }
384
385 @Test void e03_filter_empty() {
386 @SuppressWarnings("cast")
387 var supplier = new ResettableSupplier<>(() -> (String)null);
388 var filtered = supplier.filter(s -> s.length() > 3);
389 assertNull(filtered.get());
390 }
391
392 @Test void e04_filter_cached() {
393 var callCount = new AtomicInteger();
394 var supplier = new ResettableSupplier<>(() -> {
395 callCount.incrementAndGet();
396 return "hello";
397 });
398 var filtered = supplier.filter(s -> s.length() > 3);
399
400
401 assertEquals("hello", filtered.get());
402 assertEquals(1, callCount.get());
403
404
405 assertEquals("hello", filtered.get());
406 assertEquals(1, callCount.get());
407 }
408
409
410
411
412 @Test void f01_isPresent() {
413 var supplier = new ResettableSupplier<>(() -> "value");
414 assertTrue(supplier.isPresent());
415 assertFalse(supplier.isEmpty());
416 }
417
418 @Test void f02_isEmpty() {
419 var supplier = new ResettableSupplier<>(() -> null);
420 assertFalse(supplier.isPresent());
421 assertTrue(supplier.isEmpty());
422 }
423
424 @Test void f03_orElse() {
425 var supplier = new ResettableSupplier<>(() -> "value");
426 assertEquals("value", supplier.orElse("default"));
427 }
428
429 @Test void f04_orElse_empty() {
430 var supplier = new ResettableSupplier<>(() -> null);
431 assertEquals("default", supplier.orElse("default"));
432 }
433
434 @Test void f05_orElseGet() {
435 var callCount = new AtomicInteger();
436 var supplier = new ResettableSupplier<>(() -> "value");
437 var result = supplier.orElseGet(() -> {
438 callCount.incrementAndGet();
439 return "default";
440 });
441 assertEquals("value", result);
442 assertEquals(0, callCount.get());
443 }
444
445 @Test void f06_orElseGet_empty() {
446 var callCount = new AtomicInteger();
447 var supplier = new ResettableSupplier<>(() -> null);
448 var result = supplier.orElseGet(() -> {
449 callCount.incrementAndGet();
450 return "default";
451 });
452 assertEquals("default", result);
453 assertEquals(1, callCount.get());
454 }
455
456 @Test void f07_orElseThrow() {
457 var supplier = new ResettableSupplier<>(() -> "value");
458 assertEquals("value", supplier.orElseThrow(() -> new RuntimeException("should not throw")));
459 }
460
461 @Test void f08_orElseThrow_empty() {
462 var supplier = new ResettableSupplier<>(() -> null);
463 assertThrows(RuntimeException.class, () -> supplier.orElseThrow(() -> new RuntimeException("expected")));
464 }
465
466 @Test void f09_ifPresent() {
467 var callCount = new AtomicInteger();
468 var supplier = new ResettableSupplier<>(() -> "value");
469 supplier.ifPresent(s -> callCount.incrementAndGet());
470 assertEquals(1, callCount.get());
471 }
472
473 @Test void f10_ifPresent_empty() {
474 var callCount = new AtomicInteger();
475 var supplier = new ResettableSupplier<>(() -> null);
476 supplier.ifPresent(s -> callCount.incrementAndGet());
477 assertEquals(0, callCount.get());
478 }
479
480 @Test void f11_ifPresentOrElse() {
481 var presentCount = new AtomicInteger();
482 var emptyCount = new AtomicInteger();
483 var supplier = new ResettableSupplier<>(() -> "value");
484 supplier.ifPresentOrElse(
485 s -> presentCount.incrementAndGet(),
486 () -> emptyCount.incrementAndGet()
487 );
488 assertEquals(1, presentCount.get());
489 assertEquals(0, emptyCount.get());
490 }
491
492 @Test void f12_ifPresentOrElse_empty() {
493 var presentCount = new AtomicInteger();
494 var emptyCount = new AtomicInteger();
495 var supplier = new ResettableSupplier<>(() -> null);
496 supplier.ifPresentOrElse(
497 s -> presentCount.incrementAndGet(),
498 () -> emptyCount.incrementAndGet()
499 );
500 assertEquals(0, presentCount.get());
501 assertEquals(1, emptyCount.get());
502 }
503
504 @Test void f13_toOptional() {
505 var supplier = new ResettableSupplier<>(() -> "value");
506 var optional = supplier.toOptional();
507 assertTrue(optional.isPresent());
508 assertEquals("value", optional.get());
509 }
510
511 @Test void f14_toOptional_empty() {
512 var supplier = new ResettableSupplier<>(() -> null);
513 var optional = supplier.toOptional();
514 assertFalse(optional.isPresent());
515 }
516
517 @Test void f15_flatMap() {
518 var supplier = new ResettableSupplier<>(() -> "hello");
519 var mapped = supplier.flatMap(s -> OptionalSupplier.ofNullable(s.length()));
520 assertEquals(5, mapped.get());
521 }
522
523 @Test void f16_flatMap_empty() {
524 @SuppressWarnings("cast")
525 var supplier = new ResettableSupplier<>(() -> (String)null);
526 var mapped = supplier.flatMap(s -> OptionalSupplier.ofNullable(s.length()));
527 assertNull(mapped.get());
528 }
529 }
530