/* * Copyright (C) 2014 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 namespace TestWebKitAPI { static unsigned deletionCount; class CalculationDeletionTestNode : public WebCore::CalcExpressionNode { public: virtual ~CalculationDeletionTestNode() { ++deletionCount; } float evaluate(float) const override { return 0; } bool operator==(const CalcExpressionNode&) const override { ASSERT_NOT_REACHED(); return false; } }; static Ref createTestValue() { auto node = std::make_unique(); return WebCore::CalculationValue::create(WTFMove(node), WebCore::CalculationRangeAll); } TEST(CalculationValue, LengthConstruction) { RefPtr value = createTestValue(); EXPECT_EQ(1U, value->refCount()); { WebCore::Length length(*value); EXPECT_EQ(2U, value->refCount()); } EXPECT_EQ(1U, value->refCount()); { WebCore::Length lengthA(*value); EXPECT_EQ(2U, value->refCount()); WebCore::Length lengthB(lengthA); EXPECT_EQ(2U, value->refCount()); } EXPECT_EQ(1U, value->refCount()); { WebCore::Length lengthC(*value); EXPECT_EQ(2U, value->refCount()); WebCore::Length lengthD(WTFMove(lengthC)); EXPECT_EQ(2U, value->refCount()); } EXPECT_EQ(1U, value->refCount()); EXPECT_EQ(0U, deletionCount); value = nullptr; EXPECT_EQ(1U, deletionCount); deletionCount = 0; } TEST(CalculationValue, LengthConstructionReleasedValue) { RefPtr value = createTestValue(); EXPECT_EQ(1U, value->refCount()); { auto* rawValue = value.get(); WebCore::Length length(value.releaseNonNull()); EXPECT_EQ(1U, rawValue->refCount()); EXPECT_EQ(0U, deletionCount); } EXPECT_EQ(1U, deletionCount); deletionCount = 0; value = createTestValue(); { auto* rawValue = value.get(); WebCore::Length lengthA(value.releaseNonNull()); EXPECT_EQ(1U, rawValue->refCount()); WebCore::Length lengthB(lengthA); EXPECT_EQ(1U, rawValue->refCount()); EXPECT_EQ(0U, deletionCount); } EXPECT_EQ(1U, deletionCount); deletionCount = 0; value = createTestValue(); { auto* rawValue = value.get(); WebCore::Length lengthC(value.releaseNonNull()); EXPECT_EQ(1U, rawValue->refCount()); WebCore::Length lengthD(WTFMove(lengthC)); EXPECT_EQ(1U, rawValue->refCount()); EXPECT_EQ(0U, deletionCount); } EXPECT_EQ(1U, deletionCount); deletionCount = 0; } TEST(CalculationValue, LengthAssignment) { RefPtr value = createTestValue(); EXPECT_EQ(1U, value->refCount()); { WebCore::Length lengthA(*value); EXPECT_EQ(2U, value->refCount()); WebCore::Length lengthB; lengthB = lengthA; EXPECT_EQ(2U, value->refCount()); } EXPECT_EQ(1U, value->refCount()); { WebCore::Length lengthC(*value); EXPECT_EQ(2U, value->refCount()); WebCore::Length lengthD; lengthD = WTFMove(lengthC); EXPECT_EQ(2U, value->refCount()); } EXPECT_EQ(1U, value->refCount()); EXPECT_EQ(0U, deletionCount); value = nullptr; EXPECT_EQ(1U, deletionCount); deletionCount = 0; value = createTestValue(); RefPtr value2 = createTestValue(); EXPECT_EQ(1U, value->refCount()); EXPECT_EQ(1U, value2->refCount()); { WebCore::Length lengthE(*value); EXPECT_EQ(2U, value->refCount()); WebCore::Length lengthF(*value2); EXPECT_EQ(2U, value2->refCount()); lengthE = lengthF; EXPECT_EQ(1U, value->refCount()); EXPECT_EQ(2U, value2->refCount()); } EXPECT_EQ(1U, value->refCount()); EXPECT_EQ(1U, value2->refCount()); { WebCore::Length lengthG(*value); EXPECT_EQ(2U, value->refCount()); WebCore::Length lengthH(*value2); EXPECT_EQ(2U, value2->refCount()); lengthG = WTFMove(lengthH); EXPECT_EQ(1U, value->refCount()); EXPECT_EQ(2U, value2->refCount()); } EXPECT_EQ(0U, deletionCount); value = nullptr; EXPECT_EQ(1U, deletionCount); value2 = nullptr; EXPECT_EQ(2U, deletionCount); deletionCount = 0; } TEST(CalculationValue, LengthAssignmentReleasedValue) { RefPtr value = createTestValue(); { auto* rawValue = value.get(); WebCore::Length lengthA(value.releaseNonNull()); EXPECT_EQ(1U, rawValue->refCount()); WebCore::Length lengthB; lengthB = lengthA; EXPECT_EQ(1U, rawValue->refCount()); EXPECT_EQ(0U, deletionCount); } EXPECT_EQ(1U, deletionCount); deletionCount = 0; value = createTestValue(); { auto* rawValue = value.get(); WebCore::Length lengthC(value.releaseNonNull()); EXPECT_EQ(1U, rawValue->refCount()); WebCore::Length lengthD; lengthD = WTFMove(lengthC); EXPECT_EQ(1U, rawValue->refCount()); EXPECT_EQ(0U, deletionCount); } EXPECT_EQ(1U, deletionCount); deletionCount = 0; value = createTestValue(); RefPtr value2 = createTestValue(); EXPECT_EQ(1U, value->refCount()); EXPECT_EQ(1U, value2->refCount()); { auto* rawValue = value.get(); WebCore::Length lengthE(value.releaseNonNull()); EXPECT_EQ(1U, rawValue->refCount()); auto* rawValue2 = value2.get(); WebCore::Length lengthF(value2.releaseNonNull()); EXPECT_EQ(1U, rawValue2->refCount()); lengthE = lengthF; EXPECT_EQ(1U, deletionCount); EXPECT_EQ(1U, rawValue2->refCount()); } EXPECT_EQ(2U, deletionCount); deletionCount = 0; value = createTestValue(); value2 = createTestValue(); EXPECT_EQ(1U, value->refCount()); EXPECT_EQ(1U, value2->refCount()); { auto* rawValue = value.get(); WebCore::Length lengthG(value.releaseNonNull()); EXPECT_EQ(1U, rawValue->refCount()); auto* rawValue2 = value2.get(); WebCore::Length lengthH(value2.releaseNonNull()); EXPECT_EQ(1U, rawValue2->refCount()); lengthG = WTFMove(lengthH); EXPECT_EQ(1U, deletionCount); EXPECT_EQ(1U, rawValue2->refCount()); } EXPECT_EQ(2U, deletionCount); deletionCount = 0; } }