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    *      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  package org.apache.commons.geometry.io.core.internal;
18  
19  import java.io.BufferedReader;
20  import java.io.BufferedWriter;
21  import java.io.ByteArrayInputStream;
22  import java.io.ByteArrayOutputStream;
23  import java.io.FileNotFoundException;
24  import java.io.IOException;
25  import java.io.UncheckedIOException;
26  import java.net.MalformedURLException;
27  import java.net.URL;
28  import java.nio.charset.StandardCharsets;
29  import java.nio.file.Path;
30  import java.nio.file.Paths;
31  import java.util.Arrays;
32  import java.util.stream.Collectors;
33  import java.util.stream.Stream;
34  
35  import org.apache.commons.geometry.core.GeometryTestUtils;
36  import org.apache.commons.geometry.io.core.input.GeometryInput;
37  import org.apache.commons.geometry.io.core.input.StreamGeometryInput;
38  import org.apache.commons.geometry.io.core.output.GeometryOutput;
39  import org.apache.commons.geometry.io.core.output.StreamGeometryOutput;
40  import org.apache.commons.geometry.io.core.test.CloseCountInputStream;
41  import org.junit.jupiter.api.Assertions;
42  import org.junit.jupiter.api.Test;
43  
44  class GeometryIOUtilsTest {
45  
46      @Test
47      void testGetFileName_path() {
48          // act/assert
49          Assertions.assertNull(GeometryIOUtils.getFileName((Path) null));
50          Assertions.assertNull(GeometryIOUtils.getFileName(Paths.get("")));
51  
52          Assertions.assertEquals("myfile", GeometryIOUtils.getFileName(Paths.get("myfile")));
53          Assertions.assertEquals("myfile.txt", GeometryIOUtils.getFileName(Paths.get("path/to/myfile.txt")));
54      }
55  
56      @Test
57      void testGetFileName_url() throws MalformedURLException {
58          // act/assert
59          Assertions.assertNull(GeometryIOUtils.getFileName((URL) null));
60          Assertions.assertNull(GeometryIOUtils.getFileName(new URL("http://test.com/")));
61  
62          Assertions.assertEquals("myfile.txt",
63                  GeometryIOUtils.getFileName(new URL("http://test.com/myfile.txt?a=otherfile.txt")));
64      }
65  
66      @Test
67      void testGetFileName_string() {
68          // act/assert
69          Assertions.assertNull(GeometryIOUtils.getFileName((String) null));
70          Assertions.assertNull(GeometryIOUtils.getFileName(""));
71          Assertions.assertNull(GeometryIOUtils.getFileName("some/path/"));
72          Assertions.assertNull(GeometryIOUtils.getFileName("some\\path\\"));
73  
74          Assertions.assertEquals("myfile", GeometryIOUtils.getFileName("myfile"));
75          Assertions.assertEquals("myfile.txt", GeometryIOUtils.getFileName(Paths.get("path/to/myfile.txt")));
76          Assertions.assertEquals("myfile.txt", GeometryIOUtils.getFileName(Paths.get("/myfile.txt")));
77          Assertions.assertEquals("myfile.txt", GeometryIOUtils.getFileName(Paths.get("path\\to\\myfile.txt")));
78          Assertions.assertEquals("myfile.txt", GeometryIOUtils.getFileName(Paths.get("C:\\myfile.txt")));
79      }
80  
81      @Test
82      void testGetFileExtension() {
83          // act/assert
84          Assertions.assertEquals(null, GeometryIOUtils.getFileExtension(null));
85          Assertions.assertEquals("", GeometryIOUtils.getFileExtension(""));
86          Assertions.assertEquals("", GeometryIOUtils.getFileExtension("abc"));
87          Assertions.assertEquals("", GeometryIOUtils.getFileExtension("abc."));
88          Assertions.assertEquals("txt", GeometryIOUtils.getFileExtension("abc.txt"));
89          Assertions.assertEquals("X", GeometryIOUtils.getFileExtension("/a/b/c.X"));
90          Assertions.assertEquals("jpg", GeometryIOUtils.getFileExtension("/a/b/c.d.jpg"));
91      }
92  
93      @Test
94      void testCreateBufferedWriter_givenCharset() throws IOException {
95          // arrange
96          final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
97          final GeometryOutput output = new StreamGeometryOutput(bytes, null, StandardCharsets.UTF_8);
98  
99          // act
100         final BufferedWriter writer = GeometryIOUtils.createBufferedWriter(output, StandardCharsets.ISO_8859_1);
101         writer.append('\u00fc');
102         writer.flush();
103 
104         // assert
105         Assertions.assertEquals("\u00fc", new String(bytes.toByteArray(), StandardCharsets.UTF_8));
106     }
107 
108     @Test
109     void testCreateBufferedWriter_defaultCharset() throws IOException {
110         // arrange
111         final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
112         final GeometryOutput output = new StreamGeometryOutput(bytes);
113 
114         // act
115         final BufferedWriter writer = GeometryIOUtils.createBufferedWriter(output, StandardCharsets.ISO_8859_1);
116         writer.append('\u00fc');
117         writer.flush();
118 
119         // assert
120         Assertions.assertEquals("\u00fc", new String(bytes.toByteArray(), StandardCharsets.ISO_8859_1));
121     }
122 
123     @Test
124     void testCreateBufferedReader_givenCharset() throws IOException {
125         // arrange
126         final byte[] bytes = "\u00fc".getBytes(StandardCharsets.UTF_8);
127         final GeometryInput input = new StreamGeometryInput(
128                 new ByteArrayInputStream(bytes), null, StandardCharsets.UTF_8);
129 
130         // act
131         final BufferedReader reader = GeometryIOUtils.createBufferedReader(input, StandardCharsets.ISO_8859_1);
132 
133         // assert
134         Assertions.assertEquals("\u00fc", reader.readLine());
135     }
136 
137     @Test
138     void testCreateBufferedReader_defaultCharset() throws IOException {
139         // arrange
140         final byte[] bytes = "\u00fc".getBytes(StandardCharsets.UTF_8);
141         final GeometryInput input = new StreamGeometryInput(new ByteArrayInputStream(bytes));
142 
143         // act
144         final BufferedReader reader = GeometryIOUtils.createBufferedReader(input, StandardCharsets.UTF_8);
145 
146         // assert
147         Assertions.assertEquals("\u00fc", reader.readLine());
148     }
149 
150     @Test
151     void testGetUnchecked() {
152         // act
153         final Object result = GeometryIOUtils.getUnchecked(() -> "abc");
154 
155         // assert
156         Assertions.assertSame("abc", result);
157     }
158 
159     @Test
160     void testGetUnchecked_failure() {
161         // arrange
162         final IOSupplier<String> supplier = () -> {
163             throw new IOException("test");
164         };
165 
166         // act/assert
167         GeometryTestUtils.assertThrowsWithMessage(
168                 () -> GeometryIOUtils.getUnchecked(supplier),
169                 UncheckedIOException.class,
170                 "IOException: test");
171     }
172 
173     @Test
174     void testAcceptUnchecked() {
175         // arrange
176         final ByteArrayOutputStream out = new ByteArrayOutputStream();
177         final byte[] bytes = new byte[] {0, 1};
178 
179         // act
180         GeometryIOUtils.acceptUnchecked(out::write, bytes);
181 
182         // assert
183         Assertions.assertArrayEquals(bytes, out.toByteArray());
184     }
185 
186     @Test
187     void testAcceptUnchecked_failure() {
188         // arrange
189         final IOConsumer<String> consumer = str -> {
190             throw new IOException(str);
191         };
192 
193         // act/assert
194         GeometryTestUtils.assertThrowsWithMessage(
195                 () -> GeometryIOUtils.acceptUnchecked(consumer, "arg"),
196                 UncheckedIOException.class,
197                 "IOException: arg");
198     }
199 
200     @Test
201     void testApplyAsIntUnchecked() {
202         // arrange
203         final ByteArrayInputStream in = new ByteArrayInputStream(new byte[] {0, 1, 2});
204         final byte[] bytes = new byte[10];
205 
206         // act
207         int result = GeometryIOUtils.applyAsIntUnchecked(in::read, bytes);
208 
209         // assert
210         Assertions.assertEquals(3, result);
211         Assertions.assertEquals((byte) 0, bytes[0]);
212         Assertions.assertEquals((byte) 1, bytes[1]);
213         Assertions.assertEquals((byte) 2, bytes[2]);
214     }
215 
216     @Test
217     void testApplyAsIntUnchecked_failure() {
218         // arrange
219         final IOToIntFunction<String> consumer = str -> {
220             throw new IOException(str);
221         };
222 
223         // act/assert
224         GeometryTestUtils.assertThrowsWithMessage(
225                 () -> GeometryIOUtils.applyAsIntUnchecked(consumer, "arg"),
226                 UncheckedIOException.class,
227                 "IOException: arg");
228     }
229 
230     @Test
231     void testCreateUnchecked() {
232         // arrange
233         final FileNotFoundException exc = new FileNotFoundException("test");
234 
235         // act
236         final UncheckedIOException result = GeometryIOUtils.createUnchecked(exc);
237 
238         // assert
239         Assertions.assertEquals("FileNotFoundException: test", result.getMessage());
240         Assertions.assertSame(exc, result.getCause());
241     }
242 
243     @Test
244     void testParseError_noCause() {
245         // act
246         final IllegalStateException exc = GeometryIOUtils.parseError("test");
247 
248         // assert
249         Assertions.assertEquals("test", exc.getMessage());
250         Assertions.assertNull(exc.getCause());
251     }
252 
253     @Test
254     void testParseError_withCause() {
255         // arrange
256         final Throwable cause = new Throwable("cause");
257 
258         // act
259         final IllegalStateException exc = GeometryIOUtils.parseError("test", cause);
260 
261         // assert
262         Assertions.assertEquals("test", exc.getMessage());
263         Assertions.assertSame(cause, exc.getCause());
264     }
265 
266     @Test
267     void testTryApplyCloseable() {
268         // arrange
269         final CloseCountInputStream in = new CloseCountInputStream(new ByteArrayInputStream(new byte[] {1}));
270 
271         // act
272         final int result = GeometryIOUtils.tryApplyCloseable(i -> i.read(), () -> in);
273 
274         // assert
275         Assertions.assertEquals(1, result);
276         Assertions.assertEquals(0, in.getCloseCount());
277     }
278 
279     @Test
280     void testTryApplyCloseable_supplierThrows_ioException() {
281         // act/assert
282         GeometryTestUtils.assertThrowsWithMessage(() -> {
283             GeometryIOUtils.tryApplyCloseable(i -> {
284                 throw new IOException("fn");
285             }, () -> {
286                 throw new IOException("supplier");
287             });
288         }, UncheckedIOException.class, "IOException: supplier");
289     }
290 
291     @Test
292     void testTryApplyCloseable_supplierThrows_runtimeException() {
293         // act/assert
294         GeometryTestUtils.assertThrowsWithMessage(() -> {
295             GeometryIOUtils.tryApplyCloseable(i -> {
296                 throw new IOException("fn");
297             }, () -> {
298                 throw new RuntimeException("supplier");
299             });
300         }, RuntimeException.class, "supplier");
301     }
302 
303 
304     @Test
305     void testTryApplyCloseable_functionThrows() {
306         // arrange
307         final CloseCountInputStream in = new CloseCountInputStream(new ByteArrayInputStream(new byte[0]));
308 
309         // act/assert
310         GeometryTestUtils.assertThrowsWithMessage(() -> {
311             GeometryIOUtils.tryApplyCloseable(i -> {
312                 throw new IOException("fn");
313             }, () -> in);
314         }, UncheckedIOException.class, "IOException: fn");
315 
316         Assertions.assertEquals(1, in.getCloseCount());
317     }
318 
319     @Test
320     void testTryApplyCloseable_functionThrows_inputCloseThrows() {
321         // arrange
322         final CloseCountInputStream in = new CloseCountInputStream(new CloseFailByteArrayInputStream(new byte[0]));
323 
324         // act/assert
325         final Throwable thr = Assertions.assertThrows(UncheckedIOException.class, () -> {
326             GeometryIOUtils.tryApplyCloseable(i -> {
327                 throw new IOException("fn");
328             }, () -> in);
329         });
330 
331         Assertions.assertEquals(UncheckedIOException.class, thr.getClass());
332         Assertions.assertEquals("close", thr.getSuppressed()[0].getMessage());
333 
334         Assertions.assertEquals(1, in.getCloseCount());
335     }
336 
337     @Test
338     void testCreateCloseableStream() {
339         // arrange
340         final CloseCountInputStream in = new CloseCountInputStream(new ByteArrayInputStream(new byte[0]));
341 
342         // act/assert
343         try (Stream<String> stream = GeometryIOUtils.createCloseableStream(i -> Stream.of("a"), () -> in)) {
344             Assertions.assertEquals(Arrays.asList("a"), stream.collect(Collectors.toList()));
345             Assertions.assertEquals(0, in.getCloseCount());
346         }
347 
348         Assertions.assertEquals(1, in.getCloseCount());
349     }
350 
351     @Test
352     void testCreateCloseableStream_closeThrows() {
353         // arrange
354         final CloseCountInputStream in = new CloseCountInputStream(new CloseFailByteArrayInputStream(new byte[0]));
355 
356         // act/assert
357         GeometryTestUtils.assertThrowsWithMessage(
358                 () -> GeometryIOUtils.createCloseableStream(i -> Stream.of("a"), () -> in).close(),
359                 UncheckedIOException.class, "IOException: close");
360     }
361 
362     private static final class CloseFailByteArrayInputStream extends ByteArrayInputStream {
363 
364         CloseFailByteArrayInputStream(final byte[] buf) {
365             super(buf);
366         }
367 
368         @Override
369         public void close() throws IOException {
370             throw new IOException("close");
371         }
372     }
373 }