20
20
#
21
21
# Integrated tests
22
22
#
23
- # Purpose: This script runs a series of test to ensure that the messaging
23
+ # Purpose: This script runs a series of test to ensure that the messaging
24
24
# interface is properly set up for C and Cpp messages
25
25
# Author: Benjamin Bercovici
26
26
# Creation Date: June 4th, 2021
29
29
30
30
from Basilisk .architecture import bskLogging
31
31
from Basilisk .architecture import messaging
32
+ from Basilisk .moduleTemplates import cppModuleTemplate
33
+ from Basilisk .utilities import SimulationBaseClass
34
+ from Basilisk .utilities import macros
35
+ import numpy as np
32
36
33
37
34
38
# uncomment this line is this test is to be skipped in the global unit test run, adjust message as needed
@@ -47,6 +51,7 @@ def messaging_unit_tests():
47
51
test_c_msg_subscription_check ()
48
52
test_cpp_2_c_msg_subscription_check ()
49
53
test_c_2_cpp_msg_subscription_check ()
54
+ test_standalone_message_scope ()
50
55
51
56
52
57
@@ -56,13 +61,13 @@ def test_cpp_msg_subscription_check():
56
61
bskLogging .setDefaultLogLevel (bskLogging .BSK_WARNING )
57
62
testFailCount = 0 # zero unit test result counter
58
63
testMessages = [] # create empty array to store test log messages
59
-
64
+
60
65
61
66
# Try out all the existing cpp messages
62
- cppMessages = [ el for el in dir (messaging ) if el .endswith ("Msg" )]
63
-
67
+ cppMessages = [ el for el in dir (messaging ) if el .endswith ("Msg" )]
68
+
64
69
for el in cppMessages :
65
-
70
+
66
71
# Create three messages
67
72
msgA = eval ("messaging." + el + "()" )
68
73
msgB = eval ("messaging." + el + "()" )
@@ -86,8 +91,8 @@ def test_cpp_msg_subscription_check():
86
91
if msgC_subscriber .isSubscribedTo (msgA ) != 0 :
87
92
testFailCount += 1
88
93
testMessages .append (el + ": msgC_subscriber.isSubscribedTo(msgA) should be False" )
89
-
90
-
94
+
95
+
91
96
# Change subscription pattern
92
97
msgB_subscriber .subscribeTo (msgC ) # Subscribe B to C
93
98
msgC_subscriber .subscribeTo (msgA ) # Subscribe C to A
@@ -103,8 +108,8 @@ def test_cpp_msg_subscription_check():
103
108
testFailCount += 1
104
109
testMessages .append (el + ": msgC_subscriber.isSubscribedTo(msgB) should be False" )
105
110
106
-
107
-
111
+
112
+
108
113
if testFailCount == 0 :
109
114
print ("PASSED" )
110
115
else :
@@ -122,14 +127,14 @@ def test_c_msg_subscription_check():
122
127
bskLogging .setDefaultLogLevel (bskLogging .BSK_WARNING )
123
128
testFailCount = 0 # zero unit test result counter
124
129
testMessages = [] # create empty array to store test log messages
125
-
130
+
126
131
127
132
# Try out all the existing c messages
128
- cMessages = [ el for el in dir (messaging ) if el .endswith ("Msg_C" )]
133
+ cMessages = [ el for el in dir (messaging ) if el .endswith ("Msg_C" )]
134
+
129
135
130
-
131
136
for el in cMessages :
132
-
137
+
133
138
# Create three messages
134
139
msgA = eval ("messaging." + el + "()" )
135
140
msgB = eval ("messaging." + el + "()" )
@@ -149,8 +154,8 @@ def test_c_msg_subscription_check():
149
154
if msgC .isSubscribedTo (msgA ) != 0 :
150
155
testFailCount += 1
151
156
testMessages .append (el + ": msgC.isSubscribedTo(msgA) should be False" )
152
-
153
-
157
+
158
+
154
159
# Change subscription pattern
155
160
msgB .subscribeTo (msgC ) # Subscribe B to C
156
161
msgC .subscribeTo (msgA ) # Subscribe C to A
@@ -166,8 +171,8 @@ def test_c_msg_subscription_check():
166
171
testFailCount += 1
167
172
testMessages .append (el + ": msgC.isSubscribedTo(msgB) should be False" )
168
173
169
-
170
-
174
+
175
+
171
176
if testFailCount == 0 :
172
177
print ("PASSED" )
173
178
else :
@@ -176,34 +181,34 @@ def test_c_msg_subscription_check():
176
181
177
182
178
183
def test_c_2_cpp_msg_subscription_check ():
179
-
184
+
180
185
bskLogging .setDefaultLogLevel (bskLogging .BSK_WARNING )
181
186
testFailCount = 0 # zero unit test result counter
182
187
testMessages = [] # create empty array to store test log messages
183
-
188
+
184
189
185
190
# Try out all the existing messages
186
- cppMessages = [ el for el in dir (messaging ) if el .endswith ("Msg" )]
187
- cMessages = [ el for el in dir (messaging ) if el .endswith ("Msg_C" )]
188
-
191
+ cppMessages = [ el for el in dir (messaging ) if el .endswith ("Msg" )]
192
+ cMessages = [ el for el in dir (messaging ) if el .endswith ("Msg_C" )]
193
+
189
194
# Find common messages
190
195
common_messages = [el for el in cppMessages if el + "_C" in cMessages ]
191
196
192
197
193
198
for el in common_messages :
194
-
199
+
195
200
# Create c and cpp messages
196
201
msgA = eval ("messaging." + el + "()" )
197
202
msgB = eval ("messaging." + el + "()" )
198
203
199
204
msgC = eval ("messaging." + el + "_C()" )
200
205
msgD = eval ("messaging." + el + "_C()" )
201
206
202
-
207
+
203
208
# Subscribe
204
209
msgC .subscribeTo (msgA ) # Subscribe C to A
205
210
msgD .subscribeTo (msgB ) # Subscribe D to B
206
-
211
+
207
212
# Check
208
213
if msgC .isSubscribedTo (msgA ) != 1 :
209
214
testFailCount += 1
@@ -217,7 +222,7 @@ def test_c_2_cpp_msg_subscription_check():
217
222
if msgC .isSubscribedTo (msgB ) != 0 :
218
223
testFailCount += 1
219
224
testMessages .append (el + ": msgC.isSubscribedTo(msgB) should be False" )
220
-
225
+
221
226
# Change subscription pattern
222
227
msgC .subscribeTo (msgB ) # Subscribe C to B
223
228
msgD .subscribeTo (msgA ) # Subscribe D to A
@@ -236,8 +241,8 @@ def test_c_2_cpp_msg_subscription_check():
236
241
testFailCount += 1
237
242
testMessages .append (el + ": msgD.isSubscribedTo(msgB) should be False" )
238
243
239
-
240
-
244
+
245
+
241
246
if testFailCount == 0 :
242
247
print ("PASSED" )
243
248
else :
@@ -249,18 +254,18 @@ def test_cpp_2_c_msg_subscription_check():
249
254
bskLogging .setDefaultLogLevel (bskLogging .BSK_WARNING )
250
255
testFailCount = 0 # zero unit test result counter
251
256
testMessages = [] # create empty array to store test log messages
252
-
257
+
253
258
254
259
# Try out all the existing messages
255
- cppMessages = [ el for el in dir (messaging ) if el .endswith ("Msg" )]
256
- cMessages = [ el for el in dir (messaging ) if el .endswith ("Msg_C" )]
257
-
260
+ cppMessages = [ el for el in dir (messaging ) if el .endswith ("Msg" )]
261
+ cMessages = [ el for el in dir (messaging ) if el .endswith ("Msg_C" )]
262
+
258
263
# Find common messages
259
264
common_messages = [el for el in cppMessages if el + "_C" in cMessages ]
260
265
261
266
262
267
for el in common_messages :
263
-
268
+
264
269
# Create c and cpp messages
265
270
msgA = eval ("messaging." + el + "_C()" )
266
271
msgB = eval ("messaging." + el + "_C()" )
@@ -271,7 +276,7 @@ def test_cpp_2_c_msg_subscription_check():
271
276
# Create subscribers to pair messages
272
277
msgC_subscriber = msgC .addSubscriber ()
273
278
msgD_subscriber = msgD .addSubscriber ()
274
-
279
+
275
280
# Subscribe
276
281
msgC_subscriber .subscribeTo (msgA ) # Subscribe C to A
277
282
msgD_subscriber .subscribeTo (msgB ) # Subscribe D to B
@@ -289,7 +294,7 @@ def test_cpp_2_c_msg_subscription_check():
289
294
if msgC_subscriber .isSubscribedTo (msgB ) != 0 :
290
295
testFailCount += 1
291
296
testMessages .append (el + ": msgC_subscriber.isSubscribedTo(msgB) should be False" )
292
-
297
+
293
298
# Change subscription pattern
294
299
msgC_subscriber .subscribeTo (msgB ) # Subscribe C to B
295
300
msgD_subscriber .subscribeTo (msgA ) # Subscribe D to A
@@ -308,15 +313,78 @@ def test_cpp_2_c_msg_subscription_check():
308
313
testFailCount += 1
309
314
testMessages .append (el + ": msgD_subscriber.isSubscribedTo(msgB) should be False" )
310
315
311
-
312
-
316
+
317
+
313
318
if testFailCount == 0 :
314
319
print ("PASSED" )
315
320
else :
316
321
[print (msg ) for msg in testMessages ]
317
322
assert (testFailCount == 0 )
318
323
319
324
325
+ def test_standalone_message_scope ():
326
+ """
327
+ Test that subscribed messages don't get garbage collected when going out of scope
328
+ """
329
+ bskLogging .setDefaultLogLevel (bskLogging .BSK_WARNING )
330
+ testFailCount = 0 # zero unit test result counter
331
+ testMessages = [] # create empty array to store test log messages
332
+
333
+ # Create a sim module as an empty container
334
+ scSim = SimulationBaseClass .SimBaseClass ()
335
+
336
+ # create the simulation process
337
+ dynProcess = scSim .CreateNewProcess ("dynamicsProcess" )
338
+
339
+ # create the dynamics task and specify the integration update time
340
+ dynProcess .addTask (scSim .CreateNewTask ("dynamicsTask" , macros .sec2nano (1. )))
341
+
342
+ # create modules
343
+ mod1 = cppModuleTemplate .CppModuleTemplate ()
344
+ mod1 .ModelTag = "cppModule1"
345
+ scSim .AddModelToTask ("dynamicsTask" , mod1 )
346
+
347
+ # setup message recording
348
+ msgRec = mod1 .dataOutMsg .recorder ()
349
+ scSim .AddModelToTask ("dynamicsTask" , msgRec )
350
+
351
+ # Create a local scope to test message lifetime
352
+ def addLocalStandaloneMessage (module ):
353
+ """Create a stand-alone message in local scope and subscribe to it"""
354
+ msgData = messaging .CModuleTemplateMsgPayload ()
355
+ msgData .dataVector = [10. , 20. , 30. ]
356
+ msg = messaging .CModuleTemplateMsg ().write (msgData )
357
+ module .dataInMsg .subscribeTo (msg )
358
+
359
+ # Subscribe to the input message in a local scope
360
+ addLocalStandaloneMessage (mod1 )
361
+
362
+ # initialize Simulation:
363
+ scSim .InitializeSimulation ()
364
+
365
+ # configure a simulation stop time and execute the simulation run
366
+ scSim .ConfigureStopTime (macros .sec2nano (3.0 ))
367
+ scSim .ExecuteSimulation ()
368
+
369
+ # Verify output matches expected values
370
+ expected = np .array ([
371
+ [11. , 20. , 30. ],
372
+ [12. , 20. , 30. ],
373
+ [13. , 20. , 30. ],
374
+ [14. , 20. , 30. ]
375
+ ])
376
+
377
+ if not (msgRec .dataVector == expected ).all ():
378
+ testFailCount += 1
379
+ testMessages .append ("Output data does not match expected values" )
380
+
381
+ if testFailCount == 0 :
382
+ print ("PASSED" )
383
+ else :
384
+ [print (msg ) for msg in testMessages ]
385
+ assert testFailCount < 1 , testMessages
386
+
387
+
320
388
321
389
if __name__ == "__main__" :
322
390
messaging_unit_tests ()
0 commit comments