blob: 5323dea080de3cdecac48c5ff0c2741bb96f4335 [file] [log] [blame]
#include "aos/complex_thread_local.h"
#include <atomic>
#include <thread>
#include "gtest/gtest.h"
namespace aos {
namespace testing {
class ComplexThreadLocalTest : public ::testing::Test {
protected:
struct TraceableObject {
TraceableObject(int data = 0) : data(data) { ++constructions; }
~TraceableObject() { ++destructions; }
static ::std::atomic<int> constructions, destructions;
int data;
};
ComplexThreadLocal<TraceableObject> local;
private:
void SetUp() override {
local.Clear();
EXPECT_EQ(TraceableObject::constructions, TraceableObject::destructions)
<< "There should be no way to create and destroy different numbers.";
TraceableObject::constructions = TraceableObject::destructions = 0;
}
};
::std::atomic<int> ComplexThreadLocalTest::TraceableObject::constructions;
::std::atomic<int> ComplexThreadLocalTest::TraceableObject::destructions;
TEST_F(ComplexThreadLocalTest, Basic) {
EXPECT_EQ(0, TraceableObject::constructions);
EXPECT_EQ(0, TraceableObject::destructions);
EXPECT_FALSE(local.created());
EXPECT_EQ(nullptr, local.get());
local.Create(971);
EXPECT_EQ(1, TraceableObject::constructions);
EXPECT_EQ(0, TraceableObject::destructions);
EXPECT_TRUE(local.created());
EXPECT_EQ(971, local->data);
local.Create(254);
EXPECT_EQ(1, TraceableObject::constructions);
EXPECT_EQ(0, TraceableObject::destructions);
EXPECT_TRUE(local.created());
EXPECT_EQ(971, local->data);
local.Clear();
EXPECT_EQ(1, TraceableObject::constructions);
EXPECT_EQ(1, TraceableObject::destructions);
EXPECT_FALSE(local.created());
EXPECT_EQ(nullptr, local.get());
local.Create(973);
EXPECT_EQ(2, TraceableObject::constructions);
EXPECT_EQ(1, TraceableObject::destructions);
EXPECT_TRUE(local.created());
EXPECT_EQ(973, local->data);
}
TEST_F(ComplexThreadLocalTest, AnotherThread) {
EXPECT_FALSE(local.created());
std::thread t1([this]() {
EXPECT_FALSE(local.created());
local.Create(971);
EXPECT_TRUE(local.created());
EXPECT_EQ(971, local->data);
EXPECT_EQ(1, TraceableObject::constructions);
EXPECT_EQ(0, TraceableObject::destructions);
});
t1.join();
EXPECT_EQ(1, TraceableObject::constructions);
EXPECT_EQ(1, TraceableObject::destructions);
EXPECT_FALSE(local.created());
}
TEST_F(ComplexThreadLocalTest, TwoThreads) {
std::thread thread([this]() {
local.Create(971);
EXPECT_EQ(971, local->data);
EXPECT_EQ(0, TraceableObject::destructions);
});
local.Create(973);
EXPECT_EQ(973, local->data);
thread.join();
EXPECT_TRUE(local.created());
EXPECT_EQ(2, TraceableObject::constructions);
EXPECT_EQ(1, TraceableObject::destructions);
local.Clear();
EXPECT_EQ(2, TraceableObject::constructions);
EXPECT_EQ(2, TraceableObject::destructions);
EXPECT_FALSE(local.created());
}
} // namespace testing
} // namespace aos