249 lines
5.3 KiB
C++
249 lines
5.3 KiB
C++
/* Copyright (c) 2014, 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 */
|
|
|
|
// First include (the generated) my_config.h, to get correct platform defines.
|
|
#include "my_config.h"
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "malloc_allocator.h"
|
|
#include "memroot_allocator.h"
|
|
|
|
#include <vector>
|
|
#include <list>
|
|
#include <deque>
|
|
#include <algorithm>
|
|
|
|
using std::vector;
|
|
using std::list;
|
|
using std::deque;
|
|
|
|
/*
|
|
Tests of custom STL memory allocators.
|
|
*/
|
|
|
|
|
|
#if defined(GTEST_HAS_TYPED_TEST)
|
|
|
|
namespace stlalloc_unittest {
|
|
|
|
/*
|
|
Wrappers to overcome the issue that we need allocators with
|
|
default constructors for TYPED_TEST_CASE, which neither
|
|
Malloc_allocator nor Memroot_allocator have.
|
|
|
|
These wrappers need to inherit so that they are allocators themselves.
|
|
Otherwise TypeParam in the tests below will be wrong.
|
|
*/
|
|
template<typename T>
|
|
class Malloc_allocator_wrapper : public Malloc_allocator<T>
|
|
{
|
|
public:
|
|
Malloc_allocator_wrapper()
|
|
: Malloc_allocator<T>(PSI_NOT_INSTRUMENTED)
|
|
{ }
|
|
};
|
|
|
|
template<typename T>
|
|
class Memroot_allocator_wrapper : public Memroot_allocator<T>
|
|
{
|
|
MEM_ROOT m_mem_root;
|
|
|
|
public:
|
|
Memroot_allocator_wrapper()
|
|
: Memroot_allocator<T>(&m_mem_root)
|
|
{
|
|
init_sql_alloc(PSI_NOT_INSTRUMENTED, &m_mem_root, 1024, 0);
|
|
// memory allocation error is expected, don't abort unit test.
|
|
m_mem_root.error_handler= NULL;
|
|
}
|
|
|
|
~Memroot_allocator_wrapper()
|
|
{
|
|
free_root(&m_mem_root, MYF(0));
|
|
}
|
|
};
|
|
|
|
|
|
//
|
|
// Test of container with simple objects
|
|
//
|
|
|
|
template<typename T>
|
|
class STLAllocTestInt : public ::testing::Test
|
|
{
|
|
protected:
|
|
T allocator;
|
|
};
|
|
|
|
typedef ::testing::Types<Malloc_allocator_wrapper<int>,
|
|
Memroot_allocator_wrapper<int> > AllocatorTypesInt;
|
|
|
|
TYPED_TEST_CASE(STLAllocTestInt, AllocatorTypesInt);
|
|
|
|
|
|
TYPED_TEST(STLAllocTestInt, SimpleVector)
|
|
{
|
|
vector<int, TypeParam> v1(this->allocator);
|
|
vector<int, TypeParam> v2(this->allocator);
|
|
for (int i= 0; i < 100; i++)
|
|
{
|
|
v1.push_back(i);
|
|
v2.push_back(100 - i);
|
|
}
|
|
|
|
EXPECT_EQ(100U, v1.size());
|
|
EXPECT_EQ(100U, v2.size());
|
|
|
|
v1.swap(v2);
|
|
|
|
EXPECT_EQ(100U, v1.size());
|
|
EXPECT_EQ(100U, v2.size());
|
|
|
|
for (int i= 0; i < 100; i++)
|
|
{
|
|
EXPECT_EQ(i, v2[i]);
|
|
EXPECT_EQ((100 - i), v1[i]);
|
|
}
|
|
}
|
|
|
|
|
|
TYPED_TEST(STLAllocTestInt, SimpleList)
|
|
{
|
|
list<int, TypeParam> l1(this->allocator);
|
|
list<int, TypeParam> l2(this->allocator);
|
|
|
|
for (int i= 0; i < 100; i++)
|
|
l1.push_back(i);
|
|
|
|
EXPECT_EQ(100U, l1.size());
|
|
EXPECT_EQ(0U, l2.size());
|
|
|
|
l2.splice(l2.begin(), l1);
|
|
|
|
EXPECT_EQ(0U, l1.size());
|
|
EXPECT_EQ(100U, l2.size());
|
|
|
|
std::reverse(l2.begin(), l2.end());
|
|
|
|
for (int i= 0; i < 100; i++)
|
|
{
|
|
EXPECT_EQ((99 - i), l2.front());
|
|
l2.pop_front();
|
|
}
|
|
|
|
EXPECT_EQ(0U, l2.size());
|
|
}
|
|
|
|
|
|
#ifndef DBUG_OFF
|
|
TYPED_TEST(STLAllocTestInt, OutOfMemory)
|
|
{
|
|
vector<int, TypeParam> v1(this->allocator);
|
|
v1.reserve(10);
|
|
EXPECT_EQ(10U, v1.capacity());
|
|
|
|
DBUG_SET("+d,simulate_out_of_memory");
|
|
ASSERT_THROW(v1.reserve(1000), std::bad_alloc);
|
|
}
|
|
#endif
|
|
|
|
|
|
//
|
|
// Test of container with non-trival objects
|
|
//
|
|
|
|
class Container_object;
|
|
|
|
template<typename T>
|
|
class STLAllocTestObject : public STLAllocTestInt<T>
|
|
{ };
|
|
|
|
typedef ::testing::Types<Malloc_allocator_wrapper<Container_object>,
|
|
Memroot_allocator_wrapper<Container_object> >
|
|
AllocatorTypesObject;
|
|
|
|
TYPED_TEST_CASE(STLAllocTestObject, AllocatorTypesObject);
|
|
|
|
class Container_object
|
|
{
|
|
char *buffer;
|
|
|
|
public:
|
|
Container_object()
|
|
{
|
|
buffer= new char[20];
|
|
}
|
|
|
|
Container_object(const Container_object &other)
|
|
{
|
|
buffer= new char[20]; // Don't care about contents
|
|
}
|
|
|
|
~Container_object()
|
|
{
|
|
delete[] buffer;
|
|
}
|
|
};
|
|
|
|
TYPED_TEST(STLAllocTestObject, ContainerObject)
|
|
{
|
|
vector<Container_object, TypeParam> v1(this->allocator);
|
|
v1.push_back(Container_object());
|
|
v1.push_back(Container_object());
|
|
v1.push_back(Container_object());
|
|
}
|
|
|
|
|
|
//
|
|
// Test of container with containers
|
|
//
|
|
|
|
class Container_container;
|
|
|
|
template<typename T>
|
|
class STLAllocTestNested : public STLAllocTestInt<T>
|
|
{ };
|
|
|
|
typedef ::testing::Types<Malloc_allocator_wrapper<Container_container>,
|
|
Memroot_allocator_wrapper<Container_container> >
|
|
AllocatorTypesNested;
|
|
|
|
TYPED_TEST_CASE(STLAllocTestNested, AllocatorTypesNested);
|
|
|
|
class Container_container
|
|
{
|
|
deque<Container_object> d;
|
|
|
|
public:
|
|
Container_container()
|
|
{
|
|
d.push_back(Container_object());
|
|
d.push_back(Container_object());
|
|
}
|
|
};
|
|
|
|
TYPED_TEST(STLAllocTestNested, NestedContainers)
|
|
{
|
|
Container_container cc1;
|
|
Container_container cc2;
|
|
list<Container_container, TypeParam> l1(this->allocator);
|
|
l1.push_back(cc1);
|
|
l1.push_back(cc2);
|
|
}
|
|
|
|
} // namespace stlalloc_unittest
|
|
|
|
#endif // GTEST_HAS_TYPED_TEST)
|