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

addFinalizer in test body #14036

Merged
merged 5 commits into from
Mar 15, 2024
Merged

addFinalizer in test body #14036

merged 5 commits into from
Mar 15, 2024

Conversation

pondrejk
Copy link
Contributor

@pondrejk pondrejk commented Feb 12, 2024

Problem Statement

Turns out that @request.addFinalizer when used in test body (not in fixture) is dependent on the execution order, so basically when some assertion defined in the test before the finalizer part fails, finalizer is not added and so not executed.

This exactly happened in test_positive_disable_hammer_defaults in upgrades, breaking a lot of other tests in the same run. Big kudos to @lpramuk for isolating the issue there.

Solution

Moving the addFinalizer part to the start of the test, fixes the problem. Prt run won't reveal much in this case, but running the previous version of the test with induced assertion error leaves satellite with:

~]# hammer defaults list
----------------|------
PARAMETER       | VALUE
----------------|------
organization_id | 41   
----------------|------

...which means that the finalizer didn't run. With this pr, the defaults are properly cleaned up:

~]# hammer defaults list
----------|------
PARAMETER | VALUE
----------|------

Related Issues

I did a quick search for this pattern across robottelo and I found quite a bit of cases where @request.addfinalizer is added towards the end of the test body, with some preceding assertions that could possibly break it:

This doesn't include request.addFinalizer(...) calls that likely suffer from the same problem. Now, I could go and reorder all those occurrences, but I feel we should discuss this team wide and maybe abolish this practice all together

@pondrejk pondrejk added CherryPick PR needs CherryPick to previous branches 6.12.z Introduced in or relating directly to Satellite 6.12 6.13.z Introduced in or relating directly to Satellite 6.13 6.14.z Introduced in or relating directly to Satellite 6.14 6.15.z Introduced in or relating directly to Satellite 6.15 labels Feb 12, 2024
@pondrejk pondrejk self-assigned this Feb 12, 2024
@pondrejk pondrejk requested a review from a team as a code owner February 12, 2024 13:37
Copy link
Contributor

@Griffin-Sullivan Griffin-Sullivan left a comment

Choose a reason for hiding this comment

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

I see it's on the agenda for tomorrow, but yeah each team will need to fix these.

Copy link
Contributor

@lpramuk lpramuk left a comment

Choose a reason for hiding this comment

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

LGTM
I've enjoyed collab with endeavour team. Finding this problematic test by bisecting test collection 😉

Comment on lines +139 to 148

@request.addfinalizer
def _finalize():
target_sat.cli.Defaults.delete({'param-name': 'organization_id'})
result = target_sat.execute('hammer defaults list')
assert str(function_product.organization.id) not in result.stdout

target_sat.cli.Defaults.add(
{'param-name': 'organization_id', 'param-value': function_product.organization.id}
)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, Good catch, I've seen this behaviour earlier while writing some test, just one suggestion here, to add finalizer at least after we add entity for better readability

Suggested change
@request.addfinalizer
def _finalize():
target_sat.cli.Defaults.delete({'param-name': 'organization_id'})
result = target_sat.execute('hammer defaults list')
assert str(function_product.organization.id) not in result.stdout
target_sat.cli.Defaults.add(
{'param-name': 'organization_id', 'param-value': function_product.organization.id}
)
target_sat.cli.Defaults.add(
{'param-name': 'organization_id', 'param-value': function_product.organization.id}
)
@request.addfinalizer
def _finalize():
target_sat.cli.Defaults.delete({'param-name': 'organization_id'})
result = target_sat.execute('hammer defaults list')
assert str(function_product.organization.id) not in result.stdout

Copy link
Contributor

@lpramuk lpramuk Feb 13, 2024

Choose a reason for hiding this comment

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

What if defaults adding fails but default is still being added ?
So I like finalizer first

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Gauravtalreja1 It can be done for finalizers that touch just one thing, but as long as you change more items, you can't have them all defined before, because it would defer the point of making sure finalizer is always added. This may be odd to read, but on the other hand it also communicates that the finalizer behaves differently from the rest of the test code, meaning it is not executed first but needs to be added as early as possible

@pondrejk pondrejk marked this pull request as draft February 13, 2024 13:59
@pondrejk
Copy link
Contributor Author

I'm drafting this so that I could fix other occurrences as discussed on the meeting today

@pondrejk pondrejk force-pushed the finalizer branch 3 times, most recently from 7fe1635 to 73affda Compare February 14, 2024 08:58
@pondrejk pondrejk marked this pull request as ready for review February 14, 2024 08:59
Comment on lines +250 to +258
@request.addfinalizer
def _finalize():
gcehost = sat_gce.api.Host().search(query={'search': f'name={hostname}'})
if gcehost:
gcehost[0].delete()
googleclient.disconnect()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we move it at least below after variables get defined? functionally I think it wouldn't affect as we're checking if host exists here first before delete

