Skip to content

Commit aea06af

Browse files
committed
add unit test verifying fix
1 parent b67bf6e commit aea06af

File tree

1 file changed

+105
-37
lines changed

1 file changed

+105
-37
lines changed

src/tests/test_messaging.py

Lines changed: 105 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#
2121
# Integrated tests
2222
#
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
2424
# interface is properly set up for C and Cpp messages
2525
# Author: Benjamin Bercovici
2626
# Creation Date: June 4th, 2021
@@ -29,6 +29,10 @@
2929

3030
from Basilisk.architecture import bskLogging
3131
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
3236

3337

3438
# 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():
4751
test_c_msg_subscription_check()
4852
test_cpp_2_c_msg_subscription_check()
4953
test_c_2_cpp_msg_subscription_check()
54+
test_standalone_message_scope()
5055

5156

5257

@@ -56,13 +61,13 @@ def test_cpp_msg_subscription_check():
5661
bskLogging.setDefaultLogLevel(bskLogging.BSK_WARNING)
5762
testFailCount = 0 # zero unit test result counter
5863
testMessages = [] # create empty array to store test log messages
59-
64+
6065

6166
# 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+
6469
for el in cppMessages:
65-
70+
6671
# Create three messages
6772
msgA = eval("messaging." + el + "()")
6873
msgB = eval("messaging." + el + "()")
@@ -86,8 +91,8 @@ def test_cpp_msg_subscription_check():
8691
if msgC_subscriber.isSubscribedTo(msgA) != 0:
8792
testFailCount += 1
8893
testMessages.append(el + ": msgC_subscriber.isSubscribedTo(msgA) should be False")
89-
90-
94+
95+
9196
# Change subscription pattern
9297
msgB_subscriber.subscribeTo(msgC) # Subscribe B to C
9398
msgC_subscriber.subscribeTo(msgA) # Subscribe C to A
@@ -103,8 +108,8 @@ def test_cpp_msg_subscription_check():
103108
testFailCount += 1
104109
testMessages.append(el + ": msgC_subscriber.isSubscribedTo(msgB) should be False")
105110

106-
107-
111+
112+
108113
if testFailCount == 0:
109114
print("PASSED")
110115
else:
@@ -122,14 +127,14 @@ def test_c_msg_subscription_check():
122127
bskLogging.setDefaultLogLevel(bskLogging.BSK_WARNING)
123128
testFailCount = 0 # zero unit test result counter
124129
testMessages = [] # create empty array to store test log messages
125-
130+
126131

127132
# 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+
129135

130-
131136
for el in cMessages:
132-
137+
133138
# Create three messages
134139
msgA = eval("messaging." + el + "()")
135140
msgB = eval("messaging." + el + "()")
@@ -149,8 +154,8 @@ def test_c_msg_subscription_check():
149154
if msgC.isSubscribedTo(msgA) != 0:
150155
testFailCount += 1
151156
testMessages.append(el + ": msgC.isSubscribedTo(msgA) should be False")
152-
153-
157+
158+
154159
# Change subscription pattern
155160
msgB.subscribeTo(msgC) # Subscribe B to C
156161
msgC.subscribeTo(msgA) # Subscribe C to A
@@ -166,8 +171,8 @@ def test_c_msg_subscription_check():
166171
testFailCount += 1
167172
testMessages.append(el + ": msgC.isSubscribedTo(msgB) should be False")
168173

169-
170-
174+
175+
171176
if testFailCount == 0:
172177
print("PASSED")
173178
else:
@@ -176,34 +181,34 @@ def test_c_msg_subscription_check():
176181

177182

178183
def test_c_2_cpp_msg_subscription_check():
179-
184+
180185
bskLogging.setDefaultLogLevel(bskLogging.BSK_WARNING)
181186
testFailCount = 0 # zero unit test result counter
182187
testMessages = [] # create empty array to store test log messages
183-
188+
184189

185190
# 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+
189194
# Find common messages
190195
common_messages = [el for el in cppMessages if el + "_C" in cMessages]
191196

192197

193198
for el in common_messages:
194-
199+
195200
# Create c and cpp messages
196201
msgA = eval("messaging." + el + "()")
197202
msgB = eval("messaging." + el + "()")
198203

199204
msgC = eval("messaging." + el + "_C()")
200205
msgD = eval("messaging." + el + "_C()")
201206

202-
207+
203208
# Subscribe
204209
msgC.subscribeTo(msgA) # Subscribe C to A
205210
msgD.subscribeTo(msgB) # Subscribe D to B
206-
211+
207212
# Check
208213
if msgC.isSubscribedTo(msgA) != 1:
209214
testFailCount += 1
@@ -217,7 +222,7 @@ def test_c_2_cpp_msg_subscription_check():
217222
if msgC.isSubscribedTo(msgB) != 0:
218223
testFailCount += 1
219224
testMessages.append(el + ": msgC.isSubscribedTo(msgB) should be False")
220-
225+
221226
# Change subscription pattern
222227
msgC.subscribeTo(msgB) # Subscribe C to B
223228
msgD.subscribeTo(msgA) # Subscribe D to A
@@ -236,8 +241,8 @@ def test_c_2_cpp_msg_subscription_check():
236241
testFailCount += 1
237242
testMessages.append(el + ": msgD.isSubscribedTo(msgB) should be False")
238243

239-
240-
244+
245+
241246
if testFailCount == 0:
242247
print("PASSED")
243248
else:
@@ -249,18 +254,18 @@ def test_cpp_2_c_msg_subscription_check():
249254
bskLogging.setDefaultLogLevel(bskLogging.BSK_WARNING)
250255
testFailCount = 0 # zero unit test result counter
251256
testMessages = [] # create empty array to store test log messages
252-
257+
253258

254259
# 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+
258263
# Find common messages
259264
common_messages = [el for el in cppMessages if el + "_C" in cMessages]
260265

261266

262267
for el in common_messages:
263-
268+
264269
# Create c and cpp messages
265270
msgA = eval("messaging." + el + "_C()")
266271
msgB = eval("messaging." + el + "_C()")
@@ -271,7 +276,7 @@ def test_cpp_2_c_msg_subscription_check():
271276
# Create subscribers to pair messages
272277
msgC_subscriber = msgC.addSubscriber()
273278
msgD_subscriber = msgD.addSubscriber()
274-
279+
275280
# Subscribe
276281
msgC_subscriber.subscribeTo(msgA) # Subscribe C to A
277282
msgD_subscriber.subscribeTo(msgB) # Subscribe D to B
@@ -289,7 +294,7 @@ def test_cpp_2_c_msg_subscription_check():
289294
if msgC_subscriber.isSubscribedTo(msgB) != 0:
290295
testFailCount += 1
291296
testMessages.append(el + ": msgC_subscriber.isSubscribedTo(msgB) should be False")
292-
297+
293298
# Change subscription pattern
294299
msgC_subscriber.subscribeTo(msgB) # Subscribe C to B
295300
msgD_subscriber.subscribeTo(msgA) # Subscribe D to A
@@ -308,15 +313,78 @@ def test_cpp_2_c_msg_subscription_check():
308313
testFailCount += 1
309314
testMessages.append(el + ": msgD_subscriber.isSubscribedTo(msgB) should be False")
310315

311-
312-
316+
317+
313318
if testFailCount == 0:
314319
print("PASSED")
315320
else:
316321
[print(msg) for msg in testMessages]
317322
assert(testFailCount == 0)
318323

319324

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+
320388

321389
if __name__ == "__main__":
322390
messaging_unit_tests()

0 commit comments

Comments
 (0)