15#include <gtest/gtest.h>
40 std::unique_ptr<sqlite_backend>
db_;
43 db_ = std::make_unique<sqlite_backend>();
49 GTEST_SKIP() <<
"SQLite not available";
54 if (
db_ &&
db_->is_initialized()) {
64 struct mach_task_basic_info info;
65 mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT;
66 if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO,
67 (task_info_t)&info, &count) == KERN_SUCCESS) {
68 return info.resident_size;
79 if (bytes > 1024 * 1024) {
80 return std::to_string(bytes / (1024 * 1024)) +
" MB";
81 }
else if (bytes > 1024) {
82 return std::to_string(bytes / 1024) +
" KB";
84 return std::to_string(bytes) +
" B";
102 ASSERT_TRUE(db_->execute_query(
"CREATE TABLE large_data (id INTEGER PRIMARY KEY, data TEXT)"
106 constexpr int NUM_ROWS = 1000;
107 constexpr int DATA_SIZE = 1000;
108 std::string data_value(DATA_SIZE,
'X');
110 for (
int i = 0; i < NUM_ROWS; ++i) {
111 std::string query =
"INSERT INTO large_data (data) VALUES ('" + data_value +
"')";
112 auto insert_result = db_->execute_query(query);
117 size_t before_query = getCurrentMemoryUsage();
120 auto query_result = db_->select_query(
"SELECT * FROM large_data");
122 auto result = query_result.value();
124 size_t after_query = getCurrentMemoryUsage();
126 EXPECT_EQ(result.size(),
static_cast<size_t>(NUM_ROWS))
127 <<
"Expected " << NUM_ROWS <<
" rows, got " << result.size();
129 if (before_query > 0) {
130 size_t memory_growth = after_query - before_query;
131 size_t expected_min = NUM_ROWS * DATA_SIZE;
133 std::cout <<
"Large Result Set Memory:\n"
134 <<
" Rows: " << NUM_ROWS <<
" x " << DATA_SIZE <<
" bytes\n"
135 <<
" Memory before: " << formatBytes(before_query) <<
"\n"
136 <<
" Memory after: " << formatBytes(after_query) <<
"\n"
137 <<
" Growth: " << formatBytes(memory_growth) <<
"\n";
140 EXPECT_LT(memory_growth, expected_min * 10)
141 <<
"Excessive memory usage detected";
149 GTEST_SKIP() <<
"SQLite not available";
161 "CREATE TABLE test_table (id INTEGER PRIMARY KEY, value TEXT)").is_ok());
163 for (
int i = 0; i < 100; ++i) {
164 db_->execute_query(
"INSERT INTO test_table (value) VALUES ('test_value_" +
165 std::to_string(i) +
"')");
168 size_t baseline_memory = getCurrentMemoryUsage();
171 constexpr int NUM_QUERIES = 1000;
172 for (
int i = 0; i < NUM_QUERIES; ++i) {
173 auto result = db_->select_query(
"SELECT * FROM test_table");
177 size_t final_memory = getCurrentMemoryUsage();
179 if (baseline_memory > 0) {
181 double growth_ratio =
static_cast<double>(final_memory) / baseline_memory;
183 std::cout <<
"Repeated Query Memory:\n"
184 <<
" Queries: " << NUM_QUERIES <<
"\n"
185 <<
" Baseline: " << formatBytes(baseline_memory) <<
"\n"
186 <<
" Final: " << formatBytes(final_memory) <<
"\n"
187 <<
" Ratio: " << growth_ratio <<
"x\n";
189 EXPECT_LT(growth_ratio, 1.5)
190 <<
"Possible memory leak: memory grew by " << ((growth_ratio - 1) * 100) <<
"%";
195 GTEST_SKIP() <<
"SQLite not available";
209 size_t initial_memory = getCurrentMemoryUsage();
211 constexpr int NUM_BUILDERS = 1000;
213 for (
int i = 0; i < NUM_BUILDERS; ++i) {
216 .
select({
"id",
"name",
"value"})
218 .
where(
"id",
">",
static_cast<int64_t
>(i))
219 .
where(
"name",
"=", std::string(
"test"))
225 EXPECT_FALSE(query.empty());
228 size_t final_memory = getCurrentMemoryUsage();
230 if (initial_memory > 0) {
231 double growth_ratio =
static_cast<double>(final_memory) / initial_memory;
233 std::cout <<
"Query Builder Memory:\n"
234 <<
" Builders created: " << NUM_BUILDERS <<
"\n"
235 <<
" Initial: " << formatBytes(initial_memory) <<
"\n"
236 <<
" Final: " << formatBytes(final_memory) <<
"\n"
237 <<
" Ratio: " << growth_ratio <<
"x\n";
240 EXPECT_LT(growth_ratio, 2.0)
241 <<
"Query builder memory not properly released";
246 GTEST_SKIP() <<
"SQLite not available";
260 ASSERT_TRUE(db_->execute_query(
"CREATE TABLE cleanup_test (id INTEGER PRIMARY KEY, data TEXT)").is_ok());
263 std::string data(500,
'A');
264 for (
int i = 0; i < 50; ++i) {
265 db_->execute_query(
"INSERT INTO cleanup_test (data) VALUES ('" + data +
"')");
269 for (
int iteration = 0; iteration < 10; ++iteration) {
270 auto query_result = db_->select_query(
"SELECT * FROM cleanup_test");
273 EXPECT_EQ(result.size(), 50u);
277 EXPECT_TRUE(result.empty());
280 SUCCEED() <<
"Result sets properly cleaned up in all iterations";
282 GTEST_SKIP() <<
"SQLite not available";
292 ASSERT_TRUE(db_->execute_query(
"CREATE TABLE partial_test (id INTEGER PRIMARY KEY, data TEXT)").is_ok());
294 std::string data(200,
'B');
295 for (
int i = 0; i < 100; ++i) {
296 db_->execute_query(
"INSERT INTO partial_test (data) VALUES ('" + data +
"')");
299 size_t initial_memory = getCurrentMemoryUsage();
302 for (
int i = 0; i < 100; ++i) {
303 auto query_result = db_->select_query(
"SELECT * FROM partial_test");
304 if (query_result.is_ok() && !query_result.value().empty()) {
306 auto& first_row = query_result.value()[0];
312 size_t final_memory = getCurrentMemoryUsage();
314 if (initial_memory > 0) {
315 EXPECT_LT(final_memory, initial_memory * 2)
316 <<
"Memory leak with partial result consumption";
321 GTEST_SKIP() <<
"SQLite not available";
335 ASSERT_TRUE(db_->execute_query(
"CREATE TABLE mixed_test (id INTEGER PRIMARY KEY AUTOINCREMENT, value TEXT)").is_ok());
337 size_t baseline = getCurrentMemoryUsage();
338 constexpr int ITERATIONS = 100;
340 for (
int i = 0; i < ITERATIONS; ++i) {
342 db_->execute_query(
"INSERT INTO mixed_test (value) VALUES ('test_" +
343 std::to_string(i) +
"')");
346 auto result = db_->select_query(
"SELECT * FROM mixed_test");
350 db_->execute_query(
"UPDATE mixed_test SET value = 'updated_" +
351 std::to_string(i) +
"' WHERE id = " + std::to_string(i + 1));
355 db_->execute_query(
"DELETE FROM mixed_test WHERE id = " +
356 std::to_string(i - 10));
360 size_t final_memory = getCurrentMemoryUsage();
363 double growth =
static_cast<double>(final_memory) / baseline;
364 std::cout <<
"Mixed Operations Memory:\n"
365 <<
" Iterations: " << ITERATIONS <<
"\n"
366 <<
" Baseline: " << formatBytes(baseline) <<
"\n"
367 <<
" Final: " << formatBytes(final_memory) <<
"\n"
368 <<
" Growth ratio: " << growth <<
"x\n";
370 EXPECT_LT(growth, 2.0) <<
"Excessive memory growth in mixed operations";
375 GTEST_SKIP() <<
"SQLite not available";
389 ASSERT_TRUE(db_->execute_query(
"CREATE TABLE long_string_test (id INTEGER PRIMARY KEY, data TEXT)").is_ok());
392 std::vector<size_t> sizes = {1000, 5000, 10000, 50000};
394 for (
size_t size : sizes) {
395 std::string long_data(size,
'X');
396 std::string query =
"INSERT INTO long_string_test (data) VALUES ('" + long_data +
"')";
399 db_->execute_query(query);
400 }) <<
"Failed to insert string of size " << size;
404 auto query_result = db_->select_query(
"SELECT * FROM long_string_test");
406 EXPECT_EQ(query_result.value().size(), sizes.size());
408 SUCCEED() <<
"Successfully handled strings up to " << sizes.back() <<
" bytes";
410 GTEST_SKIP() <<
"SQLite not available";
420 ASSERT_TRUE(db_->execute_query(
"CREATE TABLE small_strings (id INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT)").is_ok());
422 constexpr int NUM_STRINGS = 5000;
423 constexpr int STRING_SIZE = 50;
425 size_t initial_memory = getCurrentMemoryUsage();
427 for (
int i = 0; i < NUM_STRINGS; ++i) {
428 std::string small_data(STRING_SIZE,
static_cast<char>(
'A' + (i % 26)));
429 db_->execute_query(
"INSERT INTO small_strings (data) VALUES ('" + small_data +
"')");
433 auto query_result = db_->select_query(
"SELECT * FROM small_strings");
435 EXPECT_EQ(query_result.value().size(),
static_cast<size_t>(NUM_STRINGS));
437 size_t final_memory = getCurrentMemoryUsage();
439 if (initial_memory > 0) {
440 size_t expected_data = NUM_STRINGS * STRING_SIZE;
441 size_t actual_growth = final_memory - initial_memory;
443 std::cout <<
"Many Small Strings:\n"
444 <<
" Strings: " << NUM_STRINGS <<
" x " << STRING_SIZE <<
" bytes\n"
445 <<
" Expected data: " << formatBytes(expected_data) <<
"\n"
446 <<
" Memory growth: " << formatBytes(actual_growth) <<
"\n";
451 GTEST_SKIP() <<
"SQLite not available";
Test fixture for memory stress tests.
std::unique_ptr< sqlite_backend > db_
std::string formatBytes(size_t bytes)
Convert bytes to human-readable format.
size_t getCurrentMemoryUsage()
Get current memory usage in bytes (platform-specific)
Universal query builder that adapts to different database types.
query_builder & select(const std::vector< std::string > &columns)
std::string build() const
query_builder & where(const std::string &field, const std::string &op, const core::database_value &value)
query_builder & limit(size_t count)
query_builder & order_by(const std::string &column, sort_order order=sort_order::asc)
Abstract interface for database backends.
TEST_F(MemoryStressTest, LargeResultSetMemory)
Tests memory handling with large result sets.
std::vector< database_row > database_result
SQLite database backend plugin implementation.
Configuration for database connection.
#define ASSERT_TRUE(condition, message)