1   /* Contributed in the public domain.
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS 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.orekit.utils;
18  
19  import java.util.ArrayList;
20  import java.util.Arrays;
21  import java.util.Collections;
22  import java.util.List;
23  import java.util.stream.Collectors;
24  
25  import org.hipparchus.Field;
26  import org.hipparchus.util.Binary64;
27  import org.hipparchus.util.Binary64Field;
28  import org.junit.jupiter.api.Assertions;
29  import org.junit.jupiter.api.BeforeAll;
30  import org.junit.jupiter.api.BeforeEach;
31  import org.junit.jupiter.api.Test;
32  import org.orekit.Utils;
33  import org.orekit.errors.OrekitMessages;
34  import org.orekit.errors.TimeStampedCacheException;
35  import org.orekit.time.FieldAbsoluteDate;
36  
37  /**
38   * Unit tests for {@link ImmutableTimeStampedCache}.
39   *
40   * @author Evan Ward
41   */
42  public class ImmutableFieldTimeStampedCacheTest {
43  
44      /**
45       * Binary64 field.
46       */
47      private static final Field<Binary64> field = Binary64Field.getInstance();
48  
49      /**
50       * arbitrary date
51       */
52      private static final FieldAbsoluteDate<Binary64> date = FieldAbsoluteDate.getCCSDSEpoch(field);
53  
54      /**
55       * data provided to {@link #cache}
56       */
57      private List<FieldAbsoluteDate<Binary64>> data;
58  
59      /**
60       * subject under test
61       */
62      private ImmutableFieldTimeStampedCache<FieldAbsoluteDate<Binary64>, Binary64> cache;
63  
64      /**
65       * set Orekit data for useful debugging messages from dates.
66       */
67      @BeforeAll
68      public static void setUpBefore() {
69          Utils.setDataRoot("regular-data");
70      }
71  
72      /**
73       * create {@link #cache} and {@link #data} with neighborsSize = 3
74       */
75      @BeforeEach
76      public void setUp() {
77          data  = Arrays.asList(date, date.shiftedBy(1), date.shiftedBy(2),
78                                date.shiftedBy(3), date.shiftedBy(4),
79                                date.shiftedBy(5));
80          cache = new ImmutableFieldTimeStampedCache<>(3, data);
81      }
82  
83      /**
84       * check {@link ImmutableFieldTimeStampedCache#ImmutableFieldTimeStampedCache(int, java.util.Collection)}
85       */
86      @Test
87      public void testImmutableTimeStampedCache() {
88          // exception for neighborsSize > data.size()
89          try {
90              new ImmutableFieldTimeStampedCache<>(data.size() + 1, data);
91              Assertions.fail("Expected Exception");
92          }
93          catch (IllegalArgumentException e) {
94              // expected
95          }
96  
97          // exception for non-positive neighborsSize
98          try {
99              new ImmutableFieldTimeStampedCache<>(0, data);
100             Assertions.fail("Expected Exception");
101         }
102         catch (IllegalArgumentException e) {
103             // expected
104         }
105 
106         // exception for null data
107         try {
108             new ImmutableFieldTimeStampedCache<FieldAbsoluteDate<Binary64>, Binary64>(1, null);
109             Assertions.fail("Expected Exception");
110         }
111         catch (NullPointerException e) {
112             // expected
113         }
114 
115         // exception for zero data
116         try {
117             new ImmutableFieldTimeStampedCache<FieldAbsoluteDate<Binary64>, Binary64>(
118                     1,
119                     Collections.emptyList());
120             Assertions.fail("Expected Exception");
121         }
122         catch (IllegalArgumentException e) {
123             // expected
124         }
125     }
126 
127     /**
128      * check {@link ImmutableFieldTimeStampedCache#getNeighbors(FieldAbsoluteDate)} at a series of different dates designed
129      * to test all logic paths.
130      */
131     @Test
132     public void testGetNeighbors() {
133         // setup
134         int size = data.size();
135 
136         // actions + verify
137 
138         // before fist data
139         try {
140             cache.getNeighbors(data.get(0).shiftedBy(-1));
141             Assertions.fail("Expected Exception");
142         }
143         catch (TimeStampedCacheException e) {
144             // expected
145             Assertions.assertEquals(OrekitMessages.UNABLE_TO_GENERATE_NEW_DATA_BEFORE, e.getSpecifier());
146         }
147 
148         // on fist date
149         Assertions.assertArrayEquals(cache.getNeighbors(data.get(0)).toArray(), data
150                 .subList(0, 3).toArray());
151         // between fist and second date
152         Assertions.assertArrayEquals(cache.getNeighbors(data.get(0).shiftedBy(0.5))
153                                           .toArray(), data.subList(0, 3).toArray());
154         // in the middle on a date
155         Assertions.assertArrayEquals(cache.getNeighbors(data.get(2)).toArray(), data
156                 .subList(1, 4).toArray());
157         // in the middle between dates
158         Assertions.assertArrayEquals(cache.getNeighbors(data.get(2).shiftedBy(0.5))
159                                           .toArray(), data.subList(1, 4).toArray());
160         // just before last date
161         Assertions.assertArrayEquals(cache.getNeighbors(data.get(size - 1).shiftedBy(-0.5)).toArray(),
162                                      data.subList(size - 3, size).toArray());
163         // on last date
164         Assertions.assertArrayEquals(cache.getNeighbors(data.get(size - 1)).toArray(),
165                                      data.subList(size - 3, size).toArray());
166 
167         // after last date
168         FieldAbsoluteDate<Binary64> central = data.get(size - 1).shiftedBy(1);
169         try {
170             cache.getNeighbors(central);
171             Assertions.fail("Expected Exception");
172         }
173         catch (TimeStampedCacheException e) {
174             // expected
175             Assertions.assertEquals(OrekitMessages.UNABLE_TO_GENERATE_NEW_DATA_AFTER, e.getSpecifier());
176         }
177     }
178 
179     /**
180      * check {@link ImmutableFieldTimeStampedCache#getMaxNeighborsSize()}
181      */
182     @Test
183     public void testGetNeighborsSize() {
184         Assertions.assertEquals(cache.getMaxNeighborsSize(), 3);
185     }
186 
187     /**
188      * check {@link ImmutableFieldTimeStampedCache#getEarliest()}
189      */
190     @Test
191     public void testGetEarliest() {
192         Assertions.assertEquals(cache.getEarliest(), data.get(0));
193     }
194 
195     /**
196      * check {@link ImmutableFieldTimeStampedCache#getLatest()}
197      */
198     @Test
199     public void testGetLatest() {
200         Assertions.assertEquals(cache.getLatest(), data.get(data.size() - 1));
201     }
202 
203     /**
204      * check {@link ImmutableFieldTimeStampedCache#getAll()}
205      */
206     @Test
207     public void testGetAll() {
208         Assertions.assertArrayEquals(cache.getAll().toArray(), data.toArray());
209     }
210 
211     /**
212      * check that the cache is immutable by changing the data passed in the constructor and returned from methods.
213      */
214     @Test
215     public void testImmutable() {
216         // setup
217         List<FieldAbsoluteDate<Binary64>> actuals;
218         List<FieldAbsoluteDate<Binary64>> expecteds = new ArrayList<>(data);
219         FieldAbsoluteDate<Binary64>       different = date.shiftedBy(-50);
220 
221         // actions + verify
222 
223         // check constructor
224         data.set(0, different);
225         Assertions.assertArrayEquals(cache.getAll().toArray(), expecteds.toArray());
226 
227         // check getAll
228         actuals = cache.getAll();
229         try {
230             actuals.set(0, different);
231         }
232         catch (UnsupportedOperationException e) {
233             // exception ok
234         }
235         Assertions.assertArrayEquals(cache.getAll().toArray(), expecteds.toArray());
236 
237         // check getNeighbors
238         Assertions.assertArrayEquals(cache.getAll().toArray(), expecteds.toArray());
239     }
240 
241     /**
242      * check {@link ImmutableFieldTimeStampedCache#emptyCache()}.
243      */
244     @Test
245     public void testEmptyCache() {
246         // setup
247         cache = ImmutableFieldTimeStampedCache.emptyCache();
248 
249         // actions + verify
250         try {
251             cache.getNeighbors(date);
252             Assertions.fail("Expected Exception");
253         }
254         catch (TimeStampedCacheException e) {
255             // expected
256         }
257         try {
258             cache.getEarliest();
259             Assertions.fail("Expected Exception");
260         }
261         catch (IllegalStateException e) {
262             // expected
263         }
264         try {
265             cache.getLatest();
266             Assertions.fail("Expected Exception");
267         }
268         catch (IllegalStateException e) {
269             // expected
270         }
271         Assertions.assertEquals(cache.getAll().size(), 0);
272         Assertions.assertEquals(cache.getMaxNeighborsSize(), 0);
273     }
274 
275     @Test
276     public void testNonLinear() {
277         final ImmutableFieldTimeStampedCache<FieldAbsoluteDate<Binary64>, Binary64> nonLinearCache = new ImmutableFieldTimeStampedCache<>(2,
278                         Arrays.asList(date.shiftedBy(10),
279                                       date.shiftedBy(14),
280                                       date.shiftedBy(18),
281                                       date.shiftedBy(23),
282                                       date.shiftedBy(30),
283                                       date.shiftedBy(36),
284                                       date.shiftedBy(45),
285                                       date.shiftedBy(55),
286                                       date.shiftedBy(67),
287                                       date.shiftedBy(90),
288                                       date.shiftedBy(118)));
289         for (double dt = 10; dt < 118; dt += 0.01) {
290             checkNeighbors(nonLinearCache, dt);
291         }
292     }
293 
294     private void checkNeighbors(final ImmutableFieldTimeStampedCache<FieldAbsoluteDate<Binary64>, Binary64> nonLinearCache,
295                                                                     final double offset) {
296         List<FieldAbsoluteDate<Binary64>> s = nonLinearCache.getNeighbors(date.shiftedBy(offset)).collect(Collectors.toList());
297         Assertions.assertEquals(2, s.size());
298         Assertions.assertTrue(s.get(0).durationFrom(date).getReal() <= offset);
299         Assertions.assertTrue(s.get(1).durationFrom(date).getReal() >  offset);
300     }
301     
302 }