mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-12-04 15:39:34 +01:00
Add -i/--include option to "generate" CLI command. (#7112)
This commit is contained in:
@@ -1195,6 +1195,10 @@ void TestCli::testGenerate_data()
|
||||
<< QStringList{"generate", "-L", "2", "--upper", "-l", "--every-group"} << "^[a-z][A-Z]|[A-Z][a-z]$";
|
||||
QTest::newRow("numbers + lowercase (every)")
|
||||
<< QStringList{"generate", "-L", "2", "-n", "-l", "--every-group"} << "^[a-z][0-9]|[0-9][a-z]$";
|
||||
QTest::newRow("custom character set")
|
||||
<< QStringList{"generate", "-L", "200", "-n", "-c", "abc"} << "^[abc0-9]{200}$";
|
||||
QTest::newRow("custom character set without extra options uses only custom chars")
|
||||
<< QStringList{"generate", "-L", "200", "-c", "a"} << "^a{200}$";
|
||||
}
|
||||
|
||||
void TestCli::testGenerate()
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
#include "TestPasswordGenerator.h"
|
||||
#include "core/PasswordGenerator.h"
|
||||
#include "crypto/Crypto.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
@@ -24,120 +23,261 @@
|
||||
|
||||
QTEST_GUILESS_MAIN(TestPasswordGenerator)
|
||||
|
||||
Q_DECLARE_METATYPE(PasswordGenerator::CharClasses)
|
||||
Q_DECLARE_METATYPE(PasswordGenerator::GeneratorFlags)
|
||||
|
||||
namespace
|
||||
{
|
||||
PasswordGenerator::CharClasses to_flags(PasswordGenerator::CharClass x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
PasswordGenerator::GeneratorFlags to_flags(PasswordGenerator::GeneratorFlag x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void TestPasswordGenerator::initTestCase()
|
||||
{
|
||||
QVERIFY(Crypto::init());
|
||||
}
|
||||
|
||||
void TestPasswordGenerator::testAdditionalChars()
|
||||
void TestPasswordGenerator::init()
|
||||
{
|
||||
PasswordGenerator generator;
|
||||
QVERIFY(!generator.isValid());
|
||||
generator.setAdditionalChars("aql");
|
||||
generator.setLength(2000);
|
||||
QVERIFY(generator.isValid());
|
||||
QString password = generator.generatePassword();
|
||||
m_generator.reset();
|
||||
}
|
||||
|
||||
void TestPasswordGenerator::testCustomCharacterSet_data()
|
||||
{
|
||||
QTest::addColumn<PasswordGenerator::CharClasses>("activeCharacterClasses");
|
||||
QTest::addColumn<QString>("customCharacterSet");
|
||||
QTest::addColumn<QRegularExpression>("expected");
|
||||
|
||||
QTest::addRow("With active classes") << to_flags(PasswordGenerator::CharClass::UpperLetters) << "abc"
|
||||
<< QRegularExpression("^[abcA-Z]{2000}$");
|
||||
QTest::addRow("Without any active class")
|
||||
<< to_flags(PasswordGenerator::CharClass::NoClass) << "abc" << QRegularExpression("^[abc]{2000}$");
|
||||
}
|
||||
|
||||
void TestPasswordGenerator::testCustomCharacterSet()
|
||||
{
|
||||
QFETCH(PasswordGenerator::CharClasses, activeCharacterClasses);
|
||||
QFETCH(QString, customCharacterSet);
|
||||
QFETCH(QRegularExpression, expected);
|
||||
|
||||
m_generator.setCharClasses(activeCharacterClasses);
|
||||
m_generator.setCustomCharacterSet(customCharacterSet);
|
||||
m_generator.setLength(2000);
|
||||
|
||||
QVERIFY(m_generator.isValid());
|
||||
QString password = m_generator.generatePassword();
|
||||
QCOMPARE(password.size(), 2000);
|
||||
QRegularExpression regex(R"(^[aql]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
QVERIFY(expected.match(password).hasMatch());
|
||||
}
|
||||
|
||||
void TestPasswordGenerator::testCharClasses_data()
|
||||
{
|
||||
QTest::addColumn<PasswordGenerator::CharClasses>("activeCharacterClasses");
|
||||
QTest::addColumn<QRegularExpression>("expected");
|
||||
|
||||
QTest::addRow("Lower Letters") << to_flags(PasswordGenerator::CharClass::LowerLetters)
|
||||
<< QRegularExpression(R"(^[a-z]{2000}$)");
|
||||
QTest::addRow("Upper Letters") << to_flags(PasswordGenerator::CharClass::UpperLetters)
|
||||
<< QRegularExpression(R"(^[A-Z]{2000}$)");
|
||||
QTest::addRow("Numbers") << to_flags(PasswordGenerator::CharClass::Numbers) << QRegularExpression(R"(^\d{2000}$)");
|
||||
QTest::addRow("Braces") << to_flags(PasswordGenerator::CharClass::Braces)
|
||||
<< QRegularExpression(R"(^[\(\)\[\]\{\}]{2000}$)");
|
||||
QTest::addRow("Punctuation") << to_flags(PasswordGenerator::CharClass::Punctuation)
|
||||
<< QRegularExpression(R"(^[\.,:;]{2000}$)");
|
||||
QTest::addRow("Quotes") << to_flags(PasswordGenerator::CharClass::Quotes) << QRegularExpression(R"(^["']{2000}$)");
|
||||
QTest::addRow("Dashes") << to_flags(PasswordGenerator::CharClass::Dashes)
|
||||
<< QRegularExpression(R"(^[\-/\\_|]{2000}$)");
|
||||
QTest::addRow("Math") << to_flags(PasswordGenerator::CharClass::Math) << QRegularExpression(R"(^[!\*\+\-<=>\?]+$)");
|
||||
QTest::addRow("Logograms") << to_flags(PasswordGenerator::CharClass::Logograms)
|
||||
<< QRegularExpression(R"(^[#`~%&^$@]{2000}$)");
|
||||
QTest::addRow("Extended ASCII") << to_flags(PasswordGenerator::CharClass::EASCII)
|
||||
<< QRegularExpression(R"(^[^a-zA-Z0-9\.,:;"'\-/\\_|!\*\+\-<=>\?#`~%&^$@]{2000}$)");
|
||||
QTest::addRow("Combinations 1") << (PasswordGenerator::CharClass::LowerLetters
|
||||
| PasswordGenerator::CharClass::UpperLetters
|
||||
| PasswordGenerator::CharClass::Braces)
|
||||
<< QRegularExpression(R"(^[a-zA-Z\(\)\[\]\{\}]{2000}$)");
|
||||
QTest::addRow("Combinations 2") << (PasswordGenerator::CharClass::Quotes | PasswordGenerator::CharClass::Numbers
|
||||
| PasswordGenerator::CharClass::Dashes)
|
||||
<< QRegularExpression(R"(^["'\d\-/\\_|]{2000}$)");
|
||||
}
|
||||
|
||||
void TestPasswordGenerator::testCharClasses()
|
||||
{
|
||||
PasswordGenerator generator;
|
||||
QVERIFY(!generator.isValid());
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::LowerLetters);
|
||||
generator.setLength(16);
|
||||
QVERIFY(generator.isValid());
|
||||
QCOMPARE(generator.generatePassword().size(), 16);
|
||||
|
||||
generator.setLength(2000);
|
||||
QString password = generator.generatePassword();
|
||||
QFETCH(PasswordGenerator::CharClasses, activeCharacterClasses);
|
||||
QFETCH(QRegularExpression, expected);
|
||||
|
||||
m_generator.setCharClasses(activeCharacterClasses);
|
||||
m_generator.setLength(2000);
|
||||
|
||||
QVERIFY(m_generator.isValid());
|
||||
QString password = m_generator.generatePassword();
|
||||
QCOMPARE(password.size(), 2000);
|
||||
QRegularExpression regex(R"(^[a-z]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
QVERIFY(expected.match(password).hasMatch());
|
||||
}
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::UpperLetters);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[A-Z]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
void TestPasswordGenerator::testLookalikeExclusion_data()
|
||||
{
|
||||
QTest::addColumn<PasswordGenerator::CharClasses>("activeCharacterClasses");
|
||||
QTest::addColumn<QRegularExpression>("expected");
|
||||
QTest::addRow("Upper Letters") << (PasswordGenerator::CharClass::LowerLetters
|
||||
| PasswordGenerator::CharClass::UpperLetters)
|
||||
<< QRegularExpression("^[^lBGIO]{2000}$");
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Numbers);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^\d+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
QTest::addRow("Letters and Numbers") << (PasswordGenerator::CharClass::LowerLetters
|
||||
| PasswordGenerator::CharClass::UpperLetters
|
||||
| PasswordGenerator::CharClass::Numbers)
|
||||
<< QRegularExpression("^[^lBGIO0168]{2000}$");
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Braces);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[\(\)\[\]\{\}]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Punctuation);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[\.,:;]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Quotes);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^["']+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Dashes);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[\-/\\_|]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Math);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[!\*\+\-<=>\?]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Logograms);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[#`~%&^$@]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::EASCII);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[^a-zA-Z0-9\.,:;"'\-/\\_|!\*\+\-<=>\?#`~%&^$@]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::LowerLetters | PasswordGenerator::CharClass::UpperLetters
|
||||
| PasswordGenerator::CharClass::Braces);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[a-zA-Z\(\)\[\]\{\}]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Quotes | PasswordGenerator::CharClass::Numbers
|
||||
| PasswordGenerator::CharClass::Dashes);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^["'\d\-/\\_|]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
QTest::addRow("Letters, Numbers and extended ASCII")
|
||||
<< (PasswordGenerator::CharClass::LowerLetters | PasswordGenerator::CharClass::UpperLetters
|
||||
| PasswordGenerator::CharClass::Numbers | PasswordGenerator::CharClass::EASCII)
|
||||
<< QRegularExpression("^[^lBGIO0168﹒]{2000}$");
|
||||
}
|
||||
|
||||
void TestPasswordGenerator::testLookalikeExclusion()
|
||||
{
|
||||
PasswordGenerator generator;
|
||||
generator.setLength(2000);
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::LowerLetters | PasswordGenerator::CharClass::UpperLetters);
|
||||
QVERIFY(generator.isValid());
|
||||
QString password = generator.generatePassword();
|
||||
QFETCH(PasswordGenerator::CharClasses, activeCharacterClasses);
|
||||
QFETCH(QRegularExpression, expected);
|
||||
|
||||
m_generator.setFlags(PasswordGenerator::ExcludeLookAlike);
|
||||
m_generator.setCharClasses(activeCharacterClasses);
|
||||
m_generator.setLength(2000);
|
||||
|
||||
QVERIFY(m_generator.isValid());
|
||||
QString password = m_generator.generatePassword();
|
||||
QCOMPARE(password.size(), 2000);
|
||||
|
||||
generator.setFlags(PasswordGenerator::GeneratorFlag::ExcludeLookAlike);
|
||||
password = generator.generatePassword();
|
||||
QRegularExpression regex("^[^lBGIO]+$");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::LowerLetters | PasswordGenerator::CharClass::UpperLetters
|
||||
| PasswordGenerator::CharClass::Numbers);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern("^[^lBGIO0168]+$");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::LowerLetters | PasswordGenerator::CharClass::UpperLetters
|
||||
| PasswordGenerator::CharClass::Numbers | PasswordGenerator::CharClass::EASCII);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern("^[^lBGIO0168﹒]+$");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
QVERIFY(expected.match(password).hasMatch());
|
||||
}
|
||||
|
||||
void TestPasswordGenerator::testValidity_data()
|
||||
{
|
||||
QTest::addColumn<PasswordGenerator::CharClasses>("activeCharacterClasses");
|
||||
QTest::addColumn<PasswordGenerator::GeneratorFlags>("generatorFlags");
|
||||
QTest::addColumn<QString>("customCharacterSet");
|
||||
QTest::addColumn<QString>("excludedCharacters");
|
||||
QTest::addColumn<int>("length");
|
||||
QTest::addColumn<bool>("isValid");
|
||||
|
||||
QTest::addRow("No active class") << to_flags(PasswordGenerator::CharClass::NoClass)
|
||||
<< PasswordGenerator::GeneratorFlags() << QString() << QString()
|
||||
<< PasswordGenerator::DefaultLength << false;
|
||||
QTest::addRow("0 length") << to_flags(PasswordGenerator::CharClass::DefaultCharset)
|
||||
<< PasswordGenerator::GeneratorFlags() << QString() << QString() << 0 << false;
|
||||
QTest::addRow("All active classes excluded")
|
||||
<< to_flags(PasswordGenerator::CharClass::Numbers) << PasswordGenerator::GeneratorFlags() << QString()
|
||||
<< QString("0123456789") << PasswordGenerator::DefaultLength << false;
|
||||
QTest::addRow("All active classes excluded")
|
||||
<< to_flags(PasswordGenerator::CharClass::NoClass) << PasswordGenerator::GeneratorFlags() << QString()
|
||||
<< QString("0123456789") << PasswordGenerator::DefaultLength << false;
|
||||
QTest::addRow("One from every class with too few classes")
|
||||
<< (PasswordGenerator::CharClass::LowerLetters | PasswordGenerator::CharClass::UpperLetters)
|
||||
<< to_flags(PasswordGenerator::GeneratorFlag::CharFromEveryGroup) << QString() << QString() << 1 << false;
|
||||
QTest::addRow("One from every class with excluded classes")
|
||||
<< (PasswordGenerator::CharClass::LowerLetters | PasswordGenerator::CharClass::UpperLetters
|
||||
| PasswordGenerator::CharClass::Numbers)
|
||||
<< to_flags(PasswordGenerator::GeneratorFlag::CharFromEveryGroup) << QString() << QString("0123456789") << 2
|
||||
<< true;
|
||||
QTest::addRow("Defaults valid") << to_flags(PasswordGenerator::CharClass::DefaultCharset)
|
||||
<< to_flags(PasswordGenerator::GeneratorFlag::DefaultFlags)
|
||||
<< PasswordGenerator::DefaultCustomCharacterSet
|
||||
<< PasswordGenerator::DefaultExcludedChars << PasswordGenerator::DefaultLength
|
||||
<< true;
|
||||
QTest::addRow("No active classes but custom charset")
|
||||
<< to_flags(PasswordGenerator::CharClass::NoClass) << to_flags(PasswordGenerator::GeneratorFlag::DefaultFlags)
|
||||
<< QString("a") << QString() << 1 << true;
|
||||
}
|
||||
|
||||
void TestPasswordGenerator::testValidity()
|
||||
{
|
||||
QFETCH(PasswordGenerator::CharClasses, activeCharacterClasses);
|
||||
QFETCH(PasswordGenerator::GeneratorFlags, generatorFlags);
|
||||
QFETCH(QString, customCharacterSet);
|
||||
QFETCH(QString, excludedCharacters);
|
||||
QFETCH(int, length);
|
||||
QFETCH(bool, isValid);
|
||||
|
||||
m_generator.setCharClasses(activeCharacterClasses);
|
||||
m_generator.setFlags(generatorFlags);
|
||||
m_generator.setCustomCharacterSet(customCharacterSet);
|
||||
m_generator.setExcludedCharacterSet(excludedCharacters);
|
||||
m_generator.setLength(length);
|
||||
QCOMPARE(m_generator.isValid(), isValid);
|
||||
}
|
||||
|
||||
void TestPasswordGenerator::testMinLength_data()
|
||||
{
|
||||
QTest::addColumn<PasswordGenerator::CharClasses>("activeCharacterClasses");
|
||||
QTest::addColumn<PasswordGenerator::GeneratorFlags>("generatorFlags");
|
||||
QTest::addColumn<QString>("customCharacterSet");
|
||||
QTest::addColumn<QString>("excludedCharacters");
|
||||
QTest::addColumn<int>("expectedMinLength");
|
||||
|
||||
QTest::addRow("No restriction without charsFromEveryGroup")
|
||||
<< to_flags(PasswordGenerator::CharClass::Numbers)
|
||||
<< to_flags(PasswordGenerator::GeneratorFlag::CharFromEveryGroup)
|
||||
<< PasswordGenerator::DefaultCustomCharacterSet << PasswordGenerator::DefaultExcludedChars << 1;
|
||||
|
||||
QTest::addRow("Min length should equal number of active classes")
|
||||
<< (PasswordGenerator::CharClass::LowerLetters | PasswordGenerator::CharClass::UpperLetters
|
||||
| PasswordGenerator::CharClass::Numbers)
|
||||
<< to_flags(PasswordGenerator::GeneratorFlag::CharFromEveryGroup) << QString() << QString() << 3;
|
||||
QTest::addRow("Classes fully excluded by excluded characters do not count towards min length")
|
||||
<< (PasswordGenerator::CharClass::Numbers | PasswordGenerator::LowerLetters
|
||||
| PasswordGenerator::CharClass::UpperLetters)
|
||||
<< to_flags(PasswordGenerator::GeneratorFlag::CharFromEveryGroup) << QString() << QString("0123456789") << 2;
|
||||
|
||||
QTest::addRow("Custom charset counts as class")
|
||||
<< to_flags(PasswordGenerator::CharClass::UpperLetters)
|
||||
<< to_flags(PasswordGenerator::GeneratorFlag::CharFromEveryGroup) << QString("a") << QString() << 2;
|
||||
QTest::addRow("Custom characters count even if included by an active class already")
|
||||
<< (PasswordGenerator::CharClass::LowerLetters | PasswordGenerator::CharClass::UpperLetters
|
||||
| PasswordGenerator::CharClass::Numbers)
|
||||
<< to_flags(PasswordGenerator::GeneratorFlag::CharFromEveryGroup) << QString("012345") << QString() << 4;
|
||||
}
|
||||
|
||||
void TestPasswordGenerator::testMinLength()
|
||||
{
|
||||
QFETCH(PasswordGenerator::CharClasses, activeCharacterClasses);
|
||||
QFETCH(PasswordGenerator::GeneratorFlags, generatorFlags);
|
||||
QFETCH(QString, customCharacterSet);
|
||||
QFETCH(QString, excludedCharacters);
|
||||
QFETCH(int, expectedMinLength);
|
||||
|
||||
m_generator.setCharClasses(activeCharacterClasses);
|
||||
m_generator.setFlags(generatorFlags);
|
||||
m_generator.setCustomCharacterSet(customCharacterSet);
|
||||
m_generator.setExcludedCharacterSet(excludedCharacters);
|
||||
QCOMPARE(m_generator.getMinLength(), expectedMinLength);
|
||||
}
|
||||
|
||||
void TestPasswordGenerator::testReset()
|
||||
{
|
||||
PasswordGenerator default_generator;
|
||||
|
||||
// Modify generator
|
||||
m_generator.setCharClasses(PasswordGenerator::CharClass::NoClass);
|
||||
m_generator.setFlags(PasswordGenerator::GeneratorFlag::NoFlags);
|
||||
m_generator.setCustomCharacterSet("avc");
|
||||
m_generator.setExcludedCharacterSet("asdv");
|
||||
m_generator.setLength(m_generator.getLength() + 1);
|
||||
|
||||
Q_ASSERT(m_generator.getActiveClasses() != default_generator.getActiveClasses());
|
||||
Q_ASSERT(m_generator.getFlags() != default_generator.getFlags());
|
||||
Q_ASSERT(m_generator.getCustomCharacterSet() != default_generator.getCustomCharacterSet());
|
||||
Q_ASSERT(m_generator.getExcludedCharacterSet() != default_generator.getExcludedCharacterSet());
|
||||
|
||||
m_generator.reset();
|
||||
QCOMPARE(m_generator.getActiveClasses(), default_generator.getActiveClasses());
|
||||
QCOMPARE(m_generator.getFlags(), default_generator.getFlags());
|
||||
QCOMPARE(m_generator.getCustomCharacterSet(), default_generator.getCustomCharacterSet());
|
||||
QCOMPARE(m_generator.getExcludedCharacterSet(), default_generator.getExcludedCharacterSet());
|
||||
QCOMPARE(m_generator.getLength(), default_generator.getLength());
|
||||
}
|
||||
|
||||
@@ -18,17 +18,31 @@
|
||||
#ifndef KEEPASSXC_TESTPASSWORDGENERATOR_H
|
||||
#define KEEPASSXC_TESTPASSWORDGENERATOR_H
|
||||
|
||||
#include "core/PasswordGenerator.h"
|
||||
#include <QObject>
|
||||
|
||||
class TestPasswordGenerator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
PasswordGenerator m_generator;
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
void testAdditionalChars();
|
||||
void init();
|
||||
|
||||
void testCustomCharacterSet_data();
|
||||
void testCustomCharacterSet();
|
||||
void testCharClasses_data();
|
||||
void testCharClasses();
|
||||
void testLookalikeExclusion_data();
|
||||
void testLookalikeExclusion();
|
||||
void testMinLength_data();
|
||||
void testMinLength();
|
||||
void testValidity_data();
|
||||
void testValidity();
|
||||
void testReset();
|
||||
};
|
||||
|
||||
#endif // KEEPASSXC_TESTPASSWORDGENERATOR_H
|
||||
|
||||
Reference in New Issue
Block a user