void HexDecode(not_null<benchmark::State*> const state, not_null<bool*> const correct, std::vector<uint8_t> const& input_digits, std::vector<uint8_t> const& expected_bytes) { state->PauseTiming(); std::vector<uint8_t> bytes(input_digits.size() / 2); state->ResumeTiming(); HexadecimalDecode({input_digits.data(), input_digits.size()}, {bytes.data(), bytes.size()}); state->PauseTiming(); *correct &= bytes == expected_bytes; state->ResumeTiming(); }
// The caller takes ownership of |**plugin| when it is not null. No transfer of // ownership of |*serialization| or |**deserializer|. |*deserializer| and // |*plugin| must be null on the first call and must be passed unchanged to the // successive calls. The caller must perform an extra call with // |serialization_size| set to 0 to indicate the end of the input stream. When // this last call returns, |*plugin| is not null and may be used by the caller. void principia__DeserializePlugin(char const* const serialization, int const serialization_size, PushDeserializer** const deserializer, Plugin const** const plugin) { journal::Method<journal::DeserializePlugin> m({serialization, serialization_size, deserializer, plugin}, {deserializer, plugin}); LOG(INFO) << __FUNCTION__; CHECK_NOTNULL(serialization); CHECK_NOTNULL(deserializer); CHECK_NOTNULL(plugin); // Create and start a deserializer if the caller didn't provide one. if (*deserializer == nullptr) { *deserializer = new PushDeserializer(chunk_size, number_of_chunks); auto message = make_not_null_unique<serialization::Plugin>(); (*deserializer)->Start( std::move(message), [plugin](google::protobuf::Message const& message) { *plugin = Plugin::ReadFromMessage( static_cast<serialization::Plugin const&>(message)).release(); }); } // Decode the hexadecimal representation. uint8_t const* const hexadecimal = reinterpret_cast<uint8_t const*>(serialization); int const hexadecimal_size = serialization_size; int const byte_size = hexadecimal_size >> 1; // Ownership of the following pointer is transfered to the deserializer using // the callback to |Push|. std::uint8_t* bytes = new uint8_t[byte_size]; HexadecimalDecode({hexadecimal, hexadecimal_size}, {bytes, byte_size}); // Push the data, taking ownership of it. (*deserializer)->Push(Bytes(&bytes[0], byte_size), [bytes]() { delete[] bytes; }); // If the data was empty, delete the deserializer. This ensures that // |*plugin| is filled. if (byte_size == 0) { TakeOwnership(deserializer); } return m.Return(); }
TEST_F(PluginCompatibilityTest, PreBourbaki) { // Read the entire hex data. std::fstream file = std::fstream( SOLUTION_DIR / "ksp_plugin_test" / "pre_bourbaki.proto.hex"); CHECK(file.good()); std::string hex; while (!file.eof()) { std::string line; std::getline(file, line); for (auto const c : line) { if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) { hex.append(1, c); } } } file.close(); // Parse it and convert to binary data. UniqueBytes bin(hex.size() / 2); HexadecimalDecode(Array<std::uint8_t const>( reinterpret_cast<const std::uint8_t*>(hex.c_str()), hex.size()), bin.get()); // Construct a protocol buffer from the binary data. google::protobuf::io::CodedInputStream coded_input_stream( bin.data.get(), static_cast<int>(bin.size)); serialization::Plugin pre_bourbaki_serialized_plugin; CHECK(pre_bourbaki_serialized_plugin.MergeFromCodedStream( &coded_input_stream)); // Construct a plugin from the protocol buffer. auto plugin = TestablePlugin::ReadFromMessage(pre_bourbaki_serialized_plugin); // Do some operations on the plugin. plugin->KeepAllVessels(); plugin->AdvanceTime(plugin->current_time() + 1 * Second, 2 * Radian); plugin->AdvanceTime(plugin->current_time() + 1 * Hour, 3 * Radian); // Serialize and deserialize it in the new format. serialization::Plugin post_bourbaki_serialized_plugin; plugin->WriteToMessage(&post_bourbaki_serialized_plugin); plugin = TestablePlugin::ReadFromMessage(post_bourbaki_serialized_plugin); }