Database System 0.1.0
Advanced C++20 Database System with Multi-Backend Support
Loading...
Searching...
No Matches
memory_stress_test.cpp File Reference
#include <gtest/gtest.h>
#include <memory>
#include <string>
#include <vector>
#include <chrono>
#include "database/backends/sqlite_backend.h"
#include "database/core/database_backend.h"
#include "database/query_builder.h"
Include dependency graph for memory_stress_test.cpp:

Go to the source code of this file.

Classes

class  MemoryStressTest
 Test fixture for memory stress tests. More...
 

Functions

 TEST_F (MemoryStressTest, LargeResultSetMemory)
 Tests memory handling with large result sets.
 
 TEST_F (MemoryStressTest, RepeatedQueryMemoryStability)
 Tests that memory remains stable after repeated queries.
 
 TEST_F (MemoryStressTest, QueryBuilderMemoryUsage)
 Tests query builder memory usage with many operations.
 
 TEST_F (MemoryStressTest, ResultSetProperCleanup)
 Tests that result sets are properly cleaned up.
 
 TEST_F (MemoryStressTest, PartialResultConsumption)
 Tests memory behavior when only part of result is consumed.
 
 TEST_F (MemoryStressTest, MixedOperationsMemoryStability)
 Tests memory stability under mixed CRUD operations.
 
 TEST_F (MemoryStressTest, VeryLongStringHandling)
 Tests memory handling with very long strings.
 
 TEST_F (MemoryStressTest, ManySmallStrings)
 Tests memory handling with many small strings.
 

Function Documentation

◆ TEST_F() [1/8]

TEST_F ( MemoryStressTest ,
LargeResultSetMemory  )

Tests memory handling with large result sets.

Test
LargeResultSetMemory

Creates a table with many rows and queries all data. Monitors memory usage during and after the operation.

Definition at line 99 of file memory_stress_test.cpp.

99 {
100#ifdef USE_SQLITE
101 // Create table
102 ASSERT_TRUE(db_->execute_query("CREATE TABLE large_data (id INTEGER PRIMARY KEY, data TEXT)"
103 ).is_ok());
104
105 // Insert data (1000 rows with 1KB each)
106 constexpr int NUM_ROWS = 1000;
107 constexpr int DATA_SIZE = 1000;
108 std::string data_value(DATA_SIZE, 'X');
109
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);
113 ASSERT_TRUE(insert_result.is_ok());
114 // VoidResult - success is enough
115 }
116
117 size_t before_query = getCurrentMemoryUsage();
118
119 // Query all data
120 auto query_result = db_->select_query("SELECT * FROM large_data");
121 ASSERT_TRUE(query_result.is_ok());
122 auto result = query_result.value();
123
124 size_t after_query = getCurrentMemoryUsage();
125
126 EXPECT_EQ(result.size(), static_cast<size_t>(NUM_ROWS))
127 << "Expected " << NUM_ROWS << " rows, got " << result.size();
128
129 if (before_query > 0) {
130 size_t memory_growth = after_query - before_query;
131 size_t expected_min = NUM_ROWS * DATA_SIZE; // At least the data size
132
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";
138
139 // Memory growth should be reasonable (not more than 10x the data size)
140 EXPECT_LT(memory_growth, expected_min * 10)
141 << "Excessive memory usage detected";
142 }
143
144 // Clear result and verify memory can be released
145 result.clear();
146
147 SUCCEED();
148#else
149 GTEST_SKIP() << "SQLite not available";
150#endif
151}
#define ASSERT_TRUE(condition, message)

References ASSERT_TRUE.

◆ TEST_F() [2/8]

TEST_F ( MemoryStressTest ,
ManySmallStrings  )

Tests memory handling with many small strings.

Test
ManySmallStrings

Definition at line 418 of file memory_stress_test.cpp.

418 {
419#ifdef USE_SQLITE
420 ASSERT_TRUE(db_->execute_query("CREATE TABLE small_strings (id INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT)").is_ok());
421
422 constexpr int NUM_STRINGS = 5000;
423 constexpr int STRING_SIZE = 50;
424
425 size_t initial_memory = getCurrentMemoryUsage();
426
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 + "')");
430 }
431
432 // Query all
433 auto query_result = db_->select_query("SELECT * FROM small_strings");
434 ASSERT_TRUE(query_result.is_ok());
435 EXPECT_EQ(query_result.value().size(), static_cast<size_t>(NUM_STRINGS));
436
437 size_t final_memory = getCurrentMemoryUsage();
438
439 if (initial_memory > 0) {
440 size_t expected_data = NUM_STRINGS * STRING_SIZE;
441 size_t actual_growth = final_memory - initial_memory;
442
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";
447 }
448
449 SUCCEED();
450#else
451 GTEST_SKIP() << "SQLite not available";
452#endif
453}

