1   package org.orekit.files.iirv;
2   
3   import org.hipparchus.geometry.euclidean.threed.Vector3D;
4   import org.junit.jupiter.api.BeforeEach;
5   import org.junit.jupiter.api.Test;
6   import org.orekit.Utils;
7   import org.orekit.annotation.DefaultDataContext;
8   import org.orekit.errors.OrekitIllegalArgumentException;
9   import org.orekit.files.iirv.terms.CheckSumTerm;
10  import org.orekit.files.iirv.terms.CoordinateSystemTerm;
11  import org.orekit.files.iirv.terms.CrossSectionalAreaTerm;
12  import org.orekit.files.iirv.terms.DataSourceTerm;
13  import org.orekit.files.iirv.terms.DayOfYearTerm;
14  import org.orekit.files.iirv.terms.DragCoefficientTerm;
15  import org.orekit.files.iirv.terms.MassTerm;
16  import org.orekit.files.iirv.terms.MessageClassTerm;
17  import org.orekit.files.iirv.terms.MessageIDTerm;
18  import org.orekit.files.iirv.terms.MessageSourceTerm;
19  import org.orekit.files.iirv.terms.MessageStartConstantTerm;
20  import org.orekit.files.iirv.terms.MessageTypeTerm;
21  import org.orekit.files.iirv.terms.OriginIdentificationTerm;
22  import org.orekit.files.iirv.terms.OriginatorRoutingIndicatorTerm;
23  import org.orekit.files.iirv.terms.PositionVectorComponentTerm;
24  import org.orekit.files.iirv.terms.RoutingIndicatorTerm;
25  import org.orekit.files.iirv.terms.SequenceNumberTerm;
26  import org.orekit.files.iirv.terms.SolarReflectivityCoefficientTerm;
27  import org.orekit.files.iirv.terms.SupportIdCodeTerm;
28  import org.orekit.files.iirv.terms.TransferTypeConstantTerm;
29  import org.orekit.files.iirv.terms.VectorEpochTerm;
30  import org.orekit.files.iirv.terms.VectorTypeTerm;
31  import org.orekit.files.iirv.terms.VehicleIdCodeTerm;
32  import org.orekit.files.iirv.terms.VelocityVectorComponentTerm;
33  import org.orekit.time.AbsoluteDate;
34  import org.orekit.time.TimeScalesFactory;
35  import org.orekit.time.UTCScale;
36  import org.orekit.utils.PVCoordinates;
37  import org.orekit.utils.TimeStampedPVCoordinates;
38  
39  import java.util.ArrayList;
40  import java.util.Arrays;
41  import java.util.Collections;
42  import java.util.List;
43  import java.util.stream.Collectors;
44  
45  import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
46  import static org.junit.jupiter.api.Assertions.assertEquals;
47  import static org.junit.jupiter.api.Assertions.assertFalse;
48  import static org.junit.jupiter.api.Assertions.assertNotEquals;
49  import static org.junit.jupiter.api.Assertions.assertThrows;
50  import static org.junit.jupiter.api.Assertions.assertTrue;
51  
52  
53  /**
54   * Unit tests for {@link IIRVVector}
55   */
56  public class IIRVVectorTest {
57  
58      private static UTCScale UTC;
59      private final String line1 = "030000001010GIIRV GSFC";
60      private final String line1NoMetadata = "GIIRV GSFC";
61      private final String line2 = "1111123401001001000000000017";
62      private final String line3 = " 000003038560-000003031452 000005261153067";
63      private final String line4 = " 004300791000 005897352000 000909949000103";
64      private final String line5 = "00001000010000220 1000000007";
65      private final String line6 = "ITERM GCQU";
66  
67      final IIRVVector iirv = new IIRVVector(line1, line2, line3, line4, line5, line6, UTC);
68      private final List<String> lines = new ArrayList<>(Arrays.asList(line1, line2, line3, line4, line5, line6));
69  
70      @BeforeEach
71      @DefaultDataContext
72      public void setUp() {
73          // Sets the root of data to read
74          Utils.setDataRoot("regular-data");
75          UTC = TimeScalesFactory.getUTC();
76      }
77  
78      @Test
79      void parseLineStrings() {
80          final String computedLine1 = iirv.buildLine1(true);
81          final String computedLine2 = iirv.buildLine2();
82          final String computedLine3 = iirv.buildLine3();
83          final String computedLine4 = iirv.buildLine4();
84          final String computedLine5 = iirv.buildLine5();
85          final String computedLine6 = iirv.buildLine6();
86  
87          // Check Line 1
88          assertEquals(MessageTypeTerm.DEFAULT, iirv.getMessageType());
89          assertEquals(new MessageIDTerm("0000001"), iirv.getMessageID());
90          assertEquals(MessageSourceTerm.DEFAULT, iirv.getMessageSource());
91          assertEquals(MessageClassTerm.NOMINAL, iirv.getMessageClass());
92          assertEquals(new MessageStartConstantTerm(), iirv.getMessageStart());
93          assertEquals(OriginIdentificationTerm.GSFC, iirv.getOriginIdentification());
94          assertEquals(RoutingIndicatorTerm.GSFC, iirv.getRoutingIndicator());
95          assertEquals(line1, computedLine1);
96  
97          // Check Line 2
98          assertEquals(VectorTypeTerm.FREE_FLIGHT, iirv.getVectorType());
99          assertEquals(DataSourceTerm.NOMINAL, iirv.getDataSource());
100         assertEquals(new TransferTypeConstantTerm(), iirv.getTransferType());
101         assertEquals(CoordinateSystemTerm.GEOCENTRIC_TRUE_OF_DATE_ROTATING, iirv.getCoordinateSystem());
102         assertEquals(new SupportIdCodeTerm("1234"), iirv.getSupportIdCode());
103         assertEquals(new VehicleIdCodeTerm("01"), iirv.getVehicleIdCode());
104         assertEquals(new SequenceNumberTerm("001"), iirv.getSequenceNumber());
105         assertEquals(new DayOfYearTerm("001").getDateComponents(2024),
106             iirv.getDayOfYear().getDateComponents(2024));
107         assertChecksumIsValid(iirv.getLine2CheckSum(), line2);
108         assertEquals(line2, computedLine2);
109 
110         // Check Line 3
111         assertEquals(3038560, iirv.getXPosition().value());
112         assertEquals(-3031452, iirv.getYPosition().value());
113         assertEquals(5261153, iirv.getZPosition().value());
114         assertChecksumIsValid(iirv.getLine3CheckSum(), line3);
115         assertEquals(line3, computedLine3);
116 
117         // Check Line 4
118         assertEquals(4300791, iirv.getXVelocity().value());
119         assertEquals(5897352, iirv.getYVelocity().value());
120         assertEquals(909949, iirv.getZVelocity().value());
121         assertChecksumIsValid(iirv.getLine4CheckSum(), line4);
122         assertEquals(line4, computedLine4);
123 
124         // Check Line 5
125         assertEquals(0000100.0, iirv.getMass().value());
126         assertEquals(010.00, iirv.getCrossSectionalArea().value());
127         assertEquals(2.2, iirv.getDragCoefficient().value());
128         assertEquals(1.000000, iirv.getSolarReflectivityCoefficient().value());
129         assertChecksumIsValid(iirv.getLine5CheckSum(), line5);
130         assertEquals(line5, computedLine5);
131 
132         // Check Line 6
133         assertEquals("ITERM", iirv.getMessageEnd().value());
134         assertEquals(" ", iirv.getSpareTerm().value());
135         assertEquals(new OriginatorRoutingIndicatorTerm("GCQU"), iirv.getOriginatorRoutingIndicator());
136         assertEquals(line6, computedLine6);
137     }
138 
139     @Test
140     void iirvValidConstructorValidationTests() {
141         // Term-based constructor
142         final IIRVVector iirvFromTerms = new IIRVVector(
143             MessageTypeTerm.DEFAULT,
144             new MessageIDTerm(1),
145             MessageSourceTerm.DEFAULT,
146             MessageClassTerm.NOMINAL,
147             OriginIdentificationTerm.GSFC,
148             RoutingIndicatorTerm.GSFC,
149             VectorTypeTerm.FREE_FLIGHT,
150             DataSourceTerm.NOMINAL,
151             CoordinateSystemTerm.GEOCENTRIC_TRUE_OF_DATE_ROTATING,
152             new SupportIdCodeTerm(1234),
153             new VehicleIdCodeTerm(1),
154             new SequenceNumberTerm(1),
155             new DayOfYearTerm(1),
156             new VectorEpochTerm("000000000"),
157             new PositionVectorComponentTerm(3038560),
158             new PositionVectorComponentTerm(-3031452),
159             new PositionVectorComponentTerm(5261153),
160             new VelocityVectorComponentTerm(4300791),
161             new VelocityVectorComponentTerm(5897352),
162             new VelocityVectorComponentTerm(909949),
163             new MassTerm(100),
164             new CrossSectionalAreaTerm(10),
165             new DragCoefficientTerm(2.2),
166             new SolarReflectivityCoefficientTerm(1),
167             OriginatorRoutingIndicatorTerm.GCQU,
168             UTC
169         );
170 
171         final IIRVVector iirvFromLines = new IIRVVector(lines, UTC);   // Constructor form list of lines
172         final IIRVVector iirvFromCopy = new IIRVVector(iirvFromTerms); // Copy constructor
173         final IIRVVector iirvFromString = new IIRVParser(2024, UTC).parse(lines).getIIRV().get(0); // Parsed string constructor
174 
175         final List<String> linesWithSeparators = new ArrayList<>();
176         for (String l : lines) {
177             linesWithSeparators.add(l + IIRVVector.LINE_SEPARATOR);
178         }
179         final IIRVVector iirvFromLinesWithSeparators = new IIRVVector(linesWithSeparators, UTC);
180 
181         // Compare line-by-line for equality
182         String truthIIRVString = lines.stream()
183             .map(Object::toString)
184             .collect(Collectors.joining(IIRVVector.LINE_SEPARATOR)) + IIRVVector.LINE_SEPARATOR;
185 
186         // Compare each of the different ways of creating an IIRV that should be identical
187         for (IIRVVector compareIIRV : Arrays.asList(iirv, iirvFromTerms, iirvFromLines, iirvFromCopy, iirvFromString, iirvFromLinesWithSeparators)){
188             assertEquals(truthIIRVString, compareIIRV.toIIRVString(true));  // Compare equality by string
189             assertEquals(iirv, compareIIRV);  // Compare equality by ==
190 
191             // Check that generated IIRV vector strings that include/exclude message metadata are equal
192             assertEquals(iirv.toIIRVString(true), compareIIRV.toIIRVString(true));
193             assertEquals(iirv.toIIRVString(false), compareIIRV.toIIRVString(false));
194         }
195     }
196 
197     @Test
198     void testIIRVValidation() {
199         // Check function: IIRVVector.validateLines
200         assertDoesNotThrow(() -> IIRVVector.validateLines(
201             line1, line2, line3, line4, line5, line6, true));
202         assertDoesNotThrow(() -> IIRVVector.validateLines(
203             line1NoMetadata, line2, line3, line4, line5, line6, false));
204 
205         // Check function: IIRVVector.isFormatOK
206         assertTrue(IIRVVector.isFormatOK(line1, line2, line3, line4, line5, line6));
207         assertTrue(IIRVVector.isFormatOK(line1NoMetadata, line2, line3, line4, line5, line6));
208         assertTrue(IIRVVector.isFormatOK(Arrays.asList(line1, line2, line3, line4, line5, line6)));
209         assertTrue(IIRVVector.isFormatOK(Arrays.asList(line1NoMetadata, line2, line3, line4, line5, line6)));
210 
211         // Check == error handling
212         assertNotEquals("Wrong data type", iirv);
213         assertNotEquals(null, iirv);
214 
215         // Check line validation with/without line separator
216         assertTrue(IIRVVector.validateLine(0, line1 + IIRVVector.LINE_SEPARATOR));
217         assertTrue(IIRVVector.validateLine(1, line2 ));
218         assertTrue(IIRVVector.LINE_2_PATTERN.matcher(line2 ).matches());
219         assertTrue(IIRVVector.LINE_2_PATTERN.matcher(line2 + IIRVVector.LINE_SEPARATOR).matches());
220         assertTrue(IIRVVector.validateLine(1, line2 + IIRVVector.LINE_SEPARATOR));
221         assertTrue(IIRVVector.validateLine(2, line3 + IIRVVector.LINE_SEPARATOR));
222         assertTrue(IIRVVector.validateLine(3, line4 + IIRVVector.LINE_SEPARATOR));
223         assertTrue(IIRVVector.validateLine(4, line5 + IIRVVector.LINE_SEPARATOR));
224         assertTrue(IIRVVector.validateLine(5, line6 + IIRVVector.LINE_SEPARATOR));
225     }
226 
227     @Test
228     void iirvErrorHandlingTests() {
229         // Check constructor errors
230         assertThrows(OrekitIllegalArgumentException.class, // Line 1 w/ metadata: "GIIRB" instead of "GIIRV"
231             () -> new IIRVVector("030000001010GIIRB GSFC", line2, line3, line4, line5, line6, UTC)
232         );
233         assertThrows(OrekitIllegalArgumentException.class, // Line 1 w/out metadata: "GIIRB" instead of "GIIRV"
234             () -> new IIRVVector("GIIRB GSFC", line2, line3, line4, line5, line6, UTC)
235         );
236         assertThrows(OrekitIllegalArgumentException.class, // Empty string
237             () -> new IIRVVector("", line2, line3, line4, line5, line6, UTC)
238         );
239         assertThrows(OrekitIllegalArgumentException.class, // null value
240             () -> new IIRVVector(null, line2, line3, line4, line5, line6, UTC)
241         );
242 
243         // Check function: IIRVVector.validateLines
244         assertThrows(OrekitIllegalArgumentException.class, // Empty list
245             () -> IIRVVector.validateLines(Collections.emptyList(), true)
246         );
247         assertThrows(OrekitIllegalArgumentException.class, // null list
248             () -> IIRVVector.validateLines(null, true)
249         );
250         assertThrows(OrekitIllegalArgumentException.class, // String too short
251             () -> IIRVVector.validateLine(10, "xy")
252         );
253         assertThrows(OrekitIllegalArgumentException.class, // invalid line index in validation
254             () -> IIRVVector.validateLine(10, line1)
255         );
256 
257         // Check function: IIRVVector.isFormatOK
258         assertFalse(IIRVVector.isFormatOK(Collections.emptyList()));
259         assertFalse(IIRVVector.isFormatOK(null));
260 
261         // Check invalid lines 2-6 for both versions of line 1 (w/ and w/out metadata)
262         for (String l1 : Arrays.asList(line1, line1NoMetadata)) {
263             assertThrows(OrekitIllegalArgumentException.class, // Line 2: "0" is not a valid vector type
264                 () -> new IIRVVector(l1, "0111123401001001000000000017", line3, line4, line5, line6, UTC)
265             );
266             assertThrows(OrekitIllegalArgumentException.class, // Line 2: Invalid checksum
267                 () -> new IIRVVector(l1, "0111123401001001000000000018", line3, line4, line5, line6, UTC)
268             );
269             assertThrows(OrekitIllegalArgumentException.class, // Line 2: null value
270                 () -> new IIRVVector(l1, null, line3, line4, line5, line6, UTC)
271             );
272 
273             assertThrows(OrekitIllegalArgumentException.class, // Line 3: First character must be ' ' or '-'
274                 () -> new IIRVVector(l1, line2, "0000003038560-000003031452 000005261153067", line4, line5, line6, UTC)
275             );
276             assertThrows(OrekitIllegalArgumentException.class, // Line 3: Invalid checksum
277                 () -> new IIRVVector(l1, line2, "0000003038560-000003031452 000005261153167", line4, line5, line6, UTC)
278             );
279             assertThrows(OrekitIllegalArgumentException.class, // Line 3: null value
280                 () -> new IIRVVector(l1, line2, null, line4, line5, line6, UTC)
281             );
282 
283             assertThrows(OrekitIllegalArgumentException.class, // Line 4: incorrect length
284                 () -> new IIRVVector(l1, line2, line3, " 004300791000 005897352000 0009099490000228", line5, line6, UTC)
285             );
286             assertThrows(OrekitIllegalArgumentException.class, // Line 4: Invalid checksum
287                 () -> new IIRVVector(l1, line2, line3, " 004300791000 005897352000 000909949000228", line5, line6, UTC)
288             );
289             assertThrows(OrekitIllegalArgumentException.class, // Line 4: null value
290                 () -> new IIRVVector(l1, line2, line3, null, line5, line6, UTC)
291             );
292 
293             assertThrows(OrekitIllegalArgumentException.class, // Line 5: Unexpected alphanumeric character
294                 () -> new IIRVVector(l1, line2, line3, line4, "000010a0010000220 1000000007", line6, UTC)
295             );
296             assertThrows(OrekitIllegalArgumentException.class, // Line 5: Checksum
297                 () -> new IIRVVector(l1, line2, line3, line4, "000010a0010000220 1000000017", line6, UTC)
298             );
299             assertThrows(OrekitIllegalArgumentException.class, // Line 5: null value
300                 () -> new IIRVVector(l1, line2, line3, line4, null, line6, UTC)
301             );
302 
303             assertThrows(OrekitIllegalArgumentException.class, // Line 6: missing space
304                 () -> new IIRVVector(l1, line2, line3, line4, line5, "ITERMGCQU", UTC)
305             );
306             assertThrows(OrekitIllegalArgumentException.class, // Line 6: null value
307                 () -> new IIRVVector(l1, line2, line3, line4, line5, null, UTC)
308             );
309         }
310     }
311 
312     void testParsesLinesWithSeparators() {
313 
314     }
315 
316     @Test
317     @DefaultDataContext
318     void iirvAbsoluteTimeTest() {
319         final IIRVVector iirv = new IIRVVector(lines, UTC);
320         AbsoluteDate absoluteDateFromIIRV = iirv.getAbsoluteDate(2024);
321         AbsoluteDate absoluteDateToCompare = new AbsoluteDate(
322             2024, 1, 1,
323             0, 0, 0, UTC);
324         assertEquals(absoluteDateToCompare, absoluteDateFromIIRV);
325     }
326 
327     @Test
328     void iirvVectorCreationTests() {
329         final IIRVVector iirv = new IIRVVector(lines, UTC);
330 
331         Vector3D iirvPos = iirv.getPositionVector();
332         Vector3D iirvVel = iirv.getVelocityVector();
333 
334         assertEquals(new Vector3D(3038560, -3031452, 5261153), iirvPos);
335         assertEquals(new Vector3D(4300791, 5897352, 909949), iirvVel);
336     }
337 
338 
339     @Test
340     void coordinatesTest() {
341         final IIRVVector iirv = new IIRVVector(lines, UTC);
342         PVCoordinates pvCoordinates = iirv.getPVCoordinates();
343         TimeStampedPVCoordinates timeStampedPVCoordinates = iirv.getTimeStampedPVCoordinates(1984);
344         assertEquals(pvCoordinates.getPosition(), timeStampedPVCoordinates.getPosition());
345         assertEquals(pvCoordinates.getVelocity(), timeStampedPVCoordinates.getVelocity());
346     }
347 
348     @Test
349     void iirvHumanReadableTest() {
350         final IIRVVector iirv = new IIRVVector(lines, UTC);
351         final List<String> iirvStrings = iirv.toIIRVStrings(true);
352         final List<String> humanReadableStrings = iirv.toHumanReadableLines();
353         for (int i = 0; i < 6; i++) {
354             assertEquals(humanReadableStrings.get(i).replace("/", ""), iirvStrings.get(i));
355 
356         }
357     }
358 
359     /**
360      * Performs an assertion to check that the computed check sum matches the actual
361      * check sum for a given line
362      *
363      * @param checkSum check sum term to generate the checksum
364      * @param line     IIRV message line against which to validate the computed check sum
365      */
366     void assertChecksumIsValid(CheckSumTerm checkSum, String line) {
367         int line2ComputedCheckSum = CheckSumTerm.computeChecksum(line.substring(0, line.length() - 3));
368         assertEquals(checkSum.value(), line2ComputedCheckSum);
369         assertTrue(checkSum.validateAgainstLineString(line));
370     }
371 }