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