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

[YUNIKORN-2824] Refactor preemption_test.go #985

Closed
wants to merge 13 commits into from

Conversation

SophieTech88
Copy link
Contributor

@SophieTech88 SophieTech88 commented Oct 16, 2024

What is this PR for?

Off late, lot of new tests has been added into preemption_test.go for several use cases. There is a room of improvement to simplify the whole tests especially by avoiding duplicates.
This PR focus on TestTryPreemptionOnNode , TestTryPreemption_NodeWithCapacityLesserThanAsk, and TestTryPreemptionOnQueue, those 3 tests can be merged together into single one TestTryPreemptionCombined and handle each cases through t.Run({}) construct.

What type of PR is it?

  • - Bug Fix
  • - Improvement
  • - Feature
  • - Documentation
  • - Hot Fix
  • - Refactoring

Todos

  • - Task

What is the Jira issue?

https://issues.apache.org/jira/browse/YUNIKORN-2824

How should this be tested?

It should pass all unit tests.

Screenshots (if appropriate)

Questions:

  • - The licenses files need update.
  • - There is breaking changes for older versions.
  • - It needs documentation.

Copy link
Contributor

@chenyulin0719 chenyulin0719 left a comment

Choose a reason for hiding this comment

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

I guess this PR is still in draft. I will convert it.
Leaving a few quick reviews.

Comment on lines 240 to 241
nodes []*Node
iterator func() NodeIterator
Copy link
Contributor

@chenyulin0719 chenyulin0719 Oct 16, 2024

Choose a reason for hiding this comment

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

We can remove the iterator because nodes can be used to generate an iterator.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah. And I restructure the test function again , and keep the node iterator in the body, not as parameters. I hope it will be better. Thank you!

Comment on lines 242 to 248
rootMaxRes map[string]string
parentMaxRes map[string]string
parentGuarRes map[string]string
childQ1MaxRes map[string]string
childQ1GuarRes map[string]string
childQ2MaxRes map[string]string
childQ2GuarRes map[string]string
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not in favor of using 7 paramters to represent the queue configuration, especially when there is only one difference in childQ2GuarRes in TestTryPreemption_NodeWithCapacityLesserThanAsk

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you so much. I agree that there are too many parameters here. I jus reduced to 2 parameters: rootMaxRes and childQ2GuarRes.

@chenyulin0719 chenyulin0719 marked this pull request as draft October 16, 2024 08:16
@SophieTech88
Copy link
Contributor Author

SophieTech88 commented Oct 16, 2024

Here I find there are 4 test functions:

  • TestTryPreemption: 1 node
  • TestTryPreemptionOnNode : 2 nodes
  • TestTryPreemption_NodeWithCapacityLesserThanAsk : 2 nodes
  • TestTryPreemptionOnQueue : 2 nodes

As a draft here, I made a func TestTryPreemptionCombined to deal with 3 tests, TestTryPreemptionOnNode , TestTryPreemption_NodeWithCapacityLesserThanAsk and TestTryPreemptionOnQueue, all of them have 2 nodes, they have similar process, and the test passed.

But when I want to merge test TestTryPreemption ,which has only one node, it failed. assert.Assert(t, result != nil, "no result") // assertion failed: result is nil : no result. So my guess, it failed to create a new preemptor. Welcome to any suggestions.

@SophieTech88 SophieTech88 marked this pull request as ready for review October 18, 2024 05:21
@SophieTech88
Copy link
Contributor Author

So at this moment, I only create a new test named TestTryPreemptionCombined, which includes 3 test cases:

  • TestTryPreemptionOnNode : 2 nodes
  • TestTryPreemption_NodeWithCapacityLesserThanAsk : 2 nodes
  • TestTryPreemptionOnQueue : 2 nodes

I skip the TestTryPreemption right now. And I want to check if I am on the right direction?

Copy link
Contributor

@craigcondit craigcondit left a comment

Choose a reason for hiding this comment

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

To be honest, I don't really see this as an improvement. It makes the tests themselves hard to follow.

@SophieTech88
Copy link
Contributor Author

To be honest, I don't really see this as an improvement. It makes the tests themselves hard to follow.
Hi Craig,

Thank you so much for your feedback! I completely understand your concerns regarding the readability of the combined tests.

