-
Notifications
You must be signed in to change notification settings - Fork 622
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
Add protobuf conformance tests v1 #2404
Add protobuf conformance tests v1 #2404
Conversation
Hi team, would be glad if some review can be done, I am hoping those bugs will be resolved and protobuf module can hopefully promote to stable after all tests are fixed 🙏 I am willing to help whenever I am free. |
Hi, |
if (restored.hasOneofString()) assertEquals(message.oneofString, restored.oneofString) | ||
if (restored.hasOneofBytes()) assertContentEquals(message.oneofBytes, restored.oneofBytes.toByteArray()) | ||
if (restored.hasOneofBool()) assertEquals(message.oneofBool, restored.oneofBool) | ||
if (restored.hasOneofUint64()) assertEquals(message.oneofUint64, restored.oneofUint64.toULong()) | ||
if (restored.hasOneofFloat()) assertEquals(message.oneofFloat, restored.oneofFloat) | ||
if (restored.hasOneofDouble()) assertEquals(message.oneofDouble, restored.oneofDouble) | ||
if (restored.hasOneofEnum()) assertEquals(message.oneofEnum?.name, restored.oneofEnum?.name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than checking restored, you should probably check message
Just for the clarification of your intentions — do you want this PR to be merged with commented code? Or you want to leave it as a showcase until all issues are fixed? |
Hi, My personal preference is to merge those tests, either with comments or mark them as As library maintainers, please let me know how you want to merge this. If you are against keeping comments, I think it is fine to remove them and open issues in GitHub to track. But I think we should merge the non-commented tests anyway because conformance tests are an important indicator to verify functionality. |
I see.
Yes, this is a great point. I suggest to do the following:
Does that sound plausible to you? |
Hi, Yep that sounds plausible. I am currently traveling and also sick so will complete this when I have time and feel better 😆 |
No problems, take your time and get well! |
@sandwwraith Updated the tests and opened three issues:
I believe they all are related. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall it looks ok to me (not an official dev). I'd say split the individual tests off into separate functions per type. Otherwise I find the code containing a lot of repetitive elements that don't help to make the code clear. Given that the types are local to the tests the API itself isn't really an issue, but perhaps the resulting verbosity isn't ideal (I don't really know how to solve the clarity issue though without adding just as much complexity in other places).
fun default() { | ||
listOf( | ||
KTestMessageProto3Oneof(oneofUint32 = 150u), | ||
KTestMessageProto3Oneof(oneofNestedMessage = KTestMessagesProto3Message.KNestedMessage(a = 150)), | ||
KTestMessageProto3Oneof(oneofString = "150"), | ||
KTestMessageProto3Oneof(oneofBytes = "150".toByteArray()), | ||
KTestMessageProto3Oneof(oneofBool = true), | ||
KTestMessageProto3Oneof(oneofUint64 = 150uL), | ||
KTestMessageProto3Oneof(oneofFloat = 150f), | ||
KTestMessageProto3Oneof(oneofDouble = 150.0), | ||
KTestMessageProto3Oneof(oneofEnum = KTestMessagesProto3Enum.KNestedEnum.BAR), | ||
).forEach { message -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than testing all types in a single function it would make sense to have the inner loop in a separate function and just have separate test functions for the different data members. This would help with testing individual types, and brings more visibility (each actual test function would just call the actual implementation with the message as parameter). It would also allow testing each type even in case of some failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with that. This would allow to determine what exact instance of KTestMessageProto3Oneof
caused failure.
Or, If you prefer a different way, you can add an assertion message to each assertion, but this looks much more boilerplate-ish.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to reduce boilerplate by creating some verification functions. Let me know how it looks now.
assertEquals(message.optionalInt32, restored.optionalInt32) | ||
assertEquals(message.optionalInt64, restored.optionalInt64) | ||
assertEquals(message.optionalUint32, restored.optionalUint32.toUInt()) | ||
assertEquals(message.optionalUint64, restored.optionalUint64.toULong()) | ||
assertEquals(message.optionalSint32, restored.optionalSint32) | ||
assertEquals(message.optionalSint64, restored.optionalSint64) | ||
assertEquals(message.optionalFixed32, restored.optionalFixed32) | ||
assertEquals(message.optionalFixed64, restored.optionalFixed64) | ||
assertEquals(message.optionalSfixed32, restored.optionalSfixed32) | ||
assertEquals(message.optionalSfixed64, restored.optionalSfixed64) | ||
assertEquals(message.optionalFloat, restored.optionalFloat) | ||
assertEquals(message.optionalDouble, restored.optionalDouble) | ||
assertEquals(message.optionalBool, restored.optionalBool) | ||
assertEquals(message.optionalString, restored.optionalString) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you are already comparing the full message below these comparisons seem double.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should have compared the fields with the serialized one rather than the restored.
Sometimes message can be serialized and deserialized it might be the same but the serialization format might be different so if deserialized by another library it can be something else. This is most obvious with signed ints (i.e. it appears as 2*int - 1)
My intention was to catch this serialized format check.
assertContentEquals(message.optionalBytes, restored.optionalBytes.toByteArray()) | ||
|
||
val restoredMessage = ProtoBuf.decodeFromByteArray<KTestMessagesProto3Primitive>(restored.toByteArray()) | ||
assertEquals(message, restoredMessage.copy(optionalBytes = message.optionalBytes)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may add a comment on what you are doing here (compensating for the fact that you didn't provide an equals implementation for the message type).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, a comment would be nice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, added where I do this trick.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Just fix the minor issues I've mentioned, and we can merge this.
assertContentEquals(message.optionalBytes, restored.optionalBytes.toByteArray()) | ||
|
||
val restoredMessage = ProtoBuf.decodeFromByteArray<KTestMessagesProto3Primitive>(restored.toByteArray()) | ||
assertEquals(message, restoredMessage.copy(optionalBytes = message.optionalBytes)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, a comment would be nice
fun default() { | ||
listOf( | ||
KTestMessageProto3Oneof(oneofUint32 = 150u), | ||
KTestMessageProto3Oneof(oneofNestedMessage = KTestMessagesProto3Message.KNestedMessage(a = 150)), | ||
KTestMessageProto3Oneof(oneofString = "150"), | ||
KTestMessageProto3Oneof(oneofBytes = "150".toByteArray()), | ||
KTestMessageProto3Oneof(oneofBool = true), | ||
KTestMessageProto3Oneof(oneofUint64 = 150uL), | ||
KTestMessageProto3Oneof(oneofFloat = 150f), | ||
KTestMessageProto3Oneof(oneofDouble = 150.0), | ||
KTestMessageProto3Oneof(oneofEnum = KTestMessagesProto3Enum.KNestedEnum.BAR), | ||
).forEach { message -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with that. This would allow to determine what exact instance of KTestMessageProto3Oneof
caused failure.
Or, If you prefer a different way, you can add an assertion message to each assertion, but this looks much more boilerplate-ish.
Thanks. It took me a bit of time to catch-up but fixed some stuff and ready for another round of review. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing job, thank you very much!
Includes the message type used to run conformance tests by Google.
My intention is to catch and demonstrate some serialization errors & missing features. Commented parts are proven to be non-working. Probably some tests can be improved by using generators and multiple iterations with edge cases.
A part of