31472b5413
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 21s
CI / helm (pull_request) Successful in 22s
CI / lint (pull_request) Successful in 3m20s
CI / quality (pull_request) Successful in 3m43s
CI / typecheck (pull_request) Successful in 3m58s
CI / security (pull_request) Successful in 4m8s
CI / integration_tests (pull_request) Successful in 9m33s
CI / unit_tests (pull_request) Successful in 10m12s
CI / docker (pull_request) Successful in 1m28s
CI / coverage (pull_request) Successful in 12m18s
CI / e2e_tests (pull_request) Successful in 19m51s
CI / status-check (pull_request) Successful in 1s
CI / build (push) Successful in 15s
CI / helm (push) Successful in 22s
CI / lint (push) Successful in 3m18s
CI / quality (push) Successful in 3m41s
CI / typecheck (push) Successful in 3m57s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m10s
CI / unit_tests (push) Failing after 6m58s
CI / docker (push) Has been skipped
CI / integration_tests (push) Successful in 9m15s
CI / coverage (push) Successful in 12m26s
CI / e2e_tests (push) Successful in 23m11s
CI / status-check (push) Failing after 1s
CI / benchmark-publish (push) Successful in 28m31s
CI / benchmark-regression (pull_request) Successful in 54m53s
Add Behave feature/step pairs that exercise uncovered branches across handlers, LSP, CLI, and service layers to reach the coverage gate. ISSUES CLOSED: #1232
152 lines
7.6 KiB
Gherkin
152 lines
7.6 KiB
Gherkin
Feature: LSP StdioTransport coverage
|
|
As a developer maintaining the LSP transport layer
|
|
I need thorough tests for StdioTransport
|
|
So that all error paths and normal flows are exercised
|
|
|
|
# ── start() error paths ─────────────────────────────────────────
|
|
|
|
Scenario: ltcov start raises RuntimeError when already alive
|
|
Given ltcov I create a StdioTransport for command "cat"
|
|
And ltcov the transport has a running mock process
|
|
When ltcov I try to start the transport
|
|
Then ltcov the error should be a RuntimeError with message "already started"
|
|
|
|
Scenario: ltcov start raises LspError on FileNotFoundError
|
|
Given ltcov I create a StdioTransport for command "nonexistent_binary_xyz"
|
|
And ltcov Popen is mocked to raise FileNotFoundError
|
|
When ltcov I try to start the transport
|
|
Then ltcov the error should be an LspError with message "not found"
|
|
|
|
Scenario: ltcov start raises LspError on OSError
|
|
Given ltcov I create a StdioTransport for command "bad_command"
|
|
And ltcov Popen is mocked to raise OSError with "Permission denied"
|
|
When ltcov I try to start the transport
|
|
Then ltcov the error should be an LspError with message "Failed to start"
|
|
|
|
# ── stop() paths ────────────────────────────────────────────────
|
|
|
|
Scenario: ltcov stop returns None when not started
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
When ltcov I stop the transport
|
|
Then ltcov the stop result should be None
|
|
|
|
Scenario: ltcov stop returns exit code when process already exited
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process that already exited with code 0
|
|
When ltcov I stop the transport
|
|
Then ltcov the stop result should be 0
|
|
And ltcov the internal process should be None
|
|
|
|
Scenario: ltcov stop returns exit code when process already exited with error
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process that already exited with code 1
|
|
When ltcov I stop the transport
|
|
Then ltcov the stop result should be 1
|
|
|
|
Scenario: ltcov stop force kills on timeout
|
|
Given ltcov I create a StdioTransport for command "sleep"
|
|
And ltcov the transport has a mock process that ignores terminate
|
|
When ltcov I stop the transport with timeout 0.1
|
|
Then ltcov the mock process should have been killed
|
|
And ltcov the stop result should be an integer
|
|
|
|
# ── send_message() paths ────────────────────────────────────────
|
|
|
|
Scenario: ltcov send_message raises RuntimeError when not started
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
When ltcov I try to send a message
|
|
Then ltcov the error should be a RuntimeError with message "not started"
|
|
|
|
Scenario: ltcov send_message raises RuntimeError when stdin is None
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process with no stdin
|
|
When ltcov I try to send a message
|
|
Then ltcov the error should be a RuntimeError with message "not started"
|
|
|
|
Scenario: ltcov send_message writes Content-Length framed JSON-RPC
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process with writable stdin
|
|
When ltcov I send the message {"jsonrpc":"2.0","method":"initialize","id":1}
|
|
Then ltcov the written bytes should contain "Content-Length:"
|
|
And ltcov the written bytes should contain "initialize"
|
|
|
|
Scenario: ltcov send_message raises BrokenPipeError on dead process
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process with broken stdin
|
|
When ltcov I try to send a message
|
|
Then ltcov the error should be a BrokenPipeError
|
|
|
|
# ── read_message() paths ────────────────────────────────────────
|
|
|
|
Scenario: ltcov read_message raises RuntimeError when not started
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
When ltcov I try to read a message
|
|
Then ltcov the error should be a RuntimeError with message "not started"
|
|
|
|
Scenario: ltcov read_message raises RuntimeError when stdout is None
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process with no stdout
|
|
When ltcov I try to read a message
|
|
Then ltcov the error should be a RuntimeError with message "not started"
|
|
|
|
Scenario: ltcov read_message returns None on select timeout
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process with empty stdout
|
|
And ltcov select is mocked to return not ready
|
|
When ltcov I read a message with timeout 1.0
|
|
Then ltcov the read result should be None
|
|
|
|
Scenario: ltcov read_message returns None on EOF
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process with stdout that returns EOF
|
|
When ltcov I read a message with timeout 1.0
|
|
Then ltcov the read result should be None
|
|
|
|
Scenario: ltcov read_message uses default timeout when None
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process with stdout that returns EOF
|
|
When ltcov I read a message with default timeout
|
|
Then ltcov the read result should be None
|
|
|
|
Scenario: ltcov read_message parses valid Content-Length message
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process with a valid JSON-RPC response
|
|
When ltcov I read a message with timeout 5.0
|
|
Then ltcov the read result should have key "jsonrpc" with value "2.0"
|
|
|
|
Scenario: ltcov read_message returns None on invalid content-length value
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process with invalid content-length header
|
|
When ltcov I read a message with timeout 5.0
|
|
Then ltcov the read result should be None
|
|
|
|
Scenario: ltcov read_message returns None when no content-length header
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process with no content-length header
|
|
When ltcov I read a message with timeout 5.0
|
|
Then ltcov the read result should be None
|
|
|
|
Scenario: ltcov read_message raises ValueError on oversized message
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process with oversized content-length
|
|
When ltcov I try to read a message
|
|
Then ltcov the error should be a ValueError with message "too large"
|
|
|
|
Scenario: ltcov read_message returns None on body select timeout
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process with headers but body times out
|
|
When ltcov I read a message with timeout 5.0
|
|
Then ltcov the read result should be None
|
|
|
|
Scenario: ltcov read_message returns None on truncated body
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process with truncated body
|
|
When ltcov I read a message with timeout 5.0
|
|
Then ltcov the read result should be None
|
|
|
|
Scenario: ltcov read_message returns None on invalid JSON body
|
|
Given ltcov I create a StdioTransport for command "echo"
|
|
And ltcov the transport has a mock process with invalid JSON body
|
|
When ltcov I read a message with timeout 5.0
|
|
Then ltcov the read result should be None
|