I think this boils down to finding the right balance between readability and avoiding code duplication. In the original code, the logic is certainly clearer with separated test cases, but there is a lot of duplicate code due to the similar steps involved in the preemption process. I believe this is why @manirajv06 raised the issue in the first place—hoping to simplify the tests and remove redundancy, while still preserving clarity. Please correct me if my understanding is off!

As I reviewed the three test cases, I noticed that while their goals differ, the preemption process itself is quite similar across all of them, which is where the duplicated code comes from. Here's a breakdown of the common steps:

  1. Setting up the two nodes and queues:
    • The parameters for rootMaxRes, childQ2GuarRes, and app2Res are unique to each test case to suit the specific scenario being tested.
    • One idea I considered was passing all parameters (e.g., MaxRes and GuaranteedRes for rootQ, parentQ, childQ1, childQ2) in a more structured way to simplify things, but I felt that might lead to passing too many parameters.
  2. Setting up app1 with its allocations: This is a common step across all tests.
  3. Setting up app2: Another similar step across tests.
  4. Setting up headRoom, preemptor, and triggering preemption: This is where the main difference lies between the tests:
    • TestTryPreemptionOnNode: Preemption happens due to node resource constraints.
    • TestTryPreemption_NodeWithCapacityLesserThanAsk: No preemption happens because the node's capacity is smaller than the request.
    • TestTryPreemptionOnQueue: Preemption happens due to queue resource constraints, which introduces an extra check for allocs.
  5. Validating preemption results based on the test case.

While I tried to reduce the duplicated code, I realize there’s still a challenge in balancing this with maintaining readability and clarity. The goal was to make the code more concise without sacrificing logic transparency.

I've updated the code with a new approach that attempts to address these trade-offs. I'm not sure if it fully aligns with your expectations, but I'd really appreciate your thoughts on it. If you have any specific suggestions or ideas, I'd be more than happy to incorporate them. I’m open to any feedback to further improve it!

@SophieTech88
Copy link
Contributor Author

I also had another thought. Since the logic is the key focus in these tests, and the only common parts across the three test cases are setting up app1 with its allocations and setting up app2, we could extract just those common steps into a helper function.

By creating a function that handles setting up app1 and app2, we can reuse it across the three test cases. This way, the tests remain separated, keeping the logic for each scenario clear and focused, while still reducing some of the duplicate code.

@craigcondit
Copy link
Contributor

I think keeping the tests separate and extracting common logic into helper functions makes the most sense. It allows the tests to test one thing (I'm not generally a fan of combining everything into the case-based flows), but avoids repetition.

@SophieTech88
Copy link
Contributor Author

I think keeping the tests separate and extracting common logic into helper functions makes the most sense. It allows the tests to test one thing (I'm not generally a fan of combining everything into the case-based flows), but avoids repetition.

Hi Craig. Thank you so much to review and comment, it is a great help for me to understand the next step. I love the idea of a helper function with separate tests. I will update the code, soon.

@SophieTech88
Copy link
Contributor Author

SophieTech88 commented Oct 24, 2024

I try to do the work step by step as below :

  1. return the code back to the original one (6d01a91)
  2. Create 2 helper functions: createApp1() and createApp2() (641ad5a)
  3. Update the createApp2() function, make it more flexible, and apply it to other test cases (c199547)
  4. Update the createApp1() function, make it more flexible, and apply it to other test cases (5c25d60)

If anyone has any great suggestion, just let me know.

Copy link

codecov bot commented Oct 24, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 81.29%. Comparing base (44705ae) to head (5c25d60).
Report is 4 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #985      +/-   ##
==========================================
- Coverage   81.50%   81.29%   -0.21%     
==========================================
  Files          97       97              
  Lines       12625    15463    +2838     
==========================================
+ Hits        10290    12571    +2281     
- Misses       2052     2611     +559     
+ Partials      283      281       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@craigcondit craigcondit left a comment

Choose a reason for hiding this comment

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

+1 LGTM.

@craigcondit craigcondit changed the title [YUNIKORN-2824]Refactor preemption_test.go(for debug purpose) [YUNIKORN-2824] Refactor preemption_test.go Oct 24, 2024
@SophieTech88
Copy link
Contributor Author

+1 LGTM.

Thank you so much for your suggestion and quick response. ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants