Database System 0.1.0
Advanced C++20 Database System with Multi-Backend Support
Loading...
Searching...
No Matches
database_test_utils.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
5#pragma once
6
8#include "mock_database.h"
9#include "mock_backend.h"
10#include <string>
11#include <vector>
12#include <chrono>
13#include <functional>
14
16
28inline core::database_result make_result(std::initializer_list<core::database_row> rows) {
29 return core::database_result(rows);
30}
31
35inline core::database_row make_row(std::initializer_list<std::pair<std::string, core::database_value>> fields) {
37 for (const auto& [key, value] : fields) {
38 row[key] = value;
39 }
40 return row;
41}
42
46template<typename T>
48 return core::database_value(val);
49}
50
55 return core::database_value(nullptr);
56}
57
63public:
64 test_timer() : start_(std::chrono::high_resolution_clock::now()) {}
65
66 void reset() {
67 start_ = std::chrono::high_resolution_clock::now();
68 }
69
70 double elapsed_ms() const {
71 auto now = std::chrono::high_resolution_clock::now();
72 return std::chrono::duration<double, std::milli>(now - start_).count();
73 }
74
75 double elapsed_us() const {
76 auto now = std::chrono::high_resolution_clock::now();
77 return std::chrono::duration<double, std::micro>(now - start_).count();
78 }
79
80private:
81 std::chrono::high_resolution_clock::time_point start_;
82};
83
89public:
91 : db_(db)
92 {
94 config.host = "localhost";
95 config.port = 5432;
96 config.database = "test_db";
97 db_.initialize(config);
98 }
99
101 db_.shutdown();
102 db_.reset();
103 }
104
105 mock_database& get() { return db_; }
106 const mock_database& get() const { return db_; }
107
108private:
110};
111
119 size_t count,
120 std::function<core::database_row(size_t index)> row_generator)
121{
123 result.reserve(count);
124 for (size_t i = 0; i < count; ++i) {
125 result.push_back(row_generator(i));
126 }
127 return result;
128}
129
136inline core::database_result generate_sequential_ids(size_t count, const std::string& id_column = "id") {
137 return generate_test_data(count, [&](size_t i) {
138 return core::database_row{{id_column, static_cast<int64_t>(i + 1)}};
139 });
140}
141
145namespace fixtures {
146
151 return make_result({
152 {{"id", int64_t(1)}, {"name", std::string("Alice")}, {"email", std::string("alice@example.com")}, {"active", true}},
153 {{"id", int64_t(2)}, {"name", std::string("Bob")}, {"email", std::string("bob@example.com")}, {"active", true}},
154 {{"id", int64_t(3)}, {"name", std::string("Charlie")}, {"email", std::string("charlie@example.com")}, {"active", false}}
155 });
156}
157
162 return make_result({
163 {{"id", int64_t(1)}, {"name", std::string("Widget")}, {"price", 19.99}, {"quantity", int64_t(100)}},
164 {{"id", int64_t(2)}, {"name", std::string("Gadget")}, {"price", 29.99}, {"quantity", int64_t(50)}},
165 {{"id", int64_t(3)}, {"name", std::string("Thing")}, {"price", 9.99}, {"quantity", int64_t(200)}}
166 });
167}
168
175
176} // namespace fixtures
177
181namespace assertions {
182
186inline bool has_rows(const core::database_result& result, size_t expected) {
187 return result.size() == expected;
188}
189
193inline bool is_empty(const core::database_result& result) {
194 return result.empty();
195}
196
200template<typename T>
201bool contains_field_value(const core::database_result& result, const std::string& field, const T& value) {
202 for (const auto& row : result) {
203 auto it = row.find(field);
204 if (it != row.end()) {
205 if (auto* v = std::get_if<T>(&it->second)) {
206 if (*v == value) return true;
207 }
208 }
209 }
210 return false;
211}
212
216template<typename T>
217bool is_success(const kcenon::common::Result<T>& result) {
218 return result.is_ok();
219}
220
224template<typename T>
225bool is_error(const kcenon::common::Result<T>& result) {
226 return result.is_err();
227}
228
232inline bool is_success(const kcenon::common::VoidResult& result) {
233 return result.is_ok();
234}
235
239inline bool is_error(const kcenon::common::VoidResult& result) {
240 return result.is_err();
241}
242
243} // namespace assertions
244
245} // namespace database::testing
Configurable mock for database_backend interface.
kcenon::common::VoidResult initialize(const core::connection_config &config) override
Initialize the database backend.
kcenon::common::VoidResult shutdown() override
Shutdown the database backend gracefully.
RAII wrapper for test database setup/teardown.
Simple timer for performance testing.
std::chrono::high_resolution_clock::time_point start_
Abstract interface for database backends.
std::vector< database_row > database_result
std::map< std::string, database_value > database_row
std::variant< std::string, int64_t, double, bool, std::nullptr_t > database_value
bool contains_field_value(const core::database_result &result, const std::string &field, const T &value)
Check if result contains a row with specific field value.
bool is_error(const kcenon::common::Result< T > &result)
Check if a Result<T> is an error.
bool has_rows(const core::database_result &result, size_t expected)
Check if result contains expected number of rows.
bool is_empty(const core::database_result &result)
Check if result is empty.
bool is_success(const kcenon::common::Result< T > &result)
Check if a Result<T> is successful.
core::database_result empty_result()
Empty result.
core::database_result products_data()
Standard products table data.
core::database_result users_data()
Standard user table data.
core::database_result make_result(std::initializer_list< core::database_row > rows)
Helper function to create test data rows.
core::database_result generate_sequential_ids(size_t count, const std::string &id_column="id")
Generate sequential integer test data.
core::database_value make_null()
Create a NULL value.
core::database_row make_row(std::initializer_list< std::pair< std::string, core::database_value > > fields)
Create a single row.
core::database_value make_value(const T &val)
Create a database_value from common types.
core::database_result generate_test_data(size_t count, std::function< core::database_row(size_t index)> row_generator)
Generate test data for a table.
Configuration for database connection.