Skip to content

Commit

Permalink
Merge pull request #11 from havardt/Development
Browse files Browse the repository at this point in the history
Improved check efficiency
  • Loading branch information
havardt authored Jun 3, 2019
2 parents fb469d5 + c33c7be commit 817b59e
Show file tree
Hide file tree
Showing 13 changed files with 116 additions and 86 deletions.
8 changes: 8 additions & 0 deletions source/EzPasswordValidator.Tests/LengthCheckTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ public void WhenPasswordIsNullThenPasswordIsNotValid()
Assert.IsFalse(_check.Execute(invalidPsw));
}

[TestMethod]
public void WhenPasswordIsEmptyThenPasswordIsNotValid()
{
const string invalidPsw = " ";

Assert.IsFalse(_check.Execute(invalidPsw));
}

[TestMethod]
public void WhenPasswordIsExactlyRequiredLengthThenPasswordIsValid()
{
Expand Down
3 changes: 1 addition & 2 deletions source/EzPasswordValidator.Tests/NumberCheckTest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using EzPasswordValidator.Checks;
using EzPasswordValidator.Checks;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace EzPasswordValidator.Tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ public void WhenPasswordContainsNoNumbersThenPasswordIsValid()

[DataRow("test22")]
[DataRow("te22st")]
[DataRow("22test")]
[DataRow("224test")]
[DataTestMethod]
public void WhenPasswordContainsTheSameDigitTwoTimesInARowThenPasswordIsValid(string psw) =>
Assert.IsTrue(_check.Execute(psw));

[DataRow("test222")]
[DataRow("te222st")]
[DataRow("222test")]
[DataRow("37222test")]
[DataTestMethod]
public void WhenPasswordContainsTheSameDigitThreeTimesInARowThenPasswordIsInvalid(string psw) =>
Assert.IsFalse(_check.Execute(psw));
Expand Down
32 changes: 27 additions & 5 deletions source/EzPasswordValidator/Checks/CaseCheck.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Linq;


namespace EzPasswordValidator.Checks
{
/// <inheritdoc />
Expand All @@ -21,8 +20,31 @@ public CaseCheck()
/// <summary>
/// Checks that the password contains at least one upper- and lower-case letter.
/// </summary>
protected override bool OnExecute(string password) =>
password.Any(char.IsUpper) && password.Any(char.IsLower);

protected override bool OnExecute(string password)
{
var hasUpper = false;
var hasLower = false;
foreach (char c in password)
{
if (char.IsUpper(c))
{
hasUpper = true;
if (hasLower)
{
return true;
}
continue;//No point checking if lower if the char is already an upper case char.
}
if (char.IsLower(c))
{
hasLower = true;
if (hasUpper)
{
return true;
}
}
}
return false;
}
}
}
49 changes: 49 additions & 0 deletions source/EzPasswordValidator/Checks/CheckHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System;

namespace EzPasswordValidator.Checks
{
public static class CheckHelper
{
/// <summary>
/// Checks if the given string contains character repetition of length 3 or longer.
/// </summary>
/// <param name="expr">The expression of which filters which characters to check for repetition.</param>
/// <param name="str">The string to check.</param>
/// <returns>
/// <c>true</c> if the given string passes the test and does NOT contain character repetition.
/// If the given string does contain character repetition over the allowed length then <c>false</c>
/// is returned.
/// </returns>
public static bool RepetitionCheck(Func<char, bool> expr, string str)
{
const char baseSymbol = (char)0;
char previousPrevious = baseSymbol;
char previous = baseSymbol;
foreach (char c in str)
{
if (expr.Invoke(c))
{
if (previousPrevious == baseSymbol || previousPrevious != c)
{
previousPrevious = c;
}
else if (previous == baseSymbol || previous != c)
{
previous = c;
}
else
{
if (previousPrevious == previous && previous == c)
{
return false;
}
}
continue;
}
previousPrevious = baseSymbol;
previous = baseSymbol;
}
return true;
}
}
}
2 changes: 1 addition & 1 deletion source/EzPasswordValidator/Checks/LengthCheck.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ public LengthCheck(uint requiredLength)
/// <c>null</c> is always invalid.
/// </summary>
protected override bool OnExecute(string password) =>
!string.IsNullOrWhiteSpace(password) && password.Trim().Length >= RequiredLength;
password != null && password.Trim().Length >= RequiredLength;
}
}
1 change: 0 additions & 1 deletion source/EzPasswordValidator/Checks/LetterCheck.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ protected override bool OnExecute(string password)
return true;
}
}

return false;
}
}
Expand Down
37 changes: 3 additions & 34 deletions source/EzPasswordValidator/Checks/LetterRepetitionCheck.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Text.RegularExpressions;


