Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cmd] Add and use CommandScheduler.resetInstance() #7584

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

KangarooKoala
Copy link
Contributor

Also makes the constructor private, since it was only used for the tests which now can use resetInstance(). Technically a breaking change for people putting their command unit tests in the commands package, but I doubt that many people would do that.

Closes #4866.

Python already has resetInstance(): https://github.com/robotpy/robotpy-commands-v2/blob/8480f6e3e3a5877e9489300ab8c5ec81703f2ad7/commands2/commandscheduler.py#L54.

Most of the changes are just removing try (CommandScheduler scheduler = new CommandScheduler()) {}, but there's a few other changes to the tests:

  • SchedulerTest.registerSubsystem() and SchedulerTest.unregisterSubsystem() were both changed to use Subsystem instead of SubsystemBase since SubsystemBase would automatically register the subsystem with the singleton instance.
  • A couple C++ lambdas that captured the scheduler by reference now capture this (which is by reference) since that's where the scheduler is stored now.
  • CommandRequirementsTest.RequirementInterrupt and SchedulerTest.SchedulerInterruptLambdaCause had to be changed in C++ because the command deconstructors canceled the command at the end of their scope.

@KangarooKoala KangarooKoala requested a review from a team as a code owner December 23, 2024 18:06
Copy link
Contributor

This PR modifies commands. Please open a corresponding PR in Python Commands and include a link to this PR.

@github-actions github-actions bot added the component: command-based WPILib Command Based Library label Dec 23, 2024
@KangarooKoala
Copy link
Contributor Author

This PR modifies commands. Please open a corresponding PR in Python Commands and include a link to this PR.

Already done in Python (see link in PR comment).

Copy link
Member

@Starlight220 Starlight220 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any tests that don't inherit from CommandTestBase etc?

* Resets the Scheduler instance, which is useful for testing purposes. This should not be called
* from user code.
*/
public static synchronized void resetInstance() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest it should null-op with a warning on a real robot. Is there a reason not to avoid the risk of a team accidentally resetting the scheduler in the middle of a match?

Copy link
Contributor Author

@KangarooKoala KangarooKoala Dec 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like a good idea- How could we detect we're running on a real robot versus in tests? I'd assume we wouldn't want to use isFMSAttached() because then it might lead to code working in the lab but not in an actual match, which would really suck.

I guess the way to really really avoid sneaky behavior changes is to always check (somehow) whether the call is from robot code (and not test code), but that's going to be really tricky for C++.

Another silly thought I had is to have a string parameter that must be "This method should only be called in unit tests. I promise I am not abusing this inside robot code." for the method to work, but that's not the most professional solution. (It would be pretty easy and funny, though.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isReal()/isSimulation()?

@@ -93,6 +93,10 @@ CommandScheduler& CommandScheduler::GetInstance() {
return scheduler;
}

void CommandScheduler::ResetInstance() {
std::make_unique<Impl>().swap(GetInstance().m_impl);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

@Daniel1464
Copy link
Contributor

Daniel1464 commented Dec 24, 2024

I think the safest bet here might be a "scope function" of sorts. Such as:

CommandScheduler.withInstanceOverride(() -> {
    // do tests here
})

The advantage here i think is that when the scope is done executing, the default CommandScheduler instance can be reinstated, preventing sneaky errors from occuring. All of the test can occur within the scope block

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: command-based WPILib Command Based Library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants