1 /* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 /*
24 This is a simple example of how to use the google unit test framework.
25
26 For an introduction to the constructs used below, see:
27 http://code.google.com/p/googletest/wiki/GoogleTestPrimer
28 */
29
30 // First include (the generated) my_config.h, to get correct platform defines.
31 #include "my_config.h"
32 #include <gtest/gtest.h>
33
34 #include "sql_list.h"
35
36 #include "thr_malloc.h"
37 #include "sql_string.h"
38 #include "sql_error.h"
39 #include <my_pthread.h>
40 #include "test_utils.h"
41
42 namespace sql_list_unittest {
43
44 // A simple helper function to insert values into a List.
45 template <class T, int size>
insert_values(T (& array)[size],List<T> * list)46 void insert_values(T (&array)[size], List<T> *list)
47 {
48 for (int ix= 0; ix < size; ++ix)
49 {
50 EXPECT_FALSE(list->push_back(&array[ix]));
51 }
52 }
53
54 /*
55 The fixture for testing the MySQL List and List_iterator classes.
56 A fresh instance of this class will be created for each of the
57 TEST_F functions below.
58 The functions SetUp(), TearDown(), SetUpTestCase(), TearDownTestCase() are
59 inherited from ::testing::Test (google naming style differs from MySQL).
60 */
61 class SqlListTest : public ::testing::Test
62 {
63 protected:
SqlListTest()64 SqlListTest()
65 : m_mem_root_p(&m_mem_root), m_int_list(), m_int_list_iter(m_int_list)
66 {
67 }
68
SetUp()69 virtual void SetUp()
70 {
71 init_sql_alloc(&m_mem_root, 1024, 0);
72 ASSERT_EQ(0, my_pthread_setspecific_ptr(THR_MALLOC, &m_mem_root_p));
73 MEM_ROOT *root= *my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC);
74 ASSERT_EQ(root, m_mem_root_p);
75 }
76
TearDown()77 virtual void TearDown()
78 {
79 free_root(&m_mem_root, MYF(0));
80 }
81
SetUpTestCase()82 static void SetUpTestCase()
83 {
84 ASSERT_EQ(0, pthread_key_create(&THR_THD, NULL));
85 ASSERT_EQ(0, pthread_key_create(&THR_MALLOC, NULL));
86 }
87
TearDownTestCase()88 static void TearDownTestCase()
89 {
90 pthread_key_delete(THR_THD);
91 pthread_key_delete(THR_MALLOC);
92 }
93
94 MEM_ROOT m_mem_root;
95 MEM_ROOT *m_mem_root_p;
96 List<int> m_int_list;
97 List_iterator<int> m_int_list_iter;
98
99 private:
100 // Declares (but does not define) copy constructor and assignment operator.
101 GTEST_DISALLOW_COPY_AND_ASSIGN_(SqlListTest);
102 };
103
104
105 // Tests that we can construct and destruct lists.
TEST_F(SqlListTest,ConstructAndDestruct)106 TEST_F(SqlListTest, ConstructAndDestruct)
107 {
108 EXPECT_TRUE(m_int_list.is_empty());
109 List<int> *p_int_list= new List<int>;
110 EXPECT_TRUE(p_int_list->is_empty());
111 delete p_int_list;
112 }
113
114
115 // Tests basic operations push and pop.
TEST_F(SqlListTest,BasicOperations)116 TEST_F(SqlListTest, BasicOperations)
117 {
118 int i1= 1;
119 int i2= 2;
120 EXPECT_FALSE(m_int_list.push_front(&i1));
121 EXPECT_FALSE(m_int_list.push_back(&i2));
122 EXPECT_FALSE(m_int_list.is_empty());
123 EXPECT_EQ(2U, m_int_list.elements);
124
125 EXPECT_EQ(&i1, m_int_list.head());
126 EXPECT_EQ(&i1, m_int_list.pop());
127 EXPECT_EQ(&i2, m_int_list.head());
128 EXPECT_EQ(&i2, m_int_list.pop());
129 EXPECT_TRUE(m_int_list.is_empty()) << "The list should be empty now!";
130 }
131
132
133 // Tests list copying.
TEST_F(SqlListTest,DeepCopy)134 TEST_F(SqlListTest, DeepCopy)
135 {
136 int values[] = {11, 22, 33, 42, 5};
137 insert_values(values, &m_int_list);
138 MEM_ROOT mem_root;
139 init_alloc_root(&mem_root, 4096, 4096);
140 List<int> list_copy(m_int_list, &mem_root);
141 EXPECT_EQ(list_copy.elements, m_int_list.elements);
142 while (!list_copy.is_empty())
143 {
144 EXPECT_EQ(*m_int_list.pop(), *list_copy.pop());
145 }
146 EXPECT_TRUE(m_int_list.is_empty());
147 free_root(&mem_root, MYF(0));
148 }
149
150
151 // Tests that we can iterate over values.
TEST_F(SqlListTest,Iterate)152 TEST_F(SqlListTest, Iterate)
153 {
154 int values[] = {3, 2, 1};
155 insert_values(values, &m_int_list);
156 for (int ix= 0; ix < array_size(values); ++ix)
157 {
158 EXPECT_EQ(values[ix], *m_int_list_iter++);
159 }
160 m_int_list_iter.init(m_int_list);
161 int *value;
162 int value_number= 0;
163 while ((value= m_int_list_iter++))
164 {
165 EXPECT_EQ(values[value_number++], *value);
166 }
167 }
168
169
170 // A simple helper class for testing intrusive lists.
171 class Linked_node : public ilink<Linked_node>
172 {
173 public:
Linked_node(int val)174 Linked_node(int val) : m_value(val) {}
get_value() const175 int get_value() const { return m_value; }
176 private:
177 int m_value;
178 };
179 const Linked_node * const null_node= NULL;
180
181
182 // An example of a test without any fixture.
TEST(SqlIlistTest,ConstructAndDestruct)183 TEST(SqlIlistTest, ConstructAndDestruct)
184 {
185 I_List<Linked_node> i_list;
186 I_List_iterator<Linked_node> i_list_iter(i_list);
187 EXPECT_TRUE(i_list.is_empty());
188 EXPECT_EQ(null_node, i_list_iter++);
189 }
190
191
192 // Tests iteration over intrusive lists.
TEST(SqlIlistTest,PushBackAndIterate)193 TEST(SqlIlistTest, PushBackAndIterate)
194 {
195 I_List<Linked_node> i_list;
196 I_List_iterator<Linked_node> i_list_iter(i_list);
197 int values[] = {11, 22, 33, 42, 5};
198 EXPECT_EQ(null_node, i_list.head());
199 for (int ix= 0; ix < array_size(values); ++ix)
200 {
201 i_list.push_back(new Linked_node(values[ix]));
202 }
203
204 Linked_node *node;
205 int value_number= 0;
206 while ((node= i_list_iter++))
207 {
208 EXPECT_EQ(values[value_number++], node->get_value());
209 }
210 for (value_number= 0; (node= i_list.get()); ++value_number)
211 {
212 EXPECT_EQ(values[value_number], node->get_value());
213 delete node;
214 }
215 EXPECT_EQ(array_size(values), value_number);
216 }
217
218 // Another iteration test over intrusive lists.
TEST(SqlIlistTest,PushFrontAndIterate)219 TEST(SqlIlistTest, PushFrontAndIterate)
220 {
221 I_List<Linked_node> i_list;
222 I_List_iterator<Linked_node> i_list_iter(i_list);
223 int values[] = {11, 22, 33, 42, 5};
224 for (int ix= 0; ix < array_size(values); ++ix)
225 {
226 i_list.push_front(new Linked_node(values[ix]));
227 }
228
229 Linked_node *node;
230 int value_number= array_size(values) - 1;
231 while ((node= i_list_iter++))
232 {
233 EXPECT_EQ(values[value_number--], node->get_value());
234 }
235 while ((node= i_list.get()))
236 delete node;
237 }
238
cmp_test(void * a,void * b,void * c)239 static int cmp_test(void *a, void *b, void *c)
240 {
241 EXPECT_EQ(c, (void *)0xFEE1BEEF);
242 return (*(int*)a < *(int*)b) ? -1 : (*(int*)a > *(int*)b) ? 1 : 0;
243 }
244
245 // Tests list sorting.
TEST_F(SqlListTest,Sort)246 TEST_F(SqlListTest, Sort)
247 {
248 int values[] = {1, 9, 2, 7, 3, 6, 4, 5, 8};
249 insert_values(values, &m_int_list);
250 m_int_list.sort(cmp_test, (void*)0xFEE1BEEF);
251 for (int i= 1; i < 10 ; i++)
252 {
253 EXPECT_EQ(*m_int_list.pop(), i);
254 }
255 EXPECT_TRUE(m_int_list.is_empty());
256 // Test sorting of empty string.
257 m_int_list.sort(cmp_test, (void*)0xFEE1BEEF);
258 // Check that nothing has changed.
259 EXPECT_TRUE(m_int_list.is_empty());
260 }
261
262
263 } // namespace
264