-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Fix - Broken tests #3013
Fix - Broken tests #3013
Conversation
I could fix all test failures locally (macOS), but it still remains tons of warnings (see CI/CD).
Now, the CI/CD still does not succeed: It looks like the What do you think @elegantmoose and @clenk? |
I tried to understand the remaining event loop warnings that appear when running tests, the ones that produce Task was destroyed but it is pending! or RuntimeError: Event loop is closed. I focused on a single test that cause such warnings. pytest --asyncio-mode=auto --tb=short tests/services/test_app_svc.py::TestAppService::test_mark_agent_as_untrusted_running_operation After investigating, I figured out that the "destroyed" asyncio tasks come from the application itself. That means when the test method start, It is already "too late" as the event loop has already a set of pending tasks. @bleepbop and @christophert, you both have worked on the tests. I could reduce (but not completely suppress) the amount of warning by just applying this function at the beginning or the end of the test (whatever): async def cancel_pending_tasks():
loop = asyncio.get_running_loop()
current_task = asyncio.current_task(loop)
pending_tasks = [task for task in asyncio.all_tasks(loop) if task is not current_task and not task.done()]
for task in pending_tasks:
task.cancel() However, this is not a clean way to fix that specific issue. |
c8d948b
to
44203bd
Compare
Thanks for the great work! I was working on some new features myself and ran into a lot of failing tests - wondering where they came from. Then I noticed they fail on the main branch as well. I just pulled your branch and the tests are fixed. In my opinion, adding |
While rebasing the work on the new |
@jbaptperez back on this, sorry for delay |
02af67f
to
19f568d
Compare
app/objects/c_operation.py
Outdated
data_svc_handle = BaseService.get_service('data_svc') | ||
seeded_facts = [] | ||
if self.source: | ||
seeded_facts = await data_svc_handle.get_facts_from_source(self.source.id) | ||
seeded_facts = await knowledge_svc_handle.get_facts(criteria=dict(source=self.source.id)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It sounds like these changes from #2978 were causing issues in your tests - I'd like to avoid undoing changes from previous PRs and fix the corresponding tests if possible.
@elegantmoose @clenk thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, the changes broke the tests.
However, after passing a couple of hours trying to understand what was going on (using a debugger, etc.), I figured out that related data structure were not so similar and maybe the shortcut of #2978 cannot really be applied this way.
I don't master the code so here, I clearly need help to have a proper fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. Let me talk with some folks to see how we want to approach this. Will get back to you shortly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, I figured out how to fix the 3 broken unit tests if we bring this change back:
--- a/tests/objects/test_link.py
+++ b/tests/objects/test_link.py
@@ -138,7 +138,7 @@ class TestLink:
knowledge_base_r = event_loop.run_until_complete(knowledge_svc.get_relationships(dict(edge='has_admin')))
assert len(knowledge_base_r) == 1
- def test_create_relationship_source_fact(self, event_loop, ability, executor, operation, knowledge_svc, fire_event_mock):
+ def test_create_relationship_source_fact(self, event_loop, ability, executor, operation, data_svc, knowledge_svc, fire_event_mock):
test_executor = executor(name='psh', platform='windows')
test_ability = ability(ability_id='123', executors=[test_executor])
fact1 = Fact(trait='remote.host.fqdn', value='dc')
@@ -149,6 +149,7 @@ class TestLink:
adversary=Adversary(name='sample', adversary_id='XYZ', atomic_ordering=[],
description='test'),
source=Source(id='test-source', facts=[fact1]))
+ event_loop.run_until_complete(data_svc.store(operation.source))
event_loop.run_until_complete(operation._init_source())
event_loop.run_until_complete(link1.create_relationships([relationship], operation))
@@ -161,7 +162,7 @@ class TestLink:
assert len(fact_store_operation) == 1
assert len(fact_store_operation_source[0].collected_by) == 2
- def test_save_discover_seeded_fact_not_in_command(self, event_loop, ability, executor, operation, knowledge_svc, fire_event_mock):
+ def test_save_discover_seeded_fact_not_in_command(self, event_loop, ability, executor, operation, knowledge_svc, data_svc, fire_event_mock):
test_executor = executor(name='psh', platform='windows')
test_ability = ability(ability_id='123', executors=[test_executor])
fact1 = Fact(trait='remote.host.fqdn', value='dc')
@@ -172,6 +173,7 @@ class TestLink:
adversary=Adversary(name='sample', adversary_id='XYZ', atomic_ordering=[],
description='test'),
source=Source(id='test-source', facts=[fact1, fact2]))
+ event_loop.run_until_complete(data_svc.store(operation.source))
event_loop.run_until_complete(operation._init_source())
event_loop.run_until_complete(link.save_fact(operation, fact2, 1, relationship))
diff --git a/tests/objects/test_operation.py b/tests/objects/test_operation.py
index d3d4ecc..be95d9d 100644
--- a/tests/objects/test_operation.py
+++ b/tests/objects/test_operation.py
@@ -427,6 +427,7 @@ class TestOperation:
def test_facts(self, event_loop, app_svc, contact_svc, file_svc, data_svc, learning_svc, fire_event_mock,
op_with_learning_and_seeded, make_test_link, make_test_result, knowledge_svc):
+ event_loop.run_until_complete(data_svc.store(op_with_learning_and_seeded.source))
test_link = make_test_link(9876)
op_with_learning_and_seeded.add_link(test_link)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those tests in particular need to manually store the operation fact sources in the data service - the data service loads fact sources on server startup, so I essentially had to replicate that behavior with the dummy fact sources for the unit test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@uruwhy, thank you 👍
I applied your changes and all tests are fixed now.
For the CI/CD to work properly again, only one thing is missing: The missing value of the SONAR_TOKEN
environment variable (see my previous comment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure i'm seeing the same sonar issue that you are, but I did also see some flake8 issues from the latest runs:
flake8...................................................................Failed
- hook id: flake8
- exit code: 1
app/api/v2/managers/fact_source_manager.py:3:1: E302 expected 2 blank lines, found 1
app/service/data_svc.py:484:1: W293 blank line contains whitespace
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@uruwhy, thanks, I missed them. Fixed.
Now the SONAR_TOKEN
missing value appears in the SonarCloud Scan task:
Set the SONAR_TOKEN env variable.
.github/workflows/quality.yml:64
:
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@49e6cd3b187936a73b8280d59ffd9da69df63ec9
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So PRs from forks don't have access to our github secrets, and we'd have to make some major workflow adjustments to accommodate this sort of thing. However, I looked through the coverage.xml manually and verified that all your new lines of code are covered
19f568d
to
1d3ccc3
Compare
Updates the pytest command to include the asyncio mode (required).
Jinja templates where not initialized in the test server.
A catch-all route was set in RestApi class before adding API v2 routes.
Method TestHealthApi.test_get_health. The new "access" field was not taken into account.
Method TestHealthApi.test_unauthorized_get_health. Empty access table was not taken into account.
Method TestPayloadsApi.test_get_payloads. Adds missing payloads routes. Updates the test to retrieve payloads (real temporary files).
Function test_access_denied. Deleted because there is no GET "/enter" endpoint. A catch-all route redirects "/enter" to "/".
Function test_custom_rejecting_login_handler. Using an endpoint that requires an authentication to check the redirection to the login page ("/").
Function test_home (only in CI/CD). The "index.html" template was missing in "plugins/magma/dist". Adds Node.js 20 (active LTS) dependency to the CI/CD. Adds "npm install" and "npm run build" commands to the "Install dependencies" step.
Thanks to uruwhy: > Those tests in particular need to manually store the operation fact > sources in the data service - the data service loads fact sources on > server startup, so I essentially had to replicate that behavior with > the dummy fact sources for the unit test
Makes it require authenticated users. Simplifies back the management of the returned "access" field.
Thanks to uruwhy: > Those tests in particular need to manually store the operation fact > sources in the data service - the data service loads fact sources on > server startup, so I essentially had to replicate that behavior with > the dummy fact sources for the unit test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome work @jbaptperez . TY so much. 🥇
Tested. |
@elegantmoose, note that this other PR completes test fixes with in the atomic plugin. Please have a look to it. |
Description
Fixes:
CONTRIBUTONG.md
according to new aiohttp requirements in the CLI)Type of change
Please delete options that are not relevant.
How Has This Been Tested?
All tests:
Checklist: