2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <JavaScriptCore/RedBlackTree.h>
31 #include <JavaScriptCore/Vector.h>
35 namespace TestWebKitAPI {
37 class RedBlackTreeTest: public testing::Test {
46 virtual void TearDown()
56 Pair(char key, unsigned value)
62 bool operator==(const Pair& other) const
64 return key == other.key;
67 bool operator<(const Pair& other) const
69 return key < other.key;
73 typedef Vector<Pair, 16> PairVector;
75 PairVector findExact(PairVector& asVector, char key)
79 for (size_t index = 0; index < asVector.size(); ++index) {
80 if (asVector.at(index).key == key)
81 result.append(asVector.at(index));
84 std::sort(result.begin(), result.end());
89 void remove(PairVector& asVector, size_t index)
91 asVector.at(index) = asVector.last();
92 asVector.removeLast();
95 PairVector findLeastGreaterThanOrEqual(PairVector& asVector, char key)
97 char bestKey = 0; // assignment to make gcc happy
98 bool foundKey = false;
100 for (size_t index = 0; index < asVector.size(); ++index) {
101 if (asVector.at(index).key >= key) {
102 if (asVector.at(index).key < bestKey || !foundKey) {
104 bestKey = asVector.at(index).key;
114 return findExact(asVector, bestKey);
117 void assertFoundAndRemove(PairVector& asVector, char key, unsigned value)
120 size_t foundIndex = 0; // make compilers happy
122 for (size_t index = 0; index < asVector.size(); ++index) {
123 if (asVector.at(index).key == key
124 && asVector.at(index).value == value) {
134 remove(asVector, foundIndex);
137 // This deliberately passes a copy of the vector.
138 void assertEqual(RedBlackTree<char, unsigned>& asTree, PairVector asVector)
140 for (RedBlackTree<char, unsigned>::Node* current = asTree.first(); current; current = current->successor())
141 assertFoundAndRemove(asVector, current->m_key, current->m_value);
144 void assertSameValuesForKey(RedBlackTree<char, unsigned>& asTree, RedBlackTree<char, unsigned>::Node* node, PairVector foundValues, char key)
147 EXPECT_EQ(node->m_key, key);
149 RedBlackTree<char, unsigned>::Node* prevNode = node;
152 prevNode = prevNode->predecessor();
153 } while (prevNode && prevNode->m_key == key);
155 EXPECT_EQ(node->m_key, key);
156 EXPECT_TRUE(!prevNode || prevNode->m_key < key);
159 assertFoundAndRemove(foundValues, node->m_key, node->m_value);
161 node = node->successor();
162 EXPECT_TRUE(!node || node->m_key >= key);
163 } while (node && node->m_key == key);
166 EXPECT_TRUE(foundValues.isEmpty());
169 // The control string is a null-terminated list of commands. Each
170 // command is two characters, with the first identifying the operation
171 // and the second giving a key. The commands are:
173 // *x Find all elements equal to x
174 // @x Find all elements that have the smallest key that is greater than or equal to x
175 // !x Remove all elements equal to x
176 void testDriver(const char* controlString)
179 RedBlackTree<char, unsigned> asTree;
181 for (const char* current = controlString; *current; current += 2) {
182 char command = current[0];
183 char key = current[1];
184 unsigned value = ++m_counter;
191 RedBlackTree<char, unsigned>::Node* node = new RedBlackTree<char, unsigned>::Node(key, value);
193 asVector.append(Pair(key, value));
198 RedBlackTree<char, unsigned>::Node* node = asTree.findExact(key);
200 EXPECT_EQ(node->m_key, key);
201 assertSameValuesForKey(asTree, node, findExact(asVector, key), key);
206 RedBlackTree<char, unsigned>::Node* node = asTree.findLeastGreaterThanOrEqual(key);
208 EXPECT_TRUE(node->m_key >= key);
209 assertSameValuesForKey(asTree, node, findLeastGreaterThanOrEqual(asVector, key), node->m_key);
211 EXPECT_TRUE(findLeastGreaterThanOrEqual(asVector, key).isEmpty());
217 RedBlackTree<char, unsigned>::Node* node = asTree.remove(key);
219 EXPECT_EQ(node->m_key, key);
220 assertFoundAndRemove(asVector, node->m_key, node->m_value);
222 EXPECT_TRUE(findExact(asVector, key).isEmpty());
230 ASSERT_NOT_REACHED();
234 EXPECT_EQ(asTree.size(), asVector.size());
235 assertEqual(asTree, asVector);
240 TEST_F(RedBlackTreeTest, Empty)
245 TEST_F(RedBlackTreeTest, EmptyGetFindRemove)
247 testDriver("*x@y!z");
250 TEST_F(RedBlackTreeTest, SingleAdd)
255 TEST_F(RedBlackTreeTest, SingleAddGetFindRemoveNotFound)
257 testDriver("+a*x@y!z");
260 TEST_F(RedBlackTreeTest, SingleAddGetFindRemove)
262 testDriver("+a*a@a!a");
265 TEST_F(RedBlackTreeTest, TwoAdds)
270 TEST_F(RedBlackTreeTest, ThreeAdds)
272 testDriver("+a+b+c");
275 TEST_F(RedBlackTreeTest, FourAdds)
277 testDriver("+a+b+c+d");
280 TEST_F(RedBlackTreeTest, LotsOfRepeatAdds)
282 testDriver("+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d");
285 TEST_F(RedBlackTreeTest, LotsOfRepeatAndUniqueAdds)
287 testDriver("+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+r+s+t+u+v+x+y+z");
290 TEST_F(RedBlackTreeTest, LotsOfRepeatAndUniqueAddsAndGetsAndRemoves)
292 testDriver("+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+r+s+t+u+v+x+y+z*a*b*c*d*e*f*g*h*i*j*k*l*m*n*o*p*q*r*s*t*u*v*w*x*y*z!a!b!c!d!e!f!g!h!i!j!k!l!m!n!o!p!q!r!s!t!u!v!w!x!y!z");
295 TEST_F(RedBlackTreeTest, SimpleBestFitSearch)
297 testDriver("+d+d+m+w@d@m@w@a@g@q");
300 TEST_F(RedBlackTreeTest, BiggerBestFitSearch)
302 testDriver("+d+d+d+d+d+d+d+d+d+d+f+f+f+f+f+f+f+h+h+i+j+k+l+m+o+p+q+r+z@a@b@c@d@e@f@g@h@i@j@k@l@m@n@o@p@q@r@s@t@u@v@w@x@y@z");
305 } // namespace TestWebKitAPI