261 lines
6.8 KiB
C++

/* Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/*
This is a simple example of how to use the google unit test framework.
For an introduction to the constructs used below, see:
http://code.google.com/p/googletest/wiki/GoogleTestPrimer
*/
// First include (the generated) my_config.h, to get correct platform defines.
#include "my_config.h"
#include <gtest/gtest.h>
#include "sql_list.h"
#include "thr_malloc.h"
#include "sql_string.h"
#include "sql_error.h"
#include <my_thread.h>
#include "test_utils.h"
namespace sql_list_unittest {
// A simple helper function to insert values into a List.
template <class T, int size>
void insert_values(T (&array)[size], List<T> *list)
{
for (int ix= 0; ix < size; ++ix)
{
EXPECT_FALSE(list->push_back(&array[ix]));
}
}
/*
The fixture for testing the MySQL List and List_iterator classes.
A fresh instance of this class will be created for each of the
TEST_F functions below.
The functions SetUp(), TearDown(), SetUpTestCase(), TearDownTestCase() are
inherited from ::testing::Test (google naming style differs from MySQL).
*/
class SqlListTest : public ::testing::Test
{
protected:
SqlListTest()
: m_mem_root_p(&m_mem_root), m_int_list(), m_int_list_iter(m_int_list)
{
}
virtual void SetUp()
{
init_sql_alloc(PSI_NOT_INSTRUMENTED, &m_mem_root, 1024, 0);
ASSERT_EQ(0, my_set_thread_local(THR_MALLOC, &m_mem_root_p));
MEM_ROOT *root= *static_cast<MEM_ROOT**>(my_get_thread_local(THR_MALLOC));
ASSERT_EQ(root, m_mem_root_p);
}
virtual void TearDown()
{
free_root(&m_mem_root, MYF(0));
}
static void SetUpTestCase()
{
ASSERT_EQ(0, my_create_thread_local_key(&THR_THD, NULL));
THR_THD_initialized= true;
ASSERT_EQ(0, my_create_thread_local_key(&THR_MALLOC, NULL));
THR_MALLOC_initialized= true;
}
static void TearDownTestCase()
{
my_delete_thread_local_key(THR_THD);
THR_THD_initialized= false;
my_delete_thread_local_key(THR_MALLOC);
THR_MALLOC_initialized= false;
}
MEM_ROOT m_mem_root;
MEM_ROOT *m_mem_root_p;
List<int> m_int_list;
List_iterator<int> m_int_list_iter;
private:
// Declares (but does not define) copy constructor and assignment operator.
GTEST_DISALLOW_COPY_AND_ASSIGN_(SqlListTest);
};
// Tests that we can construct and destruct lists.
TEST_F(SqlListTest, ConstructAndDestruct)
{
EXPECT_TRUE(m_int_list.is_empty());
List<int> *p_int_list= new List<int>;
EXPECT_TRUE(p_int_list->is_empty());
delete p_int_list;
}
// Tests basic operations push and pop.
TEST_F(SqlListTest, BasicOperations)
{
int i1= 1;
int i2= 2;
EXPECT_FALSE(m_int_list.push_front(&i1));
EXPECT_FALSE(m_int_list.push_back(&i2));
EXPECT_FALSE(m_int_list.is_empty());
EXPECT_EQ(2U, m_int_list.elements);
EXPECT_EQ(&i1, m_int_list.head());
EXPECT_EQ(&i1, m_int_list.pop());
EXPECT_EQ(&i2, m_int_list.head());
EXPECT_EQ(&i2, m_int_list.pop());
EXPECT_TRUE(m_int_list.is_empty()) << "The list should be empty now!";
}
// Tests list copying.
TEST_F(SqlListTest, DeepCopy)
{
int values[] = {11, 22, 33, 42, 5};
insert_values(values, &m_int_list);
MEM_ROOT mem_root;
init_alloc_root(PSI_NOT_INSTRUMENTED, &mem_root, 4096, 4096);
List<int> list_copy(m_int_list, &mem_root);
EXPECT_EQ(list_copy.elements, m_int_list.elements);
while (!list_copy.is_empty())
{
EXPECT_EQ(*m_int_list.pop(), *list_copy.pop());
}
EXPECT_TRUE(m_int_list.is_empty());
free_root(&mem_root, MYF(0));
}
// Tests that we can iterate over values.
TEST_F(SqlListTest, Iterate)
{
int values[] = {3, 2, 1};
insert_values(values, &m_int_list);
for (int ix= 0; ix < array_size(values); ++ix)
{
EXPECT_EQ(values[ix], *m_int_list_iter++);
}
m_int_list_iter.init(m_int_list);
int *value;
int value_number= 0;
while ((value= m_int_list_iter++))
{
EXPECT_EQ(values[value_number++], *value);
}
}
// A simple helper class for testing intrusive lists.
class Linked_node : public ilink<Linked_node>
{
public:
Linked_node(int val) : m_value(val) {}
int get_value() const { return m_value; }
private:
int m_value;
};
const Linked_node * const null_node= NULL;
// An example of a test without any fixture.
TEST(SqlIlistTest, ConstructAndDestruct)
{
I_List<Linked_node> i_list;
I_List_iterator<Linked_node> i_list_iter(i_list);
EXPECT_TRUE(i_list.is_empty());
EXPECT_EQ(null_node, i_list_iter++);
}
// Tests iteration over intrusive lists.
TEST(SqlIlistTest, PushBackAndIterate)
{
I_List<Linked_node> i_list;
I_List_iterator<Linked_node> i_list_iter(i_list);
int values[] = {11, 22, 33, 42, 5};
EXPECT_EQ(null_node, i_list.head());
for (int ix= 0; ix < array_size(values); ++ix)
{
i_list.push_back(new Linked_node(values[ix]));
}
Linked_node *node;
int value_number= 0;
while ((node= i_list_iter++))
{
EXPECT_EQ(values[value_number++], node->get_value());
}
for (value_number= 0; (node= i_list.get()); ++value_number)
{
EXPECT_EQ(values[value_number], node->get_value());
delete node;
}
EXPECT_EQ(array_size(values), value_number);
}
// Another iteration test over intrusive lists.
TEST(SqlIlistTest, PushFrontAndIterate)
{
I_List<Linked_node> i_list;
I_List_iterator<Linked_node> i_list_iter(i_list);
int values[] = {11, 22, 33, 42, 5};
for (int ix= 0; ix < array_size(values); ++ix)
{
i_list.push_front(new Linked_node(values[ix]));
}
Linked_node *node;
int value_number= array_size(values) - 1;
while ((node= i_list_iter++))
{
EXPECT_EQ(values[value_number--], node->get_value());
}
while ((node= i_list.get()))
delete node;
}
static int cmp_test(void *a, void *b, void *c)
{
EXPECT_EQ(c, (void *)0xFEE1BEEF);
return (*(int*)a < *(int*)b) ? -1 : (*(int*)a > *(int*)b) ? 1 : 0;
}
// Tests list sorting.
TEST_F(SqlListTest, Sort)
{
int values[] = {1, 9, 2, 7, 3, 6, 4, 5, 8};
insert_values(values, &m_int_list);
m_int_list.sort(cmp_test, (void*)0xFEE1BEEF);
for (int i= 1; i < 10 ; i++)
{
EXPECT_EQ(*m_int_list.pop(), i);
}
EXPECT_TRUE(m_int_list.is_empty());
// Test sorting of empty string.
m_int_list.sort(cmp_test, (void*)0xFEE1BEEF);
// Check that nothing has changed.
EXPECT_TRUE(m_int_list.is_empty());
}
} // namespace