From 3c4e4623d024e313b169b45f651ae9f366cdd077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Alarc=C3=B3n?= Date: Sat, 29 Jul 2023 23:46:59 -0400 Subject: [PATCH 1/6] Added the full extension for Chilean RUT for Person and Company. --- .../Extensions/Chile/ExtensionsForChile.cs | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 Source/Bogus/Extensions/Chile/ExtensionsForChile.cs diff --git a/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs b/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs new file mode 100644 index 00000000..7917a92b --- /dev/null +++ b/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs @@ -0,0 +1,91 @@ +using Bogus.DataSets; + +namespace Bogus.Extensions.Chile +{ + /// + /// API extensions specific for a geographical location. + /// + public static class ExtensionsForChile + { + /// + /// Generates a valid Chilean RUT for a Person (Rol Unico Tributario) + /// + /// Use the thousands separator for the Chilean RUT (11.111.111-1) + /// A string representation for a valid Chilean RUT (Rol Unico Tributario) + public static string Rut(this Person person, bool dotFormat = true) + { + GenerateChileanId(dotFormat); + } + + /// + /// Generates a valid Chilean RUT for a Company (Rol Unico Tributario) + /// + /// Use the thousands separator for the Chilean RUT (11.111.111-1) + /// A string representation for a valid Chilean RUT (Rol Unico Tributario) + + public static string Rut(this Company company, bool dotFormat = true) + { + GenerateChileanId(dotFormat); + } + + /// + /// A general Chilean ID generator + /// + /// Use the thousands separator for the Chilean RUT (11.111.111-1) + /// + private static string GenerateChileanId(bool dotFormat = true) + { + Random rnd = new(); + int num = rnd.Next(1000000, 99999999); + + string dig = Digito(num); + + if (dotFormat) + { + var rut = string.Format("{0:0,0}", num); + return $"{rut}-{dig}"; + } + + return $"{num}-{dig}"; + } + + /// + /// Algorithm to generate a verification digit based on an integer between 1000000 and 99999999 + /// + /// Represents a full valid RUT number + /// A string representing a number that validates the provided number + private static string Digito(int rut) + { + if (rut < 1000000 || rut > 99999999) + throw new ArgumentOutOfRangeException("The provided integer is outside of the range between 1000000 and 99999999"); + + int suma = 0; + int multiplicador = 1; + + while (rut != 0) + { + multiplicador++; + if (multiplicador == 8) + multiplicador = 2; + suma += (rut % 10) * multiplicador; + rut /= 10; + } + + suma = 11 - (suma % 11); + + if (suma == 11) + { + return "0"; + } + else if (suma == 10) + { + return "K"; + } + else + { + return suma.ToString(); + } + } + } +} + From 03d3bfdaa8cddbf990804681e1982047fe08108e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Alarc=C3=B3n?= Date: Sun, 30 Jul 2023 00:03:29 -0400 Subject: [PATCH 2/6] Fixed ArgumentOutOfRangeException and Random errors by adding a using for the System namespace. --- Source/Bogus/Extensions/Chile/ExtensionsForChile.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs b/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs index 7917a92b..474ed4c3 100644 --- a/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs +++ b/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs @@ -1,4 +1,5 @@ -using Bogus.DataSets; +using System; +using Bogus.DataSets; namespace Bogus.Extensions.Chile { @@ -57,7 +58,7 @@ private static string GenerateChileanId(bool dotFormat = true) private static string Digito(int rut) { if (rut < 1000000 || rut > 99999999) - throw new ArgumentOutOfRangeException("The provided integer is outside of the range between 1000000 and 99999999"); + throw new ArgumentOutOfRangeException($"The provided integer is outside of the range between 1000000 and 99999999"); int suma = 0; int multiplicador = 1; From 2203317da9e09c896b257db5a826702447491b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Alarc=C3=B3n?= Date: Sun, 30 Jul 2023 00:11:01 -0400 Subject: [PATCH 3/6] Fixed the return for both extension methods. --- Source/Bogus/Extensions/Chile/ExtensionsForChile.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs b/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs index 474ed4c3..9748545a 100644 --- a/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs +++ b/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs @@ -15,7 +15,7 @@ public static class ExtensionsForChile /// A string representation for a valid Chilean RUT (Rol Unico Tributario) public static string Rut(this Person person, bool dotFormat = true) { - GenerateChileanId(dotFormat); + return GenerateChileanId(dotFormat); } /// @@ -26,7 +26,7 @@ public static string Rut(this Person person, bool dotFormat = true) public static string Rut(this Company company, bool dotFormat = true) { - GenerateChileanId(dotFormat); + return GenerateChileanId(dotFormat); } /// From 025cd004ece061936b5ce279e0de37fa3ee2d210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Alarc=C3=B3n?= Date: Sun, 30 Jul 2023 01:42:43 -0400 Subject: [PATCH 4/6] Added unit tests for the ExtensionsForChile and set the generator to not use the dotFormat as default. --- .../ExtensionTests/ChileanRutExtensionTest.cs | 91 +++++++++++++++++++ .../Extensions/Chile/ExtensionsForChile.cs | 2 +- 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs diff --git a/Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs b/Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs new file mode 100644 index 00000000..57cce9c8 --- /dev/null +++ b/Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs @@ -0,0 +1,91 @@ +using Bogus.Extensions.Chile; +using FluentAssertions; +using System; +using System.Text.RegularExpressions; +using Xunit; + +namespace Bogus.Tests.ExtensionTests +{ + public class ChileanRutExtensionTest + { + + [Theory] + [InlineData(true)] //Testing random rut using the dotFormat (11.111.111-1) + [InlineData(false)] //Testing random rut not using the dotFormat (11111111-1) + public void ChileanRutExtensionForBogusShouldBeValid(bool dotFormat) + { + // Arrange + var faker = new Faker() + .RuleFor(p => p.Rut, f => f.Person.Rut(dotFormat)); + + // Act + var person = faker.Generate(); + + // Assert + InternalValidationRutHelper.IsRutValid(person.Rut).Should().Be(true); + } + + private class Person + { + internal string Rut { get; set; } = ""; + } + } + + internal static class InternalValidationRutHelper + { + internal static bool IsRutValid(string rut) + { + if (string.IsNullOrEmpty(rut)) + return false; + + rut = rut.Replace(".", ""); + + var expresion = new Regex("^([0-9]+-[0-9K])$"); + string dv = rut.Substring(rut.Length - 1, 1); + if (!expresion.IsMatch(rut)) + { + return false; + } + char[] charCorte = { '-' }; + string[] rutTemp = rut.Split(charCorte); + if (dv != Digito(int.Parse(rutTemp[0]))) + { + return false; + } + return true; + } + + private static string Digito(int rut) + { + if (rut < 1000000 || rut > 99999999) + throw new ArgumentOutOfRangeException($"The provided integer {nameof(rut)} is outside of the range between 1000000 and 99999999"); + + int suma = 0; + int multiplicador = 1; + + while (rut != 0) + { + multiplicador++; + if (multiplicador == 8) + multiplicador = 2; + suma += (rut % 10) * multiplicador; + rut /= 10; + } + + suma = 11 - (suma % 11); + + if (suma == 11) + { + return "0"; + } + else if (suma == 10) + { + return "K"; + } + else + { + return suma.ToString(); + } + } + } +} \ No newline at end of file diff --git a/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs b/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs index 9748545a..2958469e 100644 --- a/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs +++ b/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs @@ -13,7 +13,7 @@ public static class ExtensionsForChile /// /// Use the thousands separator for the Chilean RUT (11.111.111-1) /// A string representation for a valid Chilean RUT (Rol Unico Tributario) - public static string Rut(this Person person, bool dotFormat = true) + public static string Rut(this Person person, bool dotFormat = false) { return GenerateChileanId(dotFormat); } From 3715b646b79a8dbde0f2ecd861442efe022d3c5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Alarc=C3=B3n?= Date: Sat, 29 Jul 2023 23:46:59 -0400 Subject: [PATCH 5/6] Added the full extension for Chilean RUT for Person and Company, including unit tests. --- .../ExtensionTests/ChileanRutExtensionTest.cs | 91 ++++++++++++++++++ .../Extensions/Chile/ExtensionsForChile.cs | 92 +++++++++++++++++++ 2 files changed, 183 insertions(+) create mode 100644 Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs create mode 100644 Source/Bogus/Extensions/Chile/ExtensionsForChile.cs diff --git a/Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs b/Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs new file mode 100644 index 00000000..57cce9c8 --- /dev/null +++ b/Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs @@ -0,0 +1,91 @@ +using Bogus.Extensions.Chile; +using FluentAssertions; +using System; +using System.Text.RegularExpressions; +using Xunit; + +namespace Bogus.Tests.ExtensionTests +{ + public class ChileanRutExtensionTest + { + + [Theory] + [InlineData(true)] //Testing random rut using the dotFormat (11.111.111-1) + [InlineData(false)] //Testing random rut not using the dotFormat (11111111-1) + public void ChileanRutExtensionForBogusShouldBeValid(bool dotFormat) + { + // Arrange + var faker = new Faker() + .RuleFor(p => p.Rut, f => f.Person.Rut(dotFormat)); + + // Act + var person = faker.Generate(); + + // Assert + InternalValidationRutHelper.IsRutValid(person.Rut).Should().Be(true); + } + + private class Person + { + internal string Rut { get; set; } = ""; + } + } + + internal static class InternalValidationRutHelper + { + internal static bool IsRutValid(string rut) + { + if (string.IsNullOrEmpty(rut)) + return false; + + rut = rut.Replace(".", ""); + + var expresion = new Regex("^([0-9]+-[0-9K])$"); + string dv = rut.Substring(rut.Length - 1, 1); + if (!expresion.IsMatch(rut)) + { + return false; + } + char[] charCorte = { '-' }; + string[] rutTemp = rut.Split(charCorte); + if (dv != Digito(int.Parse(rutTemp[0]))) + { + return false; + } + return true; + } + + private static string Digito(int rut) + { + if (rut < 1000000 || rut > 99999999) + throw new ArgumentOutOfRangeException($"The provided integer {nameof(rut)} is outside of the range between 1000000 and 99999999"); + + int suma = 0; + int multiplicador = 1; + + while (rut != 0) + { + multiplicador++; + if (multiplicador == 8) + multiplicador = 2; + suma += (rut % 10) * multiplicador; + rut /= 10; + } + + suma = 11 - (suma % 11); + + if (suma == 11) + { + return "0"; + } + else if (suma == 10) + { + return "K"; + } + else + { + return suma.ToString(); + } + } + } +} \ No newline at end of file diff --git a/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs b/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs new file mode 100644 index 00000000..2958469e --- /dev/null +++ b/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs @@ -0,0 +1,92 @@ +using System; +using Bogus.DataSets; + +namespace Bogus.Extensions.Chile +{ + /// + /// API extensions specific for a geographical location. + /// + public static class ExtensionsForChile + { + /// + /// Generates a valid Chilean RUT for a Person (Rol Unico Tributario) + /// + /// Use the thousands separator for the Chilean RUT (11.111.111-1) + /// A string representation for a valid Chilean RUT (Rol Unico Tributario) + public static string Rut(this Person person, bool dotFormat = false) + { + return GenerateChileanId(dotFormat); + } + + /// + /// Generates a valid Chilean RUT for a Company (Rol Unico Tributario) + /// + /// Use the thousands separator for the Chilean RUT (11.111.111-1) + /// A string representation for a valid Chilean RUT (Rol Unico Tributario) + + public static string Rut(this Company company, bool dotFormat = true) + { + return GenerateChileanId(dotFormat); + } + + /// + /// A general Chilean ID generator + /// + /// Use the thousands separator for the Chilean RUT (11.111.111-1) + /// + private static string GenerateChileanId(bool dotFormat = true) + { + Random rnd = new(); + int num = rnd.Next(1000000, 99999999); + + string dig = Digito(num); + + if (dotFormat) + { + var rut = string.Format("{0:0,0}", num); + return $"{rut}-{dig}"; + } + + return $"{num}-{dig}"; + } + + /// + /// Algorithm to generate a verification digit based on an integer between 1000000 and 99999999 + /// + /// Represents a full valid RUT number + /// A string representing a number that validates the provided number + private static string Digito(int rut) + { + if (rut < 1000000 || rut > 99999999) + throw new ArgumentOutOfRangeException($"The provided integer is outside of the range between 1000000 and 99999999"); + + int suma = 0; + int multiplicador = 1; + + while (rut != 0) + { + multiplicador++; + if (multiplicador == 8) + multiplicador = 2; + suma += (rut % 10) * multiplicador; + rut /= 10; + } + + suma = 11 - (suma % 11); + + if (suma == 11) + { + return "0"; + } + else if (suma == 10) + { + return "K"; + } + else + { + return suma.ToString(); + } + } + } +} + From 1de4cf66a2b11d008ecf860e14949d2bced8ee97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Alarc=C3=B3n?= Date: Sun, 30 Jul 2023 02:10:29 -0400 Subject: [PATCH 6/6] Removed the [Theory] and replaced with [Fact] Trying to figure out why tests are passing locally but failing on appveyor #474 --- .../ExtensionTests/ChileanRutExtensionTest.cs | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs b/Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs index 57cce9c8..a711d31e 100644 --- a/Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs +++ b/Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs @@ -9,14 +9,26 @@ namespace Bogus.Tests.ExtensionTests public class ChileanRutExtensionTest { - [Theory] - [InlineData(true)] //Testing random rut using the dotFormat (11.111.111-1) - [InlineData(false)] //Testing random rut not using the dotFormat (11111111-1) - public void ChileanRutExtensionForBogusShouldBeValid(bool dotFormat) + [Fact] + public void ChileanRutExtension_Should_BeValid_When_UsingDotFormat() { // Arrange var faker = new Faker() - .RuleFor(p => p.Rut, f => f.Person.Rut(dotFormat)); + .RuleFor(p => p.Rut, f => f.Person.Rut(true)); + + // Act + var person = faker.Generate(); + + // Assert + InternalValidationRutHelper.IsRutValid(person.Rut).Should().Be(true); + } + + [Fact] + public void ChileanRutExtension_Should_BeValid_When_NotUsingDotFormat() + { + // Arrange + var faker = new Faker() + .RuleFor(p => p.Rut, f => f.Person.Rut(false)); // Act var person = faker.Generate();