Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion hyperpage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ void hyperpage::writer::store(const hyperpage::page &page)
{
sqlite3 *db = get_handle(_handle);
const std::string query =
"INSERT INTO hyperpage (path, mime_type, content) VALUES (?, ?, ?);"
"INSERT INTO hyperpage (path, mime_type, content) VALUES (?, ?, ?) "
"ON CONFLICT(path) DO UPDATE SET mime_type=excluded.mime_type, content=excluded.content;";
sqlite3_stmt *stmt = nullptr;

Expand Down
4 changes: 3 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,6 @@ endif()

maxtest_add_test(unit store_load $<TARGET_FILE_DIR:unit>)
maxtest_add_test(unit open_database $<TARGET_FILE_DIR:unit>)
maxtest_add_test(unit mime_type $<TARGET_FILE_DIR:unit>)
maxtest_add_test(unit mime_type $<TARGET_FILE_DIR:unit>)
maxtest_add_test(unit overwrite_test $<TARGET_FILE_DIR:unit>)
maxtest_add_test(unit archive_size_no_growth_test $<TARGET_FILE_DIR:unit>)
76 changes: 76 additions & 0 deletions tests/unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,80 @@ MAXTEST_MAIN
auto file_type = hyperpage::mime_type(json_path);
MAXTEST_ASSERT(file_type == json_mime_type);
};

MAXTEST_TEST_CASE(overwrite_test)
{
std::filesystem::path db_path = std::filesystem::path(args[0]) / "hyperpage_overwrite_test.db";

// Remove any existing database file to start fresh
if (std::filesystem::exists(db_path)) {
std::filesystem::remove(db_path);
}

hyperpage::writer writer(db_path.string());

// Create a page and store it
test_page original_page("/index.html", "text/html", "<html><body>Original Content</body></html>");
writer.store(original_page);

// Now overwrite with updated content using the same writer
test_page updated_page("/index.html", "text/html", "<html><body>Updated Content</body></html>");
writer.store(updated_page);

// Verify updated content is actually stored
hyperpage::reader reader(db_path.string());
auto loaded_page = reader.load("/index.html");
MAXTEST_ASSERT(loaded_page != nullptr);
MAXTEST_ASSERT(loaded_page->get_path() == "/index.html");
MAXTEST_ASSERT(loaded_page->get_mime_type() == "text/html");

// Check updated content - this is where the issue should manifest
std::string updated_content = "<html><body>Updated Content</body></html>";
MAXTEST_ASSERT(loaded_page->get_length() == updated_content.size());
MAXTEST_ASSERT(match_buffers(loaded_page->get_content(), loaded_page->get_length(),
reinterpret_cast<const uint8_t*>(updated_content.data()), updated_content.size()));
};

MAXTEST_TEST_CASE(archive_size_no_growth_test)
{
std::filesystem::path db_path = std::filesystem::path(args[0]) / "hyperpage_size_test.db";

// Remove any existing database file to start fresh
if (std::filesystem::exists(db_path)) {
std::filesystem::remove(db_path);
}

// Create initial content
test_page test_page_content("/test.html", "text/html", "<html><body>Test Content</body></html>");

// Store initial content and record database size
{
hyperpage::writer writer(db_path.string());
writer.store(test_page_content);
}

size_t initial_size = std::filesystem::file_size(db_path);

// Overwrite with identical content multiple times
for (int i = 0; i < 5; ++i) {
hyperpage::writer writer(db_path.string());
writer.store(test_page_content); // Same content each time
}

size_t final_size = std::filesystem::file_size(db_path);

// The database size should not grow significantly when overwriting with identical content
// Allow for some variance due to SQLite overhead, but it shouldn't grow substantially
MAXTEST_ASSERT(final_size <= initial_size * 1.1); // Max 10% growth tolerance

// Verify content is still correct
hyperpage::reader reader(db_path.string());
auto loaded_page = reader.load("/test.html");
MAXTEST_ASSERT(loaded_page != nullptr);
MAXTEST_ASSERT(loaded_page->get_path() == "/test.html");
std::string expected_content = "<html><body>Test Content</body></html>";
MAXTEST_ASSERT(loaded_page->get_length() == expected_content.size());
MAXTEST_ASSERT(match_buffers(loaded_page->get_content(), loaded_page->get_length(),
reinterpret_cast<const uint8_t*>(expected_content.data()), expected_content.size()));
};
}