@JacobCallahan JacobCallahan self-requested a review February 16, 2024 19:01
Comment on lines 627 to 635
@request.addfinalizer
def cleanup():
cv_filter_cleanup(
target_sat,
cv_filter['filter-id'],
module_cv,
module_sca_manifest_org,
module_lce,
)
Copy link
Member

Choose a reason for hiding this comment

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

What would happen if the finalizer here was called before one of those arguments was created, cv_filter for example?

Copy link
Contributor Author

@pondrejk pondrejk Feb 29, 2024

Choose a reason for hiding this comment

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

@JacobCallahan yeah it is a confusing syntax compared to what we are normally used to in python. The function marked with @request.addfinalizer within the test function is executed after the test runs, so you can use variables even before you define them (!). But at the same time, the position of the block within the test determines when the finalizer is added. So I place these blocks at the start to be sure the finalizer is added at all times. The position in test matters for addition but not for execution

Copy link
Contributor

Choose a reason for hiding this comment

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

And I think that's what Jacob asks about. What if the finalizer is added (here, at the start) and then something fails after it is added, but before e.g. cv_filter variable is defined. I suppose the finalizer would throw an exception?

Copy link
Member

Choose a reason for hiding this comment

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

correct @lhellebr. at that point, you'd raise an exception because the name cv_filter is referenced before definition. Moving this to right after everything is defined is safer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@JacobCallahan @lhellebr I see, yeah I suppose it would raise an exception, but that's not different from "normal" finalizer behavior if defined in fixture. Consider the two alternatives when having finalizer in test body:

a) tests fails in the middle, finalizer added before -> result: finalizer added and executed, exception raised if referencing stuff that didn't get created
b) test fails in the middle, finalizer added after -> result: finalizer not added nor executed, not cleaning up anything that got created before failure, possibly causing interference with other tests

Situation (b) actually happens in the upgrade run, and it took considerable time and effort just to find out what is going on. Therefore I'd much rather have situation (a), which would be easier to debug

Comment on lines 769 to 777
@request.addfinalizer
def cleanup():
cv_filter_cleanup(
target_sat,
cv_filter['filter-id'],
module_cv,
module_sca_manifest_org,
module_lce,
)
Copy link
Member

Choose a reason for hiding this comment

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

same question as before, and for any other similar

Comment on lines 257 to 272
@request.addfinalizer
def _finalize():
sat_maintain.cli.Defaults.delete({'param-name': 'organization_id'})
sync_plans[1].delete()
sync_plan = sat_maintain.api.SyncPlan(organization=module_org.id).search(
query={'search': f'name="{sync_plans[0]}"'}
)
if sync_plan:
sync_plans[0].delete()
Copy link
Member

Choose a reason for hiding this comment

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

similar question as before. if the finalizer is called before sync_plans is populated (with at least two entries), then this will error.

@pondrejk pondrejk force-pushed the finalizer branch 2 times, most recently from 317921b to d2029e8 Compare March 13, 2024 08:27
@pondrejk
Copy link
Contributor Author

@Gauravtalreja1 @JacobCallahan @lhellebr hello, based on your feedback I changed ordering where it made sense. Could you please revisit?

Copy link
Member

@JacobCallahan JacobCallahan left a comment

Choose a reason for hiding this comment

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

ACK. Thanks for revisiting this @pondrejk. As long as we're aware of the name error risk with ordering, I'm fine with the changes.

Comment on lines +306 to +309

@request.addfinalizer
def _finalize():
target_sat.custom_certs_cleanup()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we keep only one request.addfinalizer method in this test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

that kind of contradicts with other concerns voiced in comments, if there are more elements to remove and you want to make sure all are marked to be finalized immediately after creation but not before, then you end up with multiple finalizers

Copy link
Collaborator

Choose a reason for hiding this comment

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

I didn't understand this, do we really need to finalizers calling target_sat.custom_certs_cleanup() this specific test?
Initially, I would've held the merge on this, but now that it's self-merged, could you please take care of this in a separate PR if you agree with the above?

Copy link
Collaborator

Choose a reason for hiding this comment

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

@pondrejk pondrejk merged commit 84e54f2 into SatelliteQE:master Mar 15, 2024
7 checks passed
github-actions bot pushed a commit that referenced this pull request Mar 15, 2024
* reordered addFinalizer in test body

* Update tests/foreman/cli/test_errata.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/api/test_discoveryrule.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/cli/test_errata.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/destructive/test_capsule_loadbalancer.py

Co-authored-by: Gaurav Talreja <[email protected]>

---------

