< prev index next >

test/jdk/java/lang/ScopedValue/ScopedValueAPI.java

Print this page

 31 import java.lang.ScopedValue.CallableOp;
 32 import java.util.NoSuchElementException;
 33 import java.util.concurrent.ExecutionException;
 34 import java.util.concurrent.Executors;
 35 import java.util.concurrent.ThreadFactory;
 36 import java.util.function.Supplier;
 37 import java.util.stream.Stream;
 38 
 39 import org.junit.jupiter.api.Test;
 40 import org.junit.jupiter.params.ParameterizedTest;
 41 import org.junit.jupiter.params.provider.MethodSource;
 42 import static org.junit.jupiter.api.Assertions.*;
 43 
 44 class ScopedValueAPI {
 45 
 46     private static Stream<ThreadFactory> factories() {
 47         return Stream.of(Thread.ofPlatform().factory(), Thread.ofVirtual().factory());
 48     }
 49 
 50     /**
 51      * Test that runWhere invokes the Runnable's run method.
 52      */
 53     @ParameterizedTest
 54     @MethodSource("factories")
 55     void testRunWhere(ThreadFactory factory) throws Exception {
 56         test(factory, () -> {
 57             class Box { static boolean executed; }
 58             ScopedValue<String> name = ScopedValue.newInstance();
 59             ScopedValue.runWhere(name, "duke", () -> { Box.executed = true; });
 60             assertTrue(Box.executed);
 61         });
 62     }
 63 
 64     /**
 65      * Test runWhere when the run method throws an exception.
 66      */
 67     @ParameterizedTest
 68     @MethodSource("factories")
 69     void testRunWhereThrows(ThreadFactory factory) throws Exception {
 70         test(factory, () -> {
 71             class FooException extends RuntimeException {  }
 72             ScopedValue<String> name = ScopedValue.newInstance();
 73             Runnable op = () -> { throw new FooException(); };
 74             assertThrows(FooException.class, () -> ScopedValue.runWhere(name, "duke", op));
 75             assertFalse(name.isBound());
 76         });
 77     }
 78 
 79     /**
 80      * Test that callWhere invokes the CallableOp's call method.
 81      */
 82     @ParameterizedTest
 83     @MethodSource("factories")
 84     void testCallWhere(ThreadFactory factory) throws Exception {
 85         test(factory, () -> {
 86             ScopedValue<String> name = ScopedValue.newInstance();
 87             String result = ScopedValue.callWhere(name, "duke", name::get);
 88             assertEquals("duke", result);
 89         });
 90     }
 91 
 92     /**
 93      * Test callWhere when the call method throws an exception.
 94      */
 95     @ParameterizedTest
 96     @MethodSource("factories")
 97     void testCallWhereThrows(ThreadFactory factory) throws Exception {
 98         test(factory, () -> {
 99             class FooException extends RuntimeException {  }
100             ScopedValue<String> name = ScopedValue.newInstance();
101             CallableOp<Void, RuntimeException> op = () -> { throw new FooException(); };
102             assertThrows(FooException.class, () -> ScopedValue.callWhere(name, "duke", op));
103             assertFalse(name.isBound());
104         });
105     }
106 
107     /**
108      * Test get method.
109      */
110     @ParameterizedTest
111     @MethodSource("factories")
112     void testGet(ThreadFactory factory) throws Exception {
113         test(factory, () -> {
114             ScopedValue<String> name1 = ScopedValue.newInstance();
115             ScopedValue<String> name2 = ScopedValue.newInstance();
116             assertThrows(NoSuchElementException.class, name1::get);
117             assertThrows(NoSuchElementException.class, name2::get);
118 
119             // runWhere
120             ScopedValue.runWhere(name1, "duke", () -> {
121                 assertEquals("duke", name1.get());
122                 assertThrows(NoSuchElementException.class, name2::get);
123 
124             });
125             assertThrows(NoSuchElementException.class, name1::get);
126             assertThrows(NoSuchElementException.class, name2::get);
127 
128             // callWhere
129             ScopedValue.callWhere(name1, "duke", () -> {
130                 assertEquals("duke", name1.get());
131                 assertThrows(NoSuchElementException.class, name2::get);
132                 return null;
133             });
134             assertThrows(NoSuchElementException.class, name1::get);
135             assertThrows(NoSuchElementException.class, name2::get);
136         });
137     }
138 
139     /**
140      * Test isBound method.
141      */
142     @ParameterizedTest
143     @MethodSource("factories")
144     void testIsBound(ThreadFactory factory) throws Exception {
145         test(factory, () -> {
146             ScopedValue<String> name1 = ScopedValue.newInstance();
147             ScopedValue<String> name2 = ScopedValue.newInstance();
148             assertFalse(name1.isBound());
149             assertFalse(name2.isBound());
150 
151             // runWhere
152             ScopedValue.runWhere(name1, "duke", () -> {
153                 assertTrue(name1.isBound());
154                 assertFalse(name2.isBound());
155             });
156             assertFalse(name1.isBound());
157             assertFalse(name2.isBound());
158 
159             // callWhere
160             ScopedValue.callWhere(name1, "duke", () -> {
161                 assertTrue(name1.isBound());
162                 assertFalse(name2.isBound());
163                 return null;
164             });
165             assertFalse(name1.isBound());
166             assertFalse(name2.isBound());
167         });
168     }
169 
170     /**
171      * Test orElse method.
172      */
173     @ParameterizedTest
174     @MethodSource("factories")
175     void testOrElse(ThreadFactory factory) throws Exception {
176         test(factory, () -> {
177             ScopedValue<String> name = ScopedValue.newInstance();
178             assertNull(name.orElse(null));
179             assertEquals("default", name.orElse("default"));
180 
181             // runWhere
182             ScopedValue.runWhere(name, "duke", () -> {
183                 assertEquals("duke", name.orElse(null));
184                 assertEquals("duke", name.orElse("default"));
185             });
186 
187             // callWhere
188             ScopedValue.callWhere(name, "duke", () -> {
189                 assertEquals("duke", name.orElse(null));
190                 assertEquals("duke", name.orElse("default"));
191                 return null;
192             });
193         });
194     }
195 
196     /**
197      * Test orElseThrow method.
198      */
199     @ParameterizedTest
200     @MethodSource("factories")
201     void testOrElseThrow(ThreadFactory factory) throws Exception {
202         test(factory, () -> {
203             class FooException extends RuntimeException { }
204             ScopedValue<String> name = ScopedValue.newInstance();
205             assertThrows(FooException.class, () -> name.orElseThrow(FooException::new));
206 
207             // runWhere
208             ScopedValue.runWhere(name, "duke", () -> {
209                 assertEquals("duke", name.orElseThrow(FooException::new));
210             });
211 
212             // callWhere
213             ScopedValue.callWhere(name, "duke", () -> {
214                 assertEquals("duke", name.orElseThrow(FooException::new));
215                 return null;
216             });
217         });
218     }
219 
220     /**
221      * Test two bindings.
222      */
223     @ParameterizedTest
224     @MethodSource("factories")
225     void testTwoBindings(ThreadFactory factory) throws Exception {
226         test(factory, () -> {
227             ScopedValue<String> name = ScopedValue.newInstance();
228             ScopedValue<Integer> age = ScopedValue.newInstance();
229 
230             // Carrier.run
231             ScopedValue.where(name, "duke").where(age, 100).run(() -> {
232                 assertTrue(name.isBound());
233                 assertTrue(age.isBound());

242                 assertTrue(name.isBound());
243                 assertTrue(age.isBound());
244                 assertEquals("duke", name.get());
245                 assertEquals(100, (int) age.get());
246                 return null;
247             });
248             assertFalse(name.isBound());
249             assertFalse(age.isBound());
250         });
251     }
252 
253     /**
254      * Test rebinding.
255      */
256     @ParameterizedTest
257     @MethodSource("factories")
258     void testRebinding(ThreadFactory factory) throws Exception {
259         test(factory, () -> {
260             ScopedValue<String> name = ScopedValue.newInstance();
261 
262             // runWhere
263             ScopedValue.runWhere(name, "duke", () -> {
264                 assertTrue(name.isBound());
265                 assertEquals("duke", name.get());
266 
267                 ScopedValue.runWhere(name, "duchess", () -> {
268                     assertTrue(name.isBound());
269                     assertEquals("duchess", name.get());
270                 });
271 
272                 assertTrue(name.isBound());
273                 assertEquals("duke", name.get());
274             });
275             assertFalse(name.isBound());
276 
277             // callWhere
278             ScopedValue.callWhere(name, "duke", () -> {
279                 assertTrue(name.isBound());
280                 assertEquals("duke", name.get());
281 
282                 ScopedValue.callWhere(name, "duchess", () -> {
283                     assertTrue(name.isBound());
284                     assertEquals("duchess", name.get());
285                     return null;
286                 });
287 
288                 assertTrue(name.isBound());
289                 assertEquals("duke", name.get());
290                 return null;
291             });
292             assertFalse(name.isBound());
293         });
294     }
295 
296     /**
297      * Test rebinding from null vaue to another value.
298      */
299     @ParameterizedTest
300     @MethodSource("factories")
301     void testRebindingFromNull(ThreadFactory factory) throws Exception {
302         test(factory, () -> {
303             ScopedValue<String> name = ScopedValue.newInstance();
304 
305             // runWhere
306             ScopedValue.runWhere(name, null, () -> {
307                 assertTrue(name.isBound());
308                 assertNull(name.get());
309 
310                 ScopedValue.runWhere(name, "duchess", () -> {
311                     assertTrue(name.isBound());
312                     assertTrue("duchess".equals(name.get()));
313                 });
314 
315                 assertTrue(name.isBound());
316                 assertNull(name.get());
317             });
318             assertFalse(name.isBound());
319 
320             // callWhere
321             ScopedValue.callWhere(name, null, () -> {
322                 assertTrue(name.isBound());
323                 assertNull(name.get());
324 
325                 ScopedValue.callWhere(name, "duchess", () -> {
326                     assertTrue(name.isBound());
327                     assertTrue("duchess".equals(name.get()));
328                     return null;
329                 });
330 
331                 assertTrue(name.isBound());
332                 assertNull(name.get());
333                 return null;
334             });
335             assertFalse(name.isBound());
336         });
337     }
338 
339     /**
340      * Test rebinding to null value.
341      */
342     @ParameterizedTest
343     @MethodSource("factories")
344     void testRebindingToNull(ThreadFactory factory) throws Exception {
345         test(factory, () -> {
346             ScopedValue<String> name = ScopedValue.newInstance();
347 
348             // runWhere
349             ScopedValue.runWhere(name, "duke", () -> {
350                 assertTrue(name.isBound());
351                 assertEquals("duke", name.get());
352 
353                 ScopedValue.runWhere(name, null, () -> {
354                     assertTrue(name.isBound());
355                     assertNull(name.get());
356                 });
357 
358                 assertTrue(name.isBound());
359                 assertEquals("duke", name.get());
360             });
361             assertFalse(name.isBound());
362 
363             // callWhere
364             ScopedValue.callWhere(name, "duke", () -> {
365                 assertTrue(name.isBound());
366                 assertEquals("duke", name.get());
367 
368                 ScopedValue.callWhere(name, null, () -> {
369                     assertTrue(name.isBound());
370                     assertNull(name.get());
371                     return null;
372                 });
373 
374                 assertTrue(name.isBound());
375                 assertEquals("duke", name.get());
376                 return null;
377             });
378             assertFalse(name.isBound());
379         });
380     }
381 
382     /**
383      * Test Carrier.get.
384      */
385     @ParameterizedTest
386     @MethodSource("factories")
387     void testCarrierGet(ThreadFactory factory) throws Exception {
388         test(factory, () -> {

393             var carrier1 = ScopedValue.where(name, "duke");
394             assertEquals("duke", carrier1.get(name));
395             assertThrows(NoSuchElementException.class, () -> carrier1.get(age));
396 
397             // two scoped values
398             var carrier2 = carrier1.where(age, 20);
399             assertEquals("duke", carrier2.get(name));
400             assertEquals(20, (int) carrier2.get(age));
401         });
402     }
403 
404     /**
405      * Test NullPointerException.
406      */
407     @Test
408     void testNullPointerException() {
409         ScopedValue<String> name = ScopedValue.newInstance();
410 
411         assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "duke"));
412 
413         assertThrows(NullPointerException.class, () -> ScopedValue.runWhere(null, "duke", () -> { }));
414         assertThrows(NullPointerException.class, () -> ScopedValue.runWhere(name, "duke", null));
415 
416         assertThrows(NullPointerException.class, () -> ScopedValue.callWhere(null, "duke", () -> ""));
417         assertThrows(NullPointerException.class, () -> ScopedValue.callWhere(name, "duke", null));
418 
419         assertThrows(NullPointerException.class, () -> name.orElseThrow(null));
420 
421         var carrier = ScopedValue.where(name, "duke");
422         assertThrows(NullPointerException.class, () -> carrier.where(null, "duke"));
423         assertThrows(NullPointerException.class, () -> carrier.get((ScopedValue<?>)null));
424         assertThrows(NullPointerException.class, () -> carrier.run(null));
425         assertThrows(NullPointerException.class, () -> carrier.call(null));
426     }
427 
428     @FunctionalInterface
429     private interface ThrowingRunnable {
430         void run() throws Exception;
431     }
432 
433     /**
434      * Run the given task in a thread created with the given thread factory.
435      * @throws Exception if the task throws an exception
436      */
437     private static void test(ThreadFactory factory, ThrowingRunnable task) throws Exception {

 31 import java.lang.ScopedValue.CallableOp;
 32 import java.util.NoSuchElementException;
 33 import java.util.concurrent.ExecutionException;
 34 import java.util.concurrent.Executors;
 35 import java.util.concurrent.ThreadFactory;
 36 import java.util.function.Supplier;
 37 import java.util.stream.Stream;
 38 
 39 import org.junit.jupiter.api.Test;
 40 import org.junit.jupiter.params.ParameterizedTest;
 41 import org.junit.jupiter.params.provider.MethodSource;
 42 import static org.junit.jupiter.api.Assertions.*;
 43 
 44 class ScopedValueAPI {
 45 
 46     private static Stream<ThreadFactory> factories() {
 47         return Stream.of(Thread.ofPlatform().factory(), Thread.ofVirtual().factory());
 48     }
 49 
 50     /**
 51      * Test that where invokes the Runnable's run method.
 52      */
 53     @ParameterizedTest
 54     @MethodSource("factories")
 55     void testRunWhere(ThreadFactory factory) throws Exception {
 56         test(factory, () -> {
 57             class Box { static boolean executed; }
 58             ScopedValue<String> name = ScopedValue.newInstance();
 59             ScopedValue.where(name, "duke").run(() -> { Box.executed = true; });
 60             assertTrue(Box.executed);
 61         });
 62     }
 63 
 64     /**
 65      * Test where when the run method throws an exception.
 66      */
 67     @ParameterizedTest
 68     @MethodSource("factories")
 69     void testRunWhereThrows(ThreadFactory factory) throws Exception {
 70         test(factory, () -> {
 71             class FooException extends RuntimeException {  }
 72             ScopedValue<String> name = ScopedValue.newInstance();
 73             Runnable op = () -> { throw new FooException(); };
 74             assertThrows(FooException.class, () -> ScopedValue.where(name, "duke").run(op));
 75             assertFalse(name.isBound());
 76         });
 77     }
 78 
 79     /**
 80      * Test that callWhere invokes the CallableOp's call method.
 81      */
 82     @ParameterizedTest
 83     @MethodSource("factories")
 84     void testCallWhere(ThreadFactory factory) throws Exception {
 85         test(factory, () -> {
 86             ScopedValue<String> name = ScopedValue.newInstance();
 87             String result = ScopedValue.where(name, "duke").call(name::get);
 88             assertEquals("duke", result);
 89         });
 90     }
 91 
 92     /**
 93      * Test callWhere when the call method throws an exception.
 94      */
 95     @ParameterizedTest
 96     @MethodSource("factories")
 97     void testCallWhereThrows(ThreadFactory factory) throws Exception {
 98         test(factory, () -> {
 99             class FooException extends RuntimeException {  }
100             ScopedValue<String> name = ScopedValue.newInstance();
101             CallableOp<Void, RuntimeException> op = () -> { throw new FooException(); };
102             assertThrows(FooException.class, () -> ScopedValue.where(name, "duke").call(op));
103             assertFalse(name.isBound());
104         });
105     }
106 
107     /**
108      * Test get method.
109      */
110     @ParameterizedTest
111     @MethodSource("factories")
112     void testGet(ThreadFactory factory) throws Exception {
113         test(factory, () -> {
114             ScopedValue<String> name1 = ScopedValue.newInstance();
115             ScopedValue<String> name2 = ScopedValue.newInstance();
116             assertThrows(NoSuchElementException.class, name1::get);
117             assertThrows(NoSuchElementException.class, name2::get);
118 
119             // where
120             ScopedValue.where(name1, "duke").run(() -> {
121                 assertEquals("duke", name1.get());
122                 assertThrows(NoSuchElementException.class, name2::get);
123 
124             });
125             assertThrows(NoSuchElementException.class, name1::get);
126             assertThrows(NoSuchElementException.class, name2::get);
127 
128             // callWhere
129             ScopedValue.where(name1, "duke").call(() -> {
130                 assertEquals("duke", name1.get());
131                 assertThrows(NoSuchElementException.class, name2::get);
132                 return null;
133             });
134             assertThrows(NoSuchElementException.class, name1::get);
135             assertThrows(NoSuchElementException.class, name2::get);
136         });
137     }
138 
139     /**
140      * Test isBound method.
141      */
142     @ParameterizedTest
143     @MethodSource("factories")
144     void testIsBound(ThreadFactory factory) throws Exception {
145         test(factory, () -> {
146             ScopedValue<String> name1 = ScopedValue.newInstance();
147             ScopedValue<String> name2 = ScopedValue.newInstance();
148             assertFalse(name1.isBound());
149             assertFalse(name2.isBound());
150 
151             // where
152             ScopedValue.where(name1, "duke").run(() -> {
153                 assertTrue(name1.isBound());
154                 assertFalse(name2.isBound());
155             });
156             assertFalse(name1.isBound());
157             assertFalse(name2.isBound());
158 
159             // callWhere
160             ScopedValue.where(name1, "duke").call(() -> {
161                 assertTrue(name1.isBound());
162                 assertFalse(name2.isBound());
163                 return null;
164             });
165             assertFalse(name1.isBound());
166             assertFalse(name2.isBound());
167         });
168     }
169 
170     /**
171      * Test orElse method.
172      */
173     @ParameterizedTest
174     @MethodSource("factories")
175     void testOrElse(ThreadFactory factory) throws Exception {
176         test(factory, () -> {
177             ScopedValue<String> name = ScopedValue.newInstance();
178             assertNull(name.orElse(null));
179             assertEquals("default", name.orElse("default"));
180 
181             // where
182             ScopedValue.where(name, "duke").run(() -> {
183                 assertEquals("duke", name.orElse(null));
184                 assertEquals("duke", name.orElse("default"));
185             });
186 
187             // callWhere
188             ScopedValue.where(name, "duke").call(() -> {
189                 assertEquals("duke", name.orElse(null));
190                 assertEquals("duke", name.orElse("default"));
191                 return null;
192             });
193         });
194     }
195 
196     /**
197      * Test orElseThrow method.
198      */
199     @ParameterizedTest
200     @MethodSource("factories")
201     void testOrElseThrow(ThreadFactory factory) throws Exception {
202         test(factory, () -> {
203             class FooException extends RuntimeException { }
204             ScopedValue<String> name = ScopedValue.newInstance();
205             assertThrows(FooException.class, () -> name.orElseThrow(FooException::new));
206 
207             // where
208             ScopedValue.where(name, "duke").run(() -> {
209                 assertEquals("duke", name.orElseThrow(FooException::new));
210             });
211 
212             // callWhere
213             ScopedValue.where(name, "duke").call(() -> {
214                 assertEquals("duke", name.orElseThrow(FooException::new));
215                 return null;
216             });
217         });
218     }
219 
220     /**
221      * Test two bindings.
222      */
223     @ParameterizedTest
224     @MethodSource("factories")
225     void testTwoBindings(ThreadFactory factory) throws Exception {
226         test(factory, () -> {
227             ScopedValue<String> name = ScopedValue.newInstance();
228             ScopedValue<Integer> age = ScopedValue.newInstance();
229 
230             // Carrier.run
231             ScopedValue.where(name, "duke").where(age, 100).run(() -> {
232                 assertTrue(name.isBound());
233                 assertTrue(age.isBound());

242                 assertTrue(name.isBound());
243                 assertTrue(age.isBound());
244                 assertEquals("duke", name.get());
245                 assertEquals(100, (int) age.get());
246                 return null;
247             });
248             assertFalse(name.isBound());
249             assertFalse(age.isBound());
250         });
251     }
252 
253     /**
254      * Test rebinding.
255      */
256     @ParameterizedTest
257     @MethodSource("factories")
258     void testRebinding(ThreadFactory factory) throws Exception {
259         test(factory, () -> {
260             ScopedValue<String> name = ScopedValue.newInstance();
261 
262             // where
263             ScopedValue.where(name, "duke").run(() -> {
264                 assertTrue(name.isBound());
265                 assertEquals("duke", name.get());
266 
267                 ScopedValue.where(name, "duchess").run(() -> {
268                     assertTrue(name.isBound());
269                     assertEquals("duchess", name.get());
270                 });
271 
272                 assertTrue(name.isBound());
273                 assertEquals("duke", name.get());
274             });
275             assertFalse(name.isBound());
276 
277             // callWhere
278             ScopedValue.where(name, "duke").call(() -> {
279                 assertTrue(name.isBound());
280                 assertEquals("duke", name.get());
281 
282                 ScopedValue.where(name, "duchess").call(() -> {
283                     assertTrue(name.isBound());
284                     assertEquals("duchess", name.get());
285                     return null;
286                 });
287 
288                 assertTrue(name.isBound());
289                 assertEquals("duke", name.get());
290                 return null;
291             });
292             assertFalse(name.isBound());
293         });
294     }
295 
296     /**
297      * Test rebinding from null vaue to another value.
298      */
299     @ParameterizedTest
300     @MethodSource("factories")
301     void testRebindingFromNull(ThreadFactory factory) throws Exception {
302         test(factory, () -> {
303             ScopedValue<String> name = ScopedValue.newInstance();
304 
305             // where
306             ScopedValue.where(name, null).run(() -> {
307                 assertTrue(name.isBound());
308                 assertNull(name.get());
309 
310                 ScopedValue.where(name, "duchess").run(() -> {
311                     assertTrue(name.isBound());
312                     assertTrue("duchess".equals(name.get()));
313                 });
314 
315                 assertTrue(name.isBound());
316                 assertNull(name.get());
317             });
318             assertFalse(name.isBound());
319 
320             // callWhere
321             ScopedValue.where(name, null).call(() -> {
322                 assertTrue(name.isBound());
323                 assertNull(name.get());
324 
325                 ScopedValue.where(name, "duchess").call(() -> {
326                     assertTrue(name.isBound());
327                     assertTrue("duchess".equals(name.get()));
328                     return null;
329                 });
330 
331                 assertTrue(name.isBound());
332                 assertNull(name.get());
333                 return null;
334             });
335             assertFalse(name.isBound());
336         });
337     }
338 
339     /**
340      * Test rebinding to null value.
341      */
342     @ParameterizedTest
343     @MethodSource("factories")
344     void testRebindingToNull(ThreadFactory factory) throws Exception {
345         test(factory, () -> {
346             ScopedValue<String> name = ScopedValue.newInstance();
347 
348             // where
349             ScopedValue.where(name, "duke").run(() -> {
350                 assertTrue(name.isBound());
351                 assertEquals("duke", name.get());
352 
353                 ScopedValue.where(name, null).run(() -> {
354                     assertTrue(name.isBound());
355                     assertNull(name.get());
356                 });
357 
358                 assertTrue(name.isBound());
359                 assertEquals("duke", name.get());
360             });
361             assertFalse(name.isBound());
362 
363             // callWhere
364             ScopedValue.where(name, "duke").call(() -> {
365                 assertTrue(name.isBound());
366                 assertEquals("duke", name.get());
367 
368                 ScopedValue.where(name, null).call(() -> {
369                     assertTrue(name.isBound());
370                     assertNull(name.get());
371                     return null;
372                 });
373 
374                 assertTrue(name.isBound());
375                 assertEquals("duke", name.get());
376                 return null;
377             });
378             assertFalse(name.isBound());
379         });
380     }
381 
382     /**
383      * Test Carrier.get.
384      */
385     @ParameterizedTest
386     @MethodSource("factories")
387     void testCarrierGet(ThreadFactory factory) throws Exception {
388         test(factory, () -> {

393             var carrier1 = ScopedValue.where(name, "duke");
394             assertEquals("duke", carrier1.get(name));
395             assertThrows(NoSuchElementException.class, () -> carrier1.get(age));
396 
397             // two scoped values
398             var carrier2 = carrier1.where(age, 20);
399             assertEquals("duke", carrier2.get(name));
400             assertEquals(20, (int) carrier2.get(age));
401         });
402     }
403 
404     /**
405      * Test NullPointerException.
406      */
407     @Test
408     void testNullPointerException() {
409         ScopedValue<String> name = ScopedValue.newInstance();
410 
411         assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "duke"));
412 
413         assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "duke").run(() -> { }));
414         assertThrows(NullPointerException.class, () -> ScopedValue.where(name, "duke").run(null));
415 
416         assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "duke").call(() -> ""));
417         assertThrows(NullPointerException.class, () -> ScopedValue.where(name, "duke").call(null));
418 
419         assertThrows(NullPointerException.class, () -> name.orElseThrow(null));
420 
421         var carrier = ScopedValue.where(name, "duke");
422         assertThrows(NullPointerException.class, () -> carrier.where(null, "duke"));
423         assertThrows(NullPointerException.class, () -> carrier.get((ScopedValue<?>)null));
424         assertThrows(NullPointerException.class, () -> carrier.run(null));
425         assertThrows(NullPointerException.class, () -> carrier.call(null));
426     }
427 
428     @FunctionalInterface
429     private interface ThrowingRunnable {
430         void run() throws Exception;
431     }
432 
433     /**
434      * Run the given task in a thread created with the given thread factory.
435      * @throws Exception if the task throws an exception
436      */
437     private static void test(ThreadFactory factory, ThrowingRunnable task) throws Exception {
< prev index next >