References ASSERT_TRUE.

◆ TEST_F() [3/8]

TEST_F ( MemoryStressTest ,
MixedOperationsMemoryStability  )

Tests memory stability under mixed CRUD operations.

Test
MixedOperationsMemoryStability

Definition at line 333 of file memory_stress_test.cpp.

333 {
334#ifdef USE_SQLITE
335 ASSERT_TRUE(db_->execute_query("CREATE TABLE mixed_test (id INTEGER PRIMARY KEY AUTOINCREMENT, value TEXT)").is_ok());
336
337 size_t baseline = getCurrentMemoryUsage();
338 constexpr int ITERATIONS = 100;
339
340 for (int i = 0; i < ITERATIONS; ++i) {
341 // Insert
342 db_->execute_query("INSERT INTO mixed_test (value) VALUES ('test_" +
343 std::to_string(i) + "')");
344
345 // Select
346 auto result = db_->select_query("SELECT * FROM mixed_test");
347 (void)result;
348
349 // Update
350 db_->execute_query("UPDATE mixed_test SET value = 'updated_" +
351 std::to_string(i) + "' WHERE id = " + std::to_string(i + 1));
352
353 // Delete (delete old entries to prevent table growth)
354 if (i > 10) {
355 db_->execute_query("DELETE FROM mixed_test WHERE id = " +
356 std::to_string(i - 10));
357 }
358 }
359
360 size_t final_memory = getCurrentMemoryUsage();
361
362 if (baseline > 0) {
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";
369
370 EXPECT_LT(growth, 2.0) << "Excessive memory growth in mixed operations";
371 }
372
373 SUCCEED();
374#else
375 GTEST_SKIP() << "SQLite not available";
376#endif
377}

References ASSERT_TRUE.

◆ TEST_F() [4/8]

TEST_F ( MemoryStressTest ,
PartialResultConsumption  )

Tests memory behavior when only part of result is consumed.

Test
PartialResultConsumption

Definition at line 290 of file memory_stress_test.cpp.

290 {
291#ifdef USE_SQLITE
292 ASSERT_TRUE(db_->execute_query("CREATE TABLE partial_test (id INTEGER PRIMARY KEY, data TEXT)").is_ok());
293
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 + "')");
297 }
298
299 size_t initial_memory = getCurrentMemoryUsage();
300
301 // Query but only use first few rows
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()) {
305 // Only access first row
306 auto& first_row = query_result.value()[0];
307 (void)first_row;
308 }
309 // Result goes out of scope
310 }
311
312 size_t final_memory = getCurrentMemoryUsage();
313
314 if (initial_memory > 0) {
315 EXPECT_LT(final_memory, initial_memory * 2)
316 << "Memory leak with partial result consumption";
317 }
318
319 SUCCEED();
320#else
321 GTEST_SKIP() << "SQLite not available";
322#endif
323}

References ASSERT_TRUE.

◆ TEST_F() [5/8]

TEST_F ( MemoryStressTest ,
QueryBuilderMemoryUsage  )

Tests query builder memory usage with many operations.

Test
QueryBuilderMemoryUsage

Definition at line 207 of file memory_stress_test.cpp.

207 {
208#ifdef USE_SQLITE
209 size_t initial_memory = getCurrentMemoryUsage();
210
211 constexpr int NUM_BUILDERS = 1000;
212
213 for (int i = 0; i < NUM_BUILDERS; ++i) {
214 query_builder builder(database_types::sqlite);
215 auto query = builder
216 .select({"id", "name", "value"})
217 .from("test_table")
218 .where("id", ">", static_cast<int64_t>(i))
219 .where("name", "=", std::string("test"))
220 .order_by("id")
221 .limit(100)
222 .build();
223
224 // Use the query to prevent optimization
225 EXPECT_FALSE(query.empty());
226 }
227
228 size_t final_memory = getCurrentMemoryUsage();
229
230 if (initial_memory > 0) {
231 double growth_ratio = static_cast<double>(final_memory) / initial_memory;
232
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";
238
239 // Query builders should be cleaned up after going out of scope
240 EXPECT_LT(growth_ratio, 2.0)
241 << "Query builder memory not properly released";
242 }
243
244 SUCCEED();
245#else
246 GTEST_SKIP() << "SQLite not available";
247#endif
248}
Universal query builder that adapts to different database types.