namespace EzPasswordValidator.Checks
{
/// <inheritdoc />
Expand All @@ -26,37 +25,7 @@ public LetterRepetitionCheck()
/// <returns>
/// <c>true</c> if the password does NOT contain letter repetition; <c>false</c> otherwise.
/// </returns>
protected override bool OnExecute(string password)
{
const char baseChar = (char)0;
char previousPrevious = baseChar;
char previous = baseChar;
foreach (char c in password)
{
if (char.IsLetter(c))
{
if (previousPrevious == baseChar || previousPrevious != c)
{
previousPrevious = c;
}
else if (previous == baseChar || previous != c)
{
previous = c;
}
else
{
if (previousPrevious == previous && previous == c)
{
return false;
}
}
continue;
}

previousPrevious = baseChar;
previous = baseChar;
}
return true;
}
protected override bool OnExecute(string password) =>
CheckHelper.RepetitionCheck(char.IsLetter, password);
}
}
17 changes: 13 additions & 4 deletions source/EzPasswordValidator/Checks/NumberCheck.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Text.RegularExpressions;


namespace EzPasswordValidator.Checks
{
/// <inheritdoc />
Expand All @@ -21,7 +20,17 @@ public NumberCheck()
/// <summary>
/// Checks that the password contains at least one number.
/// </summary>
protected override bool OnExecute(string password) =>
Regex.IsMatch(password, "^.*[0-9]+.*$");
protected override bool OnExecute(string password)
{
foreach (char c in password)
{
if (char.IsDigit(c))
{
return true;
}
}

return false;
}
}
}
5 changes: 2 additions & 3 deletions source/EzPasswordValidator/Checks/NumberRepetitionCheck.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Text.RegularExpressions;


namespace EzPasswordValidator.Checks
{
/// <inheritdoc />
Expand All @@ -25,6 +24,6 @@ public NumberRepetitionCheck()
/// <c>true</c> if the check is passed and NO number repetition is found; <c>false</c> otherwise.
/// </returns>
protected override bool OnExecute(string password) =>
!Regex.IsMatch(password, @"^.*([0-9])\1{2}.*$");
CheckHelper.RepetitionCheck(char.IsDigit, password);
}
}
11 changes: 8 additions & 3 deletions source/EzPasswordValidator/Checks/NumberSequenceCheck.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Text.RegularExpressions;
using System.Linq;

namespace EzPasswordValidator.Checks
{
Expand All @@ -9,6 +9,12 @@ namespace EzPasswordValidator.Checks
/// <seealso cref="EzPasswordValidator.Checks.Check" />
public sealed class NumberSequenceCheck : Check
{
public static string[] Sequences =
{
"012", "123", "234", "345", "456", "567", "678", "789",
"987", "876", "765", "654", "543", "432", "321", "210"
};

/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="NumberSequenceCheck" /> class.
Expand All @@ -25,7 +31,6 @@ public NumberSequenceCheck()
/// <returns>
/// <c>true</c> if the check is passed and NO number sequence is found; <c>false</c> otherwise.
/// </returns>
protected override bool OnExecute(string password) =>
!Regex.IsMatch(password, @"^.*(012|123|234|345|456|567|678|789|987|876|765|654|543|432|321|210)+.*$");
protected override bool OnExecute(string password) => Sequences.All(s => !password.Contains(s));
}
}
1 change: 0 additions & 1 deletion source/EzPasswordValidator/Checks/SymbolCheck.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ protected override bool OnExecute(string password)
return true;
}
}

return false;
}
}
Expand Down
33 changes: 2 additions & 31 deletions source/EzPasswordValidator/Checks/SymbolRepetitionCheck.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,36 +25,7 @@ public SymbolRepetitionCheck()
/// <returns>
/// <c>true</c> if the password does NOT contain symbol repetition; <c>false</c> otherwise.
/// </returns>
protected override bool OnExecute(string password)
{
const char baseSymbol = (char) 0;
char previousPrevious = baseSymbol;
char previous = baseSymbol;
foreach (char c in password)
{
if (SymbolCheck.SymbolsHashSet.Contains(c))
{
if (previousPrevious == baseSymbol || previousPrevious != c)
{
previousPrevious = c;
}else if (previous == baseSymbol || previous != c)
{
previous = c;
}
else
{
if (previousPrevious == previous && previous == c)
{
return false;
}
}
continue;
}

previousPrevious = baseSymbol;
previous = baseSymbol;
}
return true;
}
protected override bool OnExecute(string password) =>
CheckHelper.RepetitionCheck(c => SymbolCheck.SymbolsHashSet.Contains(c), password);
}
}

0 comments on commit 817b59e

Please sign in to comment.