test(ci): enable verbose output in CI tests and refactor unit tests
All checks were successful
CMake / build (push) Successful in 47s
All checks were successful
CMake / build (push) Successful in 47s
- Add `-V` flag to `ctest` in CMake workflow for detailed test output - Refactor `passwdgen_test.cpp` to use manual assertions and expand test cases for better coverage - Remove redundant `test_passwdgen.cpp` file with similar but outdated test implementations
This commit is contained in:
parent
55475c4f6f
commit
5de5884aef
@ -52,4 +52,4 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
# Execute tests defined by the CMake configuration.
|
# Execute tests defined by the CMake configuration.
|
||||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||||
run: ctest -C $BUILD_TYPE
|
run: ctest -C $BUILD_TYPE -V
|
||||||
|
|||||||
@ -1,48 +1,197 @@
|
|||||||
// tests/passwdgen_test.cpp
|
|
||||||
#include "../include/passwdgen.h"
|
#include "../include/passwdgen.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <regex>
|
#include <sstream>
|
||||||
#include <cassert>
|
#include <string>
|
||||||
|
#include <cstdlib>
|
||||||
void test_random_string_length() {
|
#include <cstddef>
|
||||||
for (const int lengths[] = {0, 1, 10, 32, 100}; const auto length : lengths) {
|
|
||||||
std::string result = random_string(length, false);
|
|
||||||
assert(result.length() == length);
|
|
||||||
|
|
||||||
std::string result_with_punc = random_string(length, true);
|
|
||||||
assert(result_with_punc.length() == length);
|
|
||||||
}
|
|
||||||
std::cout << "Length test passed\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_alphanumeric_only() {
|
|
||||||
const std::regex alphanumeric_only("^[a-zA-Z0-9]*$");
|
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
std::string result = random_string(20, false);
|
|
||||||
assert(std::regex_match(result, alphanumeric_only));
|
|
||||||
}
|
|
||||||
std::cout << "Alphanumeric test passed\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_with_punctuation() {
|
|
||||||
bool found_special = false;
|
|
||||||
|
|
||||||
for (int i = 0; i < 100 && !found_special; i++) {
|
|
||||||
std::string result = random_string(100, true);
|
|
||||||
if (!std::regex_match(result, std::regex("^[a-zA-Z0-9]*$"))) {
|
|
||||||
found_special = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(found_special);
|
|
||||||
std::cout << "Punctuation test passed\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
test_random_string_length();
|
bool all_passed = true;
|
||||||
test_alphanumeric_only();
|
std::srand(12345);
|
||||||
test_with_punctuation();
|
|
||||||
std::cout << "All tests passed!\n";
|
// LengthZeroReturnsEmpty
|
||||||
|
{
|
||||||
|
std::string result = random_string(0, false);
|
||||||
|
if (result.length() != 0u) {
|
||||||
|
std::cout << "LengthZeroReturnsEmpty: FAILED" << std::endl;
|
||||||
|
all_passed = false;
|
||||||
|
} else {
|
||||||
|
std::cout << "LengthZeroReturnsEmpty: PASSED" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LengthOneNoPuncReturnsAlphanumChar
|
||||||
|
{
|
||||||
|
std::string result = random_string(1, false);
|
||||||
|
std::string alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||||
|
if (result.length() != 1u || alphanum.find(result[0]) == std::string::npos) {
|
||||||
|
std::cout << "LengthOneNoPuncReturnsAlphanumChar: FAILED" << std::endl;
|
||||||
|
all_passed = false;
|
||||||
|
} else {
|
||||||
|
std::cout << "LengthOneNoPuncReturnsAlphanumChar: PASSED" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExactLengthNoPunc
|
||||||
|
{
|
||||||
|
std::string result = random_string(10, false);
|
||||||
|
if (result.length() != 10u) {
|
||||||
|
std::cout << "ExactLengthNoPunc: FAILED" << std::endl;
|
||||||
|
all_passed = false;
|
||||||
|
} else {
|
||||||
|
std::cout << "ExactLengthNoPunc: PASSED" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LengthOneWithPuncReturnsAnyChar
|
||||||
|
{
|
||||||
|
std::string result = random_string(1, true);
|
||||||
|
std::string all_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!\"#$%&'()*+,-./:;<=>?@[\\\\]^_`{|}~";
|
||||||
|
if (result.length() != 1u || all_chars.find(result[0]) == std::string::npos) {
|
||||||
|
std::cout << "LengthOneWithPuncReturnsAnyChar: FAILED" << std::endl;
|
||||||
|
all_passed = false;
|
||||||
|
} else {
|
||||||
|
std::cout << "LengthOneWithPuncReturnsAnyChar: PASSED" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExactLengthWithPunc
|
||||||
|
{
|
||||||
|
std::string result = random_string(20, true);
|
||||||
|
if (result.length() != 20u) {
|
||||||
|
std::cout << "ExactLengthWithPunc: FAILED" << std::endl;
|
||||||
|
all_passed = false;
|
||||||
|
} else {
|
||||||
|
std::cout << "ExactLengthWithPunc: PASSED" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// VeryLargeLength
|
||||||
|
{
|
||||||
|
std::string result = random_string(10000, false);
|
||||||
|
if (result.length() != 10000u) {
|
||||||
|
std::cout << "VeryLargeLength: FAILED" << std::endl;
|
||||||
|
all_passed = false;
|
||||||
|
} else {
|
||||||
|
std::cout << "VeryLargeLength: PASSED" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxSizeTLength
|
||||||
|
{
|
||||||
|
std::size_t large_length = 1000;
|
||||||
|
std::string result = random_string(large_length, true);
|
||||||
|
if (result.length() != large_length) {
|
||||||
|
std::cout << "MaxSizeTLength: FAILED" << std::endl;
|
||||||
|
all_passed = false;
|
||||||
|
} else {
|
||||||
|
std::cout << "MaxSizeTLength: PASSED" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShowUsageTest
|
||||||
|
auto capture_cerr = [](auto func, const std::string& prog) -> std::string {
|
||||||
|
std::stringstream buffer;
|
||||||
|
std::streambuf* old_cerr = std::cerr.rdbuf(buffer.rdbuf());
|
||||||
|
func(prog);
|
||||||
|
std::cerr.rdbuf(old_cerr);
|
||||||
|
return buffer.str();
|
||||||
|
};
|
||||||
|
|
||||||
|
// BasicUsageMessage
|
||||||
|
{
|
||||||
|
std::string output = capture_cerr([&](const std::string& p){ show_usage(p); }, "passwdgen");
|
||||||
|
bool passed = !output.empty() &&
|
||||||
|
output.find("Usage: passwdgen") != std::string::npos &&
|
||||||
|
output.find("--help") != std::string::npos &&
|
||||||
|
output.find("--length") != std::string::npos &&
|
||||||
|
output.find("--punctuation") != std::string::npos;
|
||||||
|
if (!passed) {
|
||||||
|
std::cout << "BasicUsageMessage: FAILED" << std::endl;
|
||||||
|
all_passed = false;
|
||||||
|
} else {
|
||||||
|
std::cout << "BasicUsageMessage: PASSED" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CustomProgramName
|
||||||
|
{
|
||||||
|
std::string output = capture_cerr([&](const std::string& p){ show_usage(p); }, "./my-password-gen");
|
||||||
|
bool passed = output.find("Usage: ./my-password-gen") != std::string::npos;
|
||||||
|
if (!passed) {
|
||||||
|
std::cout << "CustomProgramName: FAILED" << std::endl;
|
||||||
|
all_passed = false;
|
||||||
|
} else {
|
||||||
|
std::cout << "CustomProgramName: PASSED" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmptyProgramName
|
||||||
|
{
|
||||||
|
std::string output = capture_cerr([&](const std::string& p){ show_usage(p); }, "");
|
||||||
|
bool passed = output.find("Usage: ") != std::string::npos;
|
||||||
|
if (!passed) {
|
||||||
|
std::cout << "EmptyProgramName: FAILED" << std::endl;
|
||||||
|
all_passed = false;
|
||||||
|
} else {
|
||||||
|
std::cout << "EmptyProgramName: PASSED" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CharacterSetNoPunc
|
||||||
|
{
|
||||||
|
std::string result = random_string(100, false);
|
||||||
|
std::string alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||||
|
bool has_only_alphanum = true;
|
||||||
|
for (char c : result) {
|
||||||
|
if (alphanum.find(c) == std::string::npos) {
|
||||||
|
has_only_alphanum = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!has_only_alphanum) {
|
||||||
|
std::cout << "CharacterSetNoPunc: FAILED" << std::endl;
|
||||||
|
all_passed = false;
|
||||||
|
} else {
|
||||||
|
std::cout << "CharacterSetNoPunc: PASSED" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CharacterSetWithPunc
|
||||||
|
{
|
||||||
|
std::string result = random_string(100, true);
|
||||||
|
std::string specials = "!\"#$%&'()*+,-./:;<=>?@[\\\\]^_`{|}~";
|
||||||
|
bool has_special_chars = false;
|
||||||
|
for (char c : result) {
|
||||||
|
if (specials.find(c) != std::string::npos) {
|
||||||
|
has_special_chars = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!has_special_chars) {
|
||||||
|
std::cout << "CharacterSetWithPunc: FAILED" << std::endl;
|
||||||
|
all_passed = false;
|
||||||
|
} else {
|
||||||
|
std::cout << "CharacterSetWithPunc: PASSED" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FullIntegration
|
||||||
|
{
|
||||||
|
std::string pwd = random_string(16, true);
|
||||||
|
if (pwd.length() != 16u) {
|
||||||
|
std::cout << "FullIntegration: FAILED" << std::endl;
|
||||||
|
all_passed = false;
|
||||||
|
} else {
|
||||||
|
std::cout << "FullIntegration: PASSED" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (all_passed) {
|
||||||
|
std::cout << "All tests passed!" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Some tests FAILED!" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,198 +0,0 @@
|
|||||||
#include "../passwdgen.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
bool all_passed = true;
|
|
||||||
std::srand(12345);
|
|
||||||
|
|
||||||
// LengthZeroReturnsEmpty
|
|
||||||
{
|
|
||||||
std::string result = random_string(0, false);
|
|
||||||
if (result.length() != 0u) {
|
|
||||||
std::cout << "LengthZeroReturnsEmpty: FAILED" << std::endl;
|
|
||||||
all_passed = false;
|
|
||||||
} else {
|
|
||||||
std::cout << "LengthZeroReturnsEmpty: PASSED" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// LengthOneNoPuncReturnsAlphanumChar
|
|
||||||
{
|
|
||||||
std::string result = random_string(1, false);
|
|
||||||
std::string alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
||||||
if (result.length() != 1u || alphanum.find(result[0]) == std::string::npos) {
|
|
||||||
std::cout << "LengthOneNoPuncReturnsAlphanumChar: FAILED" << std::endl;
|
|
||||||
all_passed = false;
|
|
||||||
} else {
|
|
||||||
std::cout << "LengthOneNoPuncReturnsAlphanumChar: PASSED" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExactLengthNoPunc
|
|
||||||
{
|
|
||||||
std::string result = random_string(10, false);
|
|
||||||
if (result.length() != 10u) {
|
|
||||||
std::cout << "ExactLengthNoPunc: FAILED" << std::endl;
|
|
||||||
all_passed = false;
|
|
||||||
} else {
|
|
||||||
std::cout << "ExactLengthNoPunc: PASSED" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// LengthOneWithPuncReturnsAnyChar
|
|
||||||
{
|
|
||||||
std::string result = random_string(1, true);
|
|
||||||
std::string all_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!\\"#$%&'()*+,-./:;<=>?@[\\\\]^_`{|}~";
|
|
||||||
if (result.length() != 1u || all_chars.find(result[0]) == std::string::npos) {
|
|
||||||
std::cout << "LengthOneWithPuncReturnsAnyChar: FAILED" << std::endl;
|
|
||||||
all_passed = false;
|
|
||||||
} else {
|
|
||||||
std::cout << "LengthOneWithPuncReturnsAnyChar: PASSED" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExactLengthWithPunc
|
|
||||||
{
|
|
||||||
std::string result = random_string(20, true);
|
|
||||||
if (result.length() != 20u) {
|
|
||||||
std::cout << "ExactLengthWithPunc: FAILED" << std::endl;
|
|
||||||
all_passed = false;
|
|
||||||
} else {
|
|
||||||
std::cout << "ExactLengthWithPunc: PASSED" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// VeryLargeLength
|
|
||||||
{
|
|
||||||
std::string result = random_string(10000, false);
|
|
||||||
if (result.length() != 10000u) {
|
|
||||||
std::cout << "VeryLargeLength: FAILED" << std::endl;
|
|
||||||
all_passed = false;
|
|
||||||
} else {
|
|
||||||
std::cout << "VeryLargeLength: PASSED" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MaxSizeTLength
|
|
||||||
{
|
|
||||||
std::size_t large_length = 1000;
|
|
||||||
std::string result = random_string(large_length, true);
|
|
||||||
if (result.length() != large_length) {
|
|
||||||
std::cout << "MaxSizeTLength: FAILED" << std::endl;
|
|
||||||
all_passed = false;
|
|
||||||
} else {
|
|
||||||
std::cout << "MaxSizeTLength: PASSED" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShowUsageTest
|
|
||||||
auto capture_cerr = [](auto func, const std::string& prog) -> std::string {
|
|
||||||
std::stringstream buffer;
|
|
||||||
std::streambuf* old_cerr = std::cerr.rdbuf(buffer.rdbuf());
|
|
||||||
func(prog);
|
|
||||||
std::cerr.rdbuf(old_cerr);
|
|
||||||
return buffer.str();
|
|
||||||
};
|
|
||||||
|
|
||||||
// BasicUsageMessage
|
|
||||||
{
|
|
||||||
std::string output = capture_cerr([&](const std::string& p){ show_usage(p); }, "passwdgen");
|
|
||||||
bool passed = !output.empty() &&
|
|
||||||
output.find("Usage: passwdgen") != std::string::npos &&
|
|
||||||
output.find("--help") != std::string::npos &&
|
|
||||||
output.find("--length") != std::string::npos &&
|
|
||||||
output.find("--punctuation") != std::string::npos;
|
|
||||||
if (!passed) {
|
|
||||||
std::cout << "BasicUsageMessage: FAILED" << std::endl;
|
|
||||||
all_passed = false;
|
|
||||||
} else {
|
|
||||||
std::cout << "BasicUsageMessage: PASSED" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CustomProgramName
|
|
||||||
{
|
|
||||||
std::string output = capture_cerr([&](const std::string& p){ show_usage(p); }, "./my-password-gen");
|
|
||||||
bool passed = output.find("Usage: ./my-password-gen") != std::string::npos;
|
|
||||||
if (!passed) {
|
|
||||||
std::cout << "CustomProgramName: FAILED" << std::endl;
|
|
||||||
all_passed = false;
|
|
||||||
} else {
|
|
||||||
std::cout << "CustomProgramName: PASSED" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EmptyProgramName
|
|
||||||
{
|
|
||||||
std::string output = capture_cerr([&](const std::string& p){ show_usage(p); }, "");
|
|
||||||
bool passed = output.find("Usage: ") != std::string::npos;
|
|
||||||
if (!passed) {
|
|
||||||
std::cout << "EmptyProgramName: FAILED" << std::endl;
|
|
||||||
all_passed = false;
|
|
||||||
} else {
|
|
||||||
std::cout << "EmptyProgramName: PASSED" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CharacterSetNoPunc
|
|
||||||
{
|
|
||||||
std::string result = random_string(100, false);
|
|
||||||
std::string alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
||||||
bool has_only_alphanum = true;
|
|
||||||
for (char c : result) {
|
|
||||||
if (alphanum.find(c) == std::string::npos) {
|
|
||||||
has_only_alphanum = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!has_only_alphanum) {
|
|
||||||
std::cout << "CharacterSetNoPunc: FAILED" << std::endl;
|
|
||||||
all_passed = false;
|
|
||||||
} else {
|
|
||||||
std::cout << "CharacterSetNoPunc: PASSED" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CharacterSetWithPunc
|
|
||||||
{
|
|
||||||
std::string result = random_string(100, true);
|
|
||||||
std::string specials = "!\\"#$%&'()*+,-./:;<=>?@[\\\\]^_`{|}~";
|
|
||||||
bool has_special_chars = false;
|
|
||||||
for (char c : result) {
|
|
||||||
if (specials.find(c) != std::string::npos) {
|
|
||||||
has_special_chars = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!has_special_chars) {
|
|
||||||
std::cout << "CharacterSetWithPunc: FAILED" << std::endl;
|
|
||||||
all_passed = false;
|
|
||||||
} else {
|
|
||||||
std::cout << "CharacterSetWithPunc: PASSED" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FullIntegration
|
|
||||||
{
|
|
||||||
std::string pwd = random_string(16, true);
|
|
||||||
if (pwd.length() != 16u) {
|
|
||||||
std::cout << "FullIntegration: FAILED" << std::endl;
|
|
||||||
all_passed = false;
|
|
||||||
} else {
|
|
||||||
std::cout << "FullIntegration: PASSED" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (all_passed) {
|
|
||||||
std::cout << "All tests passed!" << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cout << "Some tests FAILED!" << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user