1/*
2 * Copyright (C) 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27
28#include <WebCore/CalculationValue.h>
29#include <wtf/RefPtr.h>
30
31namespace WTF {
32class TextStream;
33};
34
35namespace TestWebKitAPI {
36
37static unsigned deletionCount;
38
39class CalculationDeletionTestNode : public WebCore::CalcExpressionNode {
40public:
41 virtual ~CalculationDeletionTestNode()
42 {
43 ++deletionCount;
44 }
45
46 float evaluate(float) const override { return 0; }
47 bool operator==(const CalcExpressionNode&) const override { ASSERT_NOT_REACHED(); return false; }
48
49private:
50 void dump(WTF::TextStream&) const override { };
51};
52
53static Ref<WebCore::CalculationValue> createTestValue()
54{
55 auto node = std::make_unique<CalculationDeletionTestNode>();
56 return WebCore::CalculationValue::create(WTFMove(node), WebCore::ValueRangeAll);
57}
58
59TEST(CalculationValue, LengthConstruction)
60{
61 RefPtr<WebCore::CalculationValue> value = createTestValue();
62
63 EXPECT_EQ(1U, value->refCount());
64
65 {
66 WebCore::Length length(*value);
67 EXPECT_EQ(2U, value->refCount());
68 }
69
70 EXPECT_EQ(1U, value->refCount());
71
72 {
73 WebCore::Length lengthA(*value);
74 EXPECT_EQ(2U, value->refCount());
75 WebCore::Length lengthB(lengthA);
76 EXPECT_EQ(2U, value->refCount());
77 }
78
79 EXPECT_EQ(1U, value->refCount());
80
81 {
82 WebCore::Length lengthC(*value);
83 EXPECT_EQ(2U, value->refCount());
84 WebCore::Length lengthD(WTFMove(lengthC));
85 EXPECT_EQ(2U, value->refCount());
86 }
87
88 EXPECT_EQ(1U, value->refCount());
89
90 EXPECT_EQ(0U, deletionCount);
91 value = nullptr;
92 EXPECT_EQ(1U, deletionCount);
93 deletionCount = 0;
94}
95
96TEST(CalculationValue, LengthConstructionReleasedValue)
97{
98 RefPtr<WebCore::CalculationValue> value = createTestValue();
99
100 EXPECT_EQ(1U, value->refCount());
101
102 {
103 auto* rawValue = value.get();
104 WebCore::Length length(value.releaseNonNull());
105 EXPECT_EQ(1U, rawValue->refCount());
106
107 EXPECT_EQ(0U, deletionCount);
108 }
109
110 EXPECT_EQ(1U, deletionCount);
111 deletionCount = 0;
112
113 value = createTestValue();
114
115 {
116 auto* rawValue = value.get();
117 WebCore::Length lengthA(value.releaseNonNull());
118 EXPECT_EQ(1U, rawValue->refCount());
119 WebCore::Length lengthB(lengthA);
120 EXPECT_EQ(1U, rawValue->refCount());
121
122 EXPECT_EQ(0U, deletionCount);
123 }
124
125 EXPECT_EQ(1U, deletionCount);
126 deletionCount = 0;
127
128 value = createTestValue();
129
130 {
131 auto* rawValue = value.get();
132 WebCore::Length lengthC(value.releaseNonNull());
133 EXPECT_EQ(1U, rawValue->refCount());
134 WebCore::Length lengthD(WTFMove(lengthC));
135 EXPECT_EQ(1U, rawValue->refCount());
136
137 EXPECT_EQ(0U, deletionCount);
138 }
139
140 EXPECT_EQ(1U, deletionCount);
141 deletionCount = 0;
142}
143
144TEST(CalculationValue, LengthAssignment)
145{
146 RefPtr<WebCore::CalculationValue> value = createTestValue();
147
148 EXPECT_EQ(1U, value->refCount());
149
150 {
151 WebCore::Length lengthA(*value);
152 EXPECT_EQ(2U, value->refCount());
153 WebCore::Length lengthB;
154 lengthB = lengthA;
155 EXPECT_EQ(2U, value->refCount());
156 }
157
158 EXPECT_EQ(1U, value->refCount());
159
160 {
161 WebCore::Length lengthC(*value);
162 EXPECT_EQ(2U, value->refCount());
163 WebCore::Length lengthD;
164 lengthD = WTFMove(lengthC);
165 EXPECT_EQ(2U, value->refCount());
166 }
167
168 EXPECT_EQ(1U, value->refCount());
169
170 EXPECT_EQ(0U, deletionCount);
171 value = nullptr;
172 EXPECT_EQ(1U, deletionCount);
173 deletionCount = 0;
174
175 value = createTestValue();
176 RefPtr<WebCore::CalculationValue> value2 = createTestValue();
177
178 EXPECT_EQ(1U, value->refCount());
179 EXPECT_EQ(1U, value2->refCount());
180
181 {
182 WebCore::Length lengthE(*value);
183 EXPECT_EQ(2U, value->refCount());
184 WebCore::Length lengthF(*value2);
185 EXPECT_EQ(2U, value2->refCount());
186 lengthE = lengthF;
187 EXPECT_EQ(1U, value->refCount());
188 EXPECT_EQ(2U, value2->refCount());
189 }
190
191 EXPECT_EQ(1U, value->refCount());
192 EXPECT_EQ(1U, value2->refCount());
193
194 {
195 WebCore::Length lengthG(*value);
196 EXPECT_EQ(2U, value->refCount());
197 WebCore::Length lengthH(*value2);
198 EXPECT_EQ(2U, value2->refCount());
199 lengthG = WTFMove(lengthH);
200 EXPECT_EQ(1U, value->refCount());
201 EXPECT_EQ(2U, value2->refCount());
202 }
203
204 EXPECT_EQ(0U, deletionCount);
205 value = nullptr;
206 EXPECT_EQ(1U, deletionCount);
207 value2 = nullptr;
208 EXPECT_EQ(2U, deletionCount);
209 deletionCount = 0;
210}
211
212TEST(CalculationValue, LengthAssignmentReleasedValue)
213{
214 RefPtr<WebCore::CalculationValue> value = createTestValue();
215
216 {
217 auto* rawValue = value.get();
218 WebCore::Length lengthA(value.releaseNonNull());
219 EXPECT_EQ(1U, rawValue->refCount());
220 WebCore::Length lengthB;
221 lengthB = lengthA;
222 EXPECT_EQ(1U, rawValue->refCount());
223
224 EXPECT_EQ(0U, deletionCount);
225 }
226
227 EXPECT_EQ(1U, deletionCount);
228 deletionCount = 0;
229
230 value = createTestValue();
231
232 {
233 auto* rawValue = value.get();
234 WebCore::Length lengthC(value.releaseNonNull());
235 EXPECT_EQ(1U, rawValue->refCount());
236 WebCore::Length lengthD;
237 lengthD = WTFMove(lengthC);
238 EXPECT_EQ(1U, rawValue->refCount());
239
240 EXPECT_EQ(0U, deletionCount);
241 }
242
243 EXPECT_EQ(1U, deletionCount);
244 deletionCount = 0;
245
246 value = createTestValue();
247 RefPtr<WebCore::CalculationValue> value2 = createTestValue();
248
249 EXPECT_EQ(1U, value->refCount());
250 EXPECT_EQ(1U, value2->refCount());
251
252 {
253 auto* rawValue = value.get();
254 WebCore::Length lengthE(value.releaseNonNull());
255 EXPECT_EQ(1U, rawValue->refCount());
256 auto* rawValue2 = value2.get();
257 WebCore::Length lengthF(value2.releaseNonNull());
258 EXPECT_EQ(1U, rawValue2->refCount());
259
260 lengthE = lengthF;
261 EXPECT_EQ(1U, deletionCount);
262 EXPECT_EQ(1U, rawValue2->refCount());
263 }
264
265 EXPECT_EQ(2U, deletionCount);
266 deletionCount = 0;
267
268 value = createTestValue();
269 value2 = createTestValue();
270
271 EXPECT_EQ(1U, value->refCount());
272 EXPECT_EQ(1U, value2->refCount());
273
274 {
275 auto* rawValue = value.get();
276 WebCore::Length lengthG(value.releaseNonNull());
277 EXPECT_EQ(1U, rawValue->refCount());
278 auto* rawValue2 = value2.get();
279 WebCore::Length lengthH(value2.releaseNonNull());
280 EXPECT_EQ(1U, rawValue2->refCount());
281
282 lengthG = WTFMove(lengthH);
283 EXPECT_EQ(1U, deletionCount);
284 EXPECT_EQ(1U, rawValue2->refCount());
285 }
286
287 EXPECT_EQ(2U, deletionCount);
288 deletionCount = 0;
289}
290
291}
292