77 constexpr int NUM_THREADS = 10;
78 constexpr int OPS_PER_THREAD = 50;
80 std::atomic<int> success_count{0};
81 std::atomic<int> failure_count{0};
82 std::vector<std::future<void>> futures;
84 auto start = std::chrono::high_resolution_clock::now();
86 for (
int t = 0; t < NUM_THREADS; ++t) {
87 futures.push_back(std::async(std::launch::async, [&, t]() {
88 for (
int i = 0; i < OPS_PER_THREAD; ++i) {
89 std::string query =
"INSERT INTO stress_test (thread_id, value) VALUES (" +
90 std::to_string(t) +
", 'value_" +
91 std::to_string(t * OPS_PER_THREAD + i) +
"')";
93 auto result = db_->execute_query(query);
106 for (
auto& f : futures) {
110 auto duration = std::chrono::high_resolution_clock::now() - start;
111 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
114 int total = success_count + failure_count;
115 double success_rate = (total > 0) ? (100.0 * success_count / total) : 0;
117 std::cout <<
"High Concurrency Insert Test:\n"
118 <<
" Threads: " << NUM_THREADS <<
"\n"
119 <<
" Ops per thread: " << OPS_PER_THREAD <<
"\n"
120 <<
" Successful: " << success_count <<
"\n"
121 <<
" Failed: " << failure_count <<
"\n"
122 <<
" Success rate: " << success_rate <<
"%\n"
123 <<
" Duration: " << ms.count() <<
"ms\n";
126 EXPECT_GT(success_count.load(), 0)
127 <<
"No successful operations under concurrent load";
129 GTEST_SKIP() <<
"SQLite not available";
141 constexpr int NUM_WRITERS = 3;
142 constexpr int NUM_READERS = 5;
143 constexpr int DURATION_MS = 2000;
145 std::atomic<bool> running{
true};
146 std::atomic<int> write_ops{0};
147 std::atomic<int> read_ops{0};
148 std::atomic<int> write_errors{0};
149 std::atomic<int> read_errors{0};
151 std::vector<std::thread> threads;
154 for (
int i = 0; i < NUM_WRITERS; ++i) {
155 threads.emplace_back([&, i]() {
159 std::string query =
"INSERT INTO stress_test (thread_id, value) VALUES (" +
160 std::to_string(i) +
", 'write_" +
161 std::to_string(counter++) +
"')";
162 auto result = db_->execute_query(query);
163 if (result.is_ok()) {
176 for (
int i = 0; i < NUM_READERS; ++i) {
177 threads.emplace_back([&]() {
180 auto result = db_->select_query(
"SELECT COUNT(*) FROM stress_test");
181 if (result.is_ok() && !result.value().empty()) {
194 std::this_thread::sleep_for(std::chrono::milliseconds(DURATION_MS));
197 for (
auto& t : threads) {
201 std::cout <<
"Mixed Read/Write Workload:\n"
202 <<
" Writers: " << NUM_WRITERS <<
", Readers: " << NUM_READERS <<
"\n"
203 <<
" Duration: " << DURATION_MS <<
"ms\n"
204 <<
" Write ops: " << write_ops <<
" (errors: " << write_errors <<
")\n"
205 <<
" Read ops: " << read_ops <<
" (errors: " << read_errors <<
")\n";
208 EXPECT_GT(write_ops.load(), 0) <<
"No write operations completed";
209 EXPECT_GT(read_ops.load(), 0) <<
"No read operations completed";
211 GTEST_SKIP() <<
"SQLite not available";
225 constexpr int NUM_THREADS = 8;
226 constexpr int QUERIES_PER_THREAD = 100;
228 std::atomic<int> build_success{0};
229 std::atomic<int> build_failure{0};
230 std::vector<std::thread> threads;
232 for (
int t = 0; t < NUM_THREADS; ++t) {
233 threads.emplace_back([&, t]() {
234 for (
int i = 0; i < QUERIES_PER_THREAD; ++i) {
241 .
where(
"thread_id",
"=",
static_cast<int64_t
>(t))
245 if (!query.empty()) {
257 for (
auto& t : threads) {
261 int total = build_success + build_failure;
262 EXPECT_EQ(total, NUM_THREADS * QUERIES_PER_THREAD);
263 EXPECT_EQ(build_failure.load(), 0)
264 <<
"Query builder failures under concurrent use";
266 GTEST_SKIP() <<
"SQLite not available";
276 constexpr int NUM_QUERIES = 1000;
278 auto start = std::chrono::high_resolution_clock::now();
283 for (
int i = 0; i < NUM_QUERIES; ++i) {
285 std::string query =
"INSERT INTO stress_test (thread_id, value) VALUES (0, 'rapid_" +
286 std::to_string(i) +
"')";
287 auto result = db_->execute_query(query);
288 if (result.is_ok()) {
298 auto duration = std::chrono::high_resolution_clock::now() - start;
299 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
301 double qps = (ms.count() > 0) ? (1000.0 *
success / ms.count()) : 0;
303 std::cout <<
"Rapid Query Execution:\n"
304 <<
" Queries: " << NUM_QUERIES <<
"\n"
305 <<
" Success: " <<
success <<
", Failure: " << failure <<
"\n"
306 <<
" Duration: " << ms.count() <<
"ms\n"
307 <<
" Throughput: " << qps <<
" queries/sec\n";
310 EXPECT_EQ(failure, 0) <<
"Failures during rapid sequential execution";
312 GTEST_SKIP() <<
"SQLite not available";
327 for (
int i = 0; i < 100; ++i) {
328 db_->execute_query(
"INSERT INTO stress_test (thread_id, value) VALUES (" +
329 std::to_string(i % 10) +
", 'load_test')");
333 auto start = std::chrono::high_resolution_clock::now();
334 auto result = db_->select_query(
"SELECT COUNT(*) FROM stress_test");
335 auto duration = std::chrono::high_resolution_clock::now() - start;
336 auto us = std::chrono::duration_cast<std::chrono::microseconds>(duration);
338 EXPECT_TRUE(result.is_ok() && !result.value().empty()) <<
"System unresponsive after load";
339 EXPECT_LT(us.count(), 100000) <<
"Query took too long after load: " << us.count() <<
"us";
341 std::cout <<
"Post-load query response time: " << us.count() <<
"us\n";
343 GTEST_SKIP() <<
"SQLite not available";
353 constexpr int NUM_THREADS = 4;
354 constexpr int OPS_PER_THREAD = 25;
355 const int EXPECTED_ROWS = NUM_THREADS * OPS_PER_THREAD;
357 std::vector<std::thread> threads;
358 std::atomic<int> actual_inserts{0};
360 for (
int t = 0; t < NUM_THREADS; ++t) {
361 threads.emplace_back([&, t]() {
362 for (
int i = 0; i < OPS_PER_THREAD; ++i) {
363 std::string unique_value =
"thread_" + std::to_string(t) +
364 "_op_" + std::to_string(i);
365 std::string query =
"INSERT INTO stress_test (thread_id, value) VALUES (" +
366 std::to_string(t) +
", '" + unique_value +
"')";
367 auto insert_result = db_->execute_query(query);
368 if (insert_result.is_ok()) {
375 for (
auto& t : threads) {
380 auto result = db_->select_query(
"SELECT COUNT(*) as cnt FROM stress_test");
381 ASSERT_TRUE(result.is_ok() && !result.value().empty());
384 if (!result.value().empty() && result.value()[0].count(
"cnt") > 0) {
385 auto& cnt_value = result.value()[0].at(
"cnt");
386 if (std::holds_alternative<int64_t>(cnt_value)) {
387 row_count =
static_cast<int>(std::get<int64_t>(cnt_value));
388 }
else if (std::holds_alternative<std::string>(cnt_value)) {
389 row_count = std::stoi(std::get<std::string>(cnt_value));
394 EXPECT_EQ(row_count, actual_inserts.load())
395 <<
"Data corruption: row count mismatch";
397 GTEST_SKIP() <<
"SQLite not available";
411 std::atomic<bool> running{
true};
412 std::atomic<int> errors_caught{0};
413 std::vector<std::thread> threads;
416 for (
int t = 0; t < 4; ++t) {
417 threads.emplace_back([&]() {
421 db_->select_query(
"SELECT * FROM stress_test LIMIT 1");
424 auto result = db_->select_query(
"SELECT * FROM nonexistent_table");
425 if (!result.is_ok()) {
435 std::this_thread::sleep_for(std::chrono::milliseconds(500));
438 for (
auto& t : threads) {
443 auto result = db_->select_query(
"SELECT 1 as test");
444 EXPECT_TRUE(result.is_ok() && !result.value().empty()) <<
"System non-functional after error handling test";
446 GTEST_SKIP() <<
"SQLite not available";