Merge pull request #495 from haberman/gtest

Migrated upb's C tests to gtest, and deleted homegrown testing framework
pull/13171/head
Joshua Haberman 3 years ago committed by GitHub
commit 85e5c76cb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      tests/BUILD
  2. 42
      tests/test_cpp.cc
  3. 249
      tests/test_generated_code.cc
  4. 300
      tests/test_table.cc
  5. 40
      tests/testmain.cc
  6. 83
      tests/upb_test.h

@ -38,22 +38,6 @@ load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test")
licenses(["notice"])
cc_library(
name = "upb_test",
testonly = 1,
srcs = [
"testmain.cc",
],
hdrs = [
"upb_test.h",
],
copts = UPB_DEFAULT_CPPOPTS,
deps = [
"//:port",
"//:upb",
],
)
proto_library(
name = "test_proto",
testonly = 1,
@ -68,13 +52,12 @@ upb_proto_library(
cc_test(
name = "test_generated_code",
srcs = ["test_generated_code.c"],
copts = UPB_DEFAULT_COPTS,
srcs = ["test_generated_code.cc"],
deps = [
":empty_upbdefs_proto",
":test_messages_proto3_proto_upb",
":test_upb_proto",
":upb_test",
"@com_google_googletest//:gtest_main",
],
)
@ -119,11 +102,11 @@ cc_test(
deps = [
":test_cpp_upb_proto",
":test_cpp_upb_proto_reflection",
":upb_test",
"//:json",
"//:port",
"//:reflection",
"//:upb",
"@com_google_googletest//:gtest_main",
],
)
@ -132,10 +115,10 @@ cc_test(
srcs = ["test_table.cc"],
copts = UPB_DEFAULT_CPPOPTS,
deps = [
":upb_test",
"//:port",
"//:table",
"//:upb",
"@com_google_googletest//:gtest_main",
],
)

@ -35,9 +35,9 @@
#include <set>
#include <sstream>
#include "gtest/gtest.h"
#include "tests/test_cpp.upb.h"
#include "tests/test_cpp.upbdefs.h"
#include "tests/upb_test.h"
#include "upb/def.h"
#include "upb/def.hpp"
#include "upb/json_decode.h"
@ -47,7 +47,7 @@
// Must be last.
#include "upb/port_def.inc"
void TestIteration() {
TEST(Cpp, Iteration) {
upb::SymbolTable symtab;
upb::MessageDefPtr md(upb_test_TestMessage_getmsgdef(symtab.ptr()));
@ -57,17 +57,17 @@ void TestIteration() {
UPB_UNUSED(field);
field_count++;
}
ASSERT(field_count == md.field_count());
EXPECT_EQ(field_count, md.field_count());
int oneof_count = 0;
for (auto oneof : md.oneofs()) {
UPB_UNUSED(oneof);
oneof_count++;
}
ASSERT(oneof_count == md.oneof_count());
EXPECT_EQ(oneof_count, md.oneof_count());
}
void TestArena() {
TEST(Cpp, Arena) {
int n = 100000;
struct Decrementer {
@ -89,7 +89,7 @@ void TestArena() {
// Test a large allocation.
upb_Arena_Malloc(arena.ptr(), 1000000);
}
ASSERT(n == 0);
EXPECT_EQ(0, n);
{
// Test fuse.
@ -103,7 +103,7 @@ void TestArena() {
}
}
void TestInlinedArena() {
TEST(Cpp, InlinedArena) {
int n = 100000;
struct Decrementer {
@ -125,36 +125,26 @@ void TestInlinedArena() {
// Test a large allocation.
upb_Arena_Malloc(arena.ptr(), 1000000);
}
ASSERT(n == 0);
EXPECT_EQ(0, n);
}
void TestDefault() {
TEST(Cpp, Default) {
upb::SymbolTable symtab;
upb::Arena arena;
upb::MessageDefPtr md(upb_test_TestMessage_getmsgdef(symtab.ptr()));
upb_test_TestMessage* msg = upb_test_TestMessage_new(arena.ptr());
size_t size = upb_JsonEncode(msg, md.ptr(), NULL, 0, NULL, 0, NULL);
ASSERT(size == 2); // "{}"
EXPECT_EQ(2, size); // "{}"
}
void TestJsonNull() {
TEST(Cpp, JsonNull) {
upb::SymbolTable symtab;
upb::MessageDefPtr md(upb_test_TestMessage_getmsgdef(symtab.ptr()));
upb::FieldDefPtr i32_f = md.FindFieldByName("i32");
upb::FieldDefPtr str_f = md.FindFieldByName("str");
ASSERT(i32_f && str_f);
ASSERT(i32_f.default_value().int32_val == 5);
ASSERT(strcmp(str_f.default_value().str_val.data, "abc") == 0);
ASSERT(str_f.default_value().str_val.size == 3);
}
extern "C" {
int run_tests() {
TestIteration();
TestArena();
TestDefault();
return 0;
}
ASSERT_TRUE(i32_f);
ASSERT_TRUE(str_f);
EXPECT_EQ(5, i32_f.default_value().int32_val);
EXPECT_EQ(0, strcmp(str_f.default_value().str_val.data, "abc"));
EXPECT_EQ(3, str_f.default_value().str_val.size);
}

@ -32,7 +32,7 @@
#include "src/google/protobuf/test_messages_proto3.upb.h"
#include "tests/test.upb.h"
#include "tests/upb_test.h"
#include "gtest/gtest.h"
#define MIN(x, y) ((x) < (y) ? (x) : (y))
@ -51,7 +51,7 @@ 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) {
TEST(GeneratedCode, Scalars) {
upb_Arena* arena = upb_Arena_New();
protobuf_test_messages_proto3_TestAllTypesProto3* msg =
protobuf_test_messages_proto3_TestAllTypesProto3_new(arena);
@ -77,30 +77,32 @@ static void test_scalars(void) {
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);
EXPECT_EQ(10, protobuf_test_messages_proto3_TestAllTypesProto3_optional_int32(
msg2));
EXPECT_EQ(20, protobuf_test_messages_proto3_TestAllTypesProto3_optional_int64(
msg2));
EXPECT_EQ(
30,
protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint32(msg2));
EXPECT_EQ(
40,
protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint64(msg2));
EXPECT_EQ(
50.5,
protobuf_test_messages_proto3_TestAllTypesProto3_optional_float(msg2));
EXPECT_EQ(
60.6,
protobuf_test_messages_proto3_TestAllTypesProto3_optional_double(msg2));
EXPECT_EQ(
true,
protobuf_test_messages_proto3_TestAllTypesProto3_optional_bool(msg2));
val = protobuf_test_messages_proto3_TestAllTypesProto3_optional_string(msg2);
ASSERT(upb_StringView_IsEqual(val, test_str_view));
EXPECT_TRUE(upb_StringView_IsEqual(val, test_str_view));
upb_Arena_Free(arena);
}
static void test_utf8(void) {
TEST(GeneratedCode, UTF8) {
const char invalid_utf8[] = "\xff";
const upb_StringView invalid_utf8_view =
upb_StringView_FromDataAndSize(invalid_utf8, 1);
@ -118,7 +120,7 @@ static void test_utf8(void) {
msg2 = protobuf_test_messages_proto3_TestAllTypesProto3_parse(
serialized.data, serialized.size, arena);
ASSERT(msg2 == NULL);
EXPECT_EQ(nullptr, msg2);
upb_Arena_Free(arena);
}
@ -127,11 +129,12 @@ static void check_string_map_empty(
protobuf_test_messages_proto3_TestAllTypesProto3* msg) {
size_t iter = kUpb_Map_Begin;
ASSERT(
EXPECT_EQ(
0,
protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_size(
msg) == 0);
ASSERT(
!protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next(
msg));
EXPECT_FALSE(
protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next(
msg, &iter));
}
@ -142,15 +145,17 @@ static void check_string_map_one_entry(
size_t iter;
upb_StringView str;
ASSERT(
EXPECT_EQ(
1,
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_StringView_IsEqual(str, test_str_view2));
ASSERT(
!protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_get(
msg));
EXPECT_TRUE(
protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_get(
msg, test_str_view, &str));
EXPECT_TRUE(upb_StringView_IsEqual(str, test_str_view2));
EXPECT_FALSE(
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. */
@ -158,12 +163,12 @@ static void check_string_map_one_entry(
const_ent =
protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next(
msg, &iter);
ASSERT(const_ent);
ASSERT(upb_StringView_IsEqual(
ASSERT_NE(nullptr, const_ent);
EXPECT_TRUE(upb_StringView_IsEqual(
test_str_view,
protobuf_test_messages_proto3_TestAllTypesProto3_MapStringStringEntry_key(
const_ent)));
ASSERT(upb_StringView_IsEqual(
EXPECT_TRUE(upb_StringView_IsEqual(
test_str_view2,
protobuf_test_messages_proto3_TestAllTypesProto3_MapStringStringEntry_value(
const_ent)));
@ -171,10 +176,10 @@ static void check_string_map_one_entry(
const_ent =
protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next(
msg, &iter);
ASSERT(!const_ent);
EXPECT_EQ(nullptr, const_ent);
}
static void test_string_double_map(void) {
TEST(GeneratedCode, StringDoubleMap) {
upb_Arena* arena = upb_Arena_New();
upb_StringView serialized;
upb_test_MapTest* msg = upb_test_MapTest_new(arena);
@ -182,23 +187,24 @@ static void test_string_double_map(void) {
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);
ASSERT_NE(nullptr, msg);
EXPECT_TRUE(upb_test_MapTest_map_string_double_get(msg, test_str_view, &val));
EXPECT_EQ(1.5, val);
val = 0;
serialized.data = upb_test_MapTest_serialize(msg, arena, &serialized.size);
ASSERT(serialized.data);
EXPECT_NE(nullptr, 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);
ASSERT_NE(nullptr, msg2);
EXPECT_TRUE(
upb_test_MapTest_map_string_double_get(msg2, test_str_view, &val));
EXPECT_EQ(1.5, val);
upb_Arena_Free(arena);
}
static void test_string_map(void) {
TEST(GeneratedCode, StringMap) {
upb_Arena* arena = upb_Arena_New();
protobuf_test_messages_proto3_TestAllTypesProto3* msg =
protobuf_test_messages_proto3_TestAllTypesProto3_new(arena);
@ -214,13 +220,13 @@ static void test_string_map(void) {
check_string_map_one_entry(msg);
/* Deleting a non-existent key does nothing. */
ASSERT(
!protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_delete(
EXPECT_FALSE(
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(
EXPECT_TRUE(
protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_delete(
msg, test_str_view));
check_string_map_empty(msg);
@ -251,14 +257,14 @@ static void test_string_map(void) {
count++;
if (upb_StringView_IsEqual(key, test_str_view)) {
ASSERT(upb_StringView_IsEqual(val, test_str_view2));
EXPECT_TRUE(upb_StringView_IsEqual(val, test_str_view2));
} else {
ASSERT(upb_StringView_IsEqual(key, test_str_view3));
ASSERT(upb_StringView_IsEqual(val, test_str_view4));
EXPECT_TRUE(upb_StringView_IsEqual(key, test_str_view3));
EXPECT_TRUE(upb_StringView_IsEqual(val, test_str_view4));
}
}
ASSERT(count == 2);
EXPECT_EQ(2, count);
/* Clearing the map goes back to empty. */
protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_clear(msg);
@ -271,10 +277,12 @@ static void check_int32_map_empty(
protobuf_test_messages_proto3_TestAllTypesProto3* msg) {
size_t iter = kUpb_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));
EXPECT_EQ(
0, protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_size(
msg));
EXPECT_FALSE(
protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_next(
msg, &iter));
}
static void check_int32_map_one_entry(
@ -284,13 +292,14 @@ static void check_int32_map_one_entry(
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(
EXPECT_EQ(
1, protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_size(
msg));
EXPECT_TRUE(protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_get(
msg, test_int32, &val));
ASSERT(val == test_int32_2);
EXPECT_EQ(val, test_int32_2);
ASSERT(!protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_get(
EXPECT_FALSE(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. */
@ -298,23 +307,23 @@ static void check_int32_map_one_entry(
const_ent =
protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_next(
msg, &iter);
ASSERT(const_ent);
ASSERT(
test_int32 ==
ASSERT_NE(nullptr, const_ent);
EXPECT_EQ(
test_int32,
protobuf_test_messages_proto3_TestAllTypesProto3_MapInt32Int32Entry_key(
const_ent));
ASSERT(
test_int32_2 ==
EXPECT_EQ(
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);
EXPECT_EQ(nullptr, const_ent);
}
static void test_int32_map(void) {
TEST(GeneratedCode, Int32Map) {
upb_Arena* arena = upb_Arena_New();
protobuf_test_messages_proto3_TestAllTypesProto3* msg =
protobuf_test_messages_proto3_TestAllTypesProto3_new(arena);
@ -330,13 +339,13 @@ static void test_int32_map(void) {
check_int32_map_one_entry(msg);
/* Deleting a non-existent key does nothing. */
ASSERT(
!protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_delete(
EXPECT_FALSE(
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(
EXPECT_TRUE(
protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_delete(
msg, test_int32));
check_int32_map_empty(msg);
@ -367,14 +376,14 @@ static void test_int32_map(void) {
count++;
if (key == test_int32) {
ASSERT(val == test_int32_2);
EXPECT_EQ(val, test_int32_2);
} else {
ASSERT(key == test_int32_3);
ASSERT(val == test_int32_4);
EXPECT_EQ(key, test_int32_3);
EXPECT_EQ(val, test_int32_4);
}
}
ASSERT(count == 2);
EXPECT_EQ(2, count);
/* Clearing the map goes back to empty. */
protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_clear(msg);
@ -383,7 +392,7 @@ static void test_int32_map(void) {
upb_Arena_Free(arena);
}
void test_repeated(void) {
TEST(GeneratedCode, TestRepeated) {
upb_Arena* arena = upb_Arena_New();
protobuf_test_messages_proto3_TestAllTypesProto3* msg =
protobuf_test_messages_proto3_TestAllTypesProto3_new(arena);
@ -396,30 +405,30 @@ void test_repeated(void) {
elems = protobuf_test_messages_proto3_TestAllTypesProto3_repeated_int32(
msg, &size);
ASSERT(size == 1);
ASSERT(elems[0] == 5);
EXPECT_EQ(1, size);
EXPECT_EQ(5, elems[0]);
upb_Arena_Free(arena);
}
void test_null_decode_buf(void) {
TEST(GeneratedCode, NullDecodeBuffer) {
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);
ASSERT_NE(nullptr, msg);
protobuf_test_messages_proto3_TestAllTypesProto3_serialize(msg, arena, &size);
ASSERT(size == 0);
EXPECT_EQ(0, size);
upb_Arena_Free(arena);
}
void test_status_truncation(void) {
TEST(GeneratedCode, StatusTruncation) {
int i, j;
upb_Status status;
upb_Status status2;
for (i = 0; i < _kUpb_Status_MaxMessage + 20; i++) {
char* msg = malloc(i + 1);
char* msg = static_cast<char*>(malloc(i + 1));
int end;
char ch = (i % 96) + 33; /* Cycle through printable chars. */
@ -431,24 +440,24 @@ void test_status_truncation(void) {
upb_Status_SetErrorMessage(&status, msg);
upb_Status_SetErrorFormat(&status2, "%s", msg);
end = MIN(i, _kUpb_Status_MaxMessage - 1);
ASSERT(strlen(status.msg) == end);
ASSERT(strlen(status2.msg) == end);
EXPECT_EQ(end, strlen(status.msg));
EXPECT_EQ(end, strlen(status2.msg));
for (j = 0; j < end; j++) {
ASSERT(status.msg[j] == ch);
ASSERT(status2.msg[j] == ch);
EXPECT_EQ(ch, status.msg[j]);
EXPECT_EQ(ch, status2.msg[j]);
}
free(msg);
}
}
void decrement_int(void* ptr) {
int* iptr = ptr;
static void decrement_int(void* ptr) {
int* iptr = static_cast<int*>(ptr);
(*iptr)--;
}
void test_arena_fuse(void) {
TEST(GeneratedCode, ArenaFuse) {
int i1 = 5;
int i2 = 5;
int i3 = 5;
@ -460,21 +469,21 @@ void test_arena_fuse(void) {
upb_Arena_AddCleanup(arena1, &i1, decrement_int);
upb_Arena_AddCleanup(arena2, &i2, decrement_int);
ASSERT(upb_Arena_Fuse(arena1, arena2));
EXPECT_TRUE(upb_Arena_Fuse(arena1, arena2));
upb_Arena_AddCleanup(arena1, &i3, decrement_int);
upb_Arena_AddCleanup(arena2, &i4, decrement_int);
upb_Arena_Free(arena1);
ASSERT(i1 == 5);
ASSERT(i2 == 5);
ASSERT(i3 == 5);
ASSERT(i4 == 5);
EXPECT_EQ(5, i1);
EXPECT_EQ(5, i2);
EXPECT_EQ(5, i3);
EXPECT_EQ(5, i4);
upb_Arena_Free(arena2);
ASSERT(i1 == 4);
ASSERT(i2 == 4);
ASSERT(i3 == 4);
ASSERT(i4 == 4);
EXPECT_EQ(4, i1);
EXPECT_EQ(4, i2);
EXPECT_EQ(4, i3);
EXPECT_EQ(4, i4);
}
/* Do nothing allocator for testing */
@ -484,7 +493,7 @@ static void* test_allocfunc(upb_alloc* alloc, void* ptr, size_t oldsize,
}
upb_alloc test_alloc = {&test_allocfunc};
void test_arena_fuse_with_initial_block(void) {
TEST(GeneratedCode, FuseWithInitialBlock) {
char buf1[1024];
char buf2[1024];
upb_Arena* arenas[] = {upb_Arena_Init(buf1, 1024, &upb_alloc_global),
@ -495,9 +504,9 @@ void test_arena_fuse_with_initial_block(void) {
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
if (i == j) {
ASSERT(upb_Arena_Fuse(arenas[i], arenas[j]));
EXPECT_TRUE(upb_Arena_Fuse(arenas[i], arenas[j]));
} else {
ASSERT(!upb_Arena_Fuse(arenas[i], arenas[j]));
EXPECT_FALSE(upb_Arena_Fuse(arenas[i], arenas[j]));
}
}
}
@ -505,7 +514,7 @@ void test_arena_fuse_with_initial_block(void) {
for (int i = 0; i < size; ++i) upb_Arena_Free(arenas[i]);
}
void test_arena_decode(void) {
TEST(GeneratedCode, ArenaDecode) {
// Tests against a bug that previously existed when passing an arena to
// upb_decode().
char large_string[1024] = {0};
@ -531,42 +540,26 @@ void test_arena_decode(void) {
int i1 = 5;
upb_Arena_AddCleanup(arena, &i1, decrement_int);
ASSERT(i1 == 5);
EXPECT_EQ(5, i1);
upb_Arena_Free(arena);
ASSERT(i1 == 4);
EXPECT_EQ(4, i1);
upb_Arena_Free(tmp);
}
void test_arena_unaligned(void) {
TEST(GeneratedCode, ArenaUnaligned) {
char buf1[1024];
// Force the pointer to be unaligned.
char* unaligned_buf_ptr = (char*)((uintptr_t)buf1 | 7);
upb_Arena* arena = upb_Arena_Init(
unaligned_buf_ptr, &buf1[sizeof(buf1)] - unaligned_buf_ptr, NULL);
char* mem = upb_Arena_Malloc(arena, 5);
ASSERT(((uintptr_t)mem & 15) == 0);
char* mem = static_cast<char*>(upb_Arena_Malloc(arena, 5));
EXPECT_EQ(0, reinterpret_cast<uintptr_t>(mem) & 15);
upb_Arena_Free(arena);
// Try the same, but with a size so small that aligning up will overflow.
arena = upb_Arena_Init(unaligned_buf_ptr, 5, &upb_alloc_global);
mem = upb_Arena_Malloc(arena, 5);
ASSERT(((uintptr_t)mem & 15) == 0);
mem = static_cast<char*>(upb_Arena_Malloc(arena, 5));
EXPECT_EQ(0, reinterpret_cast<uintptr_t>(mem) & 15);
upb_Arena_Free(arena);
}
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();
test_arena_fuse();
test_arena_fuse_with_initial_block();
test_arena_decode();
test_arena_unaligned();
return 0;
}

@ -38,7 +38,7 @@
#include <unordered_map>
#include <vector>
#include "tests/upb_test.h"
#include "gtest/gtest.h"
#include "upb/table_internal.h"
#include "upb/upb.hpp"
@ -365,46 +365,63 @@ double get_usertime() {
return usage.ru_utime.tv_sec + (usage.ru_utime.tv_usec / 1000000.0);
}
/* num_entries must be a power of 2. */
void test_strtable(const vector<std::string>& keys, uint32_t num_to_insert) {
TEST(Table, StringTable) {
vector<std::string> keys;
keys.push_back("google.protobuf.FileDescriptorSet");
keys.push_back("google.protobuf.FileDescriptorProto");
keys.push_back("google.protobuf.DescriptorProto");
keys.push_back("google.protobuf.DescriptorProto.ExtensionRange");
keys.push_back("google.protobuf.FieldDescriptorProto");
keys.push_back("google.protobuf.EnumDescriptorProto");
keys.push_back("google.protobuf.EnumValueDescriptorProto");
keys.push_back("google.protobuf.ServiceDescriptorProto");
keys.push_back("google.protobuf.MethodDescriptorProto");
keys.push_back("google.protobuf.FileOptions");
keys.push_back("google.protobuf.MessageOptions");
keys.push_back("google.protobuf.FieldOptions");
keys.push_back("google.protobuf.EnumOptions");
keys.push_back("google.protobuf.EnumValueOptions");
keys.push_back("google.protobuf.ServiceOptions");
keys.push_back("google.protobuf.MethodOptions");
keys.push_back("google.protobuf.UninterpretedOption");
keys.push_back("google.protobuf.UninterpretedOption.NamePart");
/* Initialize structures. */
std::map<std::string, int32_t> m;
typedef upb::TypedStrTable<int32_t> Table;
Table table;
std::set<std::string> all;
for (size_t i = 0; i < num_to_insert; i++) {
const std::string& key = keys[i];
for (const auto& key : keys) {
all.insert(key);
table.Insert(key, key[0]);
m[key] = key[0];
}
/* Test correctness. */
for (uint32_t i = 0; i < keys.size(); i++) {
const std::string& key = keys[i];
for (const auto& key : keys) {
std::pair<bool, int32_t> found = table.Lookup(key);
if (m.find(key) != m.end()) { /* Assume map implementation is correct. */
ASSERT(found.first);
ASSERT(found.second == key[0]);
ASSERT(m[key] == key[0]);
EXPECT_TRUE(found.first);
EXPECT_EQ(found.second, key[0]);
EXPECT_EQ(m[key], key[0]);
} else {
ASSERT(!found.first);
EXPECT_FALSE(found.first);
}
}
for (Table::iterator it = table.begin(); it != table.end(); ++it) {
std::set<std::string>::iterator i = all.find((*it).first);
ASSERT(i != all.end());
EXPECT_NE(i, all.end());
all.erase(i);
}
ASSERT(all.empty());
EXPECT_TRUE(all.empty());
// Test iteration with resizes.
for (int i = 0; i < 10; i++) {
for (Table::iterator it = table.begin(); it != table.end(); ++it) {
// Even if we invalidate the iterator it should only return real elements.
ASSERT((*it).second == m[(*it).first]);
EXPECT_EQ((*it).second, m[(*it).first]);
// Force a resize even though the size isn't changing.
// Also forces the table size to grow so some new buckets end up empty.
@ -416,16 +433,34 @@ void test_strtable(const vector<std::string>& keys, uint32_t num_to_insert) {
}
}
/* num_entries must be a power of 2. */
void test_inttable(int32_t* keys, uint16_t num_entries, const char* desc) {
class IntTableTest : public testing::TestWithParam<int> {
void SetUp() override {
if (GetParam() > 0) {
for (int i = 0; i < GetParam(); i++) {
keys_.push_back(i + 1);
}
} else {
for (int32_t i = 0; i < 64; i++) {
if (i < 32)
keys_.push_back(i + 1);
else
keys_.push_back(10101 + i);
}
}
}
protected:
std::vector<int32_t> keys_;
};
TEST_P(IntTableTest, TestIntTable) {
/* Initialize structures. */
typedef upb::TypedIntTable<uint32_t> Table;
Table table;
uint32_t largest_key = 0;
std::map<uint32_t, uint32_t> m;
std::unordered_map<uint32_t, uint32_t> hm;
for (size_t i = 0; i < num_entries; i++) {
int32_t key = keys[i];
for (const auto& key: keys_) {
largest_key = UPB_MAX((int32_t)largest_key, key);
table.Insert(key, key * 2);
m[key] = key * 2;
@ -436,35 +471,37 @@ void test_inttable(int32_t* keys, uint16_t num_entries, const char* desc) {
for (uint32_t i = 0; i <= largest_key; i++) {
std::pair<bool, uint32_t> found = table.Lookup(i);
if (m.find(i) != m.end()) { /* Assume map implementation is correct. */
ASSERT(found.first);
ASSERT(found.second == i * 2);
ASSERT(m[i] == i * 2);
ASSERT(hm[i] == i * 2);
EXPECT_TRUE(found.first);
EXPECT_EQ(found.second, i * 2);
EXPECT_EQ(m[i], i * 2);
EXPECT_EQ(hm[i], i * 2);
} else {
ASSERT(!found.first);
EXPECT_FALSE(found.first);
}
}
for (uint16_t i = 0; i < num_entries; i += 2) {
std::pair<bool, uint32_t> found = table.Remove(keys[i]);
ASSERT(found.first == (m.erase(keys[i]) == 1));
if (found.first) ASSERT(found.second == (uint32_t)keys[i] * 2);
hm.erase(keys[i]);
m.erase(keys[i]);
for (size_t i = 0; i < keys_.size(); i += 2) {
std::pair<bool, uint32_t> found = table.Remove(keys_[i]);
EXPECT_EQ(found.first, m.erase(keys_[i]) == 1);
if (found.first) {
EXPECT_EQ(found.second, (uint32_t)keys_[i] * 2);
}
hm.erase(keys_[i]);
m.erase(keys_[i]);
}
ASSERT(table.count() == hm.size());
EXPECT_EQ(table.count(), hm.size());
/* Test correctness. */
for (uint32_t i = 0; i <= largest_key; i++) {
std::pair<bool, uint32_t> found = table.Lookup(i);
if (m.find(i) != m.end()) { /* Assume map implementation is correct. */
ASSERT(found.first);
ASSERT(found.second == i * 2);
ASSERT(m[i] == i * 2);
ASSERT(hm[i] == i * 2);
EXPECT_TRUE(found.first);
EXPECT_EQ(found.second, i * 2);
EXPECT_EQ(m[i], i * 2);
EXPECT_EQ(hm[i], i * 2);
} else {
ASSERT(!found.first);
EXPECT_FALSE(found.first);
}
}
@ -472,11 +509,11 @@ void test_inttable(int32_t* keys, uint16_t num_entries, const char* desc) {
for (uint32_t i = 0; i <= largest_key; i++) {
bool replaced = table.Replace(i, i * 3);
if (m.find(i) != m.end()) { /* Assume map implementation is correct. */
ASSERT(replaced);
EXPECT_TRUE(replaced);
m[i] = i * 3;
hm[i] = i * 3;
} else {
ASSERT(!replaced);
EXPECT_FALSE(replaced);
}
}
@ -485,123 +522,24 @@ void test_inttable(int32_t* keys, uint16_t num_entries, const char* desc) {
for (uint32_t i = 0; i <= largest_key; i++) {
std::pair<bool, uint32_t> found = table.Lookup(i);
if (m.find(i) != m.end()) { /* Assume map implementation is correct. */
ASSERT(found.first);
ASSERT(found.second == i * 3);
ASSERT(m[i] == i * 3);
ASSERT(hm[i] == i * 3);
EXPECT_TRUE(found.first);
EXPECT_EQ(found.second, i * 3);
EXPECT_EQ(m[i], i * 3);
EXPECT_EQ(hm[i], i * 3);
} else {
ASSERT(!found.first);
EXPECT_FALSE(found.first);
}
}
if (!benchmark) {
return;
}
printf("%s\n", desc);
/* Test performance. We only test lookups for keys that are known to exist. */
uint16_t* rand_order = new uint16_t[num_entries];
for (uint16_t i = 0; i < num_entries; i++) {
rand_order[i] = i;
}
for (uint16_t i = num_entries - 1; i >= 1; i--) {
uint16_t rand_i = (random() / (double)RAND_MAX) * i;
ASSERT(rand_i <= i);
uint16_t tmp = rand_order[rand_i];
rand_order[rand_i] = rand_order[i];
rand_order[i] = tmp;
}
uintptr_t x = 0;
const int mask = num_entries - 1;
int time_mask = 0xffff;
printf("upb_inttable(seq): ");
fflush(stdout);
double before = get_usertime();
unsigned int i;
#define MAYBE_BREAK \
if ((i & time_mask) == 0 && (get_usertime() - before) > CPU_TIME_PER_TEST) \
break;
for (i = 0; true; i++) {
MAYBE_BREAK;
int32_t key = keys[i & mask];
upb_value v;
bool ok = upb_inttable_lookup(&table.table_.table_, key, &v);
x += (uintptr_t)ok;
}
double total = get_usertime() - before;
printf("%ld/s\n", (long)(i / total));
double upb_seq_i = i / 100; // For later percentage calcuation.
printf("upb_inttable(rand): ");
fflush(stdout);
before = get_usertime();
for (i = 0; true; i++) {
MAYBE_BREAK;
int32_t key = keys[rand_order[i & mask]];
upb_value v;
bool ok = upb_inttable_lookup(&table.table_.table_, key, &v);
x += (uintptr_t)ok;
}
total = get_usertime() - before;
printf("%ld/s\n", (long)(i / total));
double upb_rand_i = i / 100; // For later percentage calculation.
printf("std::map<int32_t, int32_t>(seq): ");
fflush(stdout);
before = get_usertime();
for (i = 0; true; i++) {
MAYBE_BREAK;
int32_t key = keys[i & mask];
x += m[key];
}
total = get_usertime() - before;
printf("%ld/s (%0.1f%% of upb)\n", (long)(i / total), i / upb_seq_i);
printf("std::map<int32_t, int32_t>(rand): ");
fflush(stdout);
before = get_usertime();
for (i = 0; true; i++) {
MAYBE_BREAK;
int32_t key = keys[rand_order[i & mask]];
x += m[key];
}
total = get_usertime() - before;
printf("%ld/s (%0.1f%% of upb)\n", (long)(i / total), i / upb_rand_i);
printf("std::unordered_map<uint32_t, uint32_t>(seq): ");
fflush(stdout);
before = get_usertime();
for (i = 0; true; i++) {
MAYBE_BREAK;
int32_t key = keys[rand_order[i & mask]];
x += hm[key];
}
total = get_usertime() - before;
printf("%ld/s (%0.1f%% of upb)\n", (long)(i / total), i / upb_seq_i);
printf("std::unordered_map<uint32_t, uint32_t>(rand): ");
fflush(stdout);
before = get_usertime();
for (i = 0; true; i++) {
MAYBE_BREAK;
int32_t key = keys[rand_order[i & mask]];
x += hm[key];
}
total = get_usertime() - before;
if (x == INT_MAX) abort();
printf("%ld/s (%0.1f%% of upb)\n\n", (long)(i / total), i / upb_rand_i);
delete[] rand_order;
}
INSTANTIATE_TEST_SUITE_P(IntTableParams, IntTableTest,
testing::Values(8, 64, 512, -32));
/*
* This test can't pass right now because the table can't store a value of
* (uint64_t)-1.
*/
void test_int64_max_value() {
TEST(Table, MaxValue) {
/*
typedef upb::TypedIntTable<uint64_t> Table;
Table table;
@ -613,13 +551,7 @@ void test_int64_max_value() {
*/
}
int32_t* get_contiguous_keys(int32_t num) {
int32_t* buf = new int32_t[num];
for (int32_t i = 0; i < num; i++) buf[i] = i;
return buf;
}
void test_delete() {
TEST(Table, Delete) {
upb::Arena arena;
upb_inttable t;
upb_inttable_init(&t, arena.ptr());
@ -634,11 +566,11 @@ void test_delete() {
upb_inttable_iter iter;
for (upb_inttable_begin(&iter, &t); !upb_inttable_done(&iter);
upb_inttable_next(&iter)) {
ASSERT(false);
ASSERT_TRUE(false);
}
}
void test_init() {
TEST(Table, Init) {
for (int i = 0; i < 2048; i++) {
/* Tests that the size calculations in init() (lg2 size for target load)
* work for all expected sizes. */
@ -647,63 +579,3 @@ void test_init() {
upb_strtable_init(&t, i, arena.ptr());
}
}
extern "C" {
int run_tests(int argc, char* argv[]) {
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "benchmark") == 0) benchmark = true;
}
vector<std::string> keys;
keys.push_back("google.protobuf.FileDescriptorSet");
keys.push_back("google.protobuf.FileDescriptorProto");
keys.push_back("google.protobuf.DescriptorProto");
keys.push_back("google.protobuf.DescriptorProto.ExtensionRange");
keys.push_back("google.protobuf.FieldDescriptorProto");
keys.push_back("google.protobuf.EnumDescriptorProto");
keys.push_back("google.protobuf.EnumValueDescriptorProto");
keys.push_back("google.protobuf.ServiceDescriptorProto");
keys.push_back("google.protobuf.MethodDescriptorProto");
keys.push_back("google.protobuf.FileOptions");
keys.push_back("google.protobuf.MessageOptions");
keys.push_back("google.protobuf.FieldOptions");
keys.push_back("google.protobuf.EnumOptions");
keys.push_back("google.protobuf.EnumValueOptions");
keys.push_back("google.protobuf.ServiceOptions");
keys.push_back("google.protobuf.MethodOptions");
keys.push_back("google.protobuf.UninterpretedOption");
keys.push_back("google.protobuf.UninterpretedOption.NamePart");
for (int i = 0; i < 10; i++) {
test_strtable(keys, 18);
}
int32_t* keys1 = get_contiguous_keys(8);
test_inttable(keys1, 8, "Table size: 8, keys: 1-8 ====");
delete[] keys1;
int32_t* keys2 = get_contiguous_keys(64);
test_inttable(keys2, 64, "Table size: 64, keys: 1-64 ====\n");
delete[] keys2;
int32_t* keys3 = get_contiguous_keys(512);
test_inttable(keys3, 512, "Table size: 512, keys: 1-512 ====\n");
delete[] keys3;
int32_t* keys4 = new int32_t[64];
for (int32_t i = 0; i < 64; i++) {
if (i < 32)
keys4[i] = i + 1;
else
keys4[i] = 10101 + i;
}
test_inttable(keys4, 64, "Table size: 64, keys: 1-32 and 10133-10164 ====\n");
delete[] keys4;
test_delete();
test_int64_max_value();
return 0;
}
}

@ -1,40 +0,0 @@
// Copyright (c) 2009-2021, Google LLC
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of Google LLC nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdlib.h>
#ifdef USE_GOOGLE
#include "base/init_google.h"
#endif
extern "C" {
int run_tests(int argc, char* argv[]);
}
int main(int argc, char* argv[]) {
#ifdef USE_GOOGLE
InitGoogle(NULL, &argc, &argv, true);
#endif
run_tests(argc, argv);
}

@ -1,83 +0,0 @@
/*
* Copyright (c) 2009-2021, Google LLC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Google LLC nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UPB_TEST_H_
#define UPB_TEST_H_
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
int num_assertions = 0;
uint32_t testhash = 0;
#define PRINT_FAILURE(expr) \
fprintf(stderr, "Assertion failed: %s:%d\n", __FILE__, __LINE__); \
fprintf(stderr, "expr: %s\n", #expr); \
if (testhash) { \
fprintf(stderr, \
"assertion failed running test %x. " \
"Run with the arg %x to run only this test.\n", \
testhash, testhash); \
}
#define ASSERT(expr) \
do { \
++num_assertions; \
if (!(expr)) { \
PRINT_FAILURE(expr) \
abort(); \
} \
} while (0)
#define ASSERT_NOCOUNT(expr) \
do { \
if (!(expr)) { \
PRINT_FAILURE(expr) \
abort(); \
} \
} while (0)
#define ASSERT_STATUS(expr, status) \
do { \
++num_assertions; \
if (!(expr)) { \
PRINT_FAILURE(expr) \
fprintf(stderr, "failed status: %s\n", upb_Status_ErrorMessage(status)); \
abort(); \
} \
} while (0)
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* UPB_DECODER_H_ */
Loading…
Cancel
Save