/* 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" #include "tests/test.upb.h" #define MIN(x, y) ((x) < (y) ? (x) : (y)) 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 = UPB_MAP_BEGIN; 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_double_map() { upb_arena *arena = upb_arena_new(); upb_strview serialized; upb_test_MapTest *msg = upb_test_MapTest_new(arena); upb_test_MapTest *msg2; double val; upb_test_MapTest_map_string_double_set(msg, test_str_view, 1.5, arena); ASSERT(msg); ASSERT(upb_test_MapTest_map_string_double_get(msg, test_str_view, &val)); ASSERT(val == 1.5); val = 0; serialized.data = upb_test_MapTest_serialize(msg, arena, &serialized.size); ASSERT(serialized.data); msg2 = upb_test_MapTest_parse(serialized.data, serialized.size, arena); ASSERT(msg2); ASSERT(upb_test_MapTest_map_string_double_get(msg2, test_str_view, &val)); ASSERT(val == 1.5); upb_arena_free(arena); } 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 = UPB_MAP_BEGIN; 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); } void test_repeated() { upb_arena *arena = upb_arena_new(); protobuf_test_messages_proto3_TestAllTypesProto3 *msg = protobuf_test_messages_proto3_TestAllTypesProto3_new(arena); size_t size; const int *elems; protobuf_test_messages_proto3_TestAllTypesProto3_add_repeated_int32( msg, 5, arena); elems = protobuf_test_messages_proto3_TestAllTypesProto3_repeated_int32( msg, &size); ASSERT(size == 1); ASSERT(elems[0] == 5); upb_arena_free(arena); } void test_null_decode_buf() { upb_arena *arena = upb_arena_new(); protobuf_test_messages_proto3_TestAllTypesProto3 *msg = protobuf_test_messages_proto3_TestAllTypesProto3_parse(NULL, 0, arena); size_t size; ASSERT(msg); protobuf_test_messages_proto3_TestAllTypesProto3_serialize(msg, arena, &size); ASSERT(size == 0); upb_arena_free(arena); } void test_status_truncation() { int i, j; upb_status status; upb_status status2; for (i = 0; i < UPB_STATUS_MAX_MESSAGE + 20; i++) { char *msg = malloc(i + 1); int end; char ch = (i % 96) + 33; /* Cycle through printable chars. */ for (j = 0; j < i; j++) { msg[j] = ch; } msg[i] = '\0'; upb_status_seterrmsg(&status, msg); upb_status_seterrf(&status2, "%s", msg); end = MIN(i, UPB_STATUS_MAX_MESSAGE - 1); ASSERT(strlen(status.msg) == end); ASSERT(strlen(status2.msg) == end); for (j = 0; j < end; j++) { ASSERT(status.msg[j] == ch); ASSERT(status2.msg[j] == ch); } free(msg); } } int run_tests(int argc, char *argv[]) { test_scalars(); test_string_map(); test_string_double_map(); test_int32_map(); test_repeated(); test_null_decode_buf(); test_status_truncation(); return 0; }