1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.commons.io.function; 19 20 import static org.junit.jupiter.api.Assertions.assertArrayEquals; 21 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; 22 import static org.junit.jupiter.api.Assertions.assertEquals; 23 import static org.junit.jupiter.api.Assertions.assertFalse; 24 import static org.junit.jupiter.api.Assertions.assertNotNull; 25 import static org.junit.jupiter.api.Assertions.assertNull; 26 import static org.junit.jupiter.api.Assertions.assertThrows; 27 import static org.junit.jupiter.api.Assertions.assertTrue; 28 29 import java.io.IOException; 30 import java.util.Arrays; 31 import java.util.Collections; 32 import java.util.concurrent.atomic.AtomicInteger; 33 import java.util.concurrent.atomic.AtomicReference; 34 import java.util.stream.Collectors; 35 import java.util.stream.DoubleStream; 36 import java.util.stream.IntStream; 37 import java.util.stream.LongStream; 38 import java.util.stream.Stream; 39 40 import org.apache.commons.lang3.JavaVersion; 41 import org.apache.commons.lang3.SystemUtils; 42 import org.junit.jupiter.api.Test; 43 44 /** 45 * Tests {@link IOStream}. 46 */ 47 public class IOStreamTest { 48 49 private static final boolean AT_LEAST_JAVA_11 = SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_11); 50 private static final boolean AT_LEAST_JAVA_17 = SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_17); 51 compareAndSetIO(final AtomicReference<String> ref, final String expected, final String update)52 private void compareAndSetIO(final AtomicReference<String> ref, final String expected, final String update) throws IOException { 53 TestUtils.compareAndSetThrowsIO(ref, expected, update); 54 } 55 compareAndSetRE(final AtomicReference<String> ref, final String expected, final String update)56 private void compareAndSetRE(final AtomicReference<String> ref, final String expected, final String update) { 57 TestUtils.compareAndSetThrowsRE(ref, expected, update); 58 } 59 ioExceptionOnNull(final Object test)60 private void ioExceptionOnNull(final Object test) throws IOException { 61 if (test == null) { 62 throw new IOException("Unexpected"); 63 } 64 } 65 66 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 67 @Test testAdapt()68 public void testAdapt() { 69 assertEquals(0, IOStream.adapt((Stream<?>) null).count()); 70 assertEquals(0, IOStream.adapt(Stream.empty()).count()); 71 assertEquals(1, IOStream.adapt(Stream.of("A")).count()); 72 } 73 74 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 75 @Test testAllMatch()76 public void testAllMatch() throws IOException { 77 assertThrows(IOException.class, () -> IOStream.of("A", "B").allMatch(TestConstants.THROWING_IO_PREDICATE)); 78 assertTrue(IOStream.of("A", "B").allMatch(IOPredicate.alwaysTrue())); 79 assertFalse(IOStream.of("A", "B").allMatch(IOPredicate.alwaysFalse())); 80 } 81 82 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 83 @Test testAnyMatch()84 public void testAnyMatch() throws IOException { 85 assertThrows(IOException.class, () -> IOStream.of("A", "B").anyMatch(TestConstants.THROWING_IO_PREDICATE)); 86 assertTrue(IOStream.of("A", "B").anyMatch(IOPredicate.alwaysTrue())); 87 assertFalse(IOStream.of("A", "B").anyMatch(IOPredicate.alwaysFalse())); 88 } 89 90 @Test testClose()91 public void testClose() { 92 IOStream.of("A", "B").close(); 93 } 94 95 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 96 @Test testCollectCollectorOfQsuperTAR()97 public void testCollectCollectorOfQsuperTAR() { 98 // TODO IOCollector? 99 IOStream.of("A", "B").collect(Collectors.toList()); 100 } 101 102 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 103 @Test testCollectSupplierOfRBiConsumerOfRQsuperTBiConsumerOfRR()104 public void testCollectSupplierOfRBiConsumerOfRQsuperTBiConsumerOfRR() throws IOException { 105 // TODO Need an IOCollector? 106 IOStream.of("A", "B").collect(() -> "A", (t, u) -> { 107 }, (t, u) -> { 108 }); 109 assertEquals("AB", Stream.of("A", "B").collect(StringBuilder::new, StringBuilder::append, StringBuilder::append).toString()); 110 assertEquals("AB", IOStream.of("A", "B").collect(StringBuilder::new, StringBuilder::append, StringBuilder::append).toString()); 111 // Exceptions 112 assertThrows(IOException.class, () -> IOStream.of("A", "B").collect(TestUtils.throwingIOSupplier(), (t, u) -> { 113 }, (t, u) -> { 114 })); 115 assertThrows(IOException.class, () -> IOStream.of("A", "B").collect(() -> "A", TestUtils.throwingIOBiConsumer(), (t, u) -> { 116 })); 117 } 118 119 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 120 @Test testCount()121 public void testCount() { 122 assertEquals(0, IOStream.of().count()); 123 assertEquals(1, IOStream.of("A").count()); 124 assertEquals(2, IOStream.of("A", "B").count()); 125 assertEquals(3, IOStream.of("A", "B", "C").count()); 126 assertEquals(3, IOStream.of("A", "A", "A").count()); 127 } 128 129 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 130 @Test testDistinct()131 public void testDistinct() { 132 assertEquals(0, IOStream.of().distinct().count()); 133 assertEquals(1, IOStream.of("A").distinct().count()); 134 assertEquals(2, IOStream.of("A", "B").distinct().count()); 135 assertEquals(3, IOStream.of("A", "B", "C").distinct().count()); 136 assertEquals(1, IOStream.of("A", "A", "A").distinct().count()); 137 } 138 139 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 140 @Test testEmpty()141 public void testEmpty() throws IOException { 142 assertEquals(0, Stream.empty().count()); 143 assertEquals(0, IOStream.empty().count()); 144 IOStream.empty().forEach(TestUtils.throwingIOConsumer()); 145 } 146 147 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 148 @Test testFilter()149 public void testFilter() throws IOException { 150 IOStream.of("A").filter(TestConstants.THROWING_IO_PREDICATE); 151 // compile vs type 152 assertThrows(IOException.class, () -> IOStream.of("A").filter(TestConstants.THROWING_IO_PREDICATE).count()); 153 // compile vs inline lambda 154 assertThrows(IOException.class, () -> IOStream.of("A").filter(e -> { 155 throw new IOException("Failure"); 156 }).count()); 157 } 158 159 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 160 @Test testFindAny()161 public void testFindAny() throws IOException { 162 // compile vs type 163 assertThrows(IOException.class, () -> IOStream.of("A").filter(TestConstants.THROWING_IO_PREDICATE).findAny()); 164 // compile vs inline lambda 165 assertThrows(IOException.class, () -> IOStream.of("A").filter(e -> { 166 throw new IOException("Failure"); 167 }).findAny()); 168 169 assertTrue(IOStream.of("A", "B").filter(IOPredicate.alwaysTrue()).findAny().isPresent()); 170 assertFalse(IOStream.of("A", "B").filter(IOPredicate.alwaysFalse()).findAny().isPresent()); 171 } 172 173 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 174 @Test testFindFirst()175 public void testFindFirst() throws IOException { 176 // compile vs type 177 assertThrows(IOException.class, () -> IOStream.of("A").filter(TestConstants.THROWING_IO_PREDICATE).findFirst()); 178 // compile vs inline lambda 179 assertThrows(IOException.class, () -> IOStream.of("A").filter(e -> { 180 throw new IOException("Failure"); 181 }).findAny()); 182 183 assertTrue(IOStream.of("A", "B").filter(IOPredicate.alwaysTrue()).findFirst().isPresent()); 184 assertFalse(IOStream.of("A", "B").filter(IOPredicate.alwaysFalse()).findFirst().isPresent()); 185 } 186 187 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 188 @Test testFlatMap()189 public void testFlatMap() throws IOException { 190 assertEquals(Arrays.asList("A", "B", "C", "D"), 191 IOStream.of(IOStream.of("A", "B"), IOStream.of("C", "D")).flatMap(IOFunction.identity()).collect(Collectors.toList())); 192 } 193 194 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 195 @Test testFlatMapToDouble()196 public void testFlatMapToDouble() throws IOException { 197 assertEquals('A' + 'B', IOStream.of("A", "B").flatMapToDouble(e -> DoubleStream.of(e.charAt(0))).sum()); 198 } 199 200 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 201 @Test testFlatMapToInt()202 public void testFlatMapToInt() throws IOException { 203 assertEquals('A' + 'B', IOStream.of("A", "B").flatMapToInt(e -> IntStream.of(e.charAt(0))).sum()); 204 } 205 206 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 207 @Test testFlatMapToLong()208 public void testFlatMapToLong() throws IOException { 209 assertEquals('A' + 'B', IOStream.of("A", "B").flatMapToLong(e -> LongStream.of(e.charAt(0))).sum()); 210 } 211 212 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 213 @Test testForaAllIOConsumer()214 public void testForaAllIOConsumer() throws IOException { 215 // compile vs type 216 assertThrows(IOException.class, () -> IOStream.of("A").forAll(TestUtils.throwingIOConsumer())); 217 // compile vs inline 218 assertThrows(IOException.class, () -> IOStream.of("A").forAll(e -> { 219 throw new IOException("Failure"); 220 })); 221 assertThrows(IOException.class, () -> IOStream.of("A", "B").forAll(TestUtils.throwingIOConsumer())); 222 final StringBuilder sb = new StringBuilder(); 223 IOStream.of("A", "B").forAll(sb::append); 224 assertEquals("AB", sb.toString()); 225 } 226 227 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 228 @Test testForaAllIOConsumerBiFunction()229 public void testForaAllIOConsumerBiFunction() throws IOException { 230 // compile vs type 231 assertThrows(IOException.class, () -> IOStream.of("A").forAll(TestUtils.throwingIOConsumer(), (i, e) -> e)); 232 // compile vs inline 233 assertThrows(IOException.class, () -> IOStream.of("A").forAll(e -> { 234 throw new IOException("Failure"); 235 }, (i, e) -> e)); 236 assertThrows(IOException.class, () -> IOStream.of("A", "B").forAll(TestUtils.throwingIOConsumer(), (i, e) -> e)); 237 final StringBuilder sb = new StringBuilder(); 238 IOStream.of("A", "B").forAll(sb::append, (i, e) -> e); 239 assertEquals("AB", sb.toString()); 240 } 241 242 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 243 @Test testForaAllIOConsumerBiFunctionNull()244 public void testForaAllIOConsumerBiFunctionNull() throws IOException { 245 // compile vs type 246 assertDoesNotThrow(() -> IOStream.of("A").forAll(TestUtils.throwingIOConsumer(), null)); 247 // compile vs inline 248 assertDoesNotThrow(() -> IOStream.of("A").forAll(e -> { 249 throw new IOException("Failure"); 250 }, null)); 251 assertDoesNotThrow(() -> IOStream.of("A", "B").forAll(TestUtils.throwingIOConsumer(), null)); 252 final StringBuilder sb = new StringBuilder(); 253 IOStream.of("A", "B").forAll(sb::append, null); 254 assertEquals("AB", sb.toString()); 255 } 256 257 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 258 @Test testForEachIOConsumerOfQsuperT()259 public void testForEachIOConsumerOfQsuperT() throws IOException { 260 // compile vs type 261 assertThrows(IOException.class, () -> IOStream.of("A").forEach(TestUtils.throwingIOConsumer())); 262 // compile vs inline 263 assertThrows(IOException.class, () -> IOStream.of("A").forEach(e -> { 264 throw new IOException("Failure"); 265 })); 266 assertThrows(IOException.class, () -> IOStream.of("A", "B").forEach(TestUtils.throwingIOConsumer())); 267 final StringBuilder sb = new StringBuilder(); 268 IOStream.of("A", "B").forEachOrdered(sb::append); 269 assertEquals("AB", sb.toString()); 270 } 271 272 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 273 @Test testForEachOrdered()274 public void testForEachOrdered() throws IOException { 275 // compile vs type 276 assertThrows(IOException.class, () -> IOStream.of("A").forEach(TestUtils.throwingIOConsumer())); 277 // compile vs inline 278 assertThrows(IOException.class, () -> IOStream.of("A").forEach(e -> { 279 throw new IOException("Failure"); 280 })); 281 assertThrows(IOException.class, () -> IOStream.of("A", "B").forEach(TestUtils.throwingIOConsumer())); 282 final StringBuilder sb = new StringBuilder(); 283 IOStream.of("A", "B").forEachOrdered(sb::append); 284 assertEquals("AB", sb.toString()); 285 } 286 287 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 288 @Test testIsParallel()289 public void testIsParallel() { 290 assertFalse(IOStream.of("A", "B").isParallel()); 291 } 292 293 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 294 @Test testIterateException()295 public void testIterateException() throws IOException { 296 final IOStream<Long> stream = IOStream.iterate(1L, TestUtils.throwingIOUnaryOperator()); 297 final IOIterator<Long> iterator = stream.iterator(); 298 assertEquals(1L, iterator.next()); 299 assertThrows(IOException.class, () -> iterator.next()); 300 } 301 302 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 303 @Test testIterateLong()304 public void testIterateLong() throws IOException { 305 final IOStream<Long> stream = IOStream.iterate(1L, i -> i + 1); 306 final IOIterator<Long> iterator = stream.iterator(); 307 assertEquals(1L, iterator.next()); 308 assertEquals(2L, iterator.next()); 309 } 310 311 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 312 @Test testIterator()313 public void testIterator() throws IOException { 314 final AtomicInteger ref = new AtomicInteger(); 315 IOStream.of("A", "B").iterator().forEachRemaining(e -> ref.incrementAndGet()); 316 assertEquals(2, ref.get()); 317 } 318 319 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 320 @Test testLimit()321 public void testLimit() { 322 assertEquals(1, IOStream.of("A", "B").limit(1).count()); 323 } 324 325 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 326 @Test testMap()327 public void testMap() throws IOException { 328 assertEquals(Arrays.asList("AC", "BC"), IOStream.of("A", "B").map(e -> e + "C").collect(Collectors.toList())); 329 } 330 331 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 332 @Test testMapToDouble()333 public void testMapToDouble() { 334 assertArrayEquals(new double[] { Double.parseDouble("1"), Double.parseDouble("2") }, IOStream.of("1", "2").mapToDouble(Double::parseDouble).toArray()); 335 } 336 337 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 338 @Test testMapToInt()339 public void testMapToInt() { 340 assertArrayEquals(new int[] { 1, 2 }, IOStream.of("1", "2").mapToInt(Integer::parseInt).toArray()); 341 } 342 343 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 344 @Test testMapToLong()345 public void testMapToLong() { 346 assertArrayEquals(new long[] { 1L, 2L }, IOStream.of("1", "2").mapToLong(Long::parseLong).toArray()); 347 } 348 349 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 350 @Test testMax()351 public void testMax() throws IOException { 352 assertEquals("B", IOStream.of("A", "B").max(String::compareTo).get()); 353 } 354 355 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 356 @Test testMin()357 public void testMin() throws IOException { 358 assertEquals("A", IOStream.of("A", "B").min(String::compareTo).get()); 359 } 360 361 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 362 @Test testNoneMatch()363 public void testNoneMatch() throws IOException { 364 assertThrows(IOException.class, () -> IOStream.of("A", "B").noneMatch(TestConstants.THROWING_IO_PREDICATE)); 365 assertFalse(IOStream.of("A", "B").noneMatch(IOPredicate.alwaysTrue())); 366 assertTrue(IOStream.of("A", "B").noneMatch(IOPredicate.alwaysFalse())); 367 } 368 369 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 370 @Test testOfArray()371 public void testOfArray() { 372 assertEquals(0, IOStream.of((String[]) null).count()); 373 assertEquals(0, IOStream.of().count()); 374 assertEquals(2, IOStream.of("A", "B").count()); 375 } 376 377 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 378 @Test testOfIterable()379 public void testOfIterable() { 380 assertEquals(0, IOStream.of((Iterable<?>) null).count()); 381 assertEquals(0, IOStream.of(Collections.emptyList()).count()); 382 assertEquals(0, IOStream.of(Collections.emptySet()).count()); 383 assertEquals(0, IOStream.of(Collections.emptySortedSet()).count()); 384 assertEquals(1, IOStream.of(Arrays.asList("a")).count()); 385 assertEquals(2, IOStream.of(Arrays.asList("a", "b")).count()); 386 } 387 388 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 389 @Test testOfOne()390 public void testOfOne() { 391 assertEquals(1, IOStream.of("A").count()); 392 } 393 394 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 395 @Test testOnClose()396 public void testOnClose() throws IOException { 397 assertThrows(IOException.class, () -> IOStream.of("A").onClose(TestConstants.THROWING_IO_RUNNABLE).close()); 398 final AtomicReference<String> ref = new AtomicReference<>(); 399 IOStream.of("A").onClose(() -> compareAndSetIO(ref, null, "new1")).close(); 400 assertEquals("new1", ref.get()); 401 } 402 403 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 404 @Test testOnCloseMultipleHandlers()405 public void testOnCloseMultipleHandlers() { 406 // 407 final AtomicReference<String> ref = new AtomicReference<>(); 408 // Sanity check 409 ref.set(null); 410 final RuntimeException thrownRE = assertThrows(RuntimeException.class, () -> { 411 // @formatter:off 412 final Stream<String> stream = Stream.of("A") 413 .onClose(() -> compareAndSetRE(ref, null, "new1")) 414 .onClose(() -> TestConstants.throwRuntimeException("Failure 2")); 415 // @formatter:on 416 stream.close(); 417 }); 418 assertEquals("new1", ref.get()); 419 assertEquals("Failure 2", thrownRE.getMessage()); 420 assertEquals(0, thrownRE.getSuppressed().length); 421 // Test 422 ref.set(null); 423 final IOException thrownIO = assertThrows(IOException.class, () -> { 424 // @formatter:off 425 final IOStream<String> stream = IOStream.of("A") 426 .onClose(() -> compareAndSetIO(ref, null, "new1")) 427 .onClose(() -> TestConstants.throwIOException("Failure 2")); 428 // @formatter:on 429 stream.close(); 430 }); 431 assertEquals("new1", ref.get()); 432 assertEquals("Failure 2", thrownIO.getMessage()); 433 assertEquals(0, thrownIO.getSuppressed().length); 434 // 435 final IOException thrownB = assertThrows(IOException.class, () -> { 436 // @formatter:off 437 final IOStream<String> stream = IOStream.of("A") 438 .onClose(TestConstants.throwIOException("Failure 1")) 439 .onClose(TestConstants.throwIOException("Failure 2")); 440 // @formatter:on 441 stream.close(); 442 }); 443 assertEquals("Failure 1", thrownB.getMessage()); 444 assertEquals(0, thrownB.getSuppressed().length); 445 } 446 447 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 448 @Test testParallel()449 public void testParallel() { 450 assertEquals(2, IOStream.of("A", "B").parallel().count()); 451 } 452 453 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 454 @Test testPeek()455 public void testPeek() throws IOException { 456 final AtomicReference<String> ref = new AtomicReference<>(); 457 // Stream sanity check 458 assertEquals(1, Stream.of("A").peek(e -> compareAndSetRE(ref, null, e)).count()); 459 // TODO Resolve, abstract or document these differences? 460 assertEquals(AT_LEAST_JAVA_11 ? null : "A", ref.get()); 461 if (AT_LEAST_JAVA_11) { 462 assertEquals(1, IOStream.of("B").peek(e -> compareAndSetRE(ref, null, e)).count()); 463 assertEquals(1, IOStream.of("B").peek(e -> compareAndSetIO(ref, null, e)).count()); 464 assertEquals(null, ref.get()); 465 } else { 466 // Java 8 467 assertThrows(RuntimeException.class, () -> IOStream.of("B").peek(e -> compareAndSetRE(ref, null, e)).count()); 468 assertThrows(IOException.class, () -> IOStream.of("B").peek(e -> compareAndSetIO(ref, null, e)).count()); 469 assertEquals("A", ref.get()); 470 } 471 } 472 473 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 474 @Test testReduceBinaryOperatorOfT()475 public void testReduceBinaryOperatorOfT() throws IOException { 476 assertEquals("AB", IOStream.of("A", "B").reduce((t, u) -> t + u).get()); 477 assertEquals(TestConstants.ABS_PATH_A.toRealPath(), 478 IOStream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B).reduce((t, u) -> t.toRealPath()).get()); 479 } 480 481 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 482 @Test testReduceTBinaryOperatorOfT()483 public void testReduceTBinaryOperatorOfT() throws IOException { 484 assertEquals("_AB", IOStream.of("A", "B").reduce("_", (t, u) -> t + u)); 485 assertEquals(TestConstants.ABS_PATH_A.toRealPath(), 486 IOStream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B).reduce(TestConstants.ABS_PATH_A, (t, u) -> t.toRealPath())); 487 } 488 489 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 490 @Test testReduceUBiFunctionOfUQsuperTUBinaryOperatorOfU()491 public void testReduceUBiFunctionOfUQsuperTUBinaryOperatorOfU() throws IOException { 492 assertEquals("_AB", IOStream.of("A", "B").reduce("_", (t, u) -> t + u, (t, u) -> t + u)); 493 assertEquals(TestConstants.ABS_PATH_A.toRealPath(), IOStream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B).reduce(TestConstants.ABS_PATH_A, 494 (t, u) -> t.toRealPath(), (t, u) -> u.toRealPath())); 495 } 496 497 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 498 @Test testSequential()499 public void testSequential() { 500 assertEquals(2, IOStream.of("A", "B").sequential().count()); 501 } 502 503 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 504 @Test testSkip()505 public void testSkip() throws IOException { 506 final AtomicReference<String> ref = new AtomicReference<>(); 507 assertEquals(1, Stream.of("A", "B").skip(1).peek(e -> compareAndSetRE(ref, null, e)).count()); 508 // TODO Resolve, abstract or document these differences? 509 assertEquals(AT_LEAST_JAVA_17 ? null : "B", ref.get()); 510 if (AT_LEAST_JAVA_17) { 511 assertEquals(1, IOStream.of("C", "D").skip(1).peek(e -> compareAndSetRE(ref, null, e)).count()); 512 assertEquals(1, IOStream.of("C", "D").skip(1).peek(e -> compareAndSetIO(ref, null, e)).count()); 513 assertNull(ref.get()); 514 } else { 515 if (AT_LEAST_JAVA_11) { 516 assertThrows(RuntimeException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetRE(ref, null, e)).count()); 517 assertThrows(IOException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetIO(ref, null, e)).count()); 518 } else { 519 assertThrows(RuntimeException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetRE(ref, null, e)).count()); 520 assertThrows(IOException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetIO(ref, null, e)).count()); 521 } 522 assertEquals("B", ref.get()); 523 } 524 } 525 526 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 527 @Test testSorted()528 public void testSorted() throws IOException { 529 assertEquals(Arrays.asList("A", "B", "C", "D"), IOStream.of("D", "A", "B", "C").sorted().collect(Collectors.toList())); 530 assertEquals(Arrays.asList("A", "B", "C", "D"), IOStream.of("D", "A", "B", "C").sorted().peek(this::ioExceptionOnNull).collect(Collectors.toList())); 531 } 532 533 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 534 @Test testSortedComparatorOfQsuperT()535 public void testSortedComparatorOfQsuperT() throws IOException { 536 assertEquals(Arrays.asList("A", "B", "C", "D"), IOStream.of("D", "A", "B", "C").sorted(String::compareTo).collect(Collectors.toList())); 537 assertEquals(Arrays.asList("A", "B", "C", "D"), 538 IOStream.of("D", "A", "B", "C").sorted(String::compareTo).peek(this::ioExceptionOnNull).collect(Collectors.toList())); 539 } 540 541 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 542 @Test testSpliterator()543 public void testSpliterator() { 544 final AtomicInteger ref = new AtomicInteger(); 545 IOStream.of("A", "B").spliterator().forEachRemaining(e -> ref.incrementAndGet()); 546 assertEquals(2, ref.get()); 547 } 548 549 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 550 @Test testToArray()551 public void testToArray() { 552 assertArrayEquals(new String[] { "A", "B" }, IOStream.of("A", "B").toArray()); 553 } 554 555 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 556 @Test testToArrayIntFunctionOfA()557 public void testToArrayIntFunctionOfA() { 558 assertArrayEquals(new String[] { "A", "B" }, IOStream.of("A", "B").toArray(String[]::new)); 559 } 560 561 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 562 @Test testUnordered()563 public void testUnordered() { 564 // Sanity check 565 assertArrayEquals(new String[] { "A", "B" }, Stream.of("A", "B").unordered().toArray()); 566 // Test 567 assertArrayEquals(new String[] { "A", "B" }, IOStream.of("A", "B").unordered().toArray()); 568 } 569 570 @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery 571 @Test testUnwrap()572 public void testUnwrap() { 573 final Stream<String> unwrap = IOStream.of("A", "B").unwrap(); 574 assertNotNull(unwrap); 575 assertEquals(2, unwrap.count()); 576 } 577 578 } 579