References database::query_builder::build(), database::query_builder::limit(), database::query_builder::order_by(), database::query_builder::select(), and database::query_builder::where().

Here is the call graph for this function:

◆ TEST_F() [6/8]

TEST_F ( MemoryStressTest ,
RepeatedQueryMemoryStability  )

Tests that memory remains stable after repeated queries.

Test
RepeatedQueryMemoryStability

Definition at line 157 of file memory_stress_test.cpp.

157 {
158#ifdef USE_SQLITE
159 // Create and populate table
160 ASSERT_TRUE(db_->execute_query(
161 "CREATE TABLE test_table (id INTEGER PRIMARY KEY, value TEXT)").is_ok());
162
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) + "')");
166 }
167
168 size_t baseline_memory = getCurrentMemoryUsage();
169
170 // Execute many queries
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");
174 // Result goes out of scope and should be freed
175 }
176
177 size_t final_memory = getCurrentMemoryUsage();
178
179 if (baseline_memory > 0) {
180 // Allow up to 20% memory growth for caching, etc.
181 double growth_ratio = static_cast<double>(final_memory) / baseline_memory;
182
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";
188
189 EXPECT_LT(growth_ratio, 1.5)
190 << "Possible memory leak: memory grew by " << ((growth_ratio - 1) * 100) << "%";
191 }
192
193 SUCCEED();
194#else
195 GTEST_SKIP() << "SQLite not available";
196#endif
197}

References ASSERT_TRUE.

◆ TEST_F() [7/8]

TEST_F ( MemoryStressTest ,
ResultSetProperCleanup  )

Tests that result sets are properly cleaned up.

Test
ResultSetProperCleanup

Definition at line 258 of file memory_stress_test.cpp.

258 {
259#ifdef USE_SQLITE
260 ASSERT_TRUE(db_->execute_query("CREATE TABLE cleanup_test (id INTEGER PRIMARY KEY, data TEXT)").is_ok());
261
262 // Insert some data
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 + "')");
266 }
267
268 // Query and clear in a loop
269 for (int iteration = 0; iteration < 10; ++iteration) {
270 auto query_result = db_->select_query("SELECT * FROM cleanup_test");
271 ASSERT_TRUE(query_result.is_ok());
272 database_result result = query_result.value();
273 EXPECT_EQ(result.size(), 50u);
274
275 // Explicitly clear
276 result.clear();
277 EXPECT_TRUE(result.empty());
278 }
279
280 SUCCEED() << "Result sets properly cleaned up in all iterations";
281#else
282 GTEST_SKIP() << "SQLite not available";
283#endif
284}
std::vector< database_row > database_result

References ASSERT_TRUE.

◆ TEST_F() [8/8]

TEST_F ( MemoryStressTest ,
VeryLongStringHandling  )

Tests memory handling with very long strings.

Test
VeryLongStringHandling

Definition at line 387 of file memory_stress_test.cpp.

387 {
388#ifdef USE_SQLITE
389 ASSERT_TRUE(db_->execute_query("CREATE TABLE long_string_test (id INTEGER PRIMARY KEY, data TEXT)").is_ok());
390
391 // Insert progressively longer strings
392 std::vector<size_t> sizes = {1000, 5000, 10000, 50000};
393
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 + "')";
397
398 EXPECT_NO_THROW({
399 db_->execute_query(query);
400 }) << "Failed to insert string of size " << size;
401 }
402
403 // Query and verify
404 auto query_result = db_->select_query("SELECT * FROM long_string_test");
405 ASSERT_TRUE(query_result.is_ok());
406 EXPECT_EQ(query_result.value().size(), sizes.size());
407
408 SUCCEED() << "Successfully handled strings up to " << sizes.back() << " bytes";
409#else
410 GTEST_SKIP() << "SQLite not available";
411#endif
412}

References ASSERT_TRUE.