|
|
|
/* 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(void) {
|
|
|
|
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;
|
|
|
|
upb_strview val;
|
|
|
|
|
|
|
|
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 < 0.01);
|
|
|
|
ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_double(
|
|
|
|
msg2) - 60.6 < 0.01);
|
|
|
|
ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_bool(
|
|
|
|
msg2) == 1);
|
|
|
|
val = protobuf_test_messages_proto3_TestAllTypesProto3_optional_string(msg2);
|
|
|
|
ASSERT(upb_strview_eql(val, test_str_view));
|
|
|
|
|
|
|
|
upb_arena_free(arena);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_utf8(void) {
|
|
|
|
const char invalid_utf8[] = "\xff";
|
|
|
|
const upb_strview invalid_utf8_view = upb_strview_make(invalid_utf8, 1);
|
|
|
|
upb_arena *arena = upb_arena_new();
|
|
|
|
upb_strview serialized;
|
|
|
|
protobuf_test_messages_proto3_TestAllTypesProto3 *msg =
|
|
|
|
protobuf_test_messages_proto3_TestAllTypesProto3_new(arena);
|
|
|
|
protobuf_test_messages_proto3_TestAllTypesProto3 *msg2;
|
|
|
|
|
|
|
|
protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_string(
|
|
|
|
msg, invalid_utf8_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(msg2 == NULL);
|
|
|
|
|
|
|
|
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(void) {
|
|
|
|
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(void) {
|
|
|
|
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(void) {
|
|
|
|
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(void) {
|
|
|
|
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(void) {
|
|
|
|
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(void) {
|
|
|
|
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_utf8();
|
|
|
|
test_string_map();
|
|
|
|
test_string_double_map();
|
|
|
|
test_int32_map();
|
|
|
|
test_repeated();
|
|
|
|
test_null_decode_buf();
|
|
|
|
test_status_truncation();
|
|
|
|
return 0;
|
|
|
|
}
|