9d75253764
"By my deeds I honor him. V8." - Add basic build files for library and unittests. - Integrate unittests also in existing V8 unittests for simplicity. The CL also adds FinalizerTrait and unittests to allow building a testing target that executes code. FinalizerTrait is used to determine how managed C++ types are finalized. The trait should not be overridable by users but needs to be exposed on API-level to avoid including library-internal headers. Bug: chromium:1056170 Change-Id: I64d91053410a17a7835e50547f58990625d2da28 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2108549 Reviewed-by: Hannes Payer <hpayer@chromium.org> Reviewed-by: Omer Katz <omerkatz@chromium.org> Reviewed-by: Michael Achenbach <machenbach@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Commit-Queue: Michael Lippautz <mlippautz@chromium.org> Cr-Commit-Position: refs/heads/master@{#66834}
119 lines
3.3 KiB
C++
119 lines
3.3 KiB
C++
// Copyright 2020 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "include/cppgc/finalizer-trait.h"
|
|
#include <type_traits>
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
namespace cppgc {
|
|
namespace internal {
|
|
|
|
namespace {
|
|
|
|
// Trivially destructible types.
|
|
class TypeWithoutDestructor final {};
|
|
class TypeWithPrimitive final {
|
|
public:
|
|
int foo = 0;
|
|
};
|
|
|
|
class InvokeCounter {
|
|
public:
|
|
static size_t kCallcount;
|
|
static void Reset() { kCallcount = 0; }
|
|
static void Invoke() { kCallcount++; }
|
|
};
|
|
|
|
size_t InvokeCounter::kCallcount = 0;
|
|
|
|
// Regular C++ use cases.
|
|
|
|
class TypeWithDestructor final : public InvokeCounter {
|
|
public:
|
|
~TypeWithDestructor() { Invoke(); }
|
|
};
|
|
|
|
class TypeWithVirtualDestructorBase {
|
|
public:
|
|
virtual ~TypeWithVirtualDestructorBase() = default;
|
|
};
|
|
|
|
class TypeWithVirtualDestructorChild final
|
|
: public TypeWithVirtualDestructorBase,
|
|
public InvokeCounter {
|
|
public:
|
|
~TypeWithVirtualDestructorChild() final { Invoke(); }
|
|
};
|
|
|
|
// Manual dispatch to avoid vtables.
|
|
|
|
class TypeWithCustomFinalizationMethod final : public InvokeCounter {
|
|
public:
|
|
void FinalizeGarbageCollectedObject() { Invoke(); }
|
|
};
|
|
|
|
class TypeWithCustomFinalizationMethodAtBase {
|
|
public:
|
|
void FinalizeGarbageCollectedObject();
|
|
};
|
|
|
|
class TypeWithCustomFinalizationMethodAtBaseChild
|
|
: public TypeWithCustomFinalizationMethodAtBase,
|
|
public InvokeCounter {
|
|
public:
|
|
~TypeWithCustomFinalizationMethodAtBaseChild() { Invoke(); }
|
|
};
|
|
|
|
void TypeWithCustomFinalizationMethodAtBase::FinalizeGarbageCollectedObject() {
|
|
// The test knows that base is only inherited by a single child. In practice
|
|
// users can maintain a map of valid types in already existing storage.
|
|
static_cast<TypeWithCustomFinalizationMethodAtBaseChild*>(this)
|
|
->~TypeWithCustomFinalizationMethodAtBaseChild();
|
|
}
|
|
|
|
template <typename Type>
|
|
void ExpectFinalizerIsInvoked(Type* object) {
|
|
InvokeCounter::Reset();
|
|
EXPECT_NE(nullptr, FinalizerTrait<Type>::kCallback);
|
|
FinalizerTrait<Type>::kCallback(object);
|
|
EXPECT_EQ(1u, InvokeCounter::kCallcount);
|
|
operator delete(object);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST(FinalizerTrait, TypeWithoutDestructorHasNoFinalizer) {
|
|
static_assert(std::is_trivially_destructible<TypeWithoutDestructor>::value,
|
|
"trivially destructible");
|
|
EXPECT_EQ(nullptr, FinalizerTrait<TypeWithoutDestructor>::kCallback);
|
|
}
|
|
|
|
TEST(FinalizerTrait, TypeWithPrimitiveHasNoFinalizer) {
|
|
static_assert(std::is_trivially_destructible<TypeWithPrimitive>::value,
|
|
"trivially destructible");
|
|
EXPECT_EQ(nullptr, FinalizerTrait<TypeWithPrimitive>::kCallback);
|
|
}
|
|
|
|
TEST(FinalizerTrait, FinalizerForTypeWithDestructor) {
|
|
ExpectFinalizerIsInvoked(new TypeWithDestructor());
|
|
}
|
|
|
|
TEST(FinalizerTrait, FinalizerForTypeWithVirtualBaseDtor) {
|
|
TypeWithVirtualDestructorBase* base = new TypeWithVirtualDestructorChild();
|
|
ExpectFinalizerIsInvoked(base);
|
|
}
|
|
|
|
TEST(FinalizerTrait, FinalizerForCustomFinalizationMethod) {
|
|
ExpectFinalizerIsInvoked(new TypeWithCustomFinalizationMethod());
|
|
}
|
|
|
|
TEST(FinalizerTrait, FinalizerForCustomFinalizationMethodInBase) {
|
|
TypeWithCustomFinalizationMethodAtBase* base =
|
|
new TypeWithCustomFinalizationMethodAtBaseChild();
|
|
ExpectFinalizerIsInvoked(base);
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace cppgc
|