@ -33,6 +33,7 @@ using ::proto2_nofieldpresence_unittest::ForeignMessage;
using : : proto2_nofieldpresence_unittest : : TestAllTypes ;
using : : testing : : Eq ;
using : : testing : : Gt ;
using : : testing : : IsEmpty ;
using : : testing : : Not ;
using : : testing : : StrEq ;
using : : testing : : UnorderedPointwise ;
@ -258,6 +259,322 @@ TEST(NoFieldPresenceTest, MessageFieldPresenceTest) {
TestAllTypes : : default_instance ( ) . has_optional_nested_message ( ) ) ;
}
class NoFieldPresenceSwapFieldTest : public testing : : Test {
protected :
NoFieldPresenceSwapFieldTest ( )
: m1_ ( ) ,
m2_ ( ) ,
r1_ ( m1_ . GetReflection ( ) ) ,
r2_ ( m2_ . GetReflection ( ) ) ,
d1_ ( m1_ . GetDescriptor ( ) ) ,
d2_ ( m2_ . GetDescriptor ( ) ) { }
// Returns a field descriptor that corresponds to the field name.
// Note that different messages would still return the same field descriptor.
const FieldDescriptor * FindFieldByName ( absl : : string_view field_name ) {
const FieldDescriptor * f1 = d1_ - > FindFieldByName ( field_name ) ;
const FieldDescriptor * f2 = d2_ - > FindFieldByName ( field_name ) ;
// We actually ensure uniqueness of *field descriptors* even if we try to
// obtain them from different *message descriptors*.
ABSL_CHECK_EQ ( f1 , f2 ) ;
return f1 ;
}
TestAllTypes m1_ ;
TestAllTypes m2_ ;
const Reflection * r1_ ;
const Reflection * r2_ ;
const Descriptor * d1_ ;
const Descriptor * d2_ ;
} ;
TEST_F ( NoFieldPresenceSwapFieldTest , ReflectionSwapFieldScalarNonZeroTest ) {
m1_ . set_optional_int32 ( 1 ) ;
m2_ . set_optional_int32 ( 2 ) ;
const FieldDescriptor * f = FindFieldByName ( " optional_int32 " ) ;
r1_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped.
EXPECT_TRUE ( r1_ - > HasField ( m1_ , f ) ) ;
EXPECT_TRUE ( r2_ - > HasField ( m2_ , f ) ) ;
EXPECT_EQ ( 2 , m1_ . optional_int32 ( ) ) ;
EXPECT_EQ ( 1 , m2_ . optional_int32 ( ) ) ;
// It doesn't matter which reflection or descriptor gets used; swapping should
// still work if m2_'s descriptor is provided.
r2_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped again.
EXPECT_TRUE ( r1_ - > HasField ( m1_ , f ) ) ;
EXPECT_TRUE ( r2_ - > HasField ( m2_ , f ) ) ;
EXPECT_EQ ( 1 , m1_ . optional_int32 ( ) ) ;
EXPECT_EQ ( 2 , m2_ . optional_int32 ( ) ) ;
}
TEST_F ( NoFieldPresenceSwapFieldTest , ReflectionSwapFieldScalarOneZeroTest ) {
m1_ . set_optional_int32 ( 1 ) ;
const FieldDescriptor * f = FindFieldByName ( " optional_int32 " ) ;
r1_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped.
EXPECT_FALSE ( r1_ - > HasField ( m1_ , f ) ) ;
EXPECT_TRUE ( r2_ - > HasField ( m2_ , f ) ) ;
EXPECT_EQ ( 0 , m1_ . optional_int32 ( ) ) ;
EXPECT_EQ ( 1 , m2_ . optional_int32 ( ) ) ;
// It doesn't matter which reflection or descriptor gets used; swapping should
// still work if m2_'s descriptor is provided.
r2_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped again.
EXPECT_TRUE ( r1_ - > HasField ( m1_ , f ) ) ;
EXPECT_FALSE ( r2_ - > HasField ( m2_ , f ) ) ;
EXPECT_EQ ( 1 , m1_ . optional_int32 ( ) ) ;
EXPECT_EQ ( 0 , m2_ . optional_int32 ( ) ) ;
}
TEST_F ( NoFieldPresenceSwapFieldTest , ReflectionSwapFieldScalarBothZeroTest ) {
m1_ . set_optional_int32 ( 0 ) ; // setting an int field to zero should be noop
const FieldDescriptor * f = FindFieldByName ( " optional_int32 " ) ;
r1_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped.
EXPECT_FALSE ( r1_ - > HasField ( m1_ , f ) ) ;
EXPECT_FALSE ( r2_ - > HasField ( m2_ , f ) ) ;
EXPECT_EQ ( 0 , m1_ . optional_int32 ( ) ) ;
EXPECT_EQ ( 0 , m2_ . optional_int32 ( ) ) ;
// It doesn't matter which reflection or descriptor gets used; swapping should
// still work if m2_'s descriptor is provided.
r2_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped again.
EXPECT_FALSE ( r1_ - > HasField ( m1_ , f ) ) ;
EXPECT_FALSE ( r2_ - > HasField ( m2_ , f ) ) ;
EXPECT_EQ ( 0 , m1_ . optional_int32 ( ) ) ;
EXPECT_EQ ( 0 , m2_ . optional_int32 ( ) ) ;
}
TEST_F ( NoFieldPresenceSwapFieldTest , ReflectionSwapFieldRepeatedNonZeroTest ) {
m1_ . add_repeated_int32 ( 1 ) ;
m2_ . add_repeated_int32 ( 2 ) ;
m2_ . add_repeated_int32 ( 22 ) ;
const FieldDescriptor * f = FindFieldByName ( " repeated_int32 " ) ;
r1_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped.
EXPECT_EQ ( r1_ - > FieldSize ( m1_ , f ) , 2 ) ;
EXPECT_EQ ( r2_ - > FieldSize ( m2_ , f ) , 1 ) ;
EXPECT_THAT ( m1_ . repeated_int32 ( ) , UnorderedPointwise ( Eq ( ) , { 2 , 22 } ) ) ;
EXPECT_THAT ( m2_ . repeated_int32 ( ) , UnorderedPointwise ( Eq ( ) , { 1 } ) ) ;
// It doesn't matter which reflection or descriptor gets used; swapping should
// still work if m2_'s descriptor is provided.
r2_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped again.
EXPECT_EQ ( r1_ - > FieldSize ( m1_ , f ) , 1 ) ;
EXPECT_EQ ( r2_ - > FieldSize ( m2_ , f ) , 2 ) ;
EXPECT_THAT ( m1_ . repeated_int32 ( ) , UnorderedPointwise ( Eq ( ) , { 1 } ) ) ;
EXPECT_THAT ( m2_ . repeated_int32 ( ) , UnorderedPointwise ( Eq ( ) , { 2 , 22 } ) ) ;
}
TEST_F ( NoFieldPresenceSwapFieldTest , ReflectionSwapFieldRepeatedOneZeroTest ) {
m1_ . add_repeated_int32 ( 1 ) ;
const FieldDescriptor * f = FindFieldByName ( " repeated_int32 " ) ;
r1_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped.
EXPECT_EQ ( r1_ - > FieldSize ( m1_ , f ) , 0 ) ;
EXPECT_EQ ( r2_ - > FieldSize ( m2_ , f ) , 1 ) ;
EXPECT_THAT ( m1_ . repeated_int32 ( ) , IsEmpty ( ) ) ;
EXPECT_THAT ( m2_ . repeated_int32 ( ) , UnorderedPointwise ( Eq ( ) , { 1 } ) ) ;
// It doesn't matter which reflection or descriptor gets used; swapping should
// still work if m2_'s descriptor is provided.
r2_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped again.
EXPECT_EQ ( r1_ - > FieldSize ( m1_ , f ) , 1 ) ;
EXPECT_EQ ( r2_ - > FieldSize ( m2_ , f ) , 0 ) ;
EXPECT_THAT ( m1_ . repeated_int32 ( ) , UnorderedPointwise ( Eq ( ) , { 1 } ) ) ;
EXPECT_THAT ( m2_ . repeated_int32 ( ) , IsEmpty ( ) ) ;
}
TEST_F ( NoFieldPresenceSwapFieldTest ,
ReflectionSwapFieldRepeatedExplicitZeroTest ) {
// For repeated fields, explicitly adding zero would cause it to be added into
// the repeated field.
m1_ . add_repeated_int32 ( 0 ) ;
const FieldDescriptor * f = FindFieldByName ( " repeated_int32 " ) ;
r1_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped.
EXPECT_EQ ( r1_ - > FieldSize ( m1_ , f ) , 0 ) ;
EXPECT_EQ ( r2_ - > FieldSize ( m2_ , f ) , 1 ) ;
EXPECT_THAT ( m1_ . repeated_int32 ( ) , IsEmpty ( ) ) ;
EXPECT_THAT ( m2_ . repeated_int32 ( ) , UnorderedPointwise ( Eq ( ) , { 0 } ) ) ;
// It doesn't matter which reflection or descriptor gets used; swapping should
// still work if m2_'s descriptor is provided.
r2_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped again.
EXPECT_EQ ( r1_ - > FieldSize ( m1_ , f ) , 1 ) ;
EXPECT_EQ ( r2_ - > FieldSize ( m2_ , f ) , 0 ) ;
EXPECT_THAT ( m1_ . repeated_int32 ( ) , UnorderedPointwise ( Eq ( ) , { 0 } ) ) ;
EXPECT_THAT ( m2_ . repeated_int32 ( ) , IsEmpty ( ) ) ;
}
TEST_F ( NoFieldPresenceSwapFieldTest ,
ReflectionSwapFieldOneofFieldDescriptorTest ) {
m1_ . set_oneof_uint32 ( 1 ) ;
m2_ . set_oneof_string ( " test " ) ;
// NOTE: Calling swap on any field descriptor within the oneof works --
// even a completely unrelated field.
const FieldDescriptor * never_set_field = d1_ - > FindFieldByName ( " oneof_enum " ) ;
r1_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { never_set_field } ) ;
// Fields should be swapped.
EXPECT_FALSE ( r1_ - > HasField ( m1_ , never_set_field ) ) ;
EXPECT_FALSE ( r1_ - > HasField ( m2_ , never_set_field ) ) ;
EXPECT_TRUE ( m1_ . has_oneof_string ( ) ) ;
EXPECT_TRUE ( m2_ . has_oneof_uint32 ( ) ) ;
EXPECT_EQ ( m1_ . oneof_string ( ) , " test " ) ;
EXPECT_EQ ( m2_ . oneof_uint32 ( ) , 1 ) ;
// Calling oneof accessors on a swapped-out field will give the default value.
EXPECT_FALSE ( m1_ . has_oneof_uint32 ( ) ) ;
EXPECT_FALSE ( m2_ . has_oneof_string ( ) ) ;
EXPECT_EQ ( m1_ . oneof_uint32 ( ) , 0 ) ;
EXPECT_THAT ( m2_ . oneof_string ( ) , IsEmpty ( ) ) ;
}
TEST_F ( NoFieldPresenceSwapFieldTest ,
ReflectionSwapFieldOneofFieldMultipleIdenticalDescriptorTest ) {
m1_ . set_oneof_uint32 ( 1 ) ;
m2_ . set_oneof_string ( " test " ) ;
// NOTE: Calling swap on any field descriptor within the oneof works --
// even a completely unrelated field.
const FieldDescriptor * never_set_field = d1_ - > FindFieldByName ( " oneof_enum " ) ;
const FieldDescriptor * f1 = d1_ - > FindFieldByName ( " oneof_uint32 " ) ;
const FieldDescriptor * f2 = d2_ - > FindFieldByName ( " oneof_string " ) ;
// Multiple instances of the identical descriptor is ignored.
r1_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { never_set_field , never_set_field } ) ;
// Fields should be swapped (just once).
EXPECT_EQ ( m1_ . oneof_string ( ) , " test " ) ;
EXPECT_EQ ( m2_ . oneof_uint32 ( ) , 1 ) ;
// Multiple instances of the identical descriptor is ignored.
r2_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f1 , f2 , never_set_field } ) ;
// Fields should be swapped (just once).
EXPECT_TRUE ( m1_ . has_oneof_uint32 ( ) ) ;
EXPECT_TRUE ( m2_ . has_oneof_string ( ) ) ;
EXPECT_TRUE ( r1_ - > HasField ( m1_ , f1 ) ) ;
EXPECT_TRUE ( r2_ - > HasField ( m2_ , f2 ) ) ;
EXPECT_EQ ( m1_ . oneof_uint32 ( ) , 1 ) ;
EXPECT_EQ ( m2_ . oneof_string ( ) , " test " ) ;
// Calling oneof accessors on a swapped-out field will give the default value.
EXPECT_FALSE ( m1_ . has_oneof_string ( ) ) ;
EXPECT_FALSE ( m2_ . has_oneof_uint32 ( ) ) ;
EXPECT_FALSE ( r1_ - > HasField ( m1_ , d1_ - > FindFieldByName ( " oneof_string " ) ) ) ;
EXPECT_FALSE ( r2_ - > HasField ( m2_ , d2_ - > FindFieldByName ( " oneof_uint32 " ) ) ) ;
EXPECT_THAT ( m1_ . oneof_string ( ) , IsEmpty ( ) ) ;
EXPECT_EQ ( m2_ . oneof_uint32 ( ) , 0 ) ;
}
TEST_F ( NoFieldPresenceSwapFieldTest , ReflectionSwapFieldOneofNonZeroTest ) {
m1_ . set_oneof_uint32 ( 1 ) ;
m2_ . set_oneof_string ( " test " ) ;
const FieldDescriptor * f = FindFieldByName ( " oneof_uint32 " ) ;
r1_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped.
EXPECT_TRUE ( m1_ . has_oneof_string ( ) ) ;
EXPECT_TRUE ( m2_ . has_oneof_uint32 ( ) ) ;
EXPECT_TRUE ( r1_ - > HasField ( m1_ , d1_ - > FindFieldByName ( " oneof_string " ) ) ) ;
EXPECT_TRUE ( r2_ - > HasField ( m2_ , f ) ) ;
EXPECT_EQ ( m1_ . oneof_string ( ) , " test " ) ;
EXPECT_EQ ( m2_ . oneof_uint32 ( ) , 1 ) ;
// It doesn't matter which reflection or descriptor gets used; swapping should
// still work if m2_'s descriptor is provided.
r2_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped.
EXPECT_TRUE ( m1_ . has_oneof_uint32 ( ) ) ;
EXPECT_TRUE ( m2_ . has_oneof_string ( ) ) ;
EXPECT_TRUE ( r1_ - > HasField ( m1_ , f ) ) ;
EXPECT_TRUE ( r2_ - > HasField ( m2_ , d2_ - > FindFieldByName ( " oneof_string " ) ) ) ;
EXPECT_EQ ( m1_ . oneof_uint32 ( ) , 1 ) ;
EXPECT_EQ ( m2_ . oneof_string ( ) , " test " ) ;
}
TEST_F ( NoFieldPresenceSwapFieldTest , ReflectionSwapFieldOneofDefaultTest ) {
m1_ . set_oneof_uint32 ( 1 ) ;
const FieldDescriptor * f = FindFieldByName ( " oneof_uint32 " ) ;
r1_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped.
EXPECT_FALSE ( r1_ - > HasField ( m1_ , d1_ - > FindFieldByName ( " oneof_string " ) ) ) ;
EXPECT_TRUE ( r2_ - > HasField ( m2_ , f ) ) ;
EXPECT_FALSE ( m1_ . has_oneof_string ( ) ) ;
EXPECT_EQ ( m2_ . oneof_uint32 ( ) , 1 ) ;
// It doesn't matter which reflection or descriptor gets used; swapping should
// still work if m2_'s descriptor is provided.
r2_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped.
EXPECT_TRUE ( r1_ - > HasField ( m1_ , f ) ) ;
EXPECT_FALSE ( r2_ - > HasField ( m2_ , d2_ - > FindFieldByName ( " oneof_string " ) ) ) ;
EXPECT_EQ ( m1_ . oneof_uint32 ( ) , 1 ) ;
EXPECT_FALSE ( m2_ . has_oneof_string ( ) ) ;
}
TEST_F ( NoFieldPresenceSwapFieldTest , ReflectionSwapFieldOneofExplicitZeroTest ) {
// Oneof fields essentially have explicit presence -- if set to zero, they
// will still be considered present.
m1_ . set_oneof_uint32 ( 0 ) ;
const FieldDescriptor * f = FindFieldByName ( " oneof_uint32 " ) ;
r1_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped.
EXPECT_FALSE ( r1_ - > HasField ( m1_ , f ) ) ;
EXPECT_TRUE ( r2_ - > HasField ( m2_ , f ) ) ;
EXPECT_FALSE ( m1_ . has_oneof_uint32 ( ) ) ;
EXPECT_TRUE ( m2_ . has_oneof_uint32 ( ) ) ;
EXPECT_EQ ( m2_ . oneof_uint32 ( ) , 0 ) ;
// It doesn't matter which reflection or descriptor gets used; swapping should
// still work if m2_'s descriptor is provided.
r2_ - > SwapFields ( & m1_ , & m2_ , /*fields=*/ { f } ) ;
// Fields should be swapped.
EXPECT_TRUE ( r1_ - > HasField ( m1_ , f ) ) ;
EXPECT_FALSE ( r2_ - > HasField ( m2_ , f ) ) ;
EXPECT_TRUE ( m1_ . has_oneof_uint32 ( ) ) ;
EXPECT_EQ ( m1_ . oneof_uint32 ( ) , 0 ) ;
EXPECT_FALSE ( m2_ . has_oneof_uint32 ( ) ) ;
}
class NoFieldPresenceListFieldsTest : public testing : : Test {
protected :
NoFieldPresenceListFieldsTest ( )