[K/N][Runtime] Support nice mocks for scoped mock functions

This commit is contained in:
Ilya Matveev
2021-07-19 17:01:10 +07:00
committed by Space
parent f098bf449c
commit e85761bc47
4 changed files with 62 additions and 37 deletions
@@ -16,6 +16,7 @@
#include "Types.h"
using namespace kotlin;
using namespace kotlin::test_support;
using testing::_;
// TODO: Also test disposal. (This requires extracting Worker interface)
@@ -15,6 +15,8 @@
using namespace kotlin;
using ::testing::_;
using ::kotlin::test_support::ScopedReportUnhandledExceptionMock;
using ::kotlin::test_support::ScopedKotlin_runUnhandledExceptionHookMock;
namespace {
@@ -12,29 +12,43 @@
#include "Types.h"
#include "Utils.hpp"
template <class F>
class ScopedStrictMockFunction : private kotlin::MoveOnly {
public:
using Mock = testing::StrictMock<testing::MockFunction<F>>;
namespace kotlin {
namespace test_support {
explicit ScopedStrictMockFunction(Mock** globalMockLocation) : globalMockLocation_(globalMockLocation) {
RuntimeCheck(globalMockLocation != nullptr, "ScopedStrictMockFunction needs non-null global mock location");
RuntimeCheck(*globalMockLocation == nullptr, "ScopedStrictMockFunction needs null global mock");
namespace internal {
extern testing::MockFunction<KInt()>* createCleanerWorkerMock;
extern testing::MockFunction<void(KInt, bool)>* shutdownCleanerWorkerMock;
extern testing::MockFunction<void(KRef)>* reportUnhandledExceptionMock;
extern testing::MockFunction<void(KRef)>* Kotlin_runUnhandledExceptionHookMock;
} // namespace internal
template <class F, bool Strict = true>
class ScopedMockFunction : private kotlin::MoveOnly {
public:
using Mock = typename std::conditional_t<Strict,
testing::StrictMock<testing::MockFunction<F>>,
testing::NiceMock<testing::MockFunction<F>>>;
explicit ScopedMockFunction(testing::MockFunction<F>** globalMockLocation) : globalMockLocation_(globalMockLocation) {
RuntimeCheck(globalMockLocation != nullptr, "ScopedMockFunction needs non-null global mock location");
RuntimeCheck(*globalMockLocation == nullptr, "ScopedMockFunction needs null global mock");
mock_ = make_unique<Mock>();
*globalMockLocation_ = mock_.get();
}
ScopedStrictMockFunction(ScopedStrictMockFunction&& rhs) : globalMockLocation_(rhs.globalMockLocation_), mock_(std::move(rhs.mock_)) {
ScopedMockFunction(ScopedMockFunction&& rhs) : globalMockLocation_(rhs.globalMockLocation_), mock_(std::move(rhs.mock_)) {
rhs.globalMockLocation_ = nullptr;
}
ScopedStrictMockFunction& operator=(ScopedStrictMockFunction&& rhs) {
ScopedStrictMockFunction tmp(std::move(rhs));
ScopedMockFunction& operator=(ScopedMockFunction&& rhs) {
ScopedMockFunction tmp(std::move(rhs));
swap(tmp);
return *this;
}
~ScopedStrictMockFunction() {
~ScopedMockFunction() {
if (!globalMockLocation_) return;
RuntimeCheck(*globalMockLocation_ == mock_.get(), "unexpected global mock location");
@@ -44,7 +58,7 @@ public:
*globalMockLocation_ = nullptr;
}
void swap(ScopedStrictMockFunction& other) {
void swap(ScopedMockFunction& other) {
std::swap(globalMockLocation_, other.globalMockLocation_);
std::swap(mock_, other.mock_);
}
@@ -54,11 +68,29 @@ public:
private:
// Can be null if moved-out of.
Mock** globalMockLocation_;
testing::MockFunction<F>** globalMockLocation_;
KStdUniquePtr<Mock> mock_;
};
ScopedStrictMockFunction<KInt()> ScopedCreateCleanerWorkerMock();
ScopedStrictMockFunction<void(KInt, bool)> ScopedShutdownCleanerWorkerMock();
ScopedStrictMockFunction<void(KRef)> ScopedReportUnhandledExceptionMock();
ScopedStrictMockFunction<void(KRef)> ScopedKotlin_runUnhandledExceptionHookMock();
template<bool Strict = true>
ScopedMockFunction<KInt(), Strict> ScopedCreateCleanerWorkerMock() {
return ScopedMockFunction<KInt(), Strict>(&internal::createCleanerWorkerMock);
}
template<bool Strict = true>
ScopedMockFunction<void(KInt, bool), Strict> ScopedShutdownCleanerWorkerMock() {
return ScopedMockFunction<void(KInt, bool), Strict>(&internal::shutdownCleanerWorkerMock);
}
template<bool Strict = true>
ScopedMockFunction<void(KRef), Strict> ScopedReportUnhandledExceptionMock() {
return ScopedMockFunction<void(KRef), Strict>(&internal::reportUnhandledExceptionMock);
}
template<bool Strict = true>
ScopedMockFunction<void(KRef), Strict> ScopedKotlin_runUnhandledExceptionHookMock() {
return ScopedMockFunction<void(KRef), Strict>(&internal::Kotlin_runUnhandledExceptionHookMock);
}
} // namespace test_support
} // namespace kotlin
@@ -8,6 +8,16 @@
#include "ObjectTestSupport.hpp"
#include "Types.h"
using kotlin::test_support::internal::createCleanerWorkerMock;
using kotlin::test_support::internal::shutdownCleanerWorkerMock;
using kotlin::test_support::internal::reportUnhandledExceptionMock;
using kotlin::test_support::internal::Kotlin_runUnhandledExceptionHookMock;
testing::MockFunction<KInt()>* kotlin::test_support::internal::createCleanerWorkerMock = nullptr;
testing::MockFunction<void(KInt, bool)>* kotlin::test_support::internal::shutdownCleanerWorkerMock = nullptr;
testing::MockFunction<void(KRef)>* kotlin::test_support::internal::reportUnhandledExceptionMock = nullptr;
testing::MockFunction<void(KRef)>* kotlin::test_support::internal::Kotlin_runUnhandledExceptionHookMock = nullptr;
namespace {
struct EmptyPayload {
@@ -49,11 +59,6 @@ struct KBox {
const T value;
};
testing::StrictMock<testing::MockFunction<KInt()>>* createCleanerWorkerMock = nullptr;
testing::StrictMock<testing::MockFunction<void(KInt, bool)>>* shutdownCleanerWorkerMock = nullptr;
testing::StrictMock<testing::MockFunction<void(KRef)>>* reportUnhandledExceptionMock = nullptr;
testing::StrictMock<testing::MockFunction<void(KRef)>>* Kotlin_runUnhandledExceptionHookMock = nullptr;
} // namespace
extern "C" {
@@ -285,18 +290,3 @@ KInt Kotlin_CleanerImpl_createCleanerWorker() {
} // extern "C"
ScopedStrictMockFunction<KInt()> ScopedCreateCleanerWorkerMock() {
return ScopedStrictMockFunction<KInt()>(&createCleanerWorkerMock);
}
ScopedStrictMockFunction<void(KInt, bool)> ScopedShutdownCleanerWorkerMock() {
return ScopedStrictMockFunction<void(KInt, bool)>(&shutdownCleanerWorkerMock);
}
ScopedStrictMockFunction<void(KRef)> ScopedReportUnhandledExceptionMock() {
return ScopedStrictMockFunction<void(KRef)>(&reportUnhandledExceptionMock);
}
ScopedStrictMockFunction<void(KRef)> ScopedKotlin_runUnhandledExceptionHookMock() {
return ScopedStrictMockFunction<void(KRef)>(&Kotlin_runUnhandledExceptionHookMock);
}