blob: 00532077eb3e67729b630e392243e021dec15996 [file]
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
#include "ExtraObjectData.hpp"
#include <atomic>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "ObjectTestSupport.hpp"
#include "ScopedThread.hpp"
#include "TestSupport.hpp"
using namespace kotlin;
namespace {
struct EmptyPayload {
using Field = ObjHeader* EmptyPayload::*;
static constexpr std::array<Field, 0> kFields{};
};
class ExtraObjectDataTest : public testing::Test {
public:
ExtraObjectDataTest() {}
~ExtraObjectDataTest() {
mm::GlobalsRegistry::Instance().ClearForTests();
#ifndef CUSTOM_ALLOCATOR
mm::GlobalData::Instance().extraObjectDataFactory().ClearForTests();
#endif
mm::GlobalData::Instance().gc().ClearForTests();
}
};
} // namespace
TEST_F(ExtraObjectDataTest, Install) {
ScopedMemoryInit init;
test_support::TypeInfoHolder type{test_support::TypeInfoHolder::ObjectBuilder<EmptyPayload>()};
test_support::Object<EmptyPayload> object(type.typeInfo());
auto* typeInfo = object.header()->type_info();
ASSERT_FALSE(object.header()->has_meta_object());
auto& extraData = mm::ExtraObjectData::Install(object.header());
EXPECT_TRUE(object.header()->has_meta_object());
EXPECT_THAT(object.header()->meta_object(), extraData.AsMetaObjHeader());
EXPECT_THAT(object.header()->type_info(), typeInfo);
EXPECT_FALSE(extraData.HasRegularWeakReferenceImpl());
EXPECT_THAT(extraData.GetBaseObject(), object.header());
extraData.Uninstall();
mm::GlobalData::Instance().threadRegistry().CurrentThreadData()->ClearForTests();
EXPECT_FALSE(object.header()->has_meta_object());
EXPECT_THAT(object.header()->type_info(), typeInfo);
}
TEST_F(ExtraObjectDataTest, ConcurrentInstall) {
ScopedMemoryInit init;
test_support::TypeInfoHolder type{test_support::TypeInfoHolder::ObjectBuilder<EmptyPayload>()};
test_support::Object<EmptyPayload> object(type.typeInfo());
constexpr int kThreadCount = kDefaultThreadCount;
std::atomic<bool> canStart(false);
std::atomic<int> readyCount(0);
std::vector<ScopedThread> threads;
std::vector<mm::ExtraObjectData*> actual(kThreadCount, nullptr);
for (int i = 0; i < kThreadCount; ++i) {
threads.emplace_back([i, &actual, &object, &canStart, &readyCount]() {
ScopedMemoryInit init;
++readyCount;
while (!canStart) {
}
auto& extraData = mm::ExtraObjectData::Install(object.header());
actual[i] = &extraData;
mm::GlobalData::Instance().threadRegistry().CurrentThreadData()->Publish();
});
}
while (readyCount < kThreadCount) {
}
canStart = true;
threads.clear();
std::vector<mm::ExtraObjectData*> expected(kThreadCount, actual[0]);
EXPECT_THAT(actual, testing::ElementsAreArray(expected));
}