initialization
This commit is contained in:
commit
9ff09693ed
92 files changed
+46209
No files matched your search
@@ -0,0 +1,225 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Generators\HighEntropyGenerator;
|
||||
use App\Generators\PasswordGeneratorInterface;
|
||||
use App\Generators\PhraseAbbreviatorGenerator;
|
||||
use App\Generators\PwgenGenerator;
|
||||
use App\Managers\PasswordGeneratorManager;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class GeneratorValidationTest extends TestCase
|
||||
{
|
||||
public function testDefaultGenerationWorksAcrossSupportedModes(): void
|
||||
{
|
||||
$manager = new PasswordGeneratorManager();
|
||||
|
||||
foreach ([
|
||||
'high-entropy',
|
||||
'xkcdpass',
|
||||
'diceware',
|
||||
'pwgen',
|
||||
'passkey',
|
||||
'phrase-abbreviator',
|
||||
] as $type) {
|
||||
$defaults = $manager->getDefaultOptions($type);
|
||||
$result = $manager->generate($type, 1, $defaults);
|
||||
|
||||
$this->assertArrayHasKey('passwords', $result);
|
||||
$this->assertNotEmpty($result['passwords']);
|
||||
$this->assertNotSame('', trim((string) $result['passwords'][0]));
|
||||
}
|
||||
}
|
||||
|
||||
public function testHighEntropyRejectsAllFalseCharacterSets(): void
|
||||
{
|
||||
$this->expectException(\RuntimeException::class);
|
||||
|
||||
(new HighEntropyGenerator())->generate(1, [
|
||||
'length' => 16,
|
||||
'include_lowercase' => false,
|
||||
'include_uppercase' => false,
|
||||
'include_numbers' => false,
|
||||
'include_symbols' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testPhraseAbbreviatorUsesFallbackSentenceWhenMissing(): void
|
||||
{
|
||||
$generator = new PhraseAbbreviatorGenerator();
|
||||
|
||||
$validated = $generator->validateOptions(['sentence' => '']);
|
||||
|
||||
$this->assertNotSame('', $validated['sentence']);
|
||||
$this->assertSame('The quick brown fox jumps over the lazy dog.', $validated['sentence']);
|
||||
}
|
||||
|
||||
public function testGeneratorDefinitionsMatchFrontendMetadataContract(): void
|
||||
{
|
||||
$manager = new PasswordGeneratorManager();
|
||||
$definitions = $manager->getGeneratorDefinitions();
|
||||
|
||||
$this->assertNotEmpty($definitions);
|
||||
$this->assertArrayHasKey('high-entropy', $definitions);
|
||||
|
||||
$highEntropy = $definitions['high-entropy'];
|
||||
$this->assertSame('high-entropy_title', $highEntropy['nameKey']);
|
||||
$this->assertSame('high-entropy_description', $highEntropy['descriptionKey']);
|
||||
$this->assertNotEmpty($highEntropy['options']);
|
||||
$this->assertSame('high-entropy_option_length', $highEntropy['options'][0]['labelKey']);
|
||||
}
|
||||
|
||||
public function testGeneratedPasswordsExposeSecurityAssessmentAndEntropyDetails(): void
|
||||
{
|
||||
$manager = new PasswordGeneratorManager();
|
||||
$result = $manager->generate('diceware', 1, [
|
||||
'words' => 6,
|
||||
'show_dice_rolls' => true,
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('passwords', $result);
|
||||
$this->assertArrayHasKey('security_assessment', $result);
|
||||
$this->assertNotSame('', trim((string) $result['security_assessment']));
|
||||
$this->assertArrayHasKey('raw_technical_details', $result);
|
||||
$this->assertArrayHasKey('entropy_bits', $result['raw_technical_details']);
|
||||
$this->assertGreaterThan(0, $result['raw_technical_details']['entropy_bits']);
|
||||
}
|
||||
|
||||
public function testPwgenGeneratorDoesNotExposeRemovedTypePresetOption(): void
|
||||
{
|
||||
$generator = new PwgenGenerator();
|
||||
$options = $generator->getOptionDefinitions();
|
||||
|
||||
$this->assertArrayNotHasKey('type', $options);
|
||||
$this->assertSame('custom', $generator->validateOptions([])['type'] ?? 'custom');
|
||||
}
|
||||
|
||||
public function testXkcdEntropyReflectsWordLengthFiltering(): void
|
||||
{
|
||||
$manager = new PasswordGeneratorManager();
|
||||
|
||||
$unfiltered = $manager->generate('xkcdpass', 1, [
|
||||
'words' => 4,
|
||||
'wordlist' => 'en',
|
||||
'separator' => '-',
|
||||
'max_word_length' => 0,
|
||||
'space_handling' => 'allow',
|
||||
'add_number' => false,
|
||||
]);
|
||||
|
||||
$shortFiltered = $manager->generate('xkcdpass', 1, [
|
||||
'words' => 4,
|
||||
'wordlist' => 'en',
|
||||
'separator' => '-',
|
||||
'max_word_length' => 4,
|
||||
'space_handling' => 'allow',
|
||||
'add_number' => false,
|
||||
]);
|
||||
|
||||
$this->assertGreaterThan($shortFiltered['entropy_bits'], $unfiltered['entropy_bits']);
|
||||
}
|
||||
|
||||
public function testXkcdResponseIncludesEntropyBreakdownDetails(): void
|
||||
{
|
||||
$manager = new PasswordGeneratorManager();
|
||||
$result = $manager->generate('xkcdpass', 1, [
|
||||
'words' => 4,
|
||||
'wordlist' => 'en',
|
||||
'separator' => '-_',
|
||||
'max_word_length' => 6,
|
||||
'space_handling' => 'skip',
|
||||
'add_number' => true,
|
||||
'number_position' => 'random',
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('raw_technical_details', $result);
|
||||
$this->assertArrayHasKey('entropy_breakdown', $result['raw_technical_details']);
|
||||
|
||||
$breakdown = $result['raw_technical_details']['entropy_breakdown'];
|
||||
$this->assertSame('xkcd-candidate-space-v1', $breakdown['entropy_model']);
|
||||
$this->assertArrayHasKey('effective_wordlist_candidates', $breakdown);
|
||||
$this->assertGreaterThan(0, $breakdown['effective_wordlist_candidates']);
|
||||
$this->assertArrayHasKey('separator_entropy_bits', $breakdown);
|
||||
$this->assertArrayHasKey('number_entropy_bits', $breakdown);
|
||||
}
|
||||
|
||||
public function testGeneratorsExposeEntropyModelConfidenceInBreakdown(): void
|
||||
{
|
||||
$manager = new PasswordGeneratorManager();
|
||||
|
||||
$cases = [
|
||||
'diceware' => ['words' => 6],
|
||||
'passkey' => ['syllables' => 6],
|
||||
'pwgen' => ['length' => 12, 'separator' => '-_', 'include_numbers' => true, 'include_capitals' => true],
|
||||
];
|
||||
|
||||
foreach ($cases as $type => $options) {
|
||||
$result = $manager->generate($type, 1, $options);
|
||||
|
||||
$this->assertArrayHasKey('raw_technical_details', $result);
|
||||
$this->assertArrayHasKey('entropy_breakdown', $result['raw_technical_details']);
|
||||
$this->assertArrayHasKey('entropy_model', $result['raw_technical_details']['entropy_breakdown']);
|
||||
$this->assertArrayHasKey('model_confidence', $result['raw_technical_details']['entropy_breakdown']);
|
||||
$this->assertContains(
|
||||
$result['raw_technical_details']['entropy_breakdown']['model_confidence'],
|
||||
['high', 'medium', 'low']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function testPwgenAndXkcdCurrentOptionsProduceExpectedBehavior(): void
|
||||
{
|
||||
$manager = new PasswordGeneratorManager();
|
||||
|
||||
$pwgen16 = (string) $manager->generate('pwgen', 1, ['length' => 16])['passwords'][0];
|
||||
$pwgen12 = (string) $manager->generate('pwgen', 1, ['length' => 12])['passwords'][0];
|
||||
$pwgen8 = (string) $manager->generate('pwgen', 1, ['length' => 8])['passwords'][0];
|
||||
|
||||
$this->assertSame(16, strlen($pwgen16));
|
||||
$this->assertSame(12, strlen($pwgen12));
|
||||
$this->assertSame(8, strlen($pwgen8));
|
||||
|
||||
$xkcdGerman = (string) $manager->generate('xkcdpass', 1, [
|
||||
'wordlist' => 'de',
|
||||
'words' => 4,
|
||||
'separator' => '-',
|
||||
'add_number' => true,
|
||||
'number_position' => 'end',
|
||||
])['passwords'][0];
|
||||
|
||||
$xkcdEnglish = (string) $manager->generate('xkcdpass', 1, [
|
||||
'wordlist' => 'en',
|
||||
'words' => 4,
|
||||
'separator' => '-',
|
||||
'add_number' => true,
|
||||
'number_position' => 'end',
|
||||
])['passwords'][0];
|
||||
|
||||
$xkcdSlaengikon = (string) $manager->generate('xkcdpass', 1, [
|
||||
'wordlist' => 'ch',
|
||||
'words' => 4,
|
||||
'separator' => '_',
|
||||
'add_number' => true,
|
||||
'number_position' => 'end',
|
||||
])['passwords'][0];
|
||||
|
||||
$this->assertSame(1, preg_match('/\d/', $xkcdGerman));
|
||||
$this->assertSame(1, preg_match('/\d/', $xkcdEnglish));
|
||||
$this->assertSame(1, preg_match('/\d/', $xkcdSlaengikon));
|
||||
}
|
||||
|
||||
public function testDicewareUsesLargeEffectiveCandidateSpace(): void
|
||||
{
|
||||
$manager = new PasswordGeneratorManager();
|
||||
$result = $manager->generate('diceware', 1, [
|
||||
'words' => 6,
|
||||
'show_dice_rolls' => true,
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('raw_technical_details', $result);
|
||||
$this->assertArrayHasKey('entropy_breakdown', $result['raw_technical_details']);
|
||||
$this->assertArrayHasKey('wordlist_size', $result['raw_technical_details']['entropy_breakdown']);
|
||||
$this->assertGreaterThanOrEqual(7000, $result['raw_technical_details']['entropy_breakdown']['wordlist_size']);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user