1   /* Copyright 2002-2025 CS GROUP
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.propagation.events;
18  
19  import java.util.Collections;
20  import java.util.NoSuchElementException;
21  
22  import org.junit.jupiter.api.Assertions;
23  import org.junit.jupiter.api.BeforeEach;
24  import org.junit.jupiter.api.Test;
25  import org.mockito.Mockito;
26  import org.orekit.propagation.SpacecraftState;
27  import org.orekit.propagation.events.handlers.EventHandler;
28  import org.orekit.propagation.events.intervals.AdaptableInterval;
29  import org.orekit.time.AbsoluteDate;
30  
31  /**
32   * Unit tests for {@link BooleanDetector}.
33   *
34   * @author Evan Ward
35   */
36  public class AndDetectorTest {
37  
38      /** first operand. */
39      private MockDetector a;
40      /** second operand. */
41      private MockDetector b;
42      /** null */
43      private SpacecraftState s;
44      /** subject under test */
45      private BooleanDetector and;
46  
47      /** create subject under test and dependencies. */
48      @BeforeEach
49      public void setUp() {
50          a = new MockDetector();
51          b = new MockDetector();
52          s = null;
53          and = BooleanDetector.andCombine(a, b);
54      }
55  
56      /**
57       * check {@link BooleanDetector#g(SpacecraftState)}.
58       */
59      @Test
60      public void testG() {
61          // test both zero
62          a.g = b.g = 0.0;
63          Assertions.assertEquals(0.0, and.g(s), 0);
64  
65          // test either zero
66          a.g = 1;
67          b.g = 0;
68          Assertions.assertEquals(0.0, and.g(s), 0);
69          a.g = 0;
70          b.g = 1;
71          Assertions.assertEquals(0.0, and.g(s), 0);
72  
73          // test either negative
74          a.g = 0;
75          b.g = -1;
76          Assertions.assertTrue(and.g(s) < 0, "negative");
77          a.g = 1;
78          b.g = -1;
79          Assertions.assertTrue(and.g(s) < 0, "negative");
80          a.g = -1;
81          b.g = 0;
82          Assertions.assertTrue(and.g(s) < 0, "negative");
83          a.g = -1;
84          b.g = 1;
85          Assertions.assertTrue(and.g(s) < 0, "negative");
86          a.g = -1;
87          b.g = -1;
88          Assertions.assertTrue(and.g(s) < 0, "negative");
89  
90          // test both positive
91          a.g = 1;
92          b.g = 1;
93          Assertions.assertTrue(and.g(s) > 0, "positive");
94  
95      }
96  
97      /**
98       * check {@link BooleanDetector} for cancellation.
99       */
100     @Test
101     public void testCancellation() {
102         a.g = -1e-10;
103         b.g = 1e10;
104         Assertions.assertTrue(and.g(s) < 0, "negative");
105         a.g = 1e10;
106         b.g = -1e-10;
107         Assertions.assertTrue(and.g(s) < 0, "negative");
108         a.g = 1e10;
109         b.g = 1e-10;
110         Assertions.assertTrue(and.g(s) > 0, "positive");
111         a.g = 1e-10;
112         b.g = 1e10;
113         Assertions.assertTrue(and.g(s) > 0, "positive");
114     }
115 
116     /**
117      * Check wrapped detectors are initialized.
118      */
119     @Test
120     public void testInit() {
121         // setup
122         EventDetector a = Mockito.mock(EventDetector.class);
123         Mockito.when(a.getMaxCheckInterval()).thenReturn(AdaptableInterval.of(AbstractDetector.DEFAULT_MAX_CHECK));
124         Mockito.when(a.getThreshold()).thenReturn(AbstractDetector.DEFAULT_THRESHOLD);
125         EventDetector b = Mockito.mock(EventDetector.class);
126         Mockito.when(b.getMaxCheckInterval()).thenReturn(AdaptableInterval.of(AbstractDetector.DEFAULT_MAX_CHECK));
127         Mockito.when(b.getThreshold()).thenReturn(AbstractDetector.DEFAULT_THRESHOLD);
128         EventHandler c = Mockito.mock(EventHandler.class);
129         BooleanDetector and = BooleanDetector.andCombine(a, b).withHandler(c);
130         AbsoluteDate t = AbsoluteDate.CCSDS_EPOCH;
131         s = Mockito.mock(SpacecraftState.class);
132         Mockito.when(s.getDate()).thenReturn(t.shiftedBy(60.0));
133 
134         // action
135         and.init(s, t);
136 
137         // verify
138         Assertions.assertEquals(2, and.getDetectors().size());
139         Mockito.verify(a).init(s, t);
140         Mockito.verify(b).init(s, t);
141         Mockito.verify(c).init(s, t, and);
142     }
143 
144     /** check when no operands are passed to the constructor. */
145     @Test
146     public void testZeroDetectors() {
147         // action
148         try {
149             BooleanDetector.andCombine(Collections.emptyList());
150             Assertions.fail("Expected Exception");
151         } catch (NoSuchElementException e) {
152             // expected
153         }
154     }
155 
156     /** Mock detector to set the g function to arbitrary values. */
157     private static class MockDetector implements EventDetector {
158 
159         /** value to return from {@link #g(SpacecraftState)}. */
160         public double g = 0;
161 
162         @Override
163         public void init(SpacecraftState s0, AbsoluteDate t) {
164 
165         }
166 
167         @Override
168         public double g(SpacecraftState s) {
169             return this.g;
170         }
171 
172         @Override
173         public EventDetectionSettings getDetectionSettings() {
174             return EventDetectionSettings.getDefaultEventDetectionSettings();
175         }
176 
177         @Override
178         public EventHandler getHandler() {
179             return null;
180         }
181     }
182 }