View Javadoc
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    *      https://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.build;
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.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  
27  import java.io.FileInputStream;
28  import java.io.InputStream;
29  import java.io.RandomAccessFile;
30  import java.net.URI;
31  import java.net.URISyntaxException;
32  import java.nio.channels.ReadableByteChannel;
33  import java.nio.channels.SeekableByteChannel;
34  import java.nio.file.Files;
35  import java.nio.file.OpenOption;
36  import java.nio.file.Path;
37  import java.nio.file.Paths;
38  import java.nio.file.StandardOpenOption;
39  import java.util.Arrays;
40  import java.util.Objects;
41  import java.util.stream.Stream;
42  
43  import org.apache.commons.io.function.IOConsumer;
44  import org.apache.commons.lang3.ArrayUtils;
45  import org.apache.commons.lang3.RandomUtils;
46  import org.junit.jupiter.api.Test;
47  import org.junit.jupiter.params.ParameterizedTest;
48  import org.junit.jupiter.params.provider.MethodSource;
49  import org.junit.jupiter.params.provider.ValueSource;
50  
51  /**
52   * Tests {@link AbstractStreamBuilder}.
53   */
54  class AbstractStreamBuilderTest {
55  
56      public static class Builder extends AbstractStreamBuilder<char[], Builder> {
57  
58          @Override
59          public char[] get() {
60              final char[] arr = new char[getBufferSize()];
61              Arrays.fill(arr, 'a');
62              return arr;
63          }
64  
65      }
66  
67      private static Stream<IOConsumer<Builder>> fileBasedConfigurers() throws URISyntaxException {
68          final URI uri = Objects.requireNonNull(AbstractStreamBuilderTest.class.getResource(AbstractOriginTest.FILE_RES_RO)).toURI();
69          final Path path = Paths.get(AbstractOriginTest.FILE_NAME_RO);
70          // @formatter:off
71          return Stream.of(
72                  b -> b.setByteArray(ArrayUtils.EMPTY_BYTE_ARRAY),
73                  b -> b.setFile(AbstractOriginTest.FILE_NAME_RO),
74                  b -> b.setFile(path.toFile()),
75                  b -> b.setPath(AbstractOriginTest.FILE_NAME_RO),
76                  b -> b.setPath(path),
77                  b -> b.setRandomAccessFile(new RandomAccessFile(AbstractOriginTest.FILE_NAME_RO, "r")),
78                  // We can convert FileInputStream to ReadableByteChannel, but not the reverse.
79                  // Therefore, we don't use Files.newInputStream.
80                  b -> b.setInputStream(new FileInputStream(AbstractOriginTest.FILE_NAME_RO)),
81                  b -> b.setChannel(Files.newByteChannel(path)),
82                  b -> b.setURI(uri));
83          // @formatter:on
84      }
85  
86      private void assertResult(final char[] arr, final int size) {
87          assertNotNull(arr);
88          assertEquals(size, arr.length);
89          for (final char c : arr) {
90              assertEquals('a', c);
91          }
92      }
93  
94      protected Builder builder() {
95          return new Builder();
96      }
97  
98      /**
99       * Tests various ways to obtain a {@link SeekableByteChannel}.
100      *
101      * @param configurer Lambda to configure the builder.
102      */
103     @ParameterizedTest
104     @MethodSource("fileBasedConfigurers")
105     void getGetSeekableByteChannel(final IOConsumer<Builder> configurer) throws Exception {
106         final Builder builder = builder();
107         configurer.accept(builder);
108         try (ReadableByteChannel channel = assertDoesNotThrow(() -> builder.getChannel(SeekableByteChannel.class))) {
109             assertTrue(channel.isOpen());
110         }
111     }
112 
113     @Test
114     void testBufferSizeChecker() {
115         // sanity
116         final Builder builder = builder();
117         assertResult(builder.get(), builder.getBufferSize());
118         // basic failure
119         assertThrows(IllegalArgumentException.class, () -> builder().setBufferSizeMax(2).setBufferSize(3));
120         // reset
121         assertResult(builder.setBufferSizeMax(2).setBufferSizeMax(0).setBufferSize(3).get(), 3);
122         // resize
123         assertResult(builder().setBufferSizeMax(2).setBufferSizeChecker(i -> 100).setBufferSize(3).get(), 100);
124     }
125 
126     /**
127      * Tests various ways to obtain a byte array.
128      *
129      * @param configurer configures a builder.
130      */
131     @ParameterizedTest
132     @MethodSource("fileBasedConfigurers")
133     void testGetByteArray(final IOConsumer<Builder> configurer) throws Exception {
134         final Builder builder = builder();
135         configurer.accept(builder);
136         assertNotNull(builder.getByteArray());
137     }
138 
139     /**
140      * Tests various ways to obtain a {@link InputStream}.
141      *
142      * @param configurer configures a builder.
143      */
144     @ParameterizedTest
145     @MethodSource("fileBasedConfigurers")
146     void testGetInputStream(final IOConsumer<Builder> configurer) throws Exception {
147         final Builder builder = builder();
148         configurer.accept(builder);
149         try (InputStream inputStream = builder.getInputStream()) {
150             assertNotNull(inputStream);
151         }
152     }
153 
154     @ParameterizedTest
155     @ValueSource(ints = { 0, 1, 2, 4 })
156     void testSetByteArrayGetByteArray(final int size) throws Exception {
157         final Builder builder = builder();
158         final byte[] randomBytes = RandomUtils.insecure().randomBytes(size);
159         builder.setByteArray(randomBytes);
160         assertArrayEquals(randomBytes, builder.getByteArray());
161     }
162 
163     @Test
164     void testSetFileGetByteArray() throws Exception {
165         final Builder builder = builder();
166         final Path path = Paths.get(AbstractOriginTest.FILE_NAME_RO);
167         builder.setFile(path.toFile());
168         assertArrayEquals(Files.readAllBytes(path), builder.getByteArray());
169     }
170 
171     @Test
172     void testSetOpenOptions() {
173         final Builder builder = builder();
174         assertEquals(0, builder.setOpenOptions().getOpenOptions().length);
175         assertEquals(0, builder.setOpenOptions((OpenOption[]) null).getOpenOptions().length);
176         assertEquals(1, builder.setOpenOptions(StandardOpenOption.READ).getOpenOptions().length);
177         final OpenOption[] options = { StandardOpenOption.READ, StandardOpenOption.WRITE };
178         assertArrayEquals(options, builder.setOpenOptions(options).getOpenOptions());
179         // Check that the builder makes a defensive copy of the array.
180         options[0] = null;
181         options[1] = null;
182         assertEquals(StandardOpenOption.READ, builder.getOpenOptions()[0]);
183         assertEquals(StandardOpenOption.WRITE, builder.getOpenOptions()[1]);
184     }
185 
186     @Test
187     void testSetPathGetByteArray() throws Exception {
188         final Builder builder = builder();
189         final Path path = Paths.get(AbstractOriginTest.FILE_NAME_RO);
190         builder.setPath(path);
191         assertArrayEquals(Files.readAllBytes(path), builder.getByteArray());
192     }
193 }