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.euclidean.threed.txt;
18  
19  import java.io.StringReader;
20  import java.util.Arrays;
21  import java.util.List;
22  
23  import org.apache.commons.geometry.core.GeometryTestUtils;
24  import org.apache.commons.geometry.euclidean.threed.Vector3D;
25  import org.apache.commons.geometry.io.core.test.CloseCountReader;
26  import org.apache.commons.geometry.io.euclidean.EuclideanIOTestUtils;
27  import org.apache.commons.geometry.io.euclidean.threed.FacetDefinition;
28  import org.junit.jupiter.api.Assertions;
29  import org.junit.jupiter.api.Test;
30  
31  class TextFacetDefinitionReaderTest {
32  
33      private static final double TEST_EPS = 1e-10;
34  
35      @Test
36      void testPropertyDefaults() {
37          // arrange
38          TextFacetDefinitionReader reader = facetReader("");
39  
40          // act/assert
41          Assertions.assertEquals("#", reader.getCommentToken());
42      }
43  
44      @Test
45      void testSetCommentToken_invalidArgs() {
46          // arrange
47          TextFacetDefinitionReader reader = facetReader("");
48          String baseMsg = "Comment token cannot contain whitespace; was [";
49  
50          // act/assert
51          GeometryTestUtils.assertThrowsWithMessage(() -> {
52              reader.setCommentToken(" ");
53          }, IllegalArgumentException.class, baseMsg + " ]");
54  
55          GeometryTestUtils.assertThrowsWithMessage(() -> {
56              reader.setCommentToken("a\tb");
57          }, IllegalArgumentException.class, baseMsg + "a\tb]");
58      }
59  
60      @Test
61      void testReadFacet_empty() {
62          // arrange
63          TextFacetDefinitionReader reader = facetReader("");
64  
65          // act
66          List<FacetDefinition> facets = EuclideanIOTestUtils.readAll(reader);
67  
68          // assert
69          Assertions.assertEquals(0, facets.size());
70      }
71  
72      @Test
73      void testReadFacet_singleFacet() {
74          // arrange
75          TextFacetDefinitionReader reader = facetReader(
76                  "1.0 2.0 3.0 40 50 60 7.0e-2 8e-2 9E-02 1.01e+1 -11.02 +12");
77  
78          // act
79          List<FacetDefinition> facets = EuclideanIOTestUtils.readAll(reader);
80  
81          // assert
82          Assertions.assertEquals(1, facets.size());
83  
84          EuclideanIOTestUtils.assertFacetVertices(facets.get(0), Arrays.asList(
85                  Vector3D.of(1, 2, 3),
86                  Vector3D.of(40, 50, 60),
87                  Vector3D.of(0.07, 0.08, 0.09),
88                  Vector3D.of(10.1, -11.02, 12)), TEST_EPS);
89      }
90  
91      @Test
92      void testReadFacet_multipleFacets() {
93          // arrange
94          TextFacetDefinitionReader reader = facetReader(
95                  "1,2,3    4,5,6 7,8,9    10,11,12\r" +
96                  "1 1 1;2 2 2;3 3 3;4 4 4;5 5 5\r\n" +
97                  "6 6 6 6 6 6 6 6 6");
98  
99          // act
100         List<FacetDefinition> facets = EuclideanIOTestUtils.readAll(reader);
101 
102         // assert
103         Assertions.assertEquals(3, facets.size());
104 
105         EuclideanIOTestUtils.assertFacetVertices(facets.get(0), Arrays.asList(
106                 Vector3D.of(1, 2, 3),
107                 Vector3D.of(4, 5, 6),
108                 Vector3D.of(7, 8, 9),
109                 Vector3D.of(10, 11, 12)), TEST_EPS);
110 
111         EuclideanIOTestUtils.assertFacetVertices(facets.get(1), Arrays.asList(
112                 Vector3D.of(1, 1, 1),
113                 Vector3D.of(2, 2, 2),
114                 Vector3D.of(3, 3, 3),
115                 Vector3D.of(4, 4, 4),
116                 Vector3D.of(5, 5, 5)), TEST_EPS);
117 
118         EuclideanIOTestUtils.assertFacetVertices(facets.get(2), Arrays.asList(
119                 Vector3D.of(6, 6, 6),
120                 Vector3D.of(6, 6, 6),
121                 Vector3D.of(6, 6, 6)), TEST_EPS);
122     }
123 
124     @Test
125     void testReadFacet_blankLinesAndComments() {
126         // arrange
127         TextFacetDefinitionReader reader = facetReader(
128                 "# some ignored numbers: 1 2 3 4 5 6\n" +
129                 "\n" +
130                 " \n" +
131                 "1 2 3 4 5 6 7 8 9 # end of line comment\n" +
132                 "1 1 1 2 2 2 3 3 3\n" +
133                 "\t\n" +
134                 "#line comment\n" +
135                 "5 5 5 5 5 5 5 5 5\n\n  \n");
136 
137         // act
138         List<FacetDefinition> facets = EuclideanIOTestUtils.readAll(reader);
139 
140         // assert
141         Assertions.assertEquals(3, facets.size());
142 
143         EuclideanIOTestUtils.assertFacetVertices(facets.get(0), Arrays.asList(
144                 Vector3D.of(1, 2, 3),
145                 Vector3D.of(4, 5, 6),
146                 Vector3D.of(7, 8, 9)), TEST_EPS);
147 
148         EuclideanIOTestUtils.assertFacetVertices(facets.get(1), Arrays.asList(
149                 Vector3D.of(1, 1, 1),
150                 Vector3D.of(2, 2, 2),
151                 Vector3D.of(3, 3, 3)), TEST_EPS);
152 
153         EuclideanIOTestUtils.assertFacetVertices(facets.get(2), Arrays.asList(
154                 Vector3D.of(5, 5, 5),
155                 Vector3D.of(5, 5, 5),
156                 Vector3D.of(5, 5, 5)), TEST_EPS);
157     }
158 
159     @Test
160     void testReadFacet_nonDefaultCommentToken() {
161         // arrange
162         TextFacetDefinitionReader reader = facetReader(
163                 "5$ some ignored numbers: 1 2 3 4 5 6\n" +
164                 "\n" +
165                 " \n" +
166                 "1 2 3 4 5 6 7 8 9 5$ end of line comment\n" +
167                 "1 1 1 2 2 2 3 3 3\n" +
168                 "\t\n" +
169                 "5$line comment\n" +
170                 "5 5 5 5 5 5 5 5 5\n");
171 
172         reader.setCommentToken("5$");
173 
174         // act
175         List<FacetDefinition> facets = EuclideanIOTestUtils.readAll(reader);
176 
177         // assert
178         Assertions.assertEquals(3, facets.size());
179 
180         EuclideanIOTestUtils.assertFacetVertices(facets.get(0), Arrays.asList(
181                 Vector3D.of(1, 2, 3),
182                 Vector3D.of(4, 5, 6),
183                 Vector3D.of(7, 8, 9)), TEST_EPS);
184 
185         EuclideanIOTestUtils.assertFacetVertices(facets.get(1), Arrays.asList(
186                 Vector3D.of(1, 1, 1),
187                 Vector3D.of(2, 2, 2),
188                 Vector3D.of(3, 3, 3)), TEST_EPS);
189 
190         EuclideanIOTestUtils.assertFacetVertices(facets.get(2), Arrays.asList(
191                 Vector3D.of(5, 5, 5),
192                 Vector3D.of(5, 5, 5),
193                 Vector3D.of(5, 5, 5)), TEST_EPS);
194     }
195 
196     @Test
197     void testReadFacet_longCommentToken() {
198         // arrange
199         TextFacetDefinitionReader reader = facetReader(
200                 "this_is-a-comment some ignored numbers: 1 2 3 4 5 6\n" +
201                 "\n" +
202                 " \n" +
203                 "1 2 3 4 5 6 7 8 9 this_is-a-comment end of line comment\n" +
204                 "1 1 1 2 2 2 3 3 3\n" +
205                 "\t\n" +
206                 "this_is-a-commentline comment\n" +
207                 "5 5 5 5 5 5 5 5 5\n");
208 
209         reader.setCommentToken("this_is-a-comment");
210 
211         // act
212         List<FacetDefinition> facets = EuclideanIOTestUtils.readAll(reader);
213 
214         // assert
215         Assertions.assertEquals(3, facets.size());
216 
217         EuclideanIOTestUtils.assertFacetVertices(facets.get(0), Arrays.asList(
218                 Vector3D.of(1, 2, 3),
219                 Vector3D.of(4, 5, 6),
220                 Vector3D.of(7, 8, 9)), TEST_EPS);
221 
222         EuclideanIOTestUtils.assertFacetVertices(facets.get(1), Arrays.asList(
223                 Vector3D.of(1, 1, 1),
224                 Vector3D.of(2, 2, 2),
225                 Vector3D.of(3, 3, 3)), TEST_EPS);
226 
227         EuclideanIOTestUtils.assertFacetVertices(facets.get(2), Arrays.asList(
228                 Vector3D.of(5, 5, 5),
229                 Vector3D.of(5, 5, 5),
230                 Vector3D.of(5, 5, 5)), TEST_EPS);
231     }
232 
233     @Test
234     void testReadFacet_emptyCommentToken() {
235         // arrange
236         TextFacetDefinitionReader reader = facetReader("# line comment\n");
237         reader.setCommentToken("");
238 
239         // act
240         GeometryTestUtils.assertThrowsWithMessage(() -> {
241             reader.readFacet();
242         }, IllegalStateException.class,
243                 "Parsing failed at line 1, column 1: expected double but found empty token followed by [#]");
244     }
245 
246     @Test
247     void testReadFacet_nullCommentToken() {
248         // arrange
249         TextFacetDefinitionReader reader = facetReader("# line comment\n");
250         reader.setCommentToken(null);
251 
252         // act/assert
253         GeometryTestUtils.assertThrowsWithMessage(() -> {
254             reader.readFacet();
255         }, IllegalStateException.class,
256                 "Parsing failed at line 1, column 1: expected double but found empty token followed by [#]");
257     }
258 
259     @Test
260     void testReadFacet_invalidTokens() {
261         // arrange
262         TextFacetDefinitionReader reader = facetReader("1 abc 3 ; 4 5 6 ; 7 8 9");
263 
264         // act/assert
265         GeometryTestUtils.assertThrowsWithMessage(() -> {
266             reader.readFacet();
267         }, IllegalStateException.class,
268                 "Parsing failed at line 1, column 3: expected double but found [abc]");
269     }
270 
271     @Test
272     void testReadFacet_notEnoughVectors() {
273         // arrange
274         TextFacetDefinitionReader reader = facetReader(
275                 "1\n" +
276                 "1 2\n" +
277                 "1 2 3\n" +
278                 "1 2 3 ; 4 5 6;\n");
279 
280         // act/assert
281         GeometryTestUtils.assertThrowsWithMessage(() -> {
282             reader.readFacet();
283         }, IllegalStateException.class,
284                 "Parsing failed at line 1, column 2: expected double but found end of line");
285 
286         GeometryTestUtils.assertThrowsWithMessage(() -> {
287             reader.readFacet();
288         }, IllegalStateException.class,
289                 "Parsing failed at line 2, column 4: expected double but found end of line");
290 
291         GeometryTestUtils.assertThrowsWithMessage(() -> {
292             reader.readFacet();
293         }, IllegalStateException.class,
294                 "Parsing failed at line 3, column 6: expected double but found end of line");
295 
296         GeometryTestUtils.assertThrowsWithMessage(() -> {
297             reader.readFacet();
298         }, IllegalStateException.class,
299                 "Parsing failed at line 4, column 15: expected double but found end of line");
300     }
301 
302     @Test
303     void testClose() {
304         // arrange
305         final CloseCountReader countReader = new CloseCountReader(new StringReader(""));
306         final TextFacetDefinitionReader reader = new TextFacetDefinitionReader(countReader);
307 
308         // act
309         reader.close();
310 
311         // assert
312         Assertions.assertEquals(1, countReader.getCloseCount());
313     }
314 
315     private static TextFacetDefinitionReader facetReader(final String content) {
316         return new TextFacetDefinitionReader(new StringReader(content));
317     }
318 }