Source code for test_multipleInterfaces

from pathlib import Path

from Basilisk import __path__
from Basilisk.simulation import spiceInterface
from Basilisk.utilities import SimulationBaseClass

bskPath = __path__[0]


[docs] def createOneSim(): """ Create a minimal Basilisk simulation containing a single SpiceInterface. Returns ------- TotalSim : Basilisk SimulationBaseClass instance The newly created simulation object. SpiceObject : SpiceInterface The SpiceInterface instance inside the created simulation. """ TotalSim = SimulationBaseClass.SimBaseClass() DynUnitTestProc = TotalSim.CreateNewProcess("process") DynUnitTestProc.addTask(TotalSim.CreateNewTask("task", 1)) # Create and register the SpiceInterface SpiceObject = spiceInterface.SpiceInterface() SpiceObject.SPICEDataPath = str(Path(bskPath) / "supportData" / "EphemerisData") TotalSim.AddModelToTask("task", SpiceObject) # Run long enough for the SpiceInterface to furnish its kernels TotalSim.ConfigureStopTime(2) TotalSim.InitializeSimulation() TotalSim.ExecuteSimulation() return TotalSim, SpiceObject
[docs] def test_multipleInterfaces(): """ Verify that SPICE kernels loaded through SpiceInterface are correctly reference-counted and unloaded when all SpiceInterface instances are gone. The test performs the following high-level checks: 1. Before creating any SpiceInterface objects, the target kernel must not be loaded in SPICE. 2. Creating the first simulation should cause the kernel to be furnished. 3. Creating many additional simulations must *not* load the kernel again. 4. After all simulations have loaded, the number of loaded kernels should be the same as after loading one sim. 5. After all simulations fall out of scope and Python's garbage collector runs, the kernel must be fully unloaded from SPICE. This guarantees that: - furnsh_c() is only called once per unique kernel file - unload_c() is only called when the last user disappears - the shared-pointer-based lifetime system works correctly """ kernel = str(Path(bskPath) / "supportData" / "EphemerisData" / "de430.bsp") # Step 1 - Kernel not yet loaded assert not spiceInterface.isKernelLoaded(kernel) def smallScope(): # Step 2 - First SpiceInterface loads the kernel firstSim, firstSpice = createOneSim() assert spiceInterface.isKernelLoaded(kernel) kernelsLoadedWithOneSim = spiceInterface.countKernelsLoaded() # Step 3 - Many more SpiceInterfaces do NOT reload the kernel cacheSims = [] N = 20 for _ in range(N): cacheSims.append(createOneSim()) kernelsLoadedWithNSims = spiceInterface.countKernelsLoaded() # Step 4 - check kernels are not being loaded again assert kernelsLoadedWithOneSim == kernelsLoadedWithNSims # sanity check kernel is still loaded assert spiceInterface.isKernelLoaded(kernel) # Everything in smallScope is destroyed once we leave the function smallScope() import gc gc.collect() # Step 5 - Kernel must now be fully unloaded assert not spiceInterface.isKernelLoaded(kernel)
if __name__ == "__main__": test_multipleInterfaces()