1 /* Copyright (c) 2009, 2021, Oracle and/or its affiliates.
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_thread.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(PSI_NOT_INSTRUMENTED, &m_mem_root, 1024, 0);
72 ASSERT_EQ(0, my_set_thread_local(THR_MALLOC, &m_mem_root_p));
73 MEM_ROOT *root= *static_cast<MEM_ROOT**>(my_get_thread_local(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, my_create_thread_local_key(&THR_THD, NULL));
85 THR_THD_initialized= true;
86 ASSERT_EQ(0, my_create_thread_local_key(&THR_MALLOC, NULL));
87 THR_MALLOC_initialized= true;
88 }
89
TearDownTestCase()90 static void TearDownTestCase()
91 {
92 my_delete_thread_local_key(THR_THD);
93 THR_THD_initialized= false;
94 my_delete_thread_local_key(THR_MALLOC);
95 THR_MALLOC_initialized= false;
96 }
97
98 MEM_ROOT m_mem_root;
99 MEM_ROOT *m_mem_root_p;
100 List<int> m_int_list;
101 List_iterator<int> m_int_list_iter;
102
103 private:
104 // Declares (but does not define) copy constructor and assignment operator.
105 GTEST_DISALLOW_COPY_AND_ASSIGN_(SqlListTest);
106 };
107
108
109 // Tests that we can construct and destruct lists.
TEST_F(SqlListTest,ConstructAndDestruct)110 TEST_F(SqlListTest, ConstructAndDestruct)
111 {
112 EXPECT_TRUE(m_int_list.is_empty());
113 List<int> *p_int_list= new List<int>;
114 EXPECT_TRUE(p_int_list->is_empty());
115 delete p_int_list;
116 }
117
118
119 // Tests basic operations push and pop.
TEST_F(SqlListTest,BasicOperations)120 TEST_F(SqlListTest, BasicOperations)
121 {
122 int i1= 1;
123 int i2= 2;
124 EXPECT_FALSE(m_int_list.push_front(&i1));
125 EXPECT_FALSE(m_int_list.push_back(&i2));
126 EXPECT_FALSE(m_int_list.is_empty());
127 EXPECT_EQ(2U, m_int_list.elements);
128
129 EXPECT_EQ(&i1, m_int_list.head());
130 EXPECT_EQ(&i1, m_int_list.pop());
131 EXPECT_EQ(&i2, m_int_list.head());
132 EXPECT_EQ(&i2, m_int_list.pop());
133 EXPECT_TRUE(m_int_list.is_empty()) << "The list should be empty now!";
134 }
135
136
137 // Tests list copying.
TEST_F(SqlListTest,DeepCopy)138 TEST_F(SqlListTest, DeepCopy)
139 {
140 int values[] = {11, 22, 33, 42, 5};
141 insert_values(values, &m_int_list);
142 MEM_ROOT mem_root;
143 init_alloc_root(PSI_NOT_INSTRUMENTED, &mem_root, 4096, 4096);
144 List<int> list_copy(m_int_list, &mem_root);
145 EXPECT_EQ(list_copy.elements, m_int_list.elements);
146 while (!list_copy.is_empty())
147 {
148 EXPECT_EQ(*m_int_list.pop(), *list_copy.pop());
149 }
150 EXPECT_TRUE(m_int_list.is_empty());
151 free_root(&mem_root, MYF(0));
152 }
153
154
155 // Tests that we can iterate over values.
TEST_F(SqlListTest,Iterate)156 TEST_F(SqlListTest, Iterate)
157 {
158 int values[] = {3, 2, 1};
159 insert_values(values, &m_int_list);
160 for (int ix= 0; ix < array_size(values); ++ix)
161 {
162 EXPECT_EQ(values[ix], *m_int_list_iter++);
163 }
164 m_int_list_iter.init(m_int_list);
165 int *value;
166 int value_number= 0;
167 while ((value= m_int_list_iter++))
168 {
169 EXPECT_EQ(values[value_number++], *value);
170 }
171 }
172
173
174 // A simple helper class for testing intrusive lists.
175 class Linked_node : public ilink<Linked_node>
176 {
177 public:
Linked_node(int val)178 Linked_node(int val) : m_value(val) {}
get_value() const179 int get_value() const { return m_value; }
180 private:
181 int m_value;
182 };
183 const Linked_node * const null_node= NULL;
184
185
186 // An example of a test without any fixture.
TEST(SqlIlistTest,ConstructAndDestruct)187 TEST(SqlIlistTest, ConstructAndDestruct)
188 {
189 I_List<Linked_node> i_list;
190 I_List_iterator<Linked_node> i_list_iter(i_list);
191 EXPECT_TRUE(i_list.is_empty());
192 EXPECT_EQ(null_node, i_list_iter++);
193 }
194
195
196 // Tests iteration over intrusive lists.
TEST(SqlIlistTest,PushBackAndIterate)197 TEST(SqlIlistTest, PushBackAndIterate)
198 {
199 I_List<Linked_node> i_list;
200 I_List_iterator<Linked_node> i_list_iter(i_list);
201 int values[] = {11, 22, 33, 42, 5};
202 EXPECT_EQ(null_node, i_list.head());
203 for (int ix= 0; ix < array_size(values); ++ix)
204 {
205 i_list.push_back(new Linked_node(values[ix]));
206 }
207
208 Linked_node *node;
209 int value_number= 0;
210 while ((node= i_list_iter++))
211 {
212 EXPECT_EQ(values[value_number++], node->get_value());
213 }
214 for (value_number= 0; (node= i_list.get()); ++value_number)
215 {
216 EXPECT_EQ(values[value_number], node->get_value());
217 delete node;
218 }
219 EXPECT_EQ(array_size(values), value_number);
220 }
221
222 // Another iteration test over intrusive lists.
TEST(SqlIlistTest,PushFrontAndIterate)223 TEST(SqlIlistTest, PushFrontAndIterate)
224 {
225 I_List<Linked_node> i_list;
226 I_List_iterator<Linked_node> i_list_iter(i_list);
227 int values[] = {11, 22, 33, 42, 5};
228 for (int ix= 0; ix < array_size(values); ++ix)
229 {
230 i_list.push_front(new Linked_node(values[ix]));
231 }
232
233 Linked_node *node;
234 int value_number= array_size(values) - 1;
235 while ((node= i_list_iter++))
236 {
237 EXPECT_EQ(values[value_number--], node->get_value());
238 }
239 while ((node= i_list.get()))
240 delete node;
241 }
242
cmp_test(void * a,void * b,void * c)243 static int cmp_test(void *a, void *b, void *c)
244 {
245 EXPECT_EQ(c, (void *)0xFEE1BEEF);
246 return (*(int*)a < *(int*)b) ? -1 : (*(int*)a > *(int*)b) ? 1 : 0;
247 }
248
249 // Tests list sorting.
TEST_F(SqlListTest,Sort)250 TEST_F(SqlListTest, Sort)
251 {
252 int values[] = {1, 9, 2, 7, 3, 6, 4, 5, 8};
253 insert_values(values, &m_int_list);
254 m_int_list.sort(cmp_test, (void*)0xFEE1BEEF);
255 for (int i= 1; i < 10 ; i++)
256 {
257 EXPECT_EQ(*m_int_list.pop(), i);
258 }
259 EXPECT_TRUE(m_int_list.is_empty());
260 // Test sorting of empty string.
261 m_int_list.sort(cmp_test, (void*)0xFEE1BEEF);
262 // Check that nothing has changed.
263 EXPECT_TRUE(m_int_list.is_empty());
264 }
265
266
267 } // namespace
268