1 /* Copyright (c) 2009, 2019, 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 #include <gtest/gtest.h>
31 #include <stddef.h>
32 
33 #include "my_inttypes.h"
34 #include "my_thread.h"
35 #include "sql/sql_error.h"
36 #include "sql/sql_list.h"
37 #include "sql/thr_malloc.h"
38 #include "sql_string.h"
39 #include "unittest/gunit/test_utils.h"
40 
41 namespace sql_list_unittest {
42 
43 // A simple helper function to insert values into a List.
44 template <class T, int size>
insert_values(T (& array)[size],List<T> * list)45 void insert_values(T (&array)[size], List<T> *list) {
46   for (int ix = 0; ix < size; ++ix) {
47     EXPECT_FALSE(list->push_back(&array[ix]));
48   }
49 }
50 
51 /*
52   The fixture for testing the MySQL List and List_iterator classes.
53   A fresh instance of this class will be created for each of the
54   TEST_F functions below.
55   The functions SetUp(), TearDown(), SetUpTestCase(), TearDownTestCase() are
56   inherited from ::testing::Test (google naming style differs from MySQL).
57 */
58 class SqlListTest : public ::testing::Test {
59  protected:
SqlListTest()60   SqlListTest()
61       : m_mem_root_p(&m_mem_root), m_int_list(), m_int_list_iter(m_int_list) {}
62 
SetUp()63   virtual void SetUp() {
64     init_sql_alloc(PSI_NOT_INSTRUMENTED, &m_mem_root, 1024, 0);
65     THR_MALLOC = &m_mem_root_p;
66   }
67 
TearDown()68   virtual void TearDown() { free_root(&m_mem_root, MYF(0)); }
69 
SetUpTestCase()70   static void SetUpTestCase() {
71     current_thd = nullptr;
72     THR_MALLOC = nullptr;
73   }
74 
75   MEM_ROOT m_mem_root;
76   MEM_ROOT *m_mem_root_p;
77   List<int> m_int_list;
78   List_iterator<int> m_int_list_iter;
79 
80  private:
81   // Declares (but does not define) copy constructor and assignment operator.
82   GTEST_DISALLOW_COPY_AND_ASSIGN_(SqlListTest);
83 };
84 
85 // Tests that we can construct and destruct lists.
TEST_F(SqlListTest,ConstructAndDestruct)86 TEST_F(SqlListTest, ConstructAndDestruct) {
87   EXPECT_TRUE(m_int_list.is_empty());
88   List<int> *p_int_list = new (*THR_MALLOC) List<int>;
89   EXPECT_TRUE(p_int_list->is_empty());
90   destroy(p_int_list);
91 }
92 
93 // Tests basic operations push and pop.
TEST_F(SqlListTest,BasicOperations)94 TEST_F(SqlListTest, BasicOperations) {
95   int i1 = 1;
96   int i2 = 2;
97   EXPECT_FALSE(m_int_list.push_front(&i1));
98   EXPECT_FALSE(m_int_list.push_back(&i2));
99   EXPECT_FALSE(m_int_list.is_empty());
100   EXPECT_EQ(2U, m_int_list.elements);
101 
102   EXPECT_EQ(&i1, m_int_list.head());
103   EXPECT_EQ(&i1, m_int_list.pop());
104   EXPECT_EQ(&i2, m_int_list.head());
105   EXPECT_EQ(&i2, m_int_list.pop());
106   EXPECT_TRUE(m_int_list.is_empty()) << "The list should be empty now!";
107 }
108 
109 // Tests list copying.
TEST_F(SqlListTest,DeepCopy)110 TEST_F(SqlListTest, DeepCopy) {
111   int values[] = {11, 22, 33, 42, 5};
112   insert_values(values, &m_int_list);
113   MEM_ROOT mem_root;
114   init_alloc_root(PSI_NOT_INSTRUMENTED, &mem_root, 4096, 4096);
115   List<int> list_copy(m_int_list, &mem_root);
116   EXPECT_EQ(list_copy.elements, m_int_list.elements);
117   while (!list_copy.is_empty()) {
118     EXPECT_EQ(*m_int_list.pop(), *list_copy.pop());
119   }
120   EXPECT_TRUE(m_int_list.is_empty());
121   free_root(&mem_root, MYF(0));
122 }
123 
124 // Tests that we can iterate over values.
TEST_F(SqlListTest,Iterate)125 TEST_F(SqlListTest, Iterate) {
126   int values[] = {3, 2, 1};
127   insert_values(values, &m_int_list);
128   for (size_t ix = 0; ix < array_elements(values); ++ix) {
129     EXPECT_EQ(values[ix], *m_int_list_iter++);
130   }
131   m_int_list_iter.init(m_int_list);
132   int *value;
133   int value_number = 0;
134   while ((value = m_int_list_iter++)) {
135     EXPECT_EQ(values[value_number++], *value);
136   }
137 }
138 
139 // A simple helper class for testing intrusive lists.
140 class Linked_node : public ilink<Linked_node> {
141  public:
Linked_node(int val)142   Linked_node(int val) : m_value(val) {}
get_value() const143   int get_value() const { return m_value; }
144 
145  private:
146   int m_value;
147 };
148 const Linked_node *const null_node = nullptr;
149 
150 // An example of a test without any fixture.
TEST(SqlIlistTest,ConstructAndDestruct)151 TEST(SqlIlistTest, ConstructAndDestruct) {
152   I_List<Linked_node> i_list;
153   I_List_iterator<Linked_node> i_list_iter(i_list);
154   EXPECT_TRUE(i_list.is_empty());
155   EXPECT_EQ(null_node, i_list_iter++);
156 }
157 
158 // Tests iteration over intrusive lists.
TEST(SqlIlistTest,PushBackAndIterate)159 TEST(SqlIlistTest, PushBackAndIterate) {
160   I_List<Linked_node> i_list;
161   I_List_iterator<Linked_node> i_list_iter(i_list);
162   int values[] = {11, 22, 33, 42, 5};
163   EXPECT_EQ(null_node, i_list.head());
164   for (size_t ix = 0; ix < array_elements(values); ++ix) {
165     i_list.push_back(new Linked_node(values[ix]));
166   }
167 
168   Linked_node *node;
169   size_t value_number = 0;
170   while ((node = i_list_iter++)) {
171     EXPECT_EQ(values[value_number++], node->get_value());
172   }
173   for (value_number = 0; (node = i_list.get()); ++value_number) {
174     EXPECT_EQ(values[value_number], node->get_value());
175     delete node;
176   }
177   EXPECT_EQ(array_elements(values), value_number);
178 }
179 
180 // Another iteration test over intrusive lists.
TEST(SqlIlistTest,PushFrontAndIterate)181 TEST(SqlIlistTest, PushFrontAndIterate) {
182   I_List<Linked_node> i_list;
183   I_List_iterator<Linked_node> i_list_iter(i_list);
184   int values[] = {11, 22, 33, 42, 5};
185   for (size_t ix = 0; ix < array_elements(values); ++ix) {
186     i_list.push_front(new Linked_node(values[ix]));
187   }
188 
189   Linked_node *node;
190   int value_number = array_elements(values) - 1;
191   while ((node = i_list_iter++)) {
192     EXPECT_EQ(values[value_number--], node->get_value());
193   }
194   while ((node = i_list.get())) delete node;
195 }
196 
cmp_test(int * a,int * b)197 static int cmp_test(int *a, int *b) {
198   return (*(int *)a < *(int *)b) ? -1 : (*(int *)a > *(int *)b) ? 1 : 0;
199 }
200 
201 // Tests list sorting.
TEST_F(SqlListTest,Sort)202 TEST_F(SqlListTest, Sort) {
203   int values[] = {1, 9, 2, 7, 3, 6, 4, 5, 8};
204   insert_values(values, &m_int_list);
205   m_int_list.sort(cmp_test);
206   for (int i = 1; i < 10; i++) {
207     EXPECT_EQ(*m_int_list.pop(), i);
208   }
209   EXPECT_TRUE(m_int_list.is_empty());
210   // Test sorting of empty string.
211   m_int_list.sort(cmp_test);
212   // Check that nothing has changed.
213   EXPECT_TRUE(m_int_list.is_empty());
214 }
215 
216 // Tests prepend on empty list followed by push_back, Bug#26813454
TEST_F(SqlListTest,PrependBug)217 TEST_F(SqlListTest, PrependBug) {
218   int values1[] = {1, 2};
219   insert_values(values1, &m_int_list);
220   EXPECT_EQ(2U, m_int_list.elements);
221 
222   List<int> ilist;
223   EXPECT_TRUE(ilist.is_empty());
224   ilist.prepend(&m_int_list);
225 
226   int values2[] = {3, 4};
227   insert_values(values2, &ilist);
228   EXPECT_EQ(4U, ilist.elements);
229 
230   for (int i = 1; i <= 4; i++) EXPECT_EQ(*ilist.pop(), i);
231 }
232 
233 // Tests swap_elts
TEST_F(SqlListTest,Swap)234 TEST_F(SqlListTest, Swap) {
235   int values[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
236   insert_values(values, &m_int_list);
237   EXPECT_EQ(m_int_list.swap_elts(1, 1), false);
238   // Expect no change
239   for (int i = 0; i < 10; i++) {
240     EXPECT_EQ(*m_int_list.pop(), i);
241   }
242 
243   insert_values(values, &m_int_list);
244   EXPECT_EQ(m_int_list.swap_elts(9, 10), true /* error */);
245   // Expect no change: 10 out of bounds
246   for (int i = 0; i < 10; i++) {
247     EXPECT_EQ(*m_int_list.pop(), i);
248   }
249 
250   insert_values(values, &m_int_list);
251   EXPECT_EQ(m_int_list.swap_elts(10, 9), true /* error */);
252   // Expect no change: 10 out of bounds
253   for (int i = 0; i < 10; i++) {
254     EXPECT_EQ(*m_int_list.pop(), i);
255   }
256 
257   insert_values(values, &m_int_list);
258   EXPECT_EQ(m_int_list.swap_elts(10, 11), true /* error */);
259   // Expect no change: 10, 11 out of bounds
260   for (int i = 0; i < 10; i++) {
261     EXPECT_EQ(*m_int_list.pop(), i);
262   }
263 
264   insert_values(values, &m_int_list);
265   EXPECT_EQ(m_int_list.swap_elts(0, 1), false);
266 
267   for (int i = 0; i < 10; i++) {
268     EXPECT_EQ(*m_int_list.pop(), (i == 0 ? 1 : (i == 1 ? 0 : i)));
269   }
270 
271   insert_values(values, &m_int_list);
272   EXPECT_EQ(m_int_list.swap_elts(0, 9), false);
273 
274   for (int i = 0; i < 10; i++) {
275     EXPECT_EQ(*m_int_list.pop(), (i == 0 ? 9 : (i == 9 ? 0 : i)));
276   }
277 
278   insert_values(values, &m_int_list);
279   EXPECT_EQ(m_int_list.swap_elts(9, 0), false);
280 
281   for (int i = 0; i < 10; i++) {
282     EXPECT_EQ(*m_int_list.pop(), (i == 0 ? 9 : (i == 9 ? 0 : i)));
283   }
284 }
285 
286 }  // namespace sql_list_unittest
287