Co-authored-by: Gaurav Talreja <[email protected]>
(cherry picked from commit 84e54f2)
Gauravtalreja1 pushed a commit that referenced this pull request Mar 15, 2024
addFinalizer in test body (#14036)

* reordered addFinalizer in test body

* Update tests/foreman/cli/test_errata.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/api/test_discoveryrule.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/cli/test_errata.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/destructive/test_capsule_loadbalancer.py

Co-authored-by: Gaurav Talreja <[email protected]>

---------

Co-authored-by: Gaurav Talreja <[email protected]>
(cherry picked from commit 84e54f2)

Co-authored-by: Peter Ondrejka <[email protected]>
damoore044 pushed a commit to damoore044/robottelo that referenced this pull request Mar 18, 2024
addFinalizer in test body (SatelliteQE#14036)

* reordered addFinalizer in test body

* Update tests/foreman/cli/test_errata.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/api/test_discoveryrule.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/cli/test_errata.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/destructive/test_capsule_loadbalancer.py

Co-authored-by: Gaurav Talreja <[email protected]>

---------

Co-authored-by: Gaurav Talreja <[email protected]>
(cherry picked from commit 84e54f2)

Co-authored-by: Peter Ondrejka <[email protected]>
pondrejk added a commit to pondrejk/robottelo that referenced this pull request Mar 19, 2024
* reordered addFinalizer in test body

* Update tests/foreman/cli/test_errata.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/api/test_discoveryrule.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/cli/test_errata.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/destructive/test_capsule_loadbalancer.py

Co-authored-by: Gaurav Talreja <[email protected]>

---------

Co-authored-by: Gaurav Talreja <[email protected]>
pondrejk added a commit to pondrejk/robottelo that referenced this pull request Mar 19, 2024
* reordered addFinalizer in test body

* Update tests/foreman/cli/test_errata.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/api/test_discoveryrule.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/cli/test_errata.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/destructive/test_capsule_loadbalancer.py

Co-authored-by: Gaurav Talreja <[email protected]>

---------

Co-authored-by: Gaurav Talreja <[email protected]>
pondrejk added a commit to pondrejk/robottelo that referenced this pull request Mar 19, 2024
* reordered addFinalizer in test body

* Update tests/foreman/cli/test_errata.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/api/test_discoveryrule.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/cli/test_errata.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/destructive/test_capsule_loadbalancer.py

Co-authored-by: Gaurav Talreja <[email protected]>

---------

Co-authored-by: Gaurav Talreja <[email protected]>
Gauravtalreja1 added a commit that referenced this pull request Mar 19, 2024
addFinalizer in test body (#14036)

* reordered addFinalizer in test body

* Update tests/foreman/cli/test_errata.py



* Update tests/foreman/api/test_discoveryrule.py



* Update tests/foreman/cli/test_errata.py



* Update tests/foreman/destructive/test_capsule_loadbalancer.py



---------

Co-authored-by: Gaurav Talreja <[email protected]>
Gauravtalreja1 added a commit that referenced this pull request Mar 19, 2024
addFinalizer in test body (#14036)

* reordered addFinalizer in test body

* Update tests/foreman/cli/test_errata.py



* Update tests/foreman/api/test_discoveryrule.py



* Update tests/foreman/cli/test_errata.py



* Update tests/foreman/destructive/test_capsule_loadbalancer.py



---------

Co-authored-by: Gaurav Talreja <[email protected]>
Gauravtalreja1 added a commit that referenced this pull request Mar 19, 2024
addFinalizer in test body (#14036)

* reordered addFinalizer in test body

* Update tests/foreman/cli/test_errata.py



* Update tests/foreman/api/test_discoveryrule.py



* Update tests/foreman/cli/test_errata.py



* Update tests/foreman/destructive/test_capsule_loadbalancer.py



---------

Co-authored-by: Gaurav Talreja <[email protected]>
Copy link
Contributor

@lhellebr lhellebr left a comment

Choose a reason for hiding this comment

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

This is already merged but I discussed this with Peter and I ACK the final result where the order of actions makes more sense.

shweta83 pushed a commit to shweta83/robottelo that referenced this pull request Apr 10, 2024
* reordered addFinalizer in test body

* Update tests/foreman/cli/test_errata.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/api/test_discoveryrule.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/cli/test_errata.py

Co-authored-by: Gaurav Talreja <[email protected]>

* Update tests/foreman/destructive/test_capsule_loadbalancer.py

Co-authored-by: Gaurav Talreja <[email protected]>

---------

Co-authored-by: Gaurav Talreja <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6.12.z Introduced in or relating directly to Satellite 6.12 6.13.z Introduced in or relating directly to Satellite 6.13 6.14.z Introduced in or relating directly to Satellite 6.14 6.15.z Introduced in or relating directly to Satellite 6.15 CherryPick PR needs CherryPick to previous branches
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants