diff --git a/BUILD b/BUILD index ceeae4fab9..adeb5ae937 100644 --- a/BUILD +++ b/BUILD @@ -317,6 +317,15 @@ cc_test( ], ) +cc_test( + name = "test_generated_code", + srcs = ["tests/test_generated_code.c"], + deps = [ + ":test_messages_proto3_proto_upb", + ":upb_test", + ], +) + proto_library( name = "test_decoder_proto", srcs = [ diff --git a/tests/test_generated_code.c b/tests/test_generated_code.c new file mode 100644 index 0000000000..9d8be79ef2 --- /dev/null +++ b/tests/test_generated_code.c @@ -0,0 +1,309 @@ +/* Test of generated code, with a special focus on features that are not used in + * descriptor.proto or conformance.proto (since these get some testing from + * upb/def.c and tests/conformance_upb.c, respectively). + */ + +#include "src/google/protobuf/test_messages_proto3.upb.h" +#include "tests/upb_test.h" + +const char test_str[] = "abcdefg"; +const char test_str2[] = "12345678910"; +const char test_str3[] = "rstlnezxcvbnm"; +const char test_str4[] = "just another test string"; + +const upb_strview test_str_view = {test_str, sizeof(test_str) - 1}; +const upb_strview test_str_view2 = {test_str2, sizeof(test_str2) - 1}; +const upb_strview test_str_view3 = {test_str3, sizeof(test_str3) - 1}; +const upb_strview test_str_view4 = {test_str4, sizeof(test_str4) - 1}; + +const int32_t test_int32 = 10; +const int32_t test_int32_2 = -20; +const int32_t test_int32_3 = 30; +const int32_t test_int32_4 = -40; + +static void test_scalars() { + upb_arena *arena = upb_arena_new(); + protobuf_test_messages_proto3_TestAllTypesProto3 *msg = + protobuf_test_messages_proto3_TestAllTypesProto3_new(arena); + protobuf_test_messages_proto3_TestAllTypesProto3 *msg2; + upb_strview serialized; + + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_int32(msg, 10); + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_int64(msg, 20); + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_uint32(msg, 30); + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_uint64(msg, 40); + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_float(msg, 50.5); + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_double(msg, 60.6); + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_bool(msg, 1); + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_string( + msg, test_str_view); + + serialized.data = protobuf_test_messages_proto3_TestAllTypesProto3_serialize( + msg, arena, &serialized.size); + + msg2 = protobuf_test_messages_proto3_TestAllTypesProto3_parse( + serialized.data, serialized.size, arena); + + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_int32( + msg2) == 10); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_int64( + msg2) == 20); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint32( + msg2) == 30); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint64( + msg2) == 40); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_float( + msg2) == 50.5); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_double( + msg2) == 60.6); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_bool( + msg2) == 1); + ASSERT(upb_strview_eql( + protobuf_test_messages_proto3_TestAllTypesProto3_optional_string(msg2), + test_str_view)); + + upb_arena_free(arena); +} + +static void check_string_map_empty( + protobuf_test_messages_proto3_TestAllTypesProto3 *msg) { + size_t iter; + + ASSERT( + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_size( + msg) == 0); + ASSERT( + !protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next( + msg, &iter)); +} + +static void check_string_map_one_entry( + protobuf_test_messages_proto3_TestAllTypesProto3 *msg) { + const protobuf_test_messages_proto3_TestAllTypesProto3_MapStringStringEntry + *const_ent; + size_t iter; + upb_strview str; + + ASSERT( + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_size( + msg) == 1); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_get( + msg, test_str_view, &str)); + ASSERT(upb_strview_eql(str, test_str_view2)); + + ASSERT( + !protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_get( + msg, test_str_view3, &str)); + + /* Test that iteration reveals a single k/v pair in the map. */ + iter = UPB_MAP_BEGIN; + const_ent = protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next( + msg, &iter); + ASSERT(const_ent); + ASSERT(upb_strview_eql( + test_str_view, + protobuf_test_messages_proto3_TestAllTypesProto3_MapStringStringEntry_key( + const_ent))); + ASSERT(upb_strview_eql( + test_str_view2, + protobuf_test_messages_proto3_TestAllTypesProto3_MapStringStringEntry_value( + const_ent))); + + const_ent = protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next( + msg, &iter); + ASSERT(!const_ent); +} + +static void test_string_map() { + upb_arena *arena = upb_arena_new(); + protobuf_test_messages_proto3_TestAllTypesProto3 *msg = + protobuf_test_messages_proto3_TestAllTypesProto3_new(arena); + const protobuf_test_messages_proto3_TestAllTypesProto3_MapStringStringEntry + *const_ent; + size_t iter, count; + + check_string_map_empty(msg); + + /* Set map[test_str_view] = test_str_view2 */ + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_set( + msg, test_str_view, test_str_view2, arena); + check_string_map_one_entry(msg); + + /* Deleting a non-existent key does nothing. */ + ASSERT( + !protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_delete( + msg, test_str_view3)); + check_string_map_one_entry(msg); + + /* Deleting the key sets the map back to empty. */ + ASSERT( + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_delete( + msg, test_str_view)); + check_string_map_empty(msg); + + /* Set two keys this time: + * map[test_str_view] = test_str_view2 + * map[test_str_view3] = test_str_view4 + */ + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_set( + msg, test_str_view, test_str_view2, arena); + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_set( + msg, test_str_view3, test_str_view4, arena); + + /* Test iteration */ + iter = UPB_MAP_BEGIN; + count = 0; + + while ( + (const_ent = + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next( + msg, &iter)) != NULL) { + upb_strview key = + protobuf_test_messages_proto3_TestAllTypesProto3_MapStringStringEntry_key( + const_ent); + upb_strview val = + protobuf_test_messages_proto3_TestAllTypesProto3_MapStringStringEntry_value( + const_ent); + + count++; + if (upb_strview_eql(key, test_str_view)) { + ASSERT(upb_strview_eql(val, test_str_view2)); + } else { + ASSERT(upb_strview_eql(key, test_str_view3)); + ASSERT(upb_strview_eql(val, test_str_view4)); + } + } + + ASSERT(count == 2); + + /* Clearing the map goes back to empty. */ + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_clear(msg); + check_string_map_empty(msg); + + upb_arena_free(arena); +} + +static void check_int32_map_empty( + protobuf_test_messages_proto3_TestAllTypesProto3 *msg) { + size_t iter; + + ASSERT( + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_size( + msg) == 0); + ASSERT( + !protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_next( + msg, &iter)); +} + +static void check_int32_map_one_entry( + protobuf_test_messages_proto3_TestAllTypesProto3 *msg) { + const protobuf_test_messages_proto3_TestAllTypesProto3_MapInt32Int32Entry + *const_ent; + size_t iter; + int32_t val; + + ASSERT( + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_size( + msg) == 1); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_get( + msg, test_int32, &val)); + ASSERT(val == test_int32_2); + + ASSERT( + !protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_get( + msg, test_int32_3, &val)); + + /* Test that iteration reveals a single k/v pair in the map. */ + iter = UPB_MAP_BEGIN; + const_ent = protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_next( + msg, &iter); + ASSERT(const_ent); + ASSERT( + test_int32 == + protobuf_test_messages_proto3_TestAllTypesProto3_MapInt32Int32Entry_key( + const_ent)); + ASSERT( + test_int32_2 == + protobuf_test_messages_proto3_TestAllTypesProto3_MapInt32Int32Entry_value( + const_ent)); + + const_ent = protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_next( + msg, &iter); + ASSERT(!const_ent); +} + +static void test_int32_map() { + upb_arena *arena = upb_arena_new(); + protobuf_test_messages_proto3_TestAllTypesProto3 *msg = + protobuf_test_messages_proto3_TestAllTypesProto3_new(arena); + const protobuf_test_messages_proto3_TestAllTypesProto3_MapInt32Int32Entry + *const_ent; + size_t iter, count; + + check_int32_map_empty(msg); + + /* Set map[test_int32] = test_int32_2 */ + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_set( + msg, test_int32, test_int32_2, arena); + check_int32_map_one_entry(msg); + + /* Deleting a non-existent key does nothing. */ + ASSERT( + !protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_delete( + msg, test_int32_3)); + check_int32_map_one_entry(msg); + + /* Deleting the key sets the map back to empty. */ + ASSERT( + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_delete( + msg, test_int32)); + check_int32_map_empty(msg); + + /* Set two keys this time: + * map[test_int32] = test_int32_2 + * map[test_int32_3] = test_int32_4 + */ + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_set( + msg, test_int32, test_int32_2, arena); + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_set( + msg, test_int32_3, test_int32_4, arena); + + /* Test iteration */ + iter = UPB_MAP_BEGIN; + count = 0; + + while ( + (const_ent = + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_next( + msg, &iter)) != NULL) { + int32_t key = + protobuf_test_messages_proto3_TestAllTypesProto3_MapInt32Int32Entry_key( + const_ent); + int32_t val = + protobuf_test_messages_proto3_TestAllTypesProto3_MapInt32Int32Entry_value( + const_ent); + + count++; + if (key == test_int32) { + ASSERT(val == test_int32_2); + } else { + ASSERT(key == test_int32_3); + ASSERT(val == test_int32_4); + } + } + + ASSERT(count == 2); + + /* Clearing the map goes back to empty. */ + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_clear(msg); + check_int32_map_empty(msg); + + upb_arena_free(arena); +} + +int run_tests(int argc, char *argv[]) { + test_scalars(); + test_string_map(); + test_int32_map(); + return 0; +}