Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPatrick Klein <42714034+libklein@users.noreply.github.com>2021-12-08 07:40:09 +0300
committerGitHub <noreply@github.com>2021-12-08 07:40:09 +0300
commita0a063b57f6f577bed505ccd652763eeadd1b876 (patch)
tree23adb424daf8e154d2a3c1943ea941780e971c6b /tests
parentb3896f260048551d1d08245f85038182cb5e303b (diff)
Add -i/--include option to "generate" CLI command. (#7112)
Diffstat (limited to 'tests')
-rw-r--r--tests/TestCli.cpp4
-rw-r--r--tests/TestPasswordGenerator.cpp338
-rw-r--r--tests/TestPasswordGenerator.h16
3 files changed, 258 insertions, 100 deletions
diff --git a/tests/TestCli.cpp b/tests/TestCli.cpp
index 1639e8a39..49b21dfa6 100644
--- a/tests/TestCli.cpp
+++ b/tests/TestCli.cpp
@@ -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()
diff --git a/tests/TestPasswordGenerator.cpp b/tests/TestPasswordGenerator.cpp
index 2ed2974a8..10b91f6af 100644
--- a/tests/TestPasswordGenerator.cpp
+++ b/tests/TestPasswordGenerator.cpp
@@ -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()
+{
+ m_generator.reset();
+}
+
+void TestPasswordGenerator::testCustomCharacterSet_data()
{
- PasswordGenerator generator;
- QVERIFY(!generator.isValid());
- generator.setAdditionalChars("aql");
- generator.setLength(2000);
- QVERIFY(generator.isValid());
- QString password = generator.generatePassword();
+ 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());
-
- generator.setCharClasses(PasswordGenerator::CharClass::UpperLetters);
- password = generator.generatePassword();
- regex.setPattern(R"(^[A-Z]+$)");
- QVERIFY(regex.match(password).hasMatch());
-
- generator.setCharClasses(PasswordGenerator::CharClass::Numbers);
- password = generator.generatePassword();
- regex.setPattern(R"(^\d+$)");
- QVERIFY(regex.match(password).hasMatch());
-
- 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());
+ QVERIFY(expected.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}$");
+
+ QTest::addRow("Letters and Numbers") << (PasswordGenerator::CharClass::LowerLetters
+ | PasswordGenerator::CharClass::UpperLetters
+ | PasswordGenerator::CharClass::Numbers)
+ << QRegularExpression("^[^lBGIO0168]{2000}$");
+
+ 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);
+ 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());
- 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());
+ 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());
}
diff --git a/tests/TestPasswordGenerator.h b/tests/TestPasswordGenerator.h
index 454d16e06..b5bfa7d23 100644
--- a/tests/TestPasswordGenerator.h
+++ b/tests/TestPasswordGenerator.h
@@ -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