From 8e96e7b81b5dd44b71029b0fd326746479c14c59 Mon Sep 17 00:00:00 2001 From: Kirill Polishchuk Date: Tue, 1 Jul 2025 16:43:56 +1200 Subject: [PATCH] Added new methods --- README.md | 29 +++++++ .../PasswordGeneratorTests.cs | 85 +++++++++++++++++++ src/KPasswordGenerator/PasswordGenerator.cs | 26 ++++++ 3 files changed, 140 insertions(+) diff --git a/README.md b/README.md index ad18632..d8d9547 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,35 @@ string password = generator.Generate(16); Console.WriteLine(password); // Example output: kAj79uV@E?m7_8eS ``` +## Additional Methods + +### `GenerateRandomLength(int minPasswordLength, int maxPasswordLength)` + +Generates a password of **random length within a specified range**. + +- Ensures the generated password meets all defined character requirements. +- Uses secure randomness to choose the length. + +**Example:** +```csharp +string password = generator.GenerateRandomLength(12, 20); +``` + +--- + +### `Validate(string password)` + +Validates whether a password meets the current `PasswordSettings` policy. + +- Checks overall length. +- Verifies that the required number of characters from each character pool are present. +- Returns `true` if all rules pass, otherwise `false`. + +- **Example:** +```csharp +bool isValid = generator.Validate("abcD123!"); +``` + ## Installation Install via NuGet: diff --git a/src/KPasswordGenerator.Tests/PasswordGeneratorTests.cs b/src/KPasswordGenerator.Tests/PasswordGeneratorTests.cs index d171147..f15a33a 100644 --- a/src/KPasswordGenerator.Tests/PasswordGeneratorTests.cs +++ b/src/KPasswordGenerator.Tests/PasswordGeneratorTests.cs @@ -60,4 +60,89 @@ public void Generate_DoesNotReturnSamePasswordEveryTime() Assert.NotEqual(password1, password2); // May rarely fail on pure randomness } + + [Theory] + [InlineData(6, 12)] + [InlineData(10, 10)] // exact length + [InlineData(4, 5)] + public void GenerateRandomLength_ReturnsPasswordWithinRange(int min, int max) + { + var generator = CreateDefaultGenerator(); + + string password = generator.GenerateRandomLength(min, max); + + Assert.InRange(password.Length, min, max); + } + + [Fact] + public void GenerateRandomLength_Throws_WhenMinGreaterThanMax() + { + var generator = CreateDefaultGenerator(); ; + + Assert.Throws(() => + generator.GenerateRandomLength(10, 5)); + } + + [Fact] + public void GenerateRandomLength_Throws_WhenMinLessThanRequired() + { + var generator = CreateDefaultGenerator(); + int tooSmall = 3; + + Assert.Throws(() => + generator.GenerateRandomLength(tooSmall, 10)); + } + + [Fact] + public void Validate_ReturnsTrue_WhenPasswordMeetsAllRequirements() + { + var generator = CreateDefaultGenerator(); + + // 'a', 'b' (from "abc"), '1' (from "123"), '!' (from "!@#") + string validPassword = "ab1!xyz"; + + Assert.True(generator.Validate(validPassword)); + } + + [Fact] + public void Validate_ReturnsFalse_WhenPasswordTooShort() + { + var generator = CreateDefaultGenerator(); + + string shortPassword = "a1!"; + + Assert.False(generator.Validate(shortPassword)); + } + + [Fact] + public void Validate_ReturnsFalse_WhenRequirementNotMet() + { + var generator = CreateDefaultGenerator(); + + // Missing digits + string invalidPassword = "ab!!xyz"; + + Assert.False(generator.Validate(invalidPassword)); + } + + [Fact] + public void Validate_Throws_WhenPasswordIsNull() + { + var generator = CreateDefaultGenerator(); + + Assert.Throws(() => + generator.Validate(null!)); + } + + private static PasswordGenerator CreateDefaultGenerator() + { + List requirements = + [ + new CharacterRequirement(2, "abc"), + new CharacterRequirement(1, "123"), + new CharacterRequirement(1, "!@#") + ]; + + return new PasswordGenerator(new PasswordSettings(requirements)); + } } \ No newline at end of file diff --git a/src/KPasswordGenerator/PasswordGenerator.cs b/src/KPasswordGenerator/PasswordGenerator.cs index 05be9ad..0feb73c 100644 --- a/src/KPasswordGenerator/PasswordGenerator.cs +++ b/src/KPasswordGenerator/PasswordGenerator.cs @@ -34,4 +34,30 @@ public string Generate(int passwordLength) return buffer.ToString(); } + + public string GenerateRandomLength(int minPasswordLength, int maxPasswordLength) + { + ArgumentOutOfRangeException.ThrowIfGreaterThan(minPasswordLength, maxPasswordLength); + ArgumentOutOfRangeException.ThrowIfLessThan(minPasswordLength, _passwordSettings.MinimumPasswordLength); + + int length = RandomNumberGenerator.GetInt32(minPasswordLength, maxPasswordLength + 1); + + return Generate(length); + } + + public bool Validate(string password) + { + ArgumentNullException.ThrowIfNull(password); + + if (password.Length < _passwordSettings.MinimumPasswordLength) return false; + + foreach (var requirement in _passwordSettings.CharacterRequirements) + { + int count = password.Count(requirement.CharacterPool.Contains); + + if (count < requirement.MinRequired) return false; + } + + return true; + } } \ No newline at end of file