Skip to content

Extract pause_resume_in_place kit; rename test_abort to test_scheduler_control - #22647

Merged
hnyls2002 merged 5 commits into
mainfrom
lsyin/pause-gen-kit
Apr 13, 2026
Merged

hnyls2002 merged 5 commits into
mainfrom
lsyin/pause-gen-kit

Conversation

@hnyls2002

@hnyls2002 hnyls2002 commented Apr 13, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Extract test_pause_resume_in_place from test_disaggregation_basic.py into reusable PauseResumeInPlaceMixin kit (python/sglang/test/kits/pause_generation_kit.py)
  • Add the kit to non-disagg TestSchedulerControl (formerly TestAbortAll) for single-server pause/resume coverage
  • Rename test_abort.py -> test_scheduler_control.py and TestAbortAll -> TestSchedulerControl to reflect broader scheduler control scope
  • Bump est_time 328->360 for the added pause test

Test plan

  • CI: test_scheduler_control.py passed (359s)
  • CI: test_disaggregation_basic.py passed (395s)

@hnyls2002

Copy link
Copy Markdown
Collaborator Author

/rerun-test test_disaggregation_basic.py

@github-actions

Copy link
Copy Markdown
Contributor

❌ test_disaggregation_basic.py: Ambiguous filename test_disaggregation_basic.py — matched 2 files:

  • test/registered/amd/disaggregation/test_disaggregation_basic.py
  • test/registered/disaggregation/test_disaggregation_basic.py

Please provide the full path, e.g. /rerun-test test/registered/disaggregation/test_disaggregation_basic.py

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

Copy link
Copy Markdown
Contributor

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 reusable PauseResumeInPlaceMixin within a new test kit to standardize pause and resume functionality testing. The TestDisaggregationAccuracy class has been refactored to inherit from this mixin, effectively removing duplicate test logic. Review feedback suggests enhancing the mixin's configurability by converting the request timeout constant into a class attribute. Additionally, it is recommended to replace the use of as_completed with concurrent.futures.wait to more robustly handle timeouts and ensure that final assertions are executed even when requests fail to resolve.

Comment on lines +6 to +24
_REQUEST_TIMEOUT = 180


class PauseResumeInPlaceMixin:
"""Test pause/resume with in_place mode.

Sends concurrent requests, pauses mid-generation, verifies no progress
during the pause window, then resumes and verifies all requests complete.

Subclass must set:
- pause_generate_url: URL to send /generate requests (or falls back to self.base_url)
- pause_target_urls: list of URLs to send /pause_generation and /continue_generation
"""

pause_num_requests: int = 32
pause_max_new_tokens: int = 512
pause_duration: float = 5
pause_generate_url: str = ""
pause_target_urls: list = []

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

To improve the configurability of this test kit, consider moving the _REQUEST_TIMEOUT constant into a class attribute (e.g., pause_request_timeout: int = 180). This would allow subclasses to override the timeout for specific test environments, consistent with how pause_num_requests and pause_duration are exposed.

Comment on lines +88 to +111
for future in as_completed(futures, timeout=_REQUEST_TIMEOUT):
prompt_id = futures[future]
try:
resp = future.result()
if resp.status_code == 200:
body = resp.json()
self.assertIn("text", body)
self.assertGreater(len(body["text"]), 0)
completed += 1
else:
errors.append(f"Request {prompt_id}: status={resp.status_code}")
except Exception as e:
errors.append(f"Request {prompt_id}: exception={e}")

self.assertEqual(
completed + len(errors),
num_requests,
"Some requests did not resolve within the timeout -- likely hung during pause.",
)
self.assertEqual(
completed,
num_requests,
f"Some requests failed: {completed}/{num_requests} succeeded. Errors: {errors}",
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The current implementation using as_completed with a timeout will raise a concurrent.futures.TimeoutError if any requests fail to complete within the specified time. This exception propagates out of the method, skipping the summary assertions at the end (lines 102-111) which are intended to provide a descriptive failure report. Additionally, if the loop finishes normally, the assertion at line 102 is redundant as the sum of completed and errored requests will always equal num_requests.

Using concurrent.futures.wait is a more robust pattern here. It allows you to collect results from all completed futures and explicitly identify which ones timed out, ensuring that the final assertions are always reached and provide a comprehensive error message.

            from concurrent.futures import wait
            # Use a slightly longer timeout for wait to allow individual request timeouts to trigger first
            done, not_done = wait(futures, timeout=_REQUEST_TIMEOUT + 5)

            completed = 0
            errors = []
            for future in done:
                prompt_id = futures[future]
                try:
                    resp = future.result()
                    if resp.status_code == 200:
                        body = resp.json()
                        self.assertIn("text", body)
                        self.assertGreater(len(body["text"]), 0)
                        completed += 1
                    else:
                        errors.append(f"Request {prompt_id}: status={resp.status_code}")
                except Exception as e:
                    errors.append(f"Request {prompt_id}: exception={e}")

            for future in not_done:
                prompt_id = futures[future]
                errors.append(f"Request {prompt_id}: timed out")

        self.assertEqual(
            completed + len(errors),
            num_requests,
            "Some requests did not resolve within the timeout -- likely hung during pause.",
        )
        self.assertEqual(
            completed,
            num_requests,
            f"Some requests failed: {completed}/{num_requests} succeeded. Errors: {errors}",
        )

@hnyls2002

Copy link
Copy Markdown
Collaborator Author

/rerun-test test/registered/scheduler/test_scheduler_control.py test/registered/disaggregation/test_disaggregation_basic.py

@github-actions

Copy link
Copy Markdown
Contributor

✅ 1-gpu-5090 (1 test): View workflow run

cd test/ && python3 registered/scheduler/test_scheduler_control.py

✅ 2-gpu-h100 (1 test): View workflow run

cd test/ && python3 registered/disaggregation/test_disaggregation_basic.py

@hnyls2002

Copy link
Copy Markdown
Collaborator Author

/tag-and-rerun-ci

@github-actions github-actions Bot added the run-ci CI: run the baseline test suite on this PR label Apr 13, 2026
@hnyls2002 hnyls2002 changed the title Extract pause_resume_in_place test into reusable kit Extract pause_resume_in_place kit; rename test_abort to test_scheduler_control Apr 13, 2026
@hnyls2002
hnyls2002 merged commit da6b8e1 into main Apr 13, 2026
85 of 105 checks passed
@hnyls2002
hnyls2002 deleted the lsyin/pause-gen-kit branch April 13, 2026 01:49
caitengwei pushed a commit to caitengwei/sglang that referenced this pull request Jun 1, 2026
Chronostasys pushed a commit to MindLab-Research/sglang that referenced this pull request Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-ci CI: run the baseline test suite on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant