Skip to content
This repository was archived by the owner on Mar 26, 2026. It is now read-only.

test: fix async showcase test#2441

Merged
parthea merged 13 commits intomainfrom
fix-async-showcase-test
Sep 24, 2025
Merged

test: fix async showcase test#2441
parthea merged 13 commits intomainfrom
fix-async-showcase-test

Conversation

@parthea
Copy link
Copy Markdown
Contributor

@parthea parthea commented Sep 20, 2025

This fixes the presubmit failures at HEAD which were caused by a breaking change in gRPC 1.75.0. The breaking change was considered a bug fix because https://grpc.github.io/grpc/python/grpc_asyncio.html#grpc-metadata mentions that a map is expected rather than a list.

Prior to grpc==1.75.0, client_call_details.metadata.append((key, value)) worked for both sync and async. With grpc==1.75.0, client_call_details.metadata.append((self._key, self._value)) only works for sync. For async, we need client_call_details.metadata[self._key] = self._value

This type of breaking change is challenging because we have test code that runs against both new and old versions of gRPC to check compatibility. Here is the error that we get with older gRPC code after making the necessary change to support gRPC 1.75.0:

    async def _add_request_metadata(self, client_call_details):
        if client_call_details.metadata is not None:
            # https://grpc.github.io/grpc/python/grpc_asyncio.html#grpc.aio.Metadata
            # Note that for async, `ClientCallDetails.metadata` is a mapping.
            # Whereas for sync, `ClientCallDetails.metadata` is a list.
            # https://grpc.github.io/grpc/python/glossary.html#term-metadata.
>           client_call_details.metadata[self._key] = self._value
E           TypeError: list indices must be integers or slices, not str

We need to have special logic to handle this breaking change in 1.75.0.

@product-auto-label product-auto-label bot added the size: xs Pull request size is extra small. label Sep 20, 2025
@product-auto-label product-auto-label bot added size: s Pull request size is small. and removed size: xs Pull request size is extra small. labels Sep 20, 2025
@parthea parthea added the owlbot:run Add this label to trigger the Owlbot post processor. label Sep 20, 2025
@gcf-owl-bot gcf-owl-bot bot removed the owlbot:run Add this label to trigger the Owlbot post processor. label Sep 20, 2025
@parthea parthea marked this pull request as ready for review September 20, 2025 15:42
@parthea parthea requested a review from a team September 20, 2025 15:42
parthea added a commit that referenced this pull request Sep 20, 2025
Comment thread tests/system/conftest.py
# echoes any metadata with key 'showcase-trailer', so the same metadata
# should appear as trailing metadata in the response.
interceptor = EchoMetadataClientGrpcInterceptor(
"showcase-trailer",
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.

Why don't we want to echo the trailing metadata like we were doing before?

Copy link
Copy Markdown
Contributor Author

@parthea parthea Sep 22, 2025

Choose a reason for hiding this comment

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

See a572ff8 where I've updated the comments to clarify that we're still expecting an echo response with showcase-trailer in tests tests/system/test_grpc_interceptor_streams.py and tests/system/test_streams.py. The metadata with showcase-trailer is being sent as part of the request, and the showcase server will echo this back.

Copy link
Copy Markdown
Contributor

@vchudnov-g vchudnov-g Sep 22, 2025

Choose a reason for hiding this comment

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

But the purpose of the test in test_grpc_interceptor_streams.py, which uses this fixture, is to test the interceptor. So the test was having the interceptor insert some new metadata, and then testing that the echoed response back from the server had that new metadata. By removing the injection in the interceptor, and sending it as part of the original request, we're no longer exercising the interceptor (we're simply checking that Showcase echoes back the metadata, which was an assumption for this original test). Am I missing something?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

But the purpose of the test in test_grpc_interceptor_streams.py, which uses this fixture, is to test the interceptor.

The interceptor is still being tested. It is reading the request and response metadata.

So the test was having the interceptor insert some new metadata, and then testing that the echoed response back from the server had that new metadata.

The code in the test was incorrect. This is not the correct way to send metadata. See the grpc examples here which show how metadata should be sent:

https://github.com/grpc/grpc/blob/master/examples/python/metadata/metadata_client.py

By removing the injection in the interceptor, and sending it as part of the original request, we're no longer exercising the interceptor (we're simply checking that Showcase echoes back the metadata, which was an assumption for this original test). Am I missing something?

The interceptor is still being exercised. interceptor.response_metadata is being used in tests.

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.

The interceptor is still being exercised. interceptor.response_metadata is being used in tests.

In test_grpc_interceptor_streams.py, I only see interceptor.response_metadata in the LHS of two assignments:
interceptor.response_metadata = response_metadata. Where is it being checked rather than assigned?

It seems we should make that into an assertion.

Somewhat separately, it seems to me that part of the intent of the previous test was to modify the metadata, not just read it, before sending the request. That's what I was thinking about in my previous comment. There's probably still value in doing that, but if we can't do that immediately, I think a TODO linking to a GitHub issue to come back to this would be fine.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 5c4c76d

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There is no requirement to modify metadata via interceptors as far as I'm aware. As per the grpc example I linked previously, metadata should be sent along with the request, and there is already a metadata argument which can be populated on the client side.

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.

Oh, the use cases for the interceptors didn't include modifing the metadata? We'd have to look back to previous docs. That's what the test was aiming to do previously, but I don't know if that was to test that functionality specifically or merely as a way of testing that the interceptor was called. If changing the metadata is allowed, it might be nice to test it/exemplify it, but we don't have to do that right now; we can defer it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I was able to restore the original test code that we had which updated metadata using an interceptor. PTAL

@product-auto-label product-auto-label bot added size: m Pull request size is medium. and removed size: s Pull request size is small. labels Sep 22, 2025
vchudnov-g added a commit that referenced this pull request Sep 22, 2025
This is based off of #2441 to include asserts on the interceptor.
vchudnov-g added a commit that referenced this pull request Sep 22, 2025
This is based off of #2441 to include asserts on the interceptor.
vchudnov-g
vchudnov-g previously approved these changes Sep 22, 2025
Comment thread tests/system/conftest.py Outdated
def _read_response_metadata_stream(self):
# Access the metadata via the original stream object
if hasattr(self, "_original_stream"):
return self._original_stream.trailing_metadata()
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.

It might make sense to assign to self.response_metadata before returning.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 95e9ae3

vchudnov-g
vchudnov-g previously approved these changes Sep 23, 2025
@product-auto-label product-auto-label bot added size: s Pull request size is small. and removed size: m Pull request size is medium. labels Sep 23, 2025
@product-auto-label product-auto-label bot added size: m Pull request size is medium. and removed size: s Pull request size is small. labels Sep 24, 2025
@parthea parthea added the owlbot:run Add this label to trigger the Owlbot post processor. label Sep 24, 2025
@gcf-owl-bot gcf-owl-bot bot removed the owlbot:run Add this label to trigger the Owlbot post processor. label Sep 24, 2025
@parthea parthea requested a review from ohmayr September 24, 2025 00:20
@parthea parthea merged commit 792e400 into main Sep 24, 2025
124 checks passed
@parthea parthea deleted the fix-async-showcase-test branch September 24, 2025 15:00
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

size: m Pull request size is medium.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants