Skip to content

Commit

Permalink
Merge 0c75674 into 4aabda0
Browse files Browse the repository at this point in the history
  • Loading branch information
Bolorunduro Winner-Timothy committed Aug 25, 2020
2 parents 4aabda0 + 0c75674 commit e140b70
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 37 deletions.
27 changes: 24 additions & 3 deletions shortid.Test/ShortId.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,39 @@ public void SetSeedThrowsWhenCharacterSetIsLessThan20Characters()
.Should()
.Throw<InvalidOperationException>()
.WithMessage(
"The replacement characters must be at least 20 letters in length and without whitespace.");
"The replacement characters must be at least 50 letters in length and without whitespace.");
}

[Fact]
public void DoesNotAllowLengthsLessThan7()
public void SetSeedWorksWithValidCharSet()
{
const string seed = "ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ①②③④⑤⑥⑦⑧⑨⑩⑪⑫";
Action action = () => { ShortId.SetCharacters(seed); };

action
.Should()
.NotThrow<InvalidOperationException>();
}

[Fact]
public void SetSeedThrowsWhenOptionsAreNull()
{
Action action = () => { ShortId.Generate(null); };

action
.Should()
.Throw<ArgumentNullException>();
}

[Fact]
public void DoesNotAllowLengthsLessThanEight()
{
Action action = () => { ShortId.Generate(6); };

action
.Should()
.ThrowExactly<ArgumentException>()
.WithMessage("The specified length of 6 is less than the lower limit of 7.");
.WithMessage("The specified length of 6 is less than the lower limit of 8 to avoid conflicts.");
}

[Fact]
Expand Down
54 changes: 24 additions & 30 deletions shortid/ShortId.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
using System;
using System.Linq;
using System.Text;
using shortid.Configuration;
using shortid.Utils;

namespace shortid
{
public static class ShortId
{
// app variables
private static Random _random = new Random();
private const string Bigs = "ABCDEFGHIJKLMNOPQRSTUVWXY";
private const string Smalls = "abcdefghjlkmnopqrstuvwxyz";
private const string Bigs = "ABCDEFGHIJKLMNPQRSTUVWXY";
private const string Smalls = "abcdefghjklmnopqrstuvwxyz";
private const string Numbers = "0123456789";
private const string Specials = "-_";
private const string Specials = "_-";
private static string _pool = $"{Smalls}{Bigs}";

// thread management variables
Expand Down Expand Up @@ -77,29 +79,21 @@ public static string Generate(int length)
/// <param name="options">The generation options.</param>
/// <returns>A random string.</returns>
/// <exception cref="ArgumentNullException">Thrown when options is null.</exception>
/// <exception cref="ArgumentException">Thrown when options.Length is less than 7.</exception>
/// <exception cref="ArgumentException">Thrown when options.Length is less than 8.</exception>
public static string Generate(GenerationOptions options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}

if (options.Length < 7)
if (options.Length < Constants.MinimumAutoLength)
{
throw new ArgumentException(
$"The specified length of {options.Length} is less than the lower limit of 7.");
}

string characterPool;
Random rand;

lock (ThreadLock)
{
characterPool = _pool;
rand = _random;
$"The specified length of {options.Length} is less than the lower limit of {Constants.MinimumAutoLength} to avoid conflicts.");
}

var characterPool = _pool;
var poolBuilder = new StringBuilder(characterPool);
if (options.UseNumbers)
{
Expand All @@ -116,8 +110,11 @@ public static string Generate(GenerationOptions options)
var output = new char[options.Length];
for (var i = 0; i < options.Length; i++)
{
var charIndex = rand.Next(0, pool.Length);
output[i] = pool[charIndex];
lock (ThreadLock)
{
var charIndex = _random.Next(0, pool.Length);
output[i] = pool[charIndex];
}
}

return new string(output);
Expand All @@ -128,32 +125,29 @@ public static string Generate(GenerationOptions options)
/// </summary>
/// <param name="characters">The new character set.</param>
/// <exception cref="ArgumentException">Thrown when <paramref name="characters"/> is null or empty.</exception>
/// <exception cref="InvalidOperationException">Thrown when the new character set is less than 20 characters.</exception>
/// <exception cref="InvalidOperationException">Thrown when the new character set is less than 50 characters.</exception>
public static void SetCharacters(string characters)
{
if (string.IsNullOrWhiteSpace(characters))
{
throw new ArgumentException("The replacement characters must not be null or empty.");
}

var stringBuilder = new StringBuilder();
foreach (var character in characters)
{
if (!char.IsWhiteSpace(character))
{
stringBuilder.Append(character);
}
}
var charSet = characters
.ToCharArray()
.Where(x => !char.IsWhiteSpace(x))
.Distinct()
.ToArray();

if (stringBuilder.Length < 20)
if (charSet.Length < Constants.MinimumCharacterSetLength)
{
throw new InvalidOperationException(
"The replacement characters must be at least 20 letters in length and without whitespace.");
$"The replacement characters must be at least {Constants.MinimumCharacterSetLength} letters in length and without whitespace.");
}

lock (ThreadLock)
{
_pool = stringBuilder.ToString();
_pool = new string(charSet);
}
}

Expand Down Expand Up @@ -181,4 +175,4 @@ public static void Reset()
}
}
}
}
}
6 changes: 4 additions & 2 deletions shortid/Utils/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ namespace shortid.Utils
{
internal static class Constants
{
public const int MinimumAutoLength = 7;
public const int MinimumAutoLength = 8;

public const int MaximumAutoLength = 15;
public const int MaximumAutoLength = 14;

public const int MinimumCharacterSetLength = 50;
}
}
8 changes: 6 additions & 2 deletions shortid/shortid.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@
<PackageIconUrl>https://members.orcid.org/sites/default/files/vector_iD_icon.svg</PackageIconUrl>
<RepositoryUrl>https://github.com/bolorundurowb/shortid/</RepositoryUrl>
<PackageTags>shortid short id databse identifier key primarykey mongodb sql</PackageTags>
<PackageReleaseNotes>- add in options validation</PackageReleaseNotes>
<PackageReleaseNotes>- fix thread safety issues
- add in further restrictions to maintain uniqueness</PackageReleaseNotes>
<Authors>Bolorunduro Winner-Timothy</Authors>
<Description>A library that generates random identifiers from 7 to 14 characters. Identifiers generated can be used as primary keys for databases or unique identifiers.</Description>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Title>shortid</Title>
<RepositoryType>git</RepositoryType>
<PackageVersion>2.0.3</PackageVersion>
<PackageVersion>3.0.0</PackageVersion>
<AssemblyVersion>3.0.0</AssemblyVersion>
<FileVersion>3.0.0</FileVersion>
<NeutralLanguage>en-NG</NeutralLanguage>
</PropertyGroup>
</Project>

0 comments on commit e140b70

Please sign in to comment.