lokinet/test/util/test_llarp_util_object.cpp

162 lines
4.3 KiB
C++
Raw Normal View History

2019-03-20 23:18:32 +00:00
#include <util/object.hpp>
#include <array>
#include <thread>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
using namespace llarp::object;
TEST(Object, VerifySize)
{
static_assert(sizeof(Buffer< char >) == sizeof(char), "");
static_assert(sizeof(Buffer< int >) == sizeof(int), "");
static_assert(sizeof(Buffer< double >) == sizeof(double), "");
static_assert(sizeof(Buffer< std::string >) == sizeof(std::string), "");
}
TEST(Object, Inplace)
{
// Verify we can create and destroy a type with a non-trivial destructor
Buffer< std::vector< std::string > > strBuf;
new(strBuf.buffer()) std::vector< std::string >(100, "abc");
strBuf.value().~vector();
}
TEST(Catalog, smoke)
{
const double value1 = 1.0;
const double value2 = 2.0;
2019-03-29 22:14:22 +00:00
int32_t handle1 = -1;
int32_t handle2 = -1;
2019-03-20 23:18:32 +00:00
Catalog< double > catalog;
handle1 = catalog.add(value1);
catalog.remove(handle1);
for(size_t j = 0; j < 5; ++j)
{
for(size_t i = 1; i < 256; ++i)
{
ASSERT_FALSE(catalog.find(handle1));
handle2 = catalog.add(value2);
catalog.remove(handle2);
}
handle2 = catalog.add(value2);
ASSERT_EQ(handle1, handle2);
ASSERT_TRUE(catalog.find(handle1));
absl::optional< double > result = catalog.find(handle1);
ASSERT_TRUE(result);
ASSERT_EQ(value2, result);
catalog.remove(handle2);
}
}
TEST(Catalog, Iterator)
{
static constexpr size_t THREAD_COUNT = 10;
static constexpr size_t ITERATION_COUNT = 1000;
2019-03-29 22:14:22 +00:00
static constexpr int32_t MAX = std::numeric_limits< int32_t >::max();
2019-03-20 23:18:32 +00:00
std::array< std::thread, THREAD_COUNT + 3 > threads;
using llarp::util::Barrier;
2019-03-29 22:14:22 +00:00
using Iterator = CatalogIterator< int32_t >;
using Cat = Catalog< int32_t >;
2019-03-20 23:18:32 +00:00
Barrier barrier(THREAD_COUNT + 3);
Cat catalog;
// Repeatedly remove + add values from the catalog
for(size_t i = 0; i < THREAD_COUNT; ++i)
{
threads[i] = std::thread(
2019-03-29 22:14:22 +00:00
[](Barrier *barrier, Cat *catalog, int32_t id) {
2019-03-20 23:18:32 +00:00
barrier->Block();
for(size_t i = 0; i < ITERATION_COUNT; ++i)
{
2019-03-29 22:14:22 +00:00
int32_t handle = catalog->add(id);
absl::optional< int32_t > res = catalog->find(handle);
2019-03-20 23:18:32 +00:00
ASSERT_TRUE(res);
ASSERT_EQ(res.value(), id);
2019-03-29 22:14:22 +00:00
ASSERT_TRUE(catalog->replace(MAX - id, handle));
res = catalog->find(handle);
2019-03-20 23:18:32 +00:00
ASSERT_TRUE(res);
2019-03-29 22:14:22 +00:00
ASSERT_EQ(MAX - id, res.value());
int32_t removed = 0;
ASSERT_TRUE(catalog->remove(handle, &removed));
ASSERT_EQ(removed, MAX - id);
ASSERT_FALSE(catalog->find(handle));
2019-03-20 23:18:32 +00:00
}
},
&barrier, &catalog, i);
}
// Verify the length constraint is never violated
threads[THREAD_COUNT] = std::thread(
[](Barrier *barrier, Cat *catalog) {
barrier->Block();
for(size_t i = 0; i < ITERATION_COUNT; ++i)
{
size_t size = catalog->size();
ASSERT_LE(size, THREAD_COUNT);
}
},
&barrier, &catalog);
// Verify that iteration always produces a valid state
threads[THREAD_COUNT + 1] = std::thread(
[](Barrier *barrier, Cat *catalog) {
barrier->Block();
for(size_t i = 0; i < ITERATION_COUNT; ++i)
{
2019-03-29 22:14:22 +00:00
int32_t arr[100];
2019-03-20 23:18:32 +00:00
size_t size = 0;
2019-03-29 22:14:22 +00:00
for(Iterator it(catalog); it; ++it)
2019-03-20 23:18:32 +00:00
{
arr[size++] = it().second;
}
2019-03-29 22:14:22 +00:00
for(int32_t j = 0; j < 100; j++)
2019-03-20 23:18:32 +00:00
{
// value must be valid
bool present = false;
2019-03-29 22:14:22 +00:00
for(int32_t id = 0; id < static_cast< int32_t >(THREAD_COUNT); id++)
2019-03-20 23:18:32 +00:00
{
2019-03-29 22:14:22 +00:00
if(id == arr[j] || MAX - id == arr[j])
2019-03-20 23:18:32 +00:00
{
present = true;
break;
}
}
// no duplicate should be there
2019-03-29 22:14:22 +00:00
for(size_t k = j + 1; k < size; k++)
2019-03-20 23:18:32 +00:00
{
2019-03-29 22:14:22 +00:00
ASSERT_NE(arr[j], arr[k]);
2019-03-20 23:18:32 +00:00
}
}
}
},
&barrier, &catalog);
// And that we don't have an invalid catalog
threads[THREAD_COUNT + 2] = std::thread(
[](Barrier *barrier, Cat *catalog) {
barrier->Block();
for(size_t i = 0; i < ITERATION_COUNT; ++i)
{
catalog->verify();
}
},
&barrier, &catalog);
for(std::thread &t : threads)
{
t.join();
}
}