用于EagleEye3.0 规则集漏报和误报测试的示例项目,项目收集于github和gitee
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

300 lines
8.8 KiB

3 months ago
/* Copyright (c) 2011, 2018, 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, version 2.0,
as published by the Free Software Foundation.
This program is also distributed with certain software (including
but not limited to OpenSSL) that is licensed under separate terms,
as designated in a particular file or component or in included license
documentation. The authors of MySQL hereby grant you an additional
permission to link the program and your derivative works with the
separately licensed software that they have included with MySQL.
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, version 2.0, 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 */
#include <gtest/gtest.h>
#include <sys/types.h>
#include <algorithm>
#include <functional>
#include <vector>
#include "my_inttypes.h"
#include "my_macros.h"
#include "my_table_map.h"
#include "sql/current_thd.h"
#include "sql/mem_root_array.h"
#include "sql/mysqld.h" // THR_MALLOC
#include "sql/sql_optimizer.h" // Key_use_array
/**
WL#5774 Decrease number of malloc's for normal DML queries.
One of the malloc's was due to DYNAMIC_ARRAY keyuse;
We replace the DYNAMIC_ARRAY with a std::vector-like class Mem_root_array.
Below are unit tests for comparing performance, and for testing
functionality of Mem_root_array.
*/
namespace dynarray_unittest {
// We generate some random data at startup, for testing of sorting.
void generate_test_data(Key_use *keys, TABLE_LIST *tables, int n) {
int ix;
for (ix = 0; ix < n; ++ix) {
tables[ix].set_tableno(ix % 3);
keys[ix] = Key_use(&tables[ix],
NULL, // Item *val
0, // table_map used_tables
ix % 4, // uint key
ix % 2, // uint keypart
0, // uint optimize
0, // keypart_map
0, // ha_rows ref_table_rows
true, // bool null_rejecting
NULL, // bool *cond_guard
0 // uint sj_pred_no
);
}
std::random_shuffle(&keys[0], &keys[n]);
}
constexpr int num_elements = 200;
/*
This class is for unit testing of Mem_root_array.
*/
class MemRootTest : public ::testing::Test {
protected:
MemRootTest() : m_mem_root_p(&m_mem_root), m_array_std(m_mem_root_p) {}
virtual void SetUp() {
init_sql_alloc(PSI_NOT_INSTRUMENTED, &m_mem_root, 1024, 0);
THR_MALLOC = &m_mem_root_p;
m_array_std.reserve(num_elements);
destroy_counter = 0;
}
virtual void TearDown() { free_root(&m_mem_root, MYF(0)); }
static void SetUpTestCase() {
generate_test_data(test_data, table_list, num_elements);
THR_MALLOC = nullptr;
}
static void TearDownTestCase() { THR_MALLOC = nullptr; }
MEM_ROOT m_mem_root;
MEM_ROOT *m_mem_root_p;
Key_use_array m_array_std;
public:
static size_t destroy_counter;
private:
static Key_use test_data[num_elements];
static TABLE_LIST table_list[num_elements];
GTEST_DISALLOW_COPY_AND_ASSIGN_(MemRootTest);
};
size_t MemRootTest::destroy_counter;
Key_use MemRootTest::test_data[num_elements];
TABLE_LIST MemRootTest::table_list[num_elements];
// Test that Mem_root_array re-expanding works.
TEST_F(MemRootTest, Reserve) {
Mem_root_array<uint> intarr(m_mem_root_p);
intarr.reserve(2);
const uint num_pushes = 20;
for (uint ix = 0; ix < num_pushes; ++ix) {
EXPECT_EQ(ix, intarr.size());
EXPECT_FALSE(intarr.push_back(ix));
EXPECT_EQ(ix, intarr.at(ix));
}
for (uint ix = 0; ix < num_pushes; ++ix) {
EXPECT_EQ(ix, intarr.at(ix));
}
EXPECT_EQ(sizeof(uint), intarr.element_size());
EXPECT_EQ(num_pushes, intarr.size());
EXPECT_LE(num_pushes, intarr.capacity());
}
// Verify that we can move MEM_ROOT without any leaks.
// Run with
// valgrind --leak-check=full <executable> --gtest_filter='-*DeathTest*' > foo
TEST_F(MemRootTest, MoveMemRoot) {
Mem_root_array<uint> intarr(m_mem_root_p);
MEM_ROOT own_root = std::move(*m_mem_root_p);
intarr.set_mem_root(&own_root);
intarr.push_back(42);
*m_mem_root_p = std::move(own_root);
}
class DestroyCounter {
public:
DestroyCounter() : p_counter(&MemRootTest::destroy_counter) {}
DestroyCounter(const DestroyCounter &rhs) : p_counter(rhs.p_counter) {}
explicit DestroyCounter(size_t *p) : p_counter(p) {}
DestroyCounter &operator=(const DestroyCounter &) = default;
~DestroyCounter() { (*p_counter) += 1; }
private:
size_t *p_counter;
};
// Test chop() and clear() and that destructors are executed.
TEST_F(MemRootTest, ChopAndClear) {
Mem_root_array<DestroyCounter> array(m_mem_root_p);
const size_t nn = 4;
array.reserve(nn);
size_t counter = 0;
DestroyCounter foo(&counter);
for (size_t ix = 0; ix < array.capacity(); ++ix) array.push_back(foo);
EXPECT_EQ(0U, counter);
array.chop(nn / 2);
EXPECT_EQ(nn / 2, counter);
EXPECT_EQ(nn / 2, array.size());
array.clear();
EXPECT_EQ(nn, counter);
}
// Test that elements are destroyed if push_back() needs to call reserve().
TEST_F(MemRootTest, ReserveDestroy) {
Mem_root_array<DestroyCounter> array(m_mem_root_p);
const size_t nn = 4;
array.reserve(nn / 2);
size_t counter = 0;
DestroyCounter foo(&counter);
for (size_t ix = 0; ix < nn; ++ix) array.push_back(foo);
EXPECT_EQ(nn / 2, counter);
EXPECT_EQ(nn, array.size());
counter = 0;
array.clear();
EXPECT_EQ(nn, counter);
}
TEST_F(MemRootTest, ResizeSame) {
Mem_root_array<DestroyCounter> array(m_mem_root_p);
array.reserve(100);
size_t counter = 0;
DestroyCounter foo(&counter);
for (int ix = 0; ix < 10; ++ix) array.push_back(foo);
EXPECT_EQ(10U, array.size());
array.resize(10U);
EXPECT_EQ(10U, array.size());
array.clear();
EXPECT_EQ(10U, counter);
}
TEST_F(MemRootTest, ResizeGrow) {
Mem_root_array<DestroyCounter> array(m_mem_root_p);
array.reserve(100);
size_t counter = 0;
DestroyCounter foo(&counter);
array.resize(10, foo);
EXPECT_EQ(0U, counter);
array.clear();
EXPECT_EQ(0U, MemRootTest::destroy_counter);
EXPECT_EQ(10U, counter);
}
TEST_F(MemRootTest, ResizeShrink) {
size_t counter = 0;
Mem_root_array<DestroyCounter> array(m_mem_root_p);
array.reserve(100);
DestroyCounter foo(&counter);
array.resize(10, foo);
EXPECT_EQ(0U, counter);
array.resize(5);
EXPECT_EQ(5U, counter);
}
TEST_F(MemRootTest, Erase) {
using A = Mem_root_array<DestroyCounter>;
size_t counter = 0;
DestroyCounter foo(&counter);
A array(m_mem_root_p);
array.resize(10, foo);
EXPECT_EQ(10U, array.size());
EXPECT_EQ(0U, counter);
A::iterator it = array.erase(array.cbegin() + 2, array.cbegin() + 4);
EXPECT_EQ(8U, array.size());
EXPECT_EQ(array.begin() + 2, it);
EXPECT_EQ(2U, counter);
it = array.erase(array.cend(), array.cend());
EXPECT_EQ(8U, array.size());
EXPECT_EQ(array.cend(), it);
EXPECT_EQ(2U, counter);
it = array.erase(array.cbegin(), array.cbegin());
EXPECT_EQ(8U, array.size());
EXPECT_EQ(array.cbegin(), it);
EXPECT_EQ(2U, counter);
it = array.erase(array.cbegin(), array.cend());
EXPECT_EQ(0U, array.size());
EXPECT_EQ(array.cbegin(), it);
EXPECT_EQ(array.cend(), it);
EXPECT_EQ(10U, counter);
}
TEST_F(MemRootTest, Erase2) {
using A = Mem_root_array<DestroyCounter>;
size_t counter = 0;
DestroyCounter foo(&counter);
A array(m_mem_root_p);
array.resize(10, foo);
EXPECT_EQ(10U, array.size());
EXPECT_EQ(0U, counter);
A::iterator it = array.erase(5);
EXPECT_EQ(9U, array.size());
EXPECT_EQ(std::next(array.cbegin(), 5), it);
EXPECT_EQ(1U, counter);
it = array.erase(static_cast<size_t>(0));
EXPECT_EQ(8U, array.size());
EXPECT_EQ(array.cbegin(), it);
EXPECT_EQ(2U, counter);
it = array.erase(7);
EXPECT_EQ(7U, array.size());
EXPECT_EQ(array.cend(), it);
EXPECT_EQ(3U, counter);
}
TEST_F(MemRootTest, Insert) {
using A = Mem_root_array<int>;
A array(m_mem_root_p);
A::iterator it = array.insert(array.cbegin(), 1);
EXPECT_EQ(array.cbegin(), it);
it = array.insert(array.cbegin(), 2);
EXPECT_EQ(array.cbegin(), it);
it = array.insert(array.cbegin() + 1, 3);
EXPECT_EQ(array.cbegin() + 1, it);
it = array.insert(array.cend(), 4);
EXPECT_EQ(array.cend() - 1, it);
EXPECT_EQ(4U, array.size());
EXPECT_EQ(2, array[0]);
EXPECT_EQ(3, array[1]);
EXPECT_EQ(1, array[2]);
EXPECT_EQ(4, array[3]);
}
} // namespace dynarray_unittest