Skip to content

test: add unit tests for managers/utils.py and template_manager.py#21227

Open
Xio-Shark wants to merge 3 commits intosgl-project:mainfrom
Xio-Shark:unit-test/managers-utils-template-manager
Open

test: add unit tests for managers/utils.py and template_manager.py#21227
Xio-Shark wants to merge 3 commits intosgl-project:mainfrom
Xio-Shark:unit-test/managers-utils-template-manager

Conversation

@Xio-Shark
Copy link

Part of #20865: add CPU-only unit tests for managers/ module.

test_utils.py (13 tests):

  • validate_input_length: normal/boundary/reject/truncate
  • get_alloc_len_per_decode: no spec/basic spec/draft tokens/page_size error
  • GenerationBatchResult: default and custom fields

test_template_manager.py (12 tests):

  • _detect_reasoning_pattern: None/empty/no-think/with-think/partial
  • guess_chat_template_from_model_path: known/unknown model
  • _select_named_template: empty/single/preferred/not-found/multi
  • _load_explicit_chat_template: invalid raises/builtin sets

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the test coverage and reliability of the sglang.srt.managers module by introducing dedicated CPU-only unit tests for utils.py and template_manager.py. These new tests validate critical functionalities related to input processing, speculative decoding resource allocation, and chat template handling, ensuring robust behavior and preventing regressions in these core components.

Highlights

  • Unit Tests for managers/utils.py: Comprehensive CPU-only unit tests were added for validate_input_length, get_alloc_len_per_decode, and the GenerationBatchResult dataclass, covering normal, boundary, and error conditions.
  • Unit Tests for managers/template_manager.py: Extensive CPU-only unit tests were introduced for TemplateManager, verifying its initialization, _detect_reasoning_pattern, guess_chat_template_from_model_path, _select_named_template, and _load_explicit_chat_template methods.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a solid suite of unit tests for template_manager.py and utils.py, significantly improving test coverage for the managers module. The tests are well-structured and cover a good range of scenarios, including normal operation, boundary conditions, and error cases. I have a couple of minor suggestions to improve the clarity and maintainability of the new tests.

Comment on lines +76 to +78
mock_tm = MagicMock()
with self.assertRaises(ValueError):
self.tm._select_named_template({}, mock_tm)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The variable mock_tm is used to mock a TokenizerManager, but its name could be confused with self.tm, which is an instance of TemplateManager. For better readability, consider renaming mock_tm to mock_tokenizer_manager throughout the test classes that use it (e.g., TestSelectNamedTemplate and TestLoadExplicitChatTemplate).

Suggested change
mock_tm = MagicMock()
with self.assertRaises(ValueError):
self.tm._select_named_template({}, mock_tm)
mock_tokenizer_manager = MagicMock()
with self.assertRaises(ValueError):
self.tm._select_named_template({}, mock_tokenizer_manager)

)
result = get_alloc_len_per_decode(args)
# page_size > 1 but topk == 1, so no error
self.assertEqual(result, max(3, 5))
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

It's a good practice in unit testing to assert against explicit, pre-calculated values rather than expressions that replicate the implementation's logic. This makes the test's intent clearer and decouples it from the implementation details.

Suggested change
self.assertEqual(result, max(3, 5))
self.assertEqual(result, 5)

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b1da11d53c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


from sglang.test.ci.ci_register import register_cpu_ci

register_cpu_ci(est_time=5, suite="stage-a-cpu-only")

Choose a reason for hiding this comment

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

P1 Badge Register these unit tests in the CPU CI suite

The new manager tests are tagged with suite="stage-a-cpu-only", but the CPU PR workflow only runs python3 run_suite.py --hw cpu --suite stage-a-test-cpu (.github/workflows/pr-test.yml lines 929-935), and test/run_suite.py only lists stage-a-test-cpu as a per-commit CPU suite. As a result, neither this file nor the companion test_template_manager.py will execute in CI, so regressions in managers/utils.py and template_manager.py can still merge unnoticed.

Useful? React with 👍 / 👎.

…ger.py (sgl-project#20865)

Add CPU-only unit tests for two modules under sglang.srt.managers/:

test_utils.py (13 tests):
- validate_input_length: normal pass, boundary (==max), reject, truncate,
  truncate order preservation, empty input
- get_alloc_len_per_decode: no speculation, basic spec, draft>steps,
  topk==1 with large page_size, page_size>1 && topk>1 raises
- GenerationBatchResult: default fields, custom fields

test_template_manager.py (12 tests):
- __init__: default values
- _detect_reasoning_pattern: None, empty, no-think, with-think, partial
- guess_chat_template_from_model_path: known model, unknown model
- _select_named_template: empty dict, single, preferred, not-found, first-of-multi
- _load_explicit_chat_template: invalid raises, builtin sets name
- Remove unused imports: dataclasses, patch
- Break long lines to comply with line-length limit
@Xio-Shark Xio-Shark force-pushed the unit-test/managers-utils-template-manager branch from 0403f16 to 5328540 Compare March 23, 2026 20:48
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5328540b33

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +40 to +42
def test_template_with_think_tag_returns_true(self):
template = r"<|im_start|>assistant\n<think>\n"
self.assertTrue(self.tm._detect_reasoning_pattern(template))

Choose a reason for hiding this comment

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

P2 Badge Exercise force-reasoning detection with real newlines

load_chat_template() feeds tokenizer.chat_template straight into _detect_reasoning_pattern(), and both _load_jinja_template() and the built-in chat templates in python/sglang/lang/chat_template.py produce strings with real newline characters (for example "<|im_start|>assistant\n"), not the literal \\n sequences used in this test. In that scenario the current regex does not match, so this test would stay green while force-reasoning detection is broken for the templates users actually load.

Useful? React with 👍 / 👎.

Comment on lines +34 to +38
def test_exactly_at_limit_returns_error(self):
"""Input length == max is treated as exceeding (>= check)."""
req = self._make_req(200)
result = validate_input_length(
req, max_req_input_len=200, allow_auto_truncate=False

Choose a reason for hiding this comment

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

P2 Badge Stop treating max-length prompts as out of bounds

The helper documents max_req_input_len as the maximum allowed input length, and --allow-auto-truncate is described as applying only when a request exceeds that limit. tp_worker.py also already reserves five tokens of headroom before computing max_req_input_len, so asserting that len == max_req_input_len must fail bakes the current off-by-one behavior into CI and will block a future fix that accepts prompts exactly at the published limit.

Useful? React with 👍 / 👎.

@Xio-Shark
Copy link
Author

@ispobock Could you please add the run-ci label to trigger CI? This PR adds 25 CPU-only unit tests for managers/utils.py and managers/template_manager.py. Thanks!

@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

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.

1 participant