diff --git a/java/core/src/main/java/com/google/protobuf/Message.java b/java/core/src/main/java/com/google/protobuf/Message.java
index 3db1c771e6..f641739e32 100644
--- a/java/core/src/main/java/com/google/protobuf/Message.java
+++ b/java/core/src/main/java/com/google/protobuf/Message.java
@@ -39,11 +39,12 @@ import java.util.Map;
*
*
See also {@link MessageLite}, which defines most of the methods that typical users care about.
* {@link Message} adds methods that are not available in the "lite" runtime. The biggest added
- * features are introspection and reflection; that is, getting descriptors for the message type
- * and accessing the field values dynamically.
+ * features are introspection and reflection; that is, getting descriptors for the message type and
+ * accessing the field values dynamically.
*
* @author kenton@google.com Kenton Varda
*/
+@CheckReturnValue
public interface Message extends MessageLite, MessageOrBuilder {
// (From MessageLite, re-declared here only for return type covariance.)
@@ -102,6 +103,7 @@ public interface Message extends MessageLite, MessageOrBuilder {
// (From MessageLite.Builder, re-declared here only for return type
// covariance.)
@Override
+ @CanIgnoreReturnValue
Builder clear();
/**
@@ -121,6 +123,7 @@ public interface Message extends MessageLite, MessageOrBuilder {
*
*
This is equivalent to the {@code Message::MergeFrom} method in C++.
*/
+ @CanIgnoreReturnValue
Builder mergeFrom(Message other);
// (From MessageLite.Builder, re-declared here only for return type
@@ -135,9 +138,11 @@ public interface Message extends MessageLite, MessageOrBuilder {
Builder clone();
@Override
+ @CanIgnoreReturnValue
Builder mergeFrom(CodedInputStream input) throws IOException;
@Override
+ @CanIgnoreReturnValue
Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
throws IOException;
@@ -190,18 +195,21 @@ public interface Message extends MessageLite, MessageOrBuilder {
* Sets a field to the given value. The value must be of the correct type for this field, that
* is, the same type that {@link Message#getField(Descriptors.FieldDescriptor)} returns.
*/
+ @CanIgnoreReturnValue
Builder setField(Descriptors.FieldDescriptor field, Object value);
/**
* Clears the field. This is exactly equivalent to calling the generated "clear" accessor method
* corresponding to the field.
*/
+ @CanIgnoreReturnValue
Builder clearField(Descriptors.FieldDescriptor field);
/**
* Clears the oneof. This is exactly equivalent to calling the generated "clear" accessor method
* corresponding to the oneof.
*/
+ @CanIgnoreReturnValue
Builder clearOneof(Descriptors.OneofDescriptor oneof);
/**
@@ -212,6 +220,7 @@ public interface Message extends MessageLite, MessageOrBuilder {
* @throws IllegalArgumentException if the field is not a repeated field, or {@code
* field.getContainingType() != getDescriptorForType()}.
*/
+ @CanIgnoreReturnValue
Builder setRepeatedField(Descriptors.FieldDescriptor field, int index, Object value);
/**
@@ -220,12 +229,15 @@ public interface Message extends MessageLite, MessageOrBuilder {
* @throws IllegalArgumentException if the field is not a repeated field, or {@code
* field.getContainingType() != getDescriptorForType()}
*/
+ @CanIgnoreReturnValue
Builder addRepeatedField(Descriptors.FieldDescriptor field, Object value);
/** Set the {@link UnknownFieldSet} for this message. */
+ @CanIgnoreReturnValue
Builder setUnknownFields(UnknownFieldSet unknownFields);
/** Merge some unknown fields into the {@link UnknownFieldSet} for this message. */
+ @CanIgnoreReturnValue
Builder mergeUnknownFields(UnknownFieldSet unknownFields);
// ---------------------------------------------------------------
@@ -234,30 +246,38 @@ public interface Message extends MessageLite, MessageOrBuilder {
// (From MessageLite.Builder, re-declared here only for return type
// covariance.)
@Override
+ @CanIgnoreReturnValue
Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
@Override
+ @CanIgnoreReturnValue
Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException;
@Override
+ @CanIgnoreReturnValue
Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
@Override
+ @CanIgnoreReturnValue
Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException;
@Override
+ @CanIgnoreReturnValue
Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException;
@Override
+ @CanIgnoreReturnValue
Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException;
@Override
+ @CanIgnoreReturnValue
Builder mergeFrom(InputStream input) throws IOException;
@Override
+ @CanIgnoreReturnValue
Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
throws IOException;
diff --git a/java/core/src/main/java/com/google/protobuf/MessageLite.java b/java/core/src/main/java/com/google/protobuf/MessageLite.java
index 8c172eef8c..d6314691be 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageLite.java
@@ -344,7 +344,6 @@ public interface MessageLite extends MessageLiteOrBuilder {
* a protobuf in the first place.
* @throws IOException an I/O error reading from the stream
*/
- @CanIgnoreReturnValue // TODO(kak): should this be @CheckReturnValue instead?
boolean mergeDelimitedFrom(InputStream input) throws IOException;
/**
@@ -357,7 +356,6 @@ public interface MessageLite extends MessageLiteOrBuilder {
* a protobuf in the first place.
* @throws IOException an I/O error reading from the stream
*/
- @CanIgnoreReturnValue // TODO(kak): should this be @CheckReturnValue instead?
boolean mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
throws IOException;
}
diff --git a/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java b/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java
index 0254df99ac..2a4d867ae1 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java
@@ -39,6 +39,7 @@ import java.util.Map;
*
* @author jonp@google.com (Jon Perlow)
*/
+@CheckReturnValue
public interface MessageOrBuilder extends MessageLiteOrBuilder {
// (From MessageLite, re-declared here only for return type covariance.)
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
index bd1df8cc77..3671c31a66 100644
--- a/python/google/protobuf/internal/message_test.py
+++ b/python/google/protobuf/internal/message_test.py
@@ -34,10 +34,6 @@
Note that the golden messages exercise every known field type, thus this
test ends up exercising and verifying nearly all of the parsing and
serialization code in the whole library.
-
-TODO(kenton): Merge with wire_format_test? It doesn't make a whole lot of
-sense to call this a test of the "message" module, which only declares an
-abstract interface.
"""
__author__ = 'gps@google.com (Gregory P. Smith)'
@@ -476,6 +472,12 @@ class MessageTest(unittest.TestCase):
'}\n')
self.assertEqual(sub_msg.bb, 1)
+ def testAssignRepeatedField(self, message_module):
+ msg = message_module.NestedTestAllTypes()
+ msg.payload.repeated_int32[:] = [1, 2, 3, 4]
+ self.assertEqual(4, len(msg.payload.repeated_int32))
+ self.assertEqual([1, 2, 3, 4], msg.payload.repeated_int32)
+
def testMergeFromRepeatedField(self, message_module):
msg = message_module.TestAllTypes()
msg.repeated_int32.append(1)
diff --git a/src/google/protobuf/message_unittest.inc b/src/google/protobuf/message_unittest.inc
index 19cc9c1486..7526ead779 100644
--- a/src/google/protobuf/message_unittest.inc
+++ b/src/google/protobuf/message_unittest.inc
@@ -422,6 +422,25 @@ TEST(MESSAGE_TEST_NAME, ParseFailsIfExtensionWireMalformed) {
EXPECT_FALSE(p.ParseFromString(serialized));
}
+TEST(MESSAGE_TEST_NAME, ParseFailsIfGroupFieldMalformed) {
+ UNITTEST::TestMutualRecursionA original, parsed;
+ original.mutable_bb()
+ ->mutable_a()
+ ->mutable_subgroup()
+ ->mutable_sub_message()
+ ->mutable_b()
+ ->set_optional_int32(-1);
+
+ std::string data;
+ ASSERT_TRUE(original.SerializeToString(&data));
+ // Should parse correctly.
+ ASSERT_TRUE(parsed.ParseFromString(data));
+ // Overwriting the last byte of varint (-1) to 0xFF results in malformed wire.
+ data[data.size() - 2] = 0xFF;
+
+ EXPECT_FALSE(parsed.ParseFromString(data));
+}
+
TEST(MESSAGE_TEST_NAME, UninitializedAndMalformed) {
UNITTEST::TestRequiredForeign o, p1, p2;
o.mutable_optional_message()->set_a(-1);
diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc
index d534411b63..b32cda8ca2 100644
--- a/src/google/protobuf/port_def.inc
+++ b/src/google/protobuf/port_def.inc
@@ -865,6 +865,8 @@
// Inconvenient macro names from usr/include/sys/syslimits.h in some macOS SDKs.
#pragma push_macro("UID_MAX")
#undef UID_MAX
+#pragma push_macro("GID_MAX")
+#undef GID_MAX
#endif // __APPLE__
#if defined(__clang__) || PROTOBUF_GNUC_MIN(3, 0) || defined(_MSC_VER)
diff --git a/src/google/protobuf/port_undef.inc b/src/google/protobuf/port_undef.inc
index e880fa5c59..f8968d9a86 100644
--- a/src/google/protobuf/port_undef.inc
+++ b/src/google/protobuf/port_undef.inc
@@ -144,6 +144,7 @@
#pragma pop_macro("TRUE")
#pragma pop_macro("FALSE")
#pragma pop_macro("UID_MAX")
+#pragma pop_macro("GID_MAX")
#endif // __APPLE__
#if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER)
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 730b06708c..a74832f787 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -454,8 +454,13 @@ class RepeatedField final {
//
// Typically, due to the fact that adder is a local stack variable, the
// compiler will be successful in mem-to-reg transformation and the machine
- // code will be loop: cmp %size, %capacity jae fallback mov dword ptr [%buffer
- // + %size * 4], %val inc %size jmp loop
+ // code will be
+ // loop:
+ // cmp %size, %capacity
+ // jae fallback
+ // mov dword ptr [%buffer + %size * 4], %val
+ // inc %size
+ // jmp loop
//
// The first version executes at 7 cycles per iteration while the second
// version executes at only 1 or 2 cycles.
@@ -467,6 +472,8 @@ class RepeatedField final {
capacity_ = repeated_field_->total_size_;
buffer_ = repeated_field_->unsafe_elements();
}
+ FastAdderImpl(const FastAdderImpl&) = delete;
+ FastAdderImpl& operator=(const FastAdderImpl&) = delete;
~FastAdderImpl() { repeated_field_->current_size_ = index_; }
void Add(Element val) {
@@ -484,8 +491,6 @@ class RepeatedField final {
int index_;
int capacity_;
Element* buffer_;
-
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastAdderImpl);
};
// FastAdder is a wrapper for adding fields. The specialization above handles
@@ -494,11 +499,12 @@ class RepeatedField final {
class FastAdderImpl {
public:
explicit FastAdderImpl(RepeatedField* rf) : repeated_field_(rf) {}
+ FastAdderImpl(const FastAdderImpl&) = delete;
+ FastAdderImpl& operator=(const FastAdderImpl&) = delete;
void Add(const Element& val) { repeated_field_->Add(val); }
private:
RepeatedField* repeated_field_;
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastAdderImpl);
};
using FastAdder = FastAdderImpl<>;
diff --git a/src/google/protobuf/stubs/status_macros.h b/src/google/protobuf/stubs/status_macros.h
index 407ff4c280..5a2cbf06ae 100644
--- a/src/google/protobuf/stubs/status_macros.h
+++ b/src/google/protobuf/stubs/status_macros.h
@@ -37,9 +37,14 @@
#include
#include
+#include
+
namespace google {
namespace protobuf {
namespace util {
+namespace status_macros_internal {
+using PROTOBUF_NAMESPACE_ID::util::Status;
+} // namespace status_macros_internal
// Run a command that returns a util::Status. If the called code returns an
// error status, return that status up out of this method too.
@@ -49,7 +54,8 @@ namespace util {
#define RETURN_IF_ERROR(expr) \
do { \
/* Using _status below to avoid capture problems if expr is "status". */ \
- const PROTOBUF_NAMESPACE_ID::util::Status _status = (expr); \
+ const ::google::protobuf::util::status_macros_internal::Status _status = \
+ (expr); \
if (PROTOBUF_PREDICT_FALSE(!_status.ok())) return _status; \
} while (0)
@@ -57,7 +63,7 @@ namespace util {
#define STATUS_MACROS_CONCAT_NAME_INNER(x, y) x##y
#define STATUS_MACROS_CONCAT_NAME(x, y) STATUS_MACROS_CONCAT_NAME_INNER(x, y)
-template
+template
Status DoAssignOrReturn(T& lhs, StatusOr result) {
if (result.ok()) {
lhs = result.value();
@@ -79,11 +85,13 @@ Status DoAssignOrReturn(T& lhs, StatusOr result) {
// WARNING: ASSIGN_OR_RETURN expands into multiple statements; it cannot be used
// in a single statement (e.g. as the body of an if statement without {})!
#define ASSIGN_OR_RETURN(lhs, rexpr) \
- ASSIGN_OR_RETURN_IMPL( \
+ ASSIGN_OR_RETURN_IMPL( \
STATUS_MACROS_CONCAT_NAME(_status_or_value, __COUNTER__), lhs, rexpr);
} // namespace util
} // namespace protobuf
} // namespace google
+#include
+
#endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_
diff --git a/src/google/protobuf/stubs/statusor.h b/src/google/protobuf/stubs/statusor.h
index 20e603ea04..1ec748d1fc 100644
--- a/src/google/protobuf/stubs/statusor.h
+++ b/src/google/protobuf/stubs/statusor.h
@@ -72,12 +72,13 @@
#ifndef GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
#define GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
+#include
+
#include
#include
#include
-#include
-
+// Must be included last.
#include
namespace google {
@@ -85,9 +86,10 @@ namespace protobuf {
namespace util {
namespace statusor_internal {
-template
+template
class StatusOr {
- template friend class StatusOr;
+ template
+ friend class StatusOr;
public:
using value_type = T;
@@ -125,14 +127,14 @@ class StatusOr {
StatusOr(const StatusOr& other);
// Conversion copy constructor, T must be copy constructible from U
- template
+ template
StatusOr(const StatusOr& other);
// Assignment operator.
StatusOr& operator=(const StatusOr& other);
// Conversion assignment operator, T must be assignable from U
- template
+ template
StatusOr& operator=(const StatusOr& other);
// Returns a reference to our status. If this contains a T, then
@@ -143,7 +145,14 @@ class StatusOr {
bool ok() const;
// Returns a reference to our current value, or CHECK-fails if !this->ok().
- const T& value () const;
+ const T& value() const;
+ T& value();
+
+ // Returns a reference to our current value; UB if not OK.
+ const T& operator*() const { return value(); }
+ T& operator*() { return value(); }
+ const T* operator->() const { return &value(); }
+ T* operator->() { return &value(); }
private:
Status status_;
@@ -159,17 +168,17 @@ class PROTOBUF_EXPORT StatusOrHelper {
static void Crash(const util::Status& status);
// Customized behavior for StatusOr vs. StatusOr
- template
+ template
struct Specialize;
};
-template
+template
struct StatusOrHelper::Specialize {
// For non-pointer T, a reference can never be nullptr.
static inline bool IsValueNull(const T& /*t*/) { return false; }
};
-template
+template
struct StatusOrHelper::Specialize {
static inline bool IsValueNull(const T* t) { return t == nullptr; }
};
@@ -177,7 +186,7 @@ struct StatusOrHelper::Specialize {
template
inline StatusOr::StatusOr() : status_(util::UnknownError("")) {}
-template
+template
inline StatusOr::StatusOr(const Status& status) {
if (status.ok()) {
status_ = util::InternalError("OkStatus() is not a valid argument.");
@@ -186,7 +195,7 @@ inline StatusOr::StatusOr(const Status& status) {
}
}
-template
+template
inline StatusOr::StatusOr(const T& value) {
if (StatusOrHelper::Specialize::IsValueNull(value)) {
status_ = util::InternalError("nullptr is not a valid argument.");
@@ -196,43 +205,41 @@ inline StatusOr::StatusOr(const T& value) {
}
}
-template
+template
inline StatusOr::StatusOr(const StatusOr& other)
- : status_(other.status_), value_(other.value_) {
-}
+ : status_(other.status_), value_(other.value_) {}
-template
+template
inline StatusOr& StatusOr::operator=(const StatusOr& other) {
status_ = other.status_;
value_ = other.value_;
return *this;
}
-template
-template
+template
+template
inline StatusOr::StatusOr(const StatusOr& other)
- : status_(other.status_), value_(other.status_.ok() ? other.value_ : T()) {
-}
+ : status_(other.status_), value_(other.status_.ok() ? other.value_ : T()) {}
-template
-template
+template
+template
inline StatusOr& StatusOr::operator=(const StatusOr& other) {
status_ = other.status_;
if (status_.ok()) value_ = other.value_;
return *this;
}
-template
+template
inline const Status& StatusOr::status() const {
return status_;
}
-template
+template
inline bool StatusOr::ok() const {
return status().ok();
}
-template
+template
inline const T& StatusOr::value() const {
if (!status_.ok()) {
StatusOrHelper::Crash(status_);
@@ -240,6 +247,13 @@ inline const T& StatusOr::value() const {
return value_;
}
+template
+inline T& StatusOr::value() {
+ if (!status_.ok()) {
+ StatusOrHelper::Crash(status_);
+ }
+ return value_;
+}
} // namespace statusor_internal
using ::google::protobuf::util::statusor_internal::StatusOr;
diff --git a/src/google/protobuf/stubs/statusor_test.cc b/src/google/protobuf/stubs/statusor_test.cc
index 403adcc0b6..17c9a4dee2 100644
--- a/src/google/protobuf/stubs/statusor_test.cc
+++ b/src/google/protobuf/stubs/statusor_test.cc
@@ -87,6 +87,16 @@ TEST(StatusOr, TestValueCtor) {
EXPECT_EQ(kI, thing.value());
}
+TEST(StatusOr, TestPtrOps) {
+ const int kI = 4;
+ StatusOr thing(kI);
+ EXPECT_TRUE(thing.ok());
+ EXPECT_EQ(kI, *thing);
+
+ StatusOr> thing2(thing);
+ EXPECT_EQ(kI, thing2->value());
+}
+
TEST(StatusOr, TestCopyCtorStatusOk) {
const int kI = 4;
StatusOr original(kI);
diff --git a/src/google/protobuf/unittest_mset.proto b/src/google/protobuf/unittest_mset.proto
index dd8a3afbf4..fd6aaa568a 100644
--- a/src/google/protobuf/unittest_mset.proto
+++ b/src/google/protobuf/unittest_mset.proto
@@ -55,6 +55,7 @@ message NestedTestMessageSetContainer {
message NestedTestInt {
optional fixed32 a = 1;
+ optional int32 b = 3;
optional NestedTestInt child = 2;
}
diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc
index ac9408d8cc..a8b68a3c76 100644
--- a/src/google/protobuf/util/json_util_test.cc
+++ b/src/google/protobuf/util/json_util_test.cc
@@ -30,11 +30,16 @@
#include
+#include
#include
-#include
#include
+#include
+#include
#include
+#include
+#include
+#include
#include
#include
#include
@@ -42,161 +47,177 @@
#include
#include
#include
+#include
#include
#include
+#include
+
+// Must be included last.
+#include
namespace google {
namespace protobuf {
namespace util {
namespace {
-using proto3::BAR;
-using proto3::FOO;
-using proto3::TestAny;
-using proto3::TestEnumValue;
-using proto3::TestMap;
-using proto3::TestMessage;
-using proto3::TestOneof;
-using proto_util_converter::testing::MapIn;
+using ::proto3::TestAny;
+using ::proto3::TestEnumValue;
+using ::proto3::TestMap;
+using ::proto3::TestMessage;
+using ::proto3::TestOneof;
+using ::proto_util_converter::testing::MapIn;
+
+// TODO(b/234474291): Use the gtest versions once that's available in OSS.
+MATCHER_P(IsOkAndHolds, inner,
+ StrCat("is OK and holds ", testing::PrintToString(inner))) {
+ if (!arg.ok()) {
+ *result_listener << arg.status();
+ return false;
+ }
+ return testing::ExplainMatchResult(inner, *arg, result_listener);
+}
+
+util::Status GetStatus(const util::Status& s) { return s; }
+template
+util::Status GetStatus(const util::StatusOr& s) {
+ return s.status();
+}
+
+MATCHER_P(StatusIs, status,
+ StrCat(".status() is ", testing::PrintToString(status))) {
+ return GetStatus(arg).code() == status;
+}
+
+#define EXPECT_OK(x) EXPECT_THAT(x, StatusIs(util::StatusCode::kOk))
+#define ASSERT_OK(x) ASSERT_THAT(x, StatusIs(util::StatusCode::kOk))
// As functions defined in json_util.h are just thin wrappers around the
// JSON conversion code in //net/proto2/util/converter, in this test we
// only cover some very basic cases to make sure the wrappers have forwarded
// parameters to the underlying implementation correctly. More detailed
// tests are contained in the //net/proto2/util/converter directory.
-class JsonUtilTest : public ::testing::Test {
- protected:
- JsonUtilTest() {}
-
- std::string ToJson(const Message& message, const JsonPrintOptions& options) {
- std::string result;
- GOOGLE_CHECK_OK(MessageToJsonString(message, &result, options));
- return result;
- }
- bool FromJson(const std::string& json, Message* message,
- const JsonParseOptions& options) {
- return JsonStringToMessage(json, message, options).ok();
- }
-
- bool FromJson(const std::string& json, Message* message) {
- return FromJson(json, message, JsonParseOptions());
- }
+util::StatusOr ToJson(const Message& message,
+ const JsonPrintOptions& options = {}) {
+ std::string result;
+ RETURN_IF_ERROR(MessageToJsonString(message, &result, options));
+ return result;
+}
- std::unique_ptr resolver_;
-};
+util::Status FromJson(StringPiece json, Message* message,
+ const JsonParseOptions& options = {}) {
+ return JsonStringToMessage(json, message, options);
+}
-TEST_F(JsonUtilTest, TestWhitespaces) {
+TEST(JsonUtilTest, TestWhitespaces) {
TestMessage m;
m.mutable_message_value();
+ EXPECT_THAT(ToJson(m), IsOkAndHolds("{\"messageValue\":{}}"));
+
JsonPrintOptions options;
- EXPECT_EQ("{\"messageValue\":{}}", ToJson(m, options));
options.add_whitespace = true;
- EXPECT_EQ(
- "{\n"
- " \"messageValue\": {}\n"
- "}\n",
- ToJson(m, options));
+ EXPECT_THAT(ToJson(m, options), IsOkAndHolds("{\n"
+ " \"messageValue\": {}\n"
+ "}\n"));
}
-TEST_F(JsonUtilTest, TestDefaultValues) {
+TEST(JsonUtilTest, TestDefaultValues) {
TestMessage m;
+ EXPECT_THAT(ToJson(m), IsOkAndHolds("{}"));
+
JsonPrintOptions options;
- EXPECT_EQ("{}", ToJson(m, options));
options.always_print_primitive_fields = true;
- EXPECT_EQ(
- "{\"boolValue\":false,"
- "\"int32Value\":0,"
- "\"int64Value\":\"0\","
- "\"uint32Value\":0,"
- "\"uint64Value\":\"0\","
- "\"floatValue\":0,"
- "\"doubleValue\":0,"
- "\"stringValue\":\"\","
- "\"bytesValue\":\"\","
- "\"enumValue\":\"FOO\","
- "\"repeatedBoolValue\":[],"
- "\"repeatedInt32Value\":[],"
- "\"repeatedInt64Value\":[],"
- "\"repeatedUint32Value\":[],"
- "\"repeatedUint64Value\":[],"
- "\"repeatedFloatValue\":[],"
- "\"repeatedDoubleValue\":[],"
- "\"repeatedStringValue\":[],"
- "\"repeatedBytesValue\":[],"
- "\"repeatedEnumValue\":[],"
- "\"repeatedMessageValue\":[]"
- "}",
- ToJson(m, options));
+ EXPECT_THAT(ToJson(m, options), IsOkAndHolds("{\"boolValue\":false,"
+ "\"int32Value\":0,"
+ "\"int64Value\":\"0\","
+ "\"uint32Value\":0,"
+ "\"uint64Value\":\"0\","
+ "\"floatValue\":0,"
+ "\"doubleValue\":0,"
+ "\"stringValue\":\"\","
+ "\"bytesValue\":\"\","
+ "\"enumValue\":\"FOO\","
+ "\"repeatedBoolValue\":[],"
+ "\"repeatedInt32Value\":[],"
+ "\"repeatedInt64Value\":[],"
+ "\"repeatedUint32Value\":[],"
+ "\"repeatedUint64Value\":[],"
+ "\"repeatedFloatValue\":[],"
+ "\"repeatedDoubleValue\":[],"
+ "\"repeatedStringValue\":[],"
+ "\"repeatedBytesValue\":[],"
+ "\"repeatedEnumValue\":[],"
+ "\"repeatedMessageValue\":[]"
+ "}"));
options.always_print_primitive_fields = true;
m.set_string_value("i am a test string value");
m.set_bytes_value("i am a test bytes value");
- EXPECT_EQ(
- "{\"boolValue\":false,"
- "\"int32Value\":0,"
- "\"int64Value\":\"0\","
- "\"uint32Value\":0,"
- "\"uint64Value\":\"0\","
- "\"floatValue\":0,"
- "\"doubleValue\":0,"
- "\"stringValue\":\"i am a test string value\","
- "\"bytesValue\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\","
- "\"enumValue\":\"FOO\","
- "\"repeatedBoolValue\":[],"
- "\"repeatedInt32Value\":[],"
- "\"repeatedInt64Value\":[],"
- "\"repeatedUint32Value\":[],"
- "\"repeatedUint64Value\":[],"
- "\"repeatedFloatValue\":[],"
- "\"repeatedDoubleValue\":[],"
- "\"repeatedStringValue\":[],"
- "\"repeatedBytesValue\":[],"
- "\"repeatedEnumValue\":[],"
- "\"repeatedMessageValue\":[]"
- "}",
- ToJson(m, options));
+ EXPECT_THAT(
+ ToJson(m, options),
+ IsOkAndHolds("{\"boolValue\":false,"
+ "\"int32Value\":0,"
+ "\"int64Value\":\"0\","
+ "\"uint32Value\":0,"
+ "\"uint64Value\":\"0\","
+ "\"floatValue\":0,"
+ "\"doubleValue\":0,"
+ "\"stringValue\":\"i am a test string value\","
+ "\"bytesValue\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\","
+ "\"enumValue\":\"FOO\","
+ "\"repeatedBoolValue\":[],"
+ "\"repeatedInt32Value\":[],"
+ "\"repeatedInt64Value\":[],"
+ "\"repeatedUint32Value\":[],"
+ "\"repeatedUint64Value\":[],"
+ "\"repeatedFloatValue\":[],"
+ "\"repeatedDoubleValue\":[],"
+ "\"repeatedStringValue\":[],"
+ "\"repeatedBytesValue\":[],"
+ "\"repeatedEnumValue\":[],"
+ "\"repeatedMessageValue\":[]"
+ "}"));
options.preserve_proto_field_names = true;
m.set_string_value("i am a test string value");
m.set_bytes_value("i am a test bytes value");
- EXPECT_EQ(
- "{\"bool_value\":false,"
- "\"int32_value\":0,"
- "\"int64_value\":\"0\","
- "\"uint32_value\":0,"
- "\"uint64_value\":\"0\","
- "\"float_value\":0,"
- "\"double_value\":0,"
- "\"string_value\":\"i am a test string value\","
- "\"bytes_value\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\","
- "\"enum_value\":\"FOO\","
- "\"repeated_bool_value\":[],"
- "\"repeated_int32_value\":[],"
- "\"repeated_int64_value\":[],"
- "\"repeated_uint32_value\":[],"
- "\"repeated_uint64_value\":[],"
- "\"repeated_float_value\":[],"
- "\"repeated_double_value\":[],"
- "\"repeated_string_value\":[],"
- "\"repeated_bytes_value\":[],"
- "\"repeated_enum_value\":[],"
- "\"repeated_message_value\":[]"
- "}",
- ToJson(m, options));
+ EXPECT_THAT(
+ ToJson(m, options),
+ IsOkAndHolds("{\"bool_value\":false,"
+ "\"int32_value\":0,"
+ "\"int64_value\":\"0\","
+ "\"uint32_value\":0,"
+ "\"uint64_value\":\"0\","
+ "\"float_value\":0,"
+ "\"double_value\":0,"
+ "\"string_value\":\"i am a test string value\","
+ "\"bytes_value\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\","
+ "\"enum_value\":\"FOO\","
+ "\"repeated_bool_value\":[],"
+ "\"repeated_int32_value\":[],"
+ "\"repeated_int64_value\":[],"
+ "\"repeated_uint32_value\":[],"
+ "\"repeated_uint64_value\":[],"
+ "\"repeated_float_value\":[],"
+ "\"repeated_double_value\":[],"
+ "\"repeated_string_value\":[],"
+ "\"repeated_bytes_value\":[],"
+ "\"repeated_enum_value\":[],"
+ "\"repeated_message_value\":[]"
+ "}"));
}
-TEST_F(JsonUtilTest, TestPreserveProtoFieldNames) {
+TEST(JsonUtilTest, TestPreserveProtoFieldNames) {
TestMessage m;
m.mutable_message_value();
JsonPrintOptions options;
options.preserve_proto_field_names = true;
- EXPECT_EQ("{\"message_value\":{}}", ToJson(m, options));
+ EXPECT_THAT(ToJson(m, options), IsOkAndHolds("{\"message_value\":{}}"));
}
-TEST_F(JsonUtilTest, TestAlwaysPrintEnumsAsInts) {
+TEST(JsonUtilTest, TestAlwaysPrintEnumsAsInts) {
TestMessage orig;
orig.set_enum_value(proto3::BAR);
orig.add_repeated_enum_value(proto3::FOO);
@@ -205,20 +226,20 @@ TEST_F(JsonUtilTest, TestAlwaysPrintEnumsAsInts) {
JsonPrintOptions print_options;
print_options.always_print_enums_as_ints = true;
- std::string expected_json = "{\"enumValue\":1,\"repeatedEnumValue\":[0,1]}";
- EXPECT_EQ(expected_json, ToJson(orig, print_options));
+ auto printed = ToJson(orig, print_options);
+ ASSERT_THAT(printed,
+ IsOkAndHolds("{\"enumValue\":1,\"repeatedEnumValue\":[0,1]}"));
TestMessage parsed;
- JsonParseOptions parse_options;
- ASSERT_TRUE(FromJson(expected_json, &parsed, parse_options));
+ ASSERT_OK(FromJson(*printed, &parsed));
- EXPECT_EQ(proto3::BAR, parsed.enum_value());
- EXPECT_EQ(2, parsed.repeated_enum_value_size());
- EXPECT_EQ(proto3::FOO, parsed.repeated_enum_value(0));
- EXPECT_EQ(proto3::BAR, parsed.repeated_enum_value(1));
+ EXPECT_EQ(parsed.enum_value(), proto3::BAR);
+ EXPECT_EQ(parsed.repeated_enum_value_size(), 2);
+ EXPECT_EQ(parsed.repeated_enum_value(0), proto3::FOO);
+ EXPECT_EQ(parsed.repeated_enum_value(1), proto3::BAR);
}
-TEST_F(JsonUtilTest, TestPrintEnumsAsIntsWithDefaultValue) {
+TEST(JsonUtilTest, TestPrintEnumsAsIntsWithDefaultValue) {
TestEnumValue orig;
// orig.set_enum_value1(proto3::FOO)
orig.set_enum_value2(proto3::FOO);
@@ -228,20 +249,20 @@ TEST_F(JsonUtilTest, TestPrintEnumsAsIntsWithDefaultValue) {
print_options.always_print_enums_as_ints = true;
print_options.always_print_primitive_fields = true;
- std::string expected_json =
- "{\"enumValue1\":0,\"enumValue2\":0,\"enumValue3\":1}";
- EXPECT_EQ(expected_json, ToJson(orig, print_options));
+ auto printed = ToJson(orig, print_options);
+ ASSERT_THAT(
+ printed,
+ IsOkAndHolds("{\"enumValue1\":0,\"enumValue2\":0,\"enumValue3\":1}"));
TestEnumValue parsed;
- JsonParseOptions parse_options;
- ASSERT_TRUE(FromJson(expected_json, &parsed, parse_options));
+ ASSERT_OK(FromJson(*printed, &parsed));
- EXPECT_EQ(proto3::FOO, parsed.enum_value1());
- EXPECT_EQ(proto3::FOO, parsed.enum_value2());
- EXPECT_EQ(proto3::BAR, parsed.enum_value3());
+ EXPECT_EQ(parsed.enum_value1(), proto3::FOO);
+ EXPECT_EQ(parsed.enum_value2(), proto3::FOO);
+ EXPECT_EQ(parsed.enum_value3(), proto3::BAR);
}
-TEST_F(JsonUtilTest, TestPrintProto2EnumAsIntWithDefaultValue) {
+TEST(JsonUtilTest, TestPrintProto2EnumAsIntWithDefaultValue) {
protobuf_unittest::TestDefaultEnumValue orig;
JsonPrintOptions print_options;
@@ -250,111 +271,105 @@ TEST_F(JsonUtilTest, TestPrintProto2EnumAsIntWithDefaultValue) {
print_options.always_print_primitive_fields = true;
// result should be int rather than string
- std::string expected_json = "{\"enumValue\":2}";
- EXPECT_EQ(expected_json, ToJson(orig, print_options));
+ auto printed = ToJson(orig, print_options);
+ ASSERT_THAT(printed, IsOkAndHolds("{\"enumValue\":2}"));
protobuf_unittest::TestDefaultEnumValue parsed;
- JsonParseOptions parse_options;
- ASSERT_TRUE(FromJson(expected_json, &parsed, parse_options));
+ ASSERT_OK(FromJson(*printed, &parsed));
- EXPECT_EQ(protobuf_unittest::DEFAULT, parsed.enum_value());
+ EXPECT_EQ(parsed.enum_value(), protobuf_unittest::DEFAULT);
}
-TEST_F(JsonUtilTest, ParseMessage) {
+TEST(JsonUtilTest, ParseMessage) {
// Some random message but good enough to verify that the parsing wrapper
// functions are working properly.
- std::string input =
- "{\n"
- " \"int32Value\": 1234567891,\n"
- " \"int64Value\": 5302428716536692736,\n"
- " \"floatValue\": 3.4028235e+38,\n"
- " \"repeatedInt32Value\": [1, 2],\n"
- " \"messageValue\": {\n"
- " \"value\": 2048\n"
- " },\n"
- " \"repeatedMessageValue\": [\n"
- " {\"value\": 40}, {\"value\": 96}\n"
- " ]\n"
- "}\n";
- JsonParseOptions options;
TestMessage m;
- ASSERT_TRUE(FromJson(input, &m, options));
- EXPECT_EQ(1234567891, m.int32_value());
- EXPECT_EQ(5302428716536692736, m.int64_value());
- EXPECT_EQ(3.402823466e+38f, m.float_value());
- ASSERT_EQ(2, m.repeated_int32_value_size());
- EXPECT_EQ(1, m.repeated_int32_value(0));
- EXPECT_EQ(2, m.repeated_int32_value(1));
- EXPECT_EQ(2048, m.message_value().value());
- ASSERT_EQ(2, m.repeated_message_value_size());
- EXPECT_EQ(40, m.repeated_message_value(0).value());
- EXPECT_EQ(96, m.repeated_message_value(1).value());
+ ASSERT_OK(FromJson(R"json(
+ {
+ "int32Value": 1234567891,
+ "int64Value": 5302428716536692736,
+ "floatValue": 3.4028235e+38,
+ "repeatedInt32Value": [1, 2],
+ "messageValue": {
+ "value": 2048
+ },
+ "repeatedMessageValue": [
+ {"value": 40},
+ {"value": 96}
+ ]
+ }
+ )json",
+ &m));
+
+ EXPECT_EQ(m.int32_value(), 1234567891);
+ EXPECT_EQ(m.int64_value(), 5302428716536692736);
+ EXPECT_EQ(m.float_value(), 3.402823466e+38f);
+ ASSERT_EQ(m.repeated_int32_value_size(), 2);
+ EXPECT_EQ(m.repeated_int32_value(0), 1);
+ EXPECT_EQ(m.repeated_int32_value(1), 2);
+ EXPECT_EQ(m.message_value().value(), 2048);
+ ASSERT_EQ(m.repeated_message_value_size(), 2);
+ EXPECT_EQ(m.repeated_message_value(0).value(), 40);
+ EXPECT_EQ(m.repeated_message_value(1).value(), 96);
}
-TEST_F(JsonUtilTest, ParseMap) {
+TEST(JsonUtilTest, ParseMap) {
TestMap message;
(*message.mutable_string_map())["hello"] = 1234;
- JsonPrintOptions print_options;
- JsonParseOptions parse_options;
- EXPECT_EQ("{\"stringMap\":{\"hello\":1234}}", ToJson(message, print_options));
+ auto printed = ToJson(message);
+ ASSERT_THAT(printed, IsOkAndHolds("{\"stringMap\":{\"hello\":1234}}"));
+
TestMap other;
- ASSERT_TRUE(FromJson(ToJson(message, print_options), &other, parse_options));
- EXPECT_EQ(message.DebugString(), other.DebugString());
+ ASSERT_OK(FromJson(*printed, &other));
+ EXPECT_EQ(other.DebugString(), message.DebugString());
}
-TEST_F(JsonUtilTest, ParsePrimitiveMapIn) {
+TEST(JsonUtilTest, ParsePrimitiveMapIn) {
MapIn message;
JsonPrintOptions print_options;
print_options.always_print_primitive_fields = true;
- JsonParseOptions parse_options;
- EXPECT_EQ("{\"other\":\"\",\"things\":[],\"mapInput\":{},\"mapAny\":{}}",
- ToJson(message, print_options));
+ auto printed = ToJson(message, print_options);
+ ASSERT_THAT(
+ ToJson(message, print_options),
+ IsOkAndHolds(
+ "{\"other\":\"\",\"things\":[],\"mapInput\":{},\"mapAny\":{}}"));
+
MapIn other;
- ASSERT_TRUE(FromJson(ToJson(message, print_options), &other, parse_options));
- EXPECT_EQ(message.DebugString(), other.DebugString());
+ ASSERT_OK(FromJson(*printed, &other));
+ EXPECT_EQ(other.DebugString(), message.DebugString());
}
-TEST_F(JsonUtilTest, PrintPrimitiveOneof) {
+TEST(JsonUtilTest, PrintPrimitiveOneof) {
TestOneof message;
JsonPrintOptions options;
options.always_print_primitive_fields = true;
message.mutable_oneof_message_value();
- EXPECT_EQ("{\"oneofMessageValue\":{\"value\":0}}", ToJson(message, options));
+ EXPECT_THAT(ToJson(message, options),
+ IsOkAndHolds("{\"oneofMessageValue\":{\"value\":0}}"));
message.set_oneof_int32_value(1);
- EXPECT_EQ("{\"oneofInt32Value\":1}", ToJson(message, options));
+ EXPECT_THAT(ToJson(message, options),
+ IsOkAndHolds("{\"oneofInt32Value\":1}"));
}
-TEST_F(JsonUtilTest, TestParseIgnoreUnknownFields) {
+TEST(JsonUtilTest, TestParseIgnoreUnknownFields) {
TestMessage m;
JsonParseOptions options;
options.ignore_unknown_fields = true;
- EXPECT_TRUE(FromJson("{\"unknownName\":0}", &m, options));
+ EXPECT_OK(FromJson("{\"unknownName\":0}", &m, options));
}
-TEST_F(JsonUtilTest, TestParseErrors) {
+TEST(JsonUtilTest, TestParseErrors) {
TestMessage m;
- JsonParseOptions options;
// Parsing should fail if the field name can not be recognized.
- EXPECT_FALSE(FromJson("{\"unknownName\":0}", &m, options));
+ EXPECT_THAT(FromJson(R"json({"unknownName": 0})json", &m),
+ StatusIs(util::StatusCode::kInvalidArgument));
// Parsing should fail if the value is invalid.
- EXPECT_FALSE(FromJson("{\"int32Value\":2147483648}", &m, options));
+ EXPECT_THAT(FromJson(R"json("{"int32Value": 2147483648})json", &m),
+ StatusIs(util::StatusCode::kInvalidArgument));
}
-TEST_F(JsonUtilTest, TestDynamicMessage) {
- // Some random message but good enough to test the wrapper functions.
- std::string input =
- "{\n"
- " \"int32Value\": 1024,\n"
- " \"repeatedInt32Value\": [1, 2],\n"
- " \"messageValue\": {\n"
- " \"value\": 2048\n"
- " },\n"
- " \"repeatedMessageValue\": [\n"
- " {\"value\": 40}, {\"value\": 96}\n"
- " ]\n"
- "}\n";
-
+TEST(JsonUtilTest, TestDynamicMessage) {
// Create a new DescriptorPool with the same protos as the generated one.
DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
DescriptorPool pool(&database);
@@ -363,218 +378,223 @@ TEST_F(JsonUtilTest, TestDynamicMessage) {
std::unique_ptr message(
factory.GetPrototype(pool.FindMessageTypeByName("proto3.TestMessage"))
->New());
- EXPECT_TRUE(FromJson(input, message.get()));
+ EXPECT_OK(FromJson(R"json(
+ {
+ "int32Value": 1024,
+ "repeatedInt32Value": [1, 2],
+ "messageValue": {
+ "value": 2048
+ },
+ "repeatedMessageValue": [
+ {"value": 40},
+ {"value": 96}
+ ]
+ }
+ )json",
+ message.get()));
// Convert to generated message for easy inspection.
TestMessage generated;
EXPECT_TRUE(generated.ParseFromString(message->SerializeAsString()));
- EXPECT_EQ(1024, generated.int32_value());
- ASSERT_EQ(2, generated.repeated_int32_value_size());
- EXPECT_EQ(1, generated.repeated_int32_value(0));
- EXPECT_EQ(2, generated.repeated_int32_value(1));
- EXPECT_EQ(2048, generated.message_value().value());
- ASSERT_EQ(2, generated.repeated_message_value_size());
- EXPECT_EQ(40, generated.repeated_message_value(0).value());
- EXPECT_EQ(96, generated.repeated_message_value(1).value());
-
- JsonOptions options;
- EXPECT_EQ(ToJson(generated, options), ToJson(*message, options));
+ EXPECT_EQ(generated.int32_value(), 1024);
+ ASSERT_EQ(generated.repeated_int32_value_size(), 2);
+ EXPECT_EQ(generated.repeated_int32_value(0), 1);
+ EXPECT_EQ(generated.repeated_int32_value(1), 2);
+ EXPECT_EQ(generated.message_value().value(), 2048);
+ ASSERT_EQ(generated.repeated_message_value_size(), 2);
+ EXPECT_EQ(generated.repeated_message_value(0).value(), 40);
+ EXPECT_EQ(generated.repeated_message_value(1).value(), 96);
+
+ auto message_json = ToJson(*message);
+ ASSERT_OK(message_json);
+ auto generated_json = ToJson(generated);
+ ASSERT_OK(generated_json);
+ EXPECT_EQ(*message_json, *generated_json);
}
-TEST_F(JsonUtilTest, TestParsingUnknownAnyFields) {
- std::string input =
- "{\n"
- " \"value\": {\n"
- " \"@type\": \"type.googleapis.com/proto3.TestMessage\",\n"
- " \"unknown_field\": \"UNKNOWN_VALUE\",\n"
- " \"string_value\": \"expected_value\"\n"
- " }\n"
- "}";
+TEST(JsonUtilTest, TestParsingUnknownAnyFields) {
+ StringPiece input = R"json(
+ {
+ "value": {
+ "@type": "type.googleapis.com/proto3.TestMessage",
+ "unknown_field": "UNKNOWN_VALUE",
+ "string_value": "expected_value"
+ }
+ }
+ )json";
TestAny m;
- JsonParseOptions options;
- EXPECT_FALSE(FromJson(input, &m, options));
+ EXPECT_THAT(FromJson(input, &m),
+ StatusIs(util::StatusCode::kInvalidArgument));
+ JsonParseOptions options;
options.ignore_unknown_fields = true;
- EXPECT_TRUE(FromJson(input, &m, options));
+ EXPECT_OK(FromJson(input, &m, options));
TestMessage t;
EXPECT_TRUE(m.value().UnpackTo(&t));
- EXPECT_EQ("expected_value", t.string_value());
+ EXPECT_EQ(t.string_value(), "expected_value");
}
-TEST_F(JsonUtilTest, TestParsingUnknownEnumsProto2) {
- std::string input =
- "{\n"
- " \"a\": \"UNKNOWN_VALUE\"\n"
- "}";
+TEST(JsonUtilTest, TestParsingUnknownEnumsProto2) {
+ StringPiece input = R"json({"a": "UNKNOWN_VALUE"})json";
protobuf_unittest::TestNumbers m;
JsonParseOptions options;
- EXPECT_FALSE(FromJson(input, &m, options));
+ EXPECT_THAT(FromJson(input, &m, options),
+ StatusIs(util::StatusCode::kInvalidArgument));
options.ignore_unknown_fields = true;
- EXPECT_TRUE(FromJson(input, &m, options));
+ EXPECT_OK(FromJson(input, &m, options));
EXPECT_FALSE(m.has_a());
}
-TEST_F(JsonUtilTest, TestParsingUnknownEnumsProto3) {
+TEST(JsonUtilTest, TestParsingUnknownEnumsProto3) {
TestMessage m;
- {
- JsonParseOptions options;
- ASSERT_FALSE(options.ignore_unknown_fields);
- std::string input =
- "{\n"
- " \"enum_value\":\"UNKNOWN_VALUE\"\n"
- "}";
- m.set_enum_value(proto3::BAR);
- EXPECT_FALSE(FromJson(input, &m, options));
- ASSERT_EQ(proto3::BAR, m.enum_value()); // Keep previous value
-
- options.ignore_unknown_fields = true;
- EXPECT_TRUE(FromJson(input, &m, options));
- EXPECT_EQ(0, m.enum_value()); // Unknown enum value must be decoded as 0
- }
- // Integer values are read as usual
- {
- JsonParseOptions options;
- std::string input =
- "{\n"
- " \"enum_value\":12345\n"
- "}";
- m.set_enum_value(proto3::BAR);
- EXPECT_TRUE(FromJson(input, &m, options));
- ASSERT_EQ(12345, m.enum_value());
-
- options.ignore_unknown_fields = true;
- EXPECT_TRUE(FromJson(input, &m, options));
- EXPECT_EQ(12345, m.enum_value());
- }
+ StringPiece input = R"json({"enum_value":"UNKNOWN_VALUE"})json";
- // Trying to pass an object as an enum field value is always treated as an
- // error
- {
- JsonParseOptions options;
- std::string input =
- "{\n"
- " \"enum_value\":{}\n"
- "}";
- options.ignore_unknown_fields = true;
- EXPECT_FALSE(FromJson(input, &m, options));
- options.ignore_unknown_fields = false;
- EXPECT_FALSE(FromJson(input, &m, options));
- }
- // Trying to pass an array as an enum field value is always treated as an
- // error
- {
- JsonParseOptions options;
- std::string input =
- "{\n"
- " \"enum_value\":[]\n"
- "}";
- EXPECT_FALSE(FromJson(input, &m, options));
- options.ignore_unknown_fields = true;
- EXPECT_FALSE(FromJson(input, &m, options));
- }
+ m.set_enum_value(proto3::BAR);
+ EXPECT_THAT(FromJson(input, &m),
+ StatusIs(util::StatusCode::kInvalidArgument));
+ ASSERT_EQ(m.enum_value(), proto3::BAR); // Keep previous value
+
+ JsonParseOptions options;
+ options.ignore_unknown_fields = true;
+ EXPECT_OK(FromJson(input, &m, options));
+ EXPECT_EQ(m.enum_value(), 0); // Unknown enum value must be decoded as 0
}
-TEST_F(JsonUtilTest, TestParsingEnumIgnoreCase) {
+TEST(JsonUtilTest, TestParsingUnknownEnumsProto3FromInt) {
TestMessage m;
- {
- JsonParseOptions options;
- std::string input =
- "{\n"
- " \"enum_value\":\"bar\"\n"
- "}";
- m.set_enum_value(proto3::FOO);
- EXPECT_FALSE(FromJson(input, &m, options));
- // Default behavior is case-sensitive, so keep previous value.
- ASSERT_EQ(proto3::FOO, m.enum_value());
- }
- {
- JsonParseOptions options;
- options.case_insensitive_enum_parsing = false;
- std::string input =
- "{\n"
- " \"enum_value\":\"bar\"\n"
- "}";
- m.set_enum_value(proto3::FOO);
- EXPECT_FALSE(FromJson(input, &m, options));
- ASSERT_EQ(proto3::FOO, m.enum_value()); // Keep previous value
- }
- {
- JsonParseOptions options;
- options.case_insensitive_enum_parsing = true;
- std::string input =
- "{\n"
- " \"enum_value\":\"bar\"\n"
- "}";
- m.set_enum_value(proto3::FOO);
- EXPECT_TRUE(FromJson(input, &m, options));
- ASSERT_EQ(proto3::BAR, m.enum_value());
- }
+ StringPiece input = R"json({"enum_value":12345})json";
+
+ m.set_enum_value(proto3::BAR);
+ EXPECT_OK(FromJson(input, &m));
+ ASSERT_EQ(m.enum_value(), 12345);
+
+ JsonParseOptions options;
+ options.ignore_unknown_fields = true;
+ EXPECT_OK(FromJson(input, &m, options));
+ EXPECT_EQ(m.enum_value(), 12345);
+}
+
+// Trying to pass an object as an enum field value is always treated as an
+// error
+TEST(JsonUtilTest, TestParsingUnknownEnumsProto3FromObject) {
+ TestMessage m;
+ StringPiece input = R"json({"enum_value": {}})json";
+
+ JsonParseOptions options;
+ options.ignore_unknown_fields = true;
+ EXPECT_THAT(FromJson(input, &m, options),
+ StatusIs(util::StatusCode::kInvalidArgument));
+
+ EXPECT_THAT(FromJson(input, &m),
+ StatusIs(util::StatusCode::kInvalidArgument));
+}
+
+TEST(JsonUtilTest, TestParsingUnknownEnumsProto3FromArray) {
+ TestMessage m;
+ StringPiece input = R"json({"enum_value": []})json";
+
+ EXPECT_THAT(FromJson(input, &m),
+ StatusIs(util::StatusCode::kInvalidArgument));
+
+ JsonParseOptions options;
+ options.ignore_unknown_fields = true;
+ EXPECT_THAT(FromJson(input, &m, options),
+ StatusIs(util::StatusCode::kInvalidArgument));
+}
+
+TEST(JsonUtilTest, TestParsingEnumCaseSensitive) {
+ TestMessage m;
+
+ StringPiece input = R"json({"enum_value": "bar"})json";
+
+ m.set_enum_value(proto3::FOO);
+ EXPECT_THAT(FromJson(input, &m),
+ StatusIs(util::StatusCode::kInvalidArgument));
+ // Default behavior is case-sensitive, so keep previous value.
+ ASSERT_EQ(m.enum_value(), proto3::FOO);
+}
+
+TEST(JsonUtilTest, TestParsingEnumIgnoreCase) {
+ TestMessage m;
+ StringPiece input = R"json({"enum_value":"bar"})json";
+
+ m.set_enum_value(proto3::FOO);
+ JsonParseOptions options;
+ options.case_insensitive_enum_parsing = true;
+ EXPECT_OK(FromJson(input, &m, options));
+ ASSERT_EQ(m.enum_value(), proto3::BAR);
}
-typedef std::pair Segment;
// A ZeroCopyOutputStream that writes to multiple buffers.
class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream {
public:
- explicit SegmentedZeroCopyOutputStream(std::list segments)
- : segments_(segments),
- last_segment_(static_cast(NULL), 0),
- byte_count_(0) {}
+ explicit SegmentedZeroCopyOutputStream(
+ std::vector segments)
+ : segments_(segments) {
+ // absl::c_* functions are not cloned in OSS.
+ std::reverse(segments_.begin(), segments_.end());
+ }
bool Next(void** buffer, int* length) override {
if (segments_.empty()) {
return false;
}
- last_segment_ = segments_.front();
- segments_.pop_front();
- *buffer = last_segment_.first;
- *length = last_segment_.second;
- byte_count_ += *length;
+ last_segment_ = segments_.back();
+ segments_.pop_back();
+ // TODO(b/234159981): This is only ever constructed in test code, and only
+ // from non-const bytes, so this is a valid cast. We need to do this since
+ // OSS proto does not yet have absl::Span; once we take a full Abseil
+ // dependency we should use that here instead.
+ *buffer = const_cast(last_segment_.data());
+ *length = static_cast(last_segment_.size());
+ byte_count_ += static_cast(last_segment_.size());
return true;
}
void BackUp(int length) override {
- GOOGLE_CHECK(length <= last_segment_.second);
- segments_.push_front(
- Segment(last_segment_.first + last_segment_.second - length, length));
- last_segment_ = Segment(last_segment_.first, last_segment_.second - length);
- byte_count_ -= length;
+ GOOGLE_CHECK(length <= static_cast(last_segment_.size()));
+
+ size_t backup = last_segment_.size() - static_cast(length);
+ segments_.push_back(last_segment_.substr(backup));
+ last_segment_ = last_segment_.substr(0, backup);
+ byte_count_ -= static_cast(length);
}
int64_t ByteCount() const override { return byte_count_; }
private:
- std::list segments_;
- Segment last_segment_;
- int64_t byte_count_;
+ std::vector segments_;
+ StringPiece last_segment_;
+ int64_t byte_count_ = 0;
};
// This test splits the output buffer and also the input data into multiple
// segments and checks that the implementation of ZeroCopyStreamByteSink
// handles all possible cases correctly.
TEST(ZeroCopyStreamByteSinkTest, TestAllInputOutputPatterns) {
- static const int kOutputBufferLength = 10;
+ static constexpr int kOutputBufferLength = 10;
// An exhaustive test takes too long, skip some combinations to make the test
// run faster.
- static const int kSkippedPatternCount = 7;
+ static constexpr int kSkippedPatternCount = 7;
char buffer[kOutputBufferLength];
for (int split_pattern = 0; split_pattern < (1 << (kOutputBufferLength - 1));
split_pattern += kSkippedPatternCount) {
// Split the buffer into small segments according to the split_pattern.
- std::list segments;
+ std::vector segments;
int segment_start = 0;
for (int i = 0; i < kOutputBufferLength - 1; ++i) {
if (split_pattern & (1 << i)) {
segments.push_back(
- Segment(buffer + segment_start, i - segment_start + 1));
+ StringPiece(buffer + segment_start, i - segment_start + 1));
segment_start = i + 1;
}
}
- segments.push_back(
- Segment(buffer + segment_start, kOutputBufferLength - segment_start));
+ segments.push_back(StringPiece(buffer + segment_start,
+ kOutputBufferLength - segment_start));
// Write exactly 10 bytes through the ByteSink.
std::string input_data = "0123456789";
@@ -593,7 +613,7 @@ TEST(ZeroCopyStreamByteSinkTest, TestAllInputOutputPatterns) {
}
byte_sink.Append(&input_data[start], input_data.length() - start);
}
- EXPECT_EQ(input_data, std::string(buffer, input_data.length()));
+ EXPECT_EQ(std::string(buffer, input_data.length()), input_data);
}
// Write only 9 bytes through the ByteSink.
@@ -613,8 +633,8 @@ TEST(ZeroCopyStreamByteSinkTest, TestAllInputOutputPatterns) {
}
byte_sink.Append(&input_data[start], input_data.length() - start);
}
- EXPECT_EQ(input_data, std::string(buffer, input_data.length()));
- EXPECT_EQ(0, buffer[input_data.length()]);
+ EXPECT_EQ(std::string(buffer, input_data.length()), input_data);
+ EXPECT_EQ(buffer[input_data.length()], 0);
}
// Write 11 bytes through the ByteSink. The extra byte will just
@@ -641,29 +661,29 @@ TEST(ZeroCopyStreamByteSinkTest, TestAllInputOutputPatterns) {
}
}
-TEST_F(JsonUtilTest, TestWrongJsonInput) {
- const char json[] = "{\"unknown_field\":\"some_value\"}";
- io::ArrayInputStream input_stream(json, strlen(json));
+TEST(JsonUtilTest, TestWrongJsonInput) {
+ StringPiece json = "{\"unknown_field\":\"some_value\"}";
+ io::ArrayInputStream input_stream(json.data(), json.size());
char proto_buffer[10000];
+
io::ArrayOutputStream output_stream(proto_buffer, sizeof(proto_buffer));
std::string message_type = "type.googleapis.com/proto3.TestMessage";
- TypeResolver* resolver = NewTypeResolverForDescriptorPool(
- "type.googleapis.com", DescriptorPool::generated_pool());
- auto result_status = util::JsonToBinaryStream(resolver, message_type,
- &input_stream, &output_stream);
+ auto* resolver = NewTypeResolverForDescriptorPool(
+ "type.googleapis.com", DescriptorPool::generated_pool());
+ EXPECT_THAT(JsonToBinaryStream(resolver, message_type, &input_stream,
+ &output_stream),
+ StatusIs(util::StatusCode::kInvalidArgument));
delete resolver;
-
- EXPECT_FALSE(result_status.ok());
- EXPECT_TRUE(util::IsInvalidArgument(result_status));
}
-TEST_F(JsonUtilTest, HtmlEscape) {
+TEST(JsonUtilTest, HtmlEscape) {
TestMessage m;
m.set_string_value("");
JsonPrintOptions options;
- EXPECT_EQ("{\"stringValue\":\"\\u003c/script\\u003e\"}", ToJson(m, options));
+ EXPECT_THAT(ToJson(m, options),
+ IsOkAndHolds("{\"stringValue\":\"\\u003c/script\\u003e\"}"));
}
} // namespace
diff --git a/third_party/benchmark b/third_party/benchmark
index 5b7683f49e..0baacde361 160000
--- a/third_party/benchmark
+++ b/third_party/benchmark
@@ -1 +1 @@
-Subproject commit 5b7683f49e1e9223cf9927b24f6fd3d6bd82e3f8
+Subproject commit 0baacde3618ca617da95375e0af13ce1baadea47