blob: 5e04ffed23163383f369eacc4d9c9fe0c2bac51f [file] [log] [blame]
/*
* Copyright (C) 2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "RefLogger.h"
#include "Utilities.h"
#include <wtf/CompactUniquePtrTuple.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
namespace TestWebKitAPI {
namespace CompactUniquePtrTupleTest {
class A {
WTF_MAKE_FAST_ALLOCATED;
public:
A() { ++s_constructorCallCount; }
virtual ~A() { ++s_destructorCallCount; }
static unsigned s_constructorCallCount;
static unsigned s_destructorCallCount;
};
unsigned A::s_constructorCallCount = 0;
unsigned A::s_destructorCallCount = 0;
} // namespace CompactUniquePtrTupleTest
using namespace CompactUniquePtrTupleTest;
TEST(WTF_CompactUniquePtrTuple, Basic)
{
A::s_constructorCallCount = 0;
A::s_destructorCallCount = 0;
CompactUniquePtrTuple<A, uint16_t> empty;
EXPECT_EQ(0U, A::s_constructorCallCount);
EXPECT_EQ(0U, A::s_destructorCallCount);
EXPECT_EQ(nullptr, empty.pointer());
EXPECT_EQ(0U, empty.type());
CompactUniquePtrTuple<A, uint16_t> a = makeCompactUniquePtr<A, uint16_t>();
EXPECT_EQ(1U, A::s_constructorCallCount);
EXPECT_EQ(0U, A::s_destructorCallCount);
EXPECT_NE(nullptr, a.pointer());
EXPECT_EQ(0U, a.type());
a.setPointer(nullptr);
EXPECT_EQ(1U, A::s_constructorCallCount);
EXPECT_EQ(1U, A::s_destructorCallCount);
EXPECT_EQ(nullptr, a.pointer());
EXPECT_EQ(0U, a.type());
a = makeCompactUniquePtr<A, uint16_t>();
EXPECT_EQ(2U, A::s_constructorCallCount);
EXPECT_EQ(1U, A::s_destructorCallCount);
EXPECT_NE(nullptr, a.pointer());
EXPECT_EQ(0U, a.type());
a.setType(0xffffU);
EXPECT_EQ(2U, A::s_constructorCallCount);
EXPECT_EQ(1U, A::s_destructorCallCount);
EXPECT_NE(nullptr, a.pointer());
EXPECT_EQ(0xffffU, a.type());
a.setPointer(makeUnique<A>());
A* oldPointer = a.pointer();
EXPECT_EQ(3U, A::s_constructorCallCount);
EXPECT_EQ(2U, A::s_destructorCallCount);
EXPECT_NE(nullptr, a.pointer());
EXPECT_EQ(0xffffU, a.type());
a.setType(0x1010U);
EXPECT_EQ(3U, A::s_constructorCallCount);
EXPECT_EQ(2U, A::s_destructorCallCount);
EXPECT_EQ(oldPointer, a.pointer());
EXPECT_EQ(0x1010U, a.type());
a = makeCompactUniquePtr<A, uint16_t>();
EXPECT_EQ(4U, A::s_constructorCallCount);
EXPECT_EQ(3U, A::s_destructorCallCount);
EXPECT_NE(nullptr, a.pointer());
EXPECT_EQ(0x0U, a.type());
a.setType(0xf2f2U);
EXPECT_EQ(4U, A::s_constructorCallCount);
EXPECT_EQ(3U, A::s_destructorCallCount);
EXPECT_NE(nullptr, a.pointer());
EXPECT_EQ(0xf2f2U, a.type());
oldPointer = a.pointer();
auto movedA = a.moveToUniquePtr();
EXPECT_EQ(4U, A::s_constructorCallCount);
EXPECT_EQ(3U, A::s_destructorCallCount);
EXPECT_EQ(nullptr, a.pointer());
EXPECT_EQ(movedA.get(), oldPointer);
EXPECT_EQ(0xf2f2U, a.type());
a.setPointer(WTFMove(movedA));
EXPECT_EQ(4U, A::s_constructorCallCount);
EXPECT_EQ(3U, A::s_destructorCallCount);
EXPECT_EQ(oldPointer, a.pointer());
EXPECT_EQ(movedA.get(), nullptr);
EXPECT_EQ(0xf2f2U, a.type());
CompactUniquePtrTuple<A, uint16_t> b = WTFMove(a);
EXPECT_EQ(4U, A::s_constructorCallCount);
EXPECT_EQ(3U, A::s_destructorCallCount);
EXPECT_EQ(nullptr, a.pointer());
EXPECT_EQ(0, a.type());
EXPECT_EQ(oldPointer, b.pointer());
EXPECT_EQ(0xf2f2U, b.type());
CompactUniquePtrTuple<A, uint16_t>* bPtr = &b;
b = WTFMove(*bPtr);
EXPECT_EQ(4U, A::s_constructorCallCount);
EXPECT_EQ(3U, A::s_destructorCallCount);
EXPECT_EQ(nullptr, a.pointer());
EXPECT_EQ(0, a.type());
EXPECT_EQ(oldPointer, b.pointer());
EXPECT_EQ(0xf2f2U, b.type());
b.setPointer(nullptr);
EXPECT_EQ(4U, A::s_constructorCallCount);
EXPECT_EQ(4U, A::s_destructorCallCount);
EXPECT_EQ(nullptr, a.pointer());
EXPECT_EQ(0, a.type());
EXPECT_EQ(nullptr, b.pointer());
EXPECT_EQ(0xf2f2U, b.type());
}
class B : public A {
WTF_MAKE_FAST_ALLOCATED;
public:
B() { ++s_constructorCallCount; }
virtual ~B() { ++s_destructorCallCount; }
static unsigned s_constructorCallCount;
static unsigned s_destructorCallCount;
};
unsigned B::s_constructorCallCount = 0;
unsigned B::s_destructorCallCount = 0;
TEST(WTF_CompactUniquePtrTuple, Subclassing)
{
A::s_constructorCallCount = 0;
A::s_destructorCallCount = 0;
B::s_constructorCallCount = 0;
B::s_destructorCallCount = 0;
CompactUniquePtrTuple<B, uint16_t> empty;
EXPECT_EQ(0U, A::s_constructorCallCount);
EXPECT_EQ(0U, A::s_destructorCallCount);
EXPECT_EQ(0U, B::s_constructorCallCount);
EXPECT_EQ(0U, B::s_destructorCallCount);
EXPECT_EQ(nullptr, empty.pointer());
EXPECT_EQ(0U, empty.type());
CompactUniquePtrTuple<B, uint16_t> b = makeCompactUniquePtr<B, uint16_t>();
EXPECT_EQ(1U, A::s_constructorCallCount);
EXPECT_EQ(0U, A::s_destructorCallCount);
EXPECT_EQ(1U, B::s_constructorCallCount);
EXPECT_EQ(0U, B::s_destructorCallCount);
EXPECT_NE(nullptr, b.pointer());
EXPECT_EQ(0U, b.type());
b.setType(0xff);
EXPECT_EQ(1U, A::s_constructorCallCount);
EXPECT_EQ(0U, A::s_destructorCallCount);
EXPECT_EQ(1U, B::s_constructorCallCount);
EXPECT_EQ(0U, B::s_destructorCallCount);
EXPECT_NE(nullptr, b.pointer());
EXPECT_EQ(0xffU, b.type());
b.setPointer(nullptr);
EXPECT_EQ(1U, A::s_constructorCallCount);
EXPECT_EQ(1U, A::s_destructorCallCount);
EXPECT_EQ(1U, B::s_constructorCallCount);
EXPECT_EQ(1U, B::s_destructorCallCount);
EXPECT_EQ(nullptr, b.pointer());
EXPECT_EQ(0xffU, b.type());
CompactUniquePtrTuple<A, uint16_t> a = makeCompactUniquePtr<B, uint16_t>();
EXPECT_EQ(2U, A::s_constructorCallCount);
EXPECT_EQ(1U, A::s_destructorCallCount);
EXPECT_EQ(2U, B::s_constructorCallCount);
EXPECT_EQ(1U, B::s_destructorCallCount);
EXPECT_NE(nullptr, a.pointer());
EXPECT_EQ(0U, a.type());
a.setType(0x1c);
EXPECT_EQ(2U, A::s_constructorCallCount);
EXPECT_EQ(1U, A::s_destructorCallCount);
EXPECT_EQ(2U, B::s_constructorCallCount);
EXPECT_EQ(1U, B::s_destructorCallCount);
EXPECT_NE(nullptr, a.pointer());
EXPECT_EQ(0x1cU, a.type());
auto* oldPointer = a.pointer();
a.setPointer(makeUnique<B>());
EXPECT_EQ(3U, A::s_constructorCallCount);
EXPECT_EQ(2U, A::s_destructorCallCount);
EXPECT_EQ(3U, B::s_constructorCallCount);
EXPECT_EQ(2U, B::s_destructorCallCount);
EXPECT_NE(oldPointer, a.pointer());
EXPECT_EQ(0x1cU, a.type());
oldPointer = a.pointer();
a = makeCompactUniquePtr<A, uint16_t>();
EXPECT_EQ(4U, A::s_constructorCallCount);
EXPECT_EQ(3U, A::s_destructorCallCount);
EXPECT_EQ(3U, B::s_constructorCallCount);
EXPECT_EQ(3U, B::s_destructorCallCount);
EXPECT_NE(oldPointer, a.pointer());
EXPECT_EQ(0U, a.type());
a.setType(0xfed);
EXPECT_EQ(4U, A::s_constructorCallCount);
EXPECT_EQ(3U, A::s_destructorCallCount);
EXPECT_EQ(3U, B::s_constructorCallCount);
EXPECT_EQ(3U, B::s_destructorCallCount);
EXPECT_NE(nullptr, a.pointer());
EXPECT_EQ(0xfedU, a.type());
oldPointer = a.pointer();
auto uniqueA = a.moveToUniquePtr();
EXPECT_EQ(4U, A::s_constructorCallCount);
EXPECT_EQ(3U, A::s_destructorCallCount);
EXPECT_EQ(3U, B::s_constructorCallCount);
EXPECT_EQ(3U, B::s_destructorCallCount);
EXPECT_EQ(nullptr, a.pointer());
EXPECT_EQ(oldPointer, uniqueA.get());
EXPECT_EQ(0xfedU, a.type());
uniqueA = nullptr;
EXPECT_EQ(4U, A::s_constructorCallCount);
EXPECT_EQ(4U, A::s_destructorCallCount);
EXPECT_EQ(3U, B::s_constructorCallCount);
EXPECT_EQ(3U, B::s_destructorCallCount);
EXPECT_EQ(nullptr, a.pointer());
EXPECT_EQ(nullptr, uniqueA.get());
EXPECT_EQ(0xfedU, a.type());
}
struct ADeleter {
static unsigned s_callCount;
void operator()(A* a) const
{
++s_callCount;
delete a;
}
};
unsigned ADeleter::s_callCount = 0;
TEST(WTF_CompactUniquePtrTuple, Deleter)
{
A::s_constructorCallCount = 0;
A::s_destructorCallCount = 0;
B::s_constructorCallCount = 0;
B::s_destructorCallCount = 0;
ADeleter::s_callCount = 0;
CompactUniquePtrTuple<B, uint16_t, ADeleter> empty;
EXPECT_EQ(0U, A::s_constructorCallCount);
EXPECT_EQ(0U, A::s_destructorCallCount);
EXPECT_EQ(0U, B::s_constructorCallCount);
EXPECT_EQ(0U, B::s_destructorCallCount);
EXPECT_EQ(0U, ADeleter::s_callCount);
EXPECT_EQ(nullptr, empty.pointer());
EXPECT_EQ(0U, empty.type());
CompactUniquePtrTuple<A, uint16_t, ADeleter> a = makeCompactUniquePtr<A, uint16_t, ADeleter>();
EXPECT_EQ(1U, A::s_constructorCallCount);
EXPECT_EQ(0U, A::s_destructorCallCount);
EXPECT_EQ(0U, B::s_constructorCallCount);
EXPECT_EQ(0U, B::s_destructorCallCount);
EXPECT_EQ(0U, ADeleter::s_callCount);
EXPECT_NE(nullptr, a.pointer());
EXPECT_EQ(0U, a.type());
a.setType(0x7e89U);
EXPECT_EQ(1U, A::s_constructorCallCount);
EXPECT_EQ(0U, A::s_destructorCallCount);
EXPECT_EQ(0U, B::s_constructorCallCount);
EXPECT_EQ(0U, B::s_destructorCallCount);
EXPECT_EQ(0U, ADeleter::s_callCount);
EXPECT_NE(nullptr, a.pointer());
EXPECT_EQ(0x7e89U, a.type());
auto* oldPointer = a.pointer();
a.setPointer(std::unique_ptr<B, ADeleter>(new B));
EXPECT_EQ(2U, A::s_constructorCallCount);
EXPECT_EQ(1U, A::s_destructorCallCount);
EXPECT_EQ(1U, B::s_constructorCallCount);
EXPECT_EQ(0U, B::s_destructorCallCount);
EXPECT_EQ(1U, ADeleter::s_callCount);
EXPECT_NE(oldPointer, a.pointer());
EXPECT_EQ(0x7e89U, a.type());
}
} // namespace TestWebKitAPI