|
2 | 2 |
|
3 | 3 | import pytest |
4 | 4 | import ntcore |
5 | | -import wpilib |
6 | 5 | from wpilib.simulation._simulation import _resetWpilibSimulationData |
7 | 6 |
|
8 | | -from pathlib import Path |
9 | | - |
10 | | -import gc |
11 | | - |
12 | | -import weakref |
13 | | - |
14 | | -import hal |
15 | | -import hal.simulation |
16 | | -import wpilib.shuffleboard |
17 | | -from wpilib.simulation import DriverStationSim, pauseTiming, restartTiming |
18 | | -import wpilib.simulation |
19 | | -from pyfrc.test_support.controller import TestController |
20 | | -from pyfrc.physics.core import PhysicsInterface |
21 | | - |
22 | 7 | try: |
23 | 8 | import commands2 |
24 | 9 | except ImportError: |
@@ -48,133 +33,3 @@ def nt(cfg_logging, wpilib_state): |
48 | 33 | finally: |
49 | 34 | instance.stopLocal() |
50 | 35 | instance._reset() |
51 | | - |
52 | | - |
53 | | -@pytest.fixture(scope="class", autouse=False) |
54 | | -def physics_and_decorated_robot_class( |
55 | | - myrobot_class, robots_sim_enable_physics |
56 | | -) -> tuple: |
57 | | - # attach physics |
58 | | - |
59 | | - robotClass = myrobot_class |
60 | | - physicsInterface = None |
61 | | - if robots_sim_enable_physics: |
62 | | - physicsInterface, robotClass = PhysicsInterface._create_and_attach( |
63 | | - myrobot_class, |
64 | | - Path(__file__).parent, |
65 | | - ) |
66 | | - |
67 | | - if physicsInterface: |
68 | | - physicsInterface.log_init_errors = False |
69 | | - |
70 | | - # Tests need to know when robotInit is called, so override the robot |
71 | | - # to do that |
72 | | - class TestRobot(robotClass): |
73 | | - def robotInit(self): |
74 | | - try: |
75 | | - super().robotInit() |
76 | | - finally: |
77 | | - self.__robotInitialized() |
78 | | - |
79 | | - TestRobot.__name__ = robotClass.__name__ |
80 | | - TestRobot.__module__ = robotClass.__module__ |
81 | | - TestRobot.__qualname__ = robotClass.__qualname__ |
82 | | - |
83 | | - return (physicsInterface, TestRobot) |
84 | | - |
85 | | - |
86 | | -@pytest.fixture(scope="function", autouse=False) |
87 | | -def robot_with_sim_setup_teardown(physics_and_decorated_robot_class): |
88 | | - """ |
89 | | - Your robot instance |
90 | | -
|
91 | | - .. note:: RobotPy/WPILib testing infrastructure is really sensitive |
92 | | - to ensuring that things get cleaned up properly. Make sure |
93 | | - that you don't store references to your robot or other |
94 | | - WPILib objects in a global or static context. |
95 | | - """ |
96 | | - |
97 | | - # |
98 | | - # This function needs to do the same things that RobotBase.main does |
99 | | - # plus some extra things needed for testing |
100 | | - # |
101 | | - # Previously this was separate from robot fixture, but we need to |
102 | | - # ensure that the robot cleanup happens deterministically relative to |
103 | | - # when handle cleanup/etc happens, otherwise unnecessary HAL errors will |
104 | | - # bubble up to the user |
105 | | - # |
106 | | - |
107 | | - nt_inst = ntcore.NetworkTableInstance.getDefault() |
108 | | - nt_inst.startLocal() |
109 | | - |
110 | | - pauseTiming() |
111 | | - restartTiming() |
112 | | - |
113 | | - wpilib.DriverStation.silenceJoystickConnectionWarning(True) |
114 | | - DriverStationSim.setAutonomous(False) |
115 | | - DriverStationSim.setEnabled(False) |
116 | | - DriverStationSim.notifyNewData() |
117 | | - |
118 | | - robot = physics_and_decorated_robot_class[1]() |
119 | | - |
120 | | - # Tests only get a proxy to ensure cleanup is more reliable |
121 | | - yield weakref.proxy(robot) |
122 | | - |
123 | | - # If running in separate processes, no need to do cleanup |
124 | | - # if ISOLATED: |
125 | | - # # .. and funny enough, in isolated mode we *don't* want the |
126 | | - # # robot to be cleaned up, as that can deadlock |
127 | | - # self._saved_robot = robot |
128 | | - # return |
129 | | - |
130 | | - # reset engine to ensure it gets cleaned up too |
131 | | - # -> might be holding wpilib objects, or the robot |
132 | | - if physics_and_decorated_robot_class[0]: |
133 | | - physics_and_decorated_robot_class[0].engine = None |
134 | | - |
135 | | - # HACK: avoid motor safety deadlock |
136 | | - wpilib.simulation._simulation._resetMotorSafety() |
137 | | - |
138 | | - del robot |
139 | | - |
140 | | - if commands2 is not None: |
141 | | - commands2.CommandScheduler.resetInstance() |
142 | | - |
143 | | - # Double-check all objects are destroyed so that HAL handles are released |
144 | | - gc.collect() |
145 | | - |
146 | | - # shutdown networktables before other kinds of global cleanup |
147 | | - # -> some reset functions will re-register listeners, so it's important |
148 | | - # to do this before so that the listeners are active on the current |
149 | | - # NetworkTables instance |
150 | | - nt_inst.stopLocal() |
151 | | - nt_inst._reset() |
152 | | - |
153 | | - # Cleanup WPILib globals |
154 | | - # -> preferences, SmartDashboard, Shuffleboard, LiveWindow, MotorSafety |
155 | | - wpilib.simulation._simulation._resetWpilibSimulationData() |
156 | | - wpilib._wpilib._clearSmartDashboardData() |
157 | | - wpilib.shuffleboard._shuffleboard._clearShuffleboardData() |
158 | | - |
159 | | - # Cancel all periodic callbacks |
160 | | - hal.simulation.cancelAllSimPeriodicCallbacks() |
161 | | - |
162 | | - # Reset the HAL handles |
163 | | - hal.simulation.resetGlobalHandles() |
164 | | - |
165 | | - # Reset the HAL data |
166 | | - hal.simulation.resetAllSimData() |
167 | | - |
168 | | - # Don't call HAL shutdown! This is only used to cleanup HAL extensions, |
169 | | - # and functions will only be called the first time (unless re-registered) |
170 | | - # hal.shutdown() |
171 | | - |
172 | | - |
173 | | -@pytest.fixture(scope="function") |
174 | | -def getTestController( |
175 | | - reraise, robot_with_sim_setup_teardown: wpilib.RobotBase |
176 | | -) -> TestController: |
177 | | - """ |
178 | | - A pytest fixture that provides control over your robot_with_sim_setup_teardown |
179 | | - """ |
180 | | - return TestController(reraise, robot_with_sim_setup_teardown) |
0 commit comments