/* Copyright (c) 2014, 2017, 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 */ /* See http://code.google.com/p/googletest/wiki/Primer */ // First include (the generated) my_config.h, to get correct platform defines. #include "my_config.h" #include #include "univ.i" #include "ut0new.h" namespace innodb_ut0new_unittest { class C { public: C(int x = 42) : m_x(x) { } int m_x; }; static void start() { static bool ut_new_boot_called = false; if (!ut_new_boot_called) { ut_new_boot(); ut_new_boot_called = true; } } /* test UT_NEW*() */ TEST(ut0new, utnew) { start(); C* p; p = UT_NEW_NOKEY(C(12)); EXPECT_EQ(12, p->m_x); UT_DELETE(p); p = UT_NEW(C(34), mem_key_buf_buf_pool); EXPECT_EQ(34, p->m_x); UT_DELETE(p); p = UT_NEW_ARRAY_NOKEY(C, 5); EXPECT_EQ(42, p[0].m_x); EXPECT_EQ(42, p[1].m_x); EXPECT_EQ(42, p[2].m_x); EXPECT_EQ(42, p[3].m_x); EXPECT_EQ(42, p[4].m_x); UT_DELETE_ARRAY(p); p = UT_NEW_ARRAY(C, 5, mem_key_buf_buf_pool); EXPECT_EQ(42, p[0].m_x); EXPECT_EQ(42, p[1].m_x); EXPECT_EQ(42, p[2].m_x); EXPECT_EQ(42, p[3].m_x); EXPECT_EQ(42, p[4].m_x); UT_DELETE_ARRAY(p); } /* test ut_*alloc*() */ TEST(ut0new, utmalloc) { start(); int* p; p = static_cast(ut_malloc_nokey(sizeof(int))); *p = 12; ut_free(p); p = static_cast(ut_malloc(sizeof(int), mem_key_buf_buf_pool)); *p = 34; ut_free(p); p = static_cast(ut_zalloc_nokey(sizeof(int))); EXPECT_EQ(0, *p); *p = 56; ut_free(p); p = static_cast(ut_zalloc(sizeof(int), mem_key_buf_buf_pool)); EXPECT_EQ(0, *p); *p = 78; ut_free(p); p = static_cast(ut_malloc_nokey(sizeof(int))); *p = 90; p = static_cast(ut_realloc(p, 2 * sizeof(int))); EXPECT_EQ(90, p[0]); p[1] = 91; ut_free(p); } /* test ut_allocator() */ TEST(ut0new, utallocator) { start(); typedef int basic_t; typedef ut_allocator vec_allocator_t; typedef std::vector vec_t; vec_t v1; v1.push_back(21); v1.push_back(31); v1.push_back(41); EXPECT_EQ(21, v1[0]); EXPECT_EQ(31, v1[1]); EXPECT_EQ(41, v1[2]); /* We use "new" instead of "UT_NEW()" for simplicity here. Real InnoDB code should use UT_NEW(). */ /* This could of course be written as: std::vector >* v2 = new std::vector >(ut_allocator( mem_key_buf_buf_pool)); */ vec_t* v2 = new vec_t(vec_allocator_t(mem_key_buf_buf_pool)); v2->push_back(27); v2->push_back(37); v2->push_back(47); EXPECT_EQ(27, v2->at(0)); EXPECT_EQ(37, v2->at(1)); EXPECT_EQ(47, v2->at(2)); delete v2; } static int n_construct = 0; class cc_t { public: cc_t() { n_construct++; if (n_construct % 4 == 0) { throw(1); } } }; struct big_t { char x[128]; }; /* test edge cases */ TEST(ut0new, edgecases) { ut_allocator alloc1(mem_key_buf_buf_pool); ut_new_pfx_t pfx; void* ret; const void* null_ptr= NULL; ret = alloc1.allocate_large(0, &pfx); EXPECT_EQ(null_ptr, ret); #ifdef UNIV_PFS_MEMORY ret = alloc1.allocate(16); ASSERT_TRUE(ret != NULL); ret = alloc1.reallocate(ret, 0, __FILE__); EXPECT_EQ(null_ptr, ret); ret = UT_NEW_ARRAY_NOKEY(byte, 0); EXPECT_EQ(null_ptr, ret); #endif /* UNIV_PFS_MEMORY */ ut_allocator alloc2(mem_key_buf_buf_pool); const ut_allocator::size_type too_many_elements = std::numeric_limits::size_type>::max() / sizeof(big_t) + 1; #ifdef UNIV_PFS_MEMORY ret = alloc2.allocate(16); ASSERT_TRUE(ret != NULL); void *ret2 = alloc2.reallocate(ret, too_many_elements, __FILE__); EXPECT_EQ(null_ptr, ret2); /* If reallocate fails due to too many elements, memory is still allocated. Do explicit deallocate do avoid mem leak. */ alloc2.deallocate(static_cast(ret)); #endif /* UNIV_PFS_MEMORY */ bool threw = false; try { ret = alloc2.allocate(too_many_elements); } catch (...) { threw = true; } EXPECT_TRUE(threw); ret = alloc2.allocate(too_many_elements, NULL, NULL, false, false); EXPECT_EQ(null_ptr, ret); threw = false; try { cc_t* cc = UT_NEW_ARRAY_NOKEY(cc_t, 16); /* Not reached, but silence a compiler warning about unused 'cc': */ ASSERT_TRUE(cc != NULL); } catch (...) { threw = true; } EXPECT_TRUE(threw); } }