Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rpc_util: Reduce extra byte from limit reader #4957

Closed
wants to merge 3 commits into from

Conversation

uds5501
Copy link
Contributor

@uds5501 uds5501 commented Nov 5, 2021

Fixes #4552

RELEASE NOTES: None

@uds5501
Copy link
Contributor Author

uds5501 commented Nov 5, 2021

Currently removing the +1 made sense to me for the problem.
Frankly, I couldn't understand the thought process of keeping it there in the first place, maybe someone could shed some light on the same?

@zasweq zasweq added this to the 1.43 release milestone Nov 6, 2021
@zasweq zasweq requested a review from dfawley November 6, 2021 00:04
Copy link
Member

@dfawley dfawley left a comment

Choose a reason for hiding this comment

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

This is done to distinguish whether a message is exactly the same size as the limit or over the limit. Is there a test that covers a message of exactly the limit? I kind of doubt it, since I would have expected it to fail with this change. If not, please add one, thank you!

@dfawley dfawley assigned uds5501 and unassigned dfawley Nov 8, 2021
@uds5501
Copy link
Contributor Author

uds5501 commented Nov 9, 2021

There is no such test I believe, will add one.
One small doubt though, how do I test decompress? Should I export it or copy the logic in the unit test?

@dfawley
Copy link
Member

dfawley commented Nov 9, 2021

There is no such test I believe, will add one.
One small doubt though, how do I test decompress? Should I export it or copy the logic in the unit test?

This would be best as a test in grpc/test/ since those tests are done at the API layer. I wouldn't use proto messages for such a test (use the grpc APIs directly), so you can exactly control the payload size here. A decompressor can be implemented to do whatever you want it to do; the interface is small and pretty simple to implement. One example would be to output each byte in the input stream twice. Or, output the input contents and add one extra byte to the end.

@uds5501
Copy link
Contributor Author

uds5501 commented Nov 11, 2021

This would be best as a test in grpc/test/ since those tests are done at the API layer. I wouldn't use proto messages for such a test (use the grpc APIs directly), so you can exactly control the payload size here. A decompressor can be implemented to do whatever you want it to do; the interface is small and pretty simple to implement. One example would be to output each byte in the input stream twice. Or, output the input contents and add one extra byte to the end.

Got it, I will try and add it by this weekend, a little caught up in official tasks.

@uds5501
Copy link
Contributor Author

uds5501 commented Nov 14, 2021

Is there a test that covers a message of exactly the limit?

@dfawley I am able to implement the encoding.Compressor interface but I am not sure how do I write a test for this? How do I invoke the decompress() function in a way that data bytes == max receive limit?

Should I push the changes I have done so far?

@dfawley
Copy link
Member

dfawley commented Nov 15, 2021

@uds5501 I would just have the compressor implement a Reader that outputs some number of bytes exactly equal to a magic value you initialize it with. And set the max receive message size on the client to the same value. E.g.

func (f *fakeCompressor) Decompress(r io.Reader) (io.Reader, error) {
	// Not sure if this needs to read from r at all.. if so, ioutil.ReadAll(r) and ignore the result.
	return bytes.NewBuffer(make([]byte, f.size)), nil 
}

@uds5501
Copy link
Contributor Author

uds5501 commented Nov 16, 2021

@dfawley I have created a small sample test to see if the implementation is as expected.
If it is, please let me know, I will add the required comments on the sample interfaces afterward. Thank you.

@uds5501 uds5501 requested a review from dfawley November 16, 2021 17:48
Copy link
Member

@dfawley dfawley left a comment

Choose a reason for hiding this comment

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

Thanks for writing this test. Comments inline.

@@ -6730,6 +6730,73 @@ func testRPCTimeout(t *testing.T, e env) {
}
}

type FakeCompressor struct {
Copy link
Member

Choose a reason for hiding this comment

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

No need to export. It would be nice to parameterize the size (or add a payload buffer directly here?) for reusability.

}

func (c *FakeCompressor) Compress(w io.Writer) (io.WriteCloser, error) {
customCloser := &customWriterCloser{w}
Copy link
Member

Choose a reason for hiding this comment

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

Nit: use field names: Writer: w. Also, omit local variable and return directly.

@@ -6730,6 +6730,73 @@ func testRPCTimeout(t *testing.T, e env) {
}
}

type FakeCompressor struct {
name string
Copy link
Member

Choose a reason for hiding this comment

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

This field is unnecessary, or should be returned from Name().


func (s) TestDecompressionWithMaximumBytes(t *testing.T) {
encoding.RegisterCompressor(&FakeCompressor{name: "fakeCompressor"})
payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, 10098)
Copy link
Member

Choose a reason for hiding this comment

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

This payload is actually unnecessary.

}

func (c *FakeCompressor) Decompress(r io.Reader) (io.Reader, error) {
return bytes.NewBuffer(make([]byte, 10098)), nil
Copy link
Member

Choose a reason for hiding this comment

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

This will decompress zeroes -- will it work with protobuf to deserialize this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am not sure actually, i couldn't study the test server well enough. I went through a few examples used in tests so copied one of them, I'll admit that I don't see how decompression will work here. Will research more on this.

Comment on lines +6772 to +6790
s := grpc.NewServer()
testpb.RegisterTestServiceServer(s, ss)
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("Failed to create listener: %v", err)
}

go func() {
s.Serve(lis)
}()
defer s.Stop()

dctx, dcancel := context.WithTimeout(context.Background(), 5*time.Second)
defer dcancel()
cc, err := grpc.DialContext(dctx, lis.Addr().String(), grpc.WithInsecure(), grpc.WithDefaultCallOptions(grpc.UseCompressor("fakeCompressor"), grpc.MaxCallRecvMsgSize(10098)))
if err != nil {
t.Fatalf("Failed to dial server")
}
defer cc.Close()
Copy link
Member

Choose a reason for hiding this comment

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

Since you are using protobuf..assuming it works..why not use ss.Start(nil, <dial options>)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Again, not sure.
Will need some guidance to understand where is our decompression actually coming into play.


dctx, dcancel := context.WithTimeout(context.Background(), 5*time.Second)
defer dcancel()
cc, err := grpc.DialContext(dctx, lis.Addr().String(), grpc.WithInsecure(), grpc.WithDefaultCallOptions(grpc.UseCompressor("fakeCompressor"), grpc.MaxCallRecvMsgSize(10098)))
Copy link
Member

Choose a reason for hiding this comment

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

We also need to test with a max recv msg size of N-1 and ensure it fails. This is where I believe your PR is incorrect.

@easwars
Copy link
Contributor

easwars commented Nov 17, 2021

@uds5501 : Looks like the tests are broken.

@github-actions
Copy link

This PR is labeled as requiring an update from the reporter, and no update has been received after 6 days. If no update is provided in the next 7 days, this issue will be automatically closed.

@github-actions github-actions bot added the stale label Nov 25, 2021
@github-actions github-actions bot closed this Dec 2, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 1, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Get empty response when compress enabled and maxReceiveMessageSize be maxInt64
4 participants