Tests: add live integration test (optional via PRIVATEBIN_IT), fix WinHTTP host/port + TLS opts, robust JSON parser (meta.time_to_live), CTest wiring; Add LLVM/clang-cl coverage option and docs; add build_thinkpad.bat; README updates

This commit is contained in:
mbusc
2025-08-28 15:22:00 +02:00
parent 7a125a4c9c
commit 0f58d40f52
10 changed files with 467 additions and 39 deletions

View File

@ -3,23 +3,26 @@ project(PrivateBinAPITests)
set(CMAKE_CXX_STANDARD 17)
# Find the privatebinapi library
find_library(PRIVATEBINAPI_LIB privatebinapi
PATHS ${CMAKE_CURRENT_SOURCE_DIR}/../build)
# If not found, build it as part of the project
if(NOT PRIVATEBINAPI_LIB)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/privatebinapi)
set(PRIVATEBINAPI_LIB privatebinapi)
endif()
# Create test executable
add_executable(test_basic test_basic.cpp)
# Link with the privatebinapi library
target_link_libraries(test_basic ${PRIVATEBINAPI_LIB})
# Link with the already-defined privatebinapi target from the root project
target_link_libraries(test_basic PRIVATE privatebinapi)
# Ensure the DLL is available next to the test executable on Windows
if(WIN32)
add_dependencies(test_basic privatebinapi)
add_custom_command(TARGET test_basic POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:privatebinapi>
$<TARGET_FILE_DIR:test_basic>
)
endif()
# Include directories
target_include_directories(test_basic PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../include
)
)
# Register the test with CTest
add_test(NAME test_basic COMMAND test_basic)

View File

@ -1,15 +1,90 @@
// Network integration test hitting a live PrivateBin instance (optional)
// Server under test: https://privatebin.medisoftware.org/
// Enable by setting environment variable PRIVATEBIN_IT=1
#include "privatebinapi.h"
#include <iostream>
#include <string>
#include <cassert>
#include <cstdlib>
static bool extract_paste_id_and_key(const std::string& full_url, std::string& paste_id, std::string& key) {
// Expected format: https://host/path?PASTEID#BASE58_KEY
const std::size_t qpos = full_url.find('?');
const std::size_t hpos = full_url.find('#');
if (qpos == std::string::npos || hpos == std::string::npos || hpos <= qpos + 1) {
return false;
}
paste_id = full_url.substr(qpos + 1, hpos - (qpos + 1));
key = full_url.substr(hpos + 1);
return !paste_id.empty() && !key.empty();
}
int main() {
// Test Base58 encoding/decoding
std::cout << "Testing Base58 encoding/decoding..." << std::endl;
// This is just a basic test to verify the API compiles and links
// In a real test, we would test actual functionality
std::cout << "API test completed successfully!" << std::endl;
const char* it = std::getenv("PRIVATEBIN_IT");
if (!it || std::string(it) == "0") {
std::cout << "[test] PRIVATEBIN_IT not set; skipping integration test." << std::endl;
return 0; // treat as success when integration testing is disabled
}
const char* server = "https://privatebin.medisoftware.org/";
const char* content = "Integration test from lib-privatebin";
const char* password = nullptr; // no password
const char* expiration = "5min"; // short-lived
const char* format = "plaintext";
const int burn_after_reading = 0;
const int open_discussion = 0;
char* paste_url = nullptr;
char* delete_token = nullptr;
std::cout << "[test] create_paste..." << std::endl;
int rc = create_paste(server, content, password, expiration, format,
burn_after_reading, open_discussion, &paste_url, &delete_token);
if (rc != 0 || paste_url == nullptr || delete_token == nullptr) {
std::cerr << "[test][ERROR] create_paste failed, rc=" << rc << std::endl;
if (paste_url) free_string(paste_url);
if (delete_token) free_string(delete_token);
return 1;
}
std::string full_url = paste_url;
std::string paste_id;
std::string key;
const bool ok_parse = extract_paste_id_and_key(full_url, paste_id, key);
if (!ok_parse) {
std::cerr << "[test][ERROR] failed to parse paste id/key from URL: " << full_url << std::endl;
free_string(paste_url);
free_string(delete_token);
return 1;
}
std::cout << "[test] get_paste... id=" << paste_id << std::endl;
char* fetched = nullptr;
rc = get_paste(server, paste_id.c_str(), key.c_str(), &fetched);
if (rc != 0 || fetched == nullptr) {
std::cerr << "[test][ERROR] get_paste failed, rc=" << rc << std::endl;
free_string(paste_url);
free_string(delete_token);
return 1;
}
std::string fetched_str = fetched;
assert(fetched_str == content && "fetched content mismatch");
std::cout << "[test] delete_paste..." << std::endl;
rc = delete_paste(server, paste_id.c_str(), delete_token);
if (rc != 0) {
std::cerr << "[test][ERROR] delete_paste failed, rc=" << rc << std::endl;
free_string(paste_url);
free_string(delete_token);
free_string(fetched);
return 1;
}
// cleanup
free_string(paste_url);
free_string(delete_token);
free_string(fetched);
std::cout << "[test] all API functions passed." << std::endl;
return 0;
}