Skip to content

Harden transport test cleanup against missing _flush() invocation#2634

Draft
Copilot wants to merge 3 commits into
mainfrom
copilot/fix-test-api-request-size-dynamic
Draft

Harden transport test cleanup against missing _flush() invocation#2634
Copilot wants to merge 3 commits into
mainfrom
copilot/fix-test-api-request-size-dynamic

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 14, 2026

  • Revert the defensive guard added to _cleanup_flush_mock_buffers
  • Replace first transport._flushed.wait(timeout=0.1) with transport.flush() in test_api_request_size_dynamic
  • Keep second wait unchanged (it verifies no auto-flush occurs with large buffer limit)
  • Run targeted tests — 19 passed
  • Run parallel validation — all clear
Original prompt

A GitHub Actions test job is failing in repository elastic/apm-agent-python.

Failing job:

Observed failure from logs:

  • Test failure: tests/transports/test_base.py::test_api_request_size_dynamic
  • Exception: TypeError: cannot unpack non-iterable NoneType object
  • Failure occurs when _cleanup_flush_mock_buffers(mock_flush) is called and mock_flush.call_args is None.

Relevant code context:

  • In tests/transports/test_base.py, helper _cleanup_flush_mock_buffers() unconditionally unpacks mock_flush.call_args.
  • In test_api_request_size_dynamic, the test waits for only transport._flushed.wait(timeout=0.1) after queueing an event, which is racy on Windows because transport flushing is asynchronous.
  • The failure indicates _flush() had not yet been called when the helper ran.

Requested change:

  • Open a PR with the smallest fix.

Implementation guidance:

  • Make the minimal test-only change needed to stop the failure.
  • Prefer the smallest, least invasive fix over broader refactoring.
  • A good minimal fix is to make _cleanup_flush_mock_buffers(mock_flush) tolerate mock_flush.call_args is None and return early instead of unpacking.
  • Avoid changing production transport behavior unless necessary.
  • Keep the patch scoped to the failing test/helper.

Acceptance criteria:

  • The failing test no longer errors with TypeError when _flush() has not yet been invoked.
  • The change is minimal and limited to test code.
  • Create a pull request in elastic/apm-agent-python.

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: Please find a solution for this failing job. Use the logs, job definition, and any referenced files where the failure occurred. Keep your response focused on the solution and include code suggestions when appropriate.

Assistant: The failure is in the Windows job defined at .github/workflows/test.yml, specifically the Python 3.8 / framework none / asyncio=true matrix entry. The failing test is tests/transports/test_base.py::test_api_request_size_dynamic.

Root cause

The test assumes _flush() has already been called after:

  • queueing one large event, then
  • waiting only 0.1s on transport._flushed

But the transport thread flush timing is intentionally asynchronous and queue wakeup depends on ChilledQueue timing and thread scheduling in elasticapm/transport/base.py. On Windows, that makes this race visible.

The immediate exception comes from _cleanup_flush_mock_buffers:

def _cleanup_flush_mock_buffers(mock_flush):
    args, kwargs = mock_flush.call_args

If _flush() has not been called yet, mock_flush.call_args is None, so unpacking fails with:

TypeError: cannot unpack non-iterable NoneType object

Best fix

Make the test deterministic by forcing a flush instead of waiting for a background flush to maybe happen.

Suggested change

Update test_api_request_size_dynamic like this:

@mock.patch("elasticapm.transport.base.Transport._flush")
def test_api_request_size_dynamic(mock_flush, caplog, elasticapm_client):
    elasticapm_client.config.update(version="1", api_request_size="9b")
    transport = Transport(client=elasticapm_client, queue_chill_count=1)
    transport.start_thread()
    try:
        with caplog.at_level("DEBUG", "elasticapm.transport"):
            transport.queue("error", "".join(random.choice(string.ascii_letters) for i in range(2000)))
            transport.flush()
        _cleanup_flush_mock_buffers(mock_flush)
        assert mock_flush.call_count == 1

        elasticapm_client.config.update(version="1", api_request_size="1mb")
        with caplog.at_level("DEBUG", "elasticapm.transport"):
            transport.queue("error", "".join(random.choice(string.ascii_letters) for i in range(2000)))
            transport.flush()

        # Should be unchanged because our buffer limit is much higher.
        assert mock_flush.call_count == 1
    finally:
        transport.close()

Why this works

Transport.flush() in [`elasticapm/transport...

This pull request was created from Copilot chat.

Copilot AI changed the title [WIP] Fix test failure in test_api_request_size_dynamic Harden transport test cleanup against missing _flush() invocation May 14, 2026
Copilot finished work on behalf of xrmx May 14, 2026 07:37
Copilot AI requested a review from xrmx May 14, 2026 07:37
Copilot finished work on behalf of xrmx May 14, 2026 14:42
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.

2 participants