-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Serialize (and deserialize) bool values #791
Changes from all commits
099d8b3
6dbfd5b
99204f4
74892fc
37d7c6c
5e390dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,26 @@ | |
* limitations under the License. | ||
*/ | ||
|
||
/* NB: proto bytes were created via: | ||
echo 'TEXT_FORMAT_PROTO' \ | ||
| ./build/external/protobuf/src/protobuf-build/src/protoc \ | ||
-I./Firestore/Protos/protos \ | ||
-I./build/external/protobuf/src/protobuf/src \ | ||
--encode=google.firestore.v1beta1.Value \ | ||
google/firestore/v1beta1/document.proto \ | ||
| hexdump -C | ||
* where TEXT_FORMAT_PROTO is the text format of the protobuf. (go/textformat). | ||
* | ||
* Examples: | ||
* - For null, TEXT_FORMAT_PROTO would be 'null_value: NULL_VALUE' and would | ||
* yield the bytes: { 0x58, 0x00 }. | ||
* - For true, TEXT_FORMAT_PROTO would be 'boolean_value: true' and would yield | ||
* the bytes { 0x08, 0x01 }. | ||
* | ||
* All uses are documented below, so search for TEXT_FORMAT_PROTO to find more | ||
* examples. | ||
*/ | ||
|
||
#include "Firestore/core/src/firebase/firestore/remote/serializer.h" | ||
|
||
#include <pb.h> | ||
|
@@ -80,18 +100,41 @@ TEST_F(SerializerTest, EncodesNullProtoToBytes) { | |
// sanity check (the _init_default above should set this to _NULL_VALUE) | ||
EXPECT_EQ(google_protobuf_NullValue_NULL_VALUE, proto.value.null_value); | ||
|
||
/* NB: proto bytes were created via: | ||
echo 'null_value: NULL_VALUE' \ | ||
| ./build/external/protobuf/src/protobuf-build/src/protoc \ | ||
-I./Firestore/Protos/protos \ | ||
-I./build/external/protobuf/src/protobuf/src/ \ | ||
--encode=google.firestore.v1beta1.Value \ | ||
google/firestore/v1beta1/document.proto \ | ||
> output.bin | ||
*/ | ||
// TEXT_FORMAT_PROTO: 'null_value: NULL_VALUE' | ||
std::vector<uint8_t> bytes{0x58, 0x00}; | ||
ExpectRoundTrip(proto, bytes, FieldValue::Type::Null); | ||
} | ||
|
||
TEST_F(SerializerTest, EncodesBoolModelToProto) { | ||
for (bool test : {true, false}) { | ||
FieldValue model = FieldValue::BooleanValue(test); | ||
Serializer::TypedValue proto{FieldValue::Type::Boolean, | ||
google_firestore_v1beta1_Value_init_default}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Continuing the discussion from the previous PR: why does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It doesn't. It's done this way for symmetry with the underlying nanopb struct. We could add some ctors/etc, but we do still need to work with the underlying nanopb POD, so I don't think that's going to buy us very much. Additionally, there (probably) won't be wrappers for the other nanopb protos. (The only reason this one exists is because of the oneof within the proto.) So code that uses this has to deal with nanopb POD structs anyways. (All that said, I don't object to converting it. Though that path may lead us to wrapping all of nanopbs structs.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In general, I think it's preferable to have higher-level code, unless there is a specific reason not to. So in this case, hiding the Why would this lead to wrapping other nanopb structs? Is it for symmetry? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Discussed offline. Summary:
Decision: Defer for now. (But others are welcome to chime in.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SGTM to defer; I'd make the argument that we can deviate from convention if it keeps us from repeating code too much. We can also just wrap these in local functions if we find ourselves repeating this incantation too often in tests. |
||
proto.value.boolean_value = test; | ||
ExpectRoundTrip(model, proto, FieldValue::Type::Boolean); | ||
} | ||
} | ||
|
||
TEST_F(SerializerTest, EncodesBoolProtoToBytes) { | ||
struct TestCase { | ||
bool value; | ||
std::vector<uint8_t> bytes; | ||
}; | ||
|
||
std::vector<TestCase> cases{// TEXT_FORMAT_PROTO: 'boolean_value: true' | ||
{true, {0x08, 0x01}}, | ||
// TEXT_FORMAT_PROTO: 'boolean_value: false' | ||
{false, {0x08, 0x00}}}; | ||
|
||
for (const TestCase& test : cases) { | ||
Serializer::TypedValue proto{FieldValue::Type::Boolean, | ||
google_firestore_v1beta1_Value_init_default}; | ||
proto.value.boolean_value = test.value; | ||
ExpectRoundTrip(proto, test.bytes, FieldValue::Type::Boolean); | ||
} | ||
} | ||
|
||
// TODO(rsgowman): Test [en|de]coding multiple protos into the same output | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. optional: death-test for decode invalid bytes? say, if there is data-corruption, I guess those should be caught by decoder. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, we'll definitely need that. Error handling's not there yet though, so I've just added a TODO for now. |
||
// vector. | ||
|
||
// TODO(rsgowman): Death test for decoding invalid bytes. |
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 wonder if we could wrap this up in a little script we just check in. Constructing this command-line is tedious (though perhaps that's just because of all the plus signs in the diff).
Perhaps even that script should run at the higher level and just run through the cases we care about.
Feel free to push back.
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.
In practice, constructing the command line is easy. (Just sweep your mouse over it... unless you're looking at a diff.) Also note the lack of '*' at the beginning of these lines to enable that.
Checking in a script would be reasonable. Alternatively, we could link the test suite (not the main sdk) against libprotobuf and use the normal protobuf api, or even the libprotobuf text format api to construct these protos.
i.e. driving the test from the script? So something like this:
I like that it wouldn't require us to record the raw bytes in the .cc file... but I'm less wild about driving the test from outside the normal mechanism. If we're going to build the bytes on the fly, I like linking libprotobuf better.
So I think our options are:
make test
runs it)(Either way, if we decide to do 2 or 3, I'll issue a followup PR rather than including in this one.)
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 didn't mean to change the way tests are run; I think that's a bridge too far. GoogleTest is our test runner and changing that is too painful. I can't imagine making this play nice with Xcode.
Option 3 (using the protobuf API) has some serious appeal but is probably the most work. I worry that encoding bytes directly works at this low a level but but is basically infeasible once you get up to the oneofs in e.g. StructuredQuery and friends.
We can proceed for now and switch to 3 once this approach proves impractical
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.
sg