blob: 5a33fb0e8fd91457a1cb616e0bcb11c164daf5c8 [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 "Cleaner.h"
#include <future>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "TestSupport.hpp"
#include "TestSupportCompilerGenerated.hpp"
#include "Types.h"
using namespace kotlin;
using namespace kotlin::test_support;
using testing::_;
// TODO: Also test disposal. (This requires extracting Worker interface)
class CleanerTest : public testing::Test {
public:
CleanerTest() {}
~CleanerTest() {
ResetCleanerWorkerForTests();
}
};
TEST_F(CleanerTest, ConcurrentCreation) {
constexpr int threadCount = kotlin::kDefaultThreadCount;
constexpr KInt workerId = 42;
auto createCleanerWorkerMock = ScopedCreateCleanerWorkerMock();
EXPECT_CALL(*createCleanerWorkerMock, Call()).Times(1).WillOnce(testing::Return(workerId));
std::atomic startedThreads = 0;
std::atomic allowRunning = false;
std::vector<std::future<KInt>> futures;
for (int i = 0; i < threadCount; ++i) {
auto future = std::async(std::launch::async, [&startedThreads, &allowRunning]() {
// Thread state switching requires initilized memory subsystem.
ScopedMemoryInit init;
++startedThreads;
while (!allowRunning.load()) {
}
return Kotlin_CleanerImpl_getCleanerWorker();
});
futures.push_back(std::move(future));
}
while (startedThreads.load() != threadCount) {
}
allowRunning = true;
std::vector<KInt> values;
for (auto& future : futures) {
values.push_back(future.get());
}
ASSERT_THAT(values.size(), threadCount);
EXPECT_THAT(values, testing::Each(workerId));
}
TEST_F(CleanerTest, ShutdownWithoutCreation) {
RunInNewThread([]() {
auto createCleanerWorkerMock = ScopedCreateCleanerWorkerMock();
auto shutdownCleanerWorkerMock = ScopedShutdownCleanerWorkerMock();
EXPECT_CALL(*createCleanerWorkerMock, Call()).Times(0);
EXPECT_CALL(*shutdownCleanerWorkerMock, Call(_, _)).Times(0);
ShutdownCleaners(true);
});
}
TEST_F(CleanerTest, ShutdownWithCreation) {
RunInNewThread([]() {
constexpr KInt workerId = 42;
constexpr bool executeScheduledCleaners = true;
auto createCleanerWorkerMock = ScopedCreateCleanerWorkerMock();
auto shutdownCleanerWorkerMock = ScopedShutdownCleanerWorkerMock();
EXPECT_CALL(*createCleanerWorkerMock, Call()).WillOnce(testing::Return(workerId));
Kotlin_CleanerImpl_getCleanerWorker();
EXPECT_CALL(*shutdownCleanerWorkerMock, Call(workerId, executeScheduledCleaners));
ShutdownCleaners(executeScheduledCleaners);
});
}