Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<RepositoryType>git</RepositoryType>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>autopoco;testdata;test-data;poco;generator;fluent;fake-data</PackageTags>
<PackageReleaseNotes>6.0: Lambda data sources (FuncSource, Setup(...).From(() => ...), Source(expr, () => ...) at generation time). Opt-in nullability-aware null generation via RespectNullableAnnotations(threshold). Generic NumberSource&lt;T&gt; and NullableNumberSource&lt;T&gt; with min/max for every built-in numeric type (integers uniform and inclusive, floating point and decimal overflow safe). Records and immutable types are constructed through their constructor, parameters are fed from the registered members with the same name, no parameterless constructor needed anymore; unconfigured struct parameters stay default instead of throwing. Seeds: UseSeed(seed) per factory, CreateSession(recursionLimit, seed) per session, every member gets its own stream derived from the seed. Own deterministic generator (StableRandom, xoshiro256**) instead of System.Random, sequences are stable across .NET versions. Breaking: AutoPocoGlobalSettings removed (AutoPocoDefaults constants instead), every generated sequence changed once, the max of IntegerSource/LongSource/RandomNumberSource and their nullable variants is inclusive now (it was exclusive), Int128Source/NullableInt128Source pick uniformly instead of clamping to the bounds (they never produced a negative value before), RandomStringSource and UrlSource reach the last character resp. the last top level domain, ColorSource/RandomTextSource/RandomUtfTextSource treat their maximum as inclusive, ColorSource applies the alpha of SetColorRange, and UrlSource and ExtendedEmailAddressSource seed their nested sources (the URL host ignored the session seed completely). TimeSpanSource was rewritten: it returned TimeSpan.MinValue on every draw of the default range, produced values outside a requested range and looped forever on a reversed one. DoubleSource returned infinity over its default range, DoubleSource/FloatSource/DecimalSource interpolate overflow safe now and DecimalSource keeps its full precision. Index-aware Impose on lists and selections (value from the position, or from position and item), Impose(member, item => value) on a single generator. Invoke arguments: Use.From(lambda), constants and variables arrive as values. Context lambdas get a non-nullable IGenerationContext. Argument validation over the public API, meaningful exception messages, XML documentation file. IDataSource&lt;T&gt; is covariant. Bug fixes: Nullable* sources honor an explicit null creation threshold (null positions of stable sequences changed), DateTime/DateOnly/TimeOnly/DateOfBirth sources cover their whole range including the upper bound (sequences changed), RandomUtfTextSource no longer loops forever. Build and packaging modernized: GitHub Actions CI, trusted publishing to nuget.org, MinVer tag based versioning, central package management, xunit.v3 tests on net8/9/10. FluentAssertions and Moq are no longer dependencies of the library. See README for details.</PackageReleaseNotes>
<PackageReleaseNotes>6.0: Lambda data sources (FuncSource, Setup(...).From(() => ...), Source(expr, () => ...) at generation time). Opt-in nullability-aware null generation via RespectNullableAnnotations(threshold). Generic NumberSource&lt;T&gt; and NullableNumberSource&lt;T&gt; with min/max for every built-in numeric type (integers uniform and inclusive, floating point and decimal overflow safe). Records and immutable types are constructed through their constructor, parameters are fed from the registered members with the same name, no parameterless constructor needed anymore; unconfigured struct parameters stay default instead of throwing. Seeds: UseSeed(seed) per factory, CreateSession(recursionLimit, seed) per session, every member gets its own stream derived from the seed. Own deterministic generator (StableRandom, xoshiro256**) instead of System.Random, sequences are stable across .NET versions. Breaking: AutoPocoGlobalSettings removed (AutoPocoDefaults constants instead), every generated sequence changed once, the max of IntegerSource/LongSource/RandomNumberSource and their nullable variants is inclusive now (it was exclusive), Int128Source/NullableInt128Source pick uniformly instead of clamping to the bounds (they never produced a negative value before), RandomStringSource and UrlSource reach the last character resp. the last top level domain, ColorSource/RandomTextSource/RandomUtfTextSource treat their maximum as inclusive, ColorSource applies the alpha of SetColorRange, and UrlSource and ExtendedEmailAddressSource seed their nested sources (the URL host ignored the session seed completely). CreditCardSource never produced a Discover card. TimeSpanSource was rewritten: it returned TimeSpan.MinValue on every draw of the default range, produced values outside a requested range and looped forever on a reversed one. DoubleSource returned infinity over its default range, DoubleSource/FloatSource/DecimalSource interpolate overflow safe now and DecimalSource keeps its full precision. Index-aware Impose on lists and selections (value from the position, or from position and item), Impose(member, item => value) on a single generator. Invoke arguments: Use.From(lambda), constants and variables arrive as values. Context lambdas get a non-nullable IGenerationContext. Argument validation over the public API, meaningful exception messages, XML documentation file. IDataSource&lt;T&gt; is covariant. Bug fixes: Nullable* sources honor an explicit null creation threshold (null positions of stable sequences changed), DateTime/DateOnly/TimeOnly/DateOfBirth sources cover their whole range including the upper bound (sequences changed), RandomUtfTextSource no longer loops forever. Build and packaging modernized: GitHub Actions CI, trusted publishing to nuget.org, MinVer tag based versioning, central package management, xunit.v3 tests on net8/9/10. FluentAssertions and Moq are no longer dependencies of the library. See README for details.</PackageReleaseNotes>
</PropertyGroup>

<PropertyGroup Label="Package build">
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ holonsoft ported this famous lib to newest version of dotnet
* `Int128Source` and `NullableInt128Source` pick uniformly from their range instead of generating a value and clamping it to the bounds. The old implementation never produced a negative value and returned the upper bound almost always on a restricted range.
* `RandomStringSource` and `UrlSource` never used the last character of the allowed character set and the last top level domain of their list. `ColorSource`, `RandomTextSource` and `RandomUtfTextSource` treat their maximum as inclusive now, so `new ColorSource(0, 255)` reaches 255 and a text source asked for 3 to 6 paragraphs can produce 6.
* `ColorSource` applies the alpha given to `SetColorRange(alpha, ...)`, it used to be silently dropped and every color came back fully opaque.
* `CreditCardSource` with `CreditCardType.Random` draws every card type. `Discover` was the last value of the enum and could never come out, the picker stopped at `AmericanExpress`.
* `TimeSpanSource` and `NullableTimeSpanSource` pick uniformly from the inclusive tick range now. The old implementation returned `TimeSpan.MinValue` on every draw of the default range, produced values outside the range that was asked for (1 to 2 hours gave 22 to 58 minutes) and looped forever when the maximum lay before the minimum.
* `DoubleSource`, `FloatSource` and `DecimalSource` interpolate between their bounds without overflowing. `new DoubleSource()` returned infinity on every draw, and `DecimalSource` lost about half of its significant digits on the way through `double`.
* `UrlSource` follows the session seed with its host part as well. The nested string source kept the default seed, so every session produced the same host names no matter what `UseSeed` said. `ExtendedEmailAddressSource` gives its first and last name source separate streams, they used to share one and repeated the same name pairs.
Expand Down Expand Up @@ -140,6 +141,7 @@ x.Include<SimpleUser>()
* Bug fix: the integer sources that existed before `NumberSource<T>` never produced their maximum, `new IntegerSource(1, 3)` gave 1 or 2 only. `IntegerSource`, `LongSource`, `RandomNumberSource` and their nullable variants draw uniformly from the inclusive range now, both bounds can be produced. `Int128Source` and `NullableInt128Source` were worse: they built a value from two non-negative draws and clamped it to the range, so the default source never produced a negative value and `new Int128Source(1, 5)` returned 5 almost every time. All of them share the pick of `NumberSource<T>` now. `LongSourceBase.SetMinMax` takes `long` arguments at last, and all four throw an `ArgumentOutOfRangeException` when the maximum lies below the minimum. The generated sequences of the long and Int128 sources changed, the ones of the integer sources did not.
* Bug fix: `TimeSpanSource` did not work at all. `new TimeSpanSource()` returned `TimeSpan.MinValue` on every single draw, `new TimeSpanSource(TimeSpan.FromHours(1), TimeSpan.FromHours(2))` returned values between 22 and 58 minutes, so every value was outside the range that was asked for, and a maximum before the minimum sent it into an endless loop. It picks uniformly from the inclusive tick range now, the same way `DateTimeSource` does, and throws an `ArgumentOutOfRangeException` on a reversed range.
* Bug fix: `new DoubleSource()` returned infinity on every draw, because the default range is the whole range of `double` and the old code computed `max - min`. `DoubleSource`, `FloatSource` and `DecimalSource` interpolate as `min * (1 - sample) + max * sample` now, which cannot overflow. `DecimalSource` does it in decimal arithmetic instead of going through `double`, so it keeps its full precision; it used to give numbers like `27879346472004300000000000000` where it now gives `27879346472004256951386422019`. All three throw an `ArgumentOutOfRangeException` when the maximum lies below the minimum.
* Bug fix: `CreditCardSource` never produced a `Discover` card. `CreditCardType.Random` picked with `Random.Next(1, 4)`, which stops at `AmericanExpress`, so the last value of the enum was unreachable; 5000 generated cards contained not a single one. The picker reads the card types from the enum now, so a type added later is drawn as well.
* Bug fix: a handful of sources could not reach the last element of what they draw from. `RandomStringSource` never used the last character of its allowed character set, `UrlSource` never used the last top level domain of its list, and `ColorSource`, `RandomTextSource` and `RandomUtfTextSource` treated their maximum as exclusive, so a colour channel range of 0 to 255 never gave 255 and a text source asked for 3 to 6 paragraphs never gave 6. On top of that `ColorSource` dropped the alpha of `SetColorRange(alpha, ...)` and always returned an opaque colour.
* Bug fix: sources that drive another source internally seed it now. `UrlSource` builds its host with a nested `RandomStringSource` that kept the default seed, so `UseSeed` and `CreateSession(limit, seed)` changed the top level domain but every session saw the same host names. `ExtendedEmailAddressSource` passed one seed to both its first and last name source, so the two followed the same sequence of draws and the same first name came back with the same last name. Both give their nested sources a derived stream of their own now, inside a session and standalone.
* Bug fix: every `Nullable*` source ignored an explicit null creation threshold. The fixed array and dictionary based sources (names, companies, cities, capitals, countries, states, zip codes, urls) even used the threshold as their random seed. The threshold is honored now. As a consequence the null positions in the stable sequences of these sources changed, the data itself comes in the same order as before.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,23 @@ public void NextReturnsRandomCreditCardNumber() {
[Fact]
public void NextReturnsStableCreditCardListInTermsOfTestability()
=> NextReturnsStableElementListInTermsOfTestability(
new CreditCardSource(), new string[] { "5343 1380 7226 1800", "4963 6432 2865 0035", "4655 0609 2255 2430", "5914 8329 7669 1747", "3306 710005 18638", "3576 703413 80305", "5171 2438 3073 1141", "5030 2600 8079 1583", "5159 0467 9793 1279", "5238 6720 4807 5702" });
new CreditCardSource(), new string[] { "5343 1380 7226 1800", "4963 6432 2865 0035", "4655 0609 2255 2430", "6891 4832 9766 9177", "3430 671000 51867", "6657 6703 4138 0302", "5171 2438 3073 1141", "6030 2600 8079 1582", "5159 0467 9793 1279", "5238 6720 4807 5702" });

[Fact]
public void NextReturnsStableCreditCardListInTermsOfTestabilityAndListCanContainNull()
=> NextReturnsStableElementListInTermsOfTestability(
new NullableCreditCardSource()!, new string[] { "5343 1380 7226 1800", "4963 6432 2865 0035", "4655 0609 2255 2430", "5914 8329 7669 1747", "3306 710005 18638", "3576 703413 80305", "5171 2438 3073 1141", "5030 2600 8079 1583", "5159 0467 9793 1279", "5238 6720 4807 5702" });
new NullableCreditCardSource()!, new string[] { "5343 1380 7226 1800", "4963 6432 2865 0035", "4655 0609 2255 2430", "6891 4832 9766 9177", "3430 671000 51867", "6657 6703 4138 0302", "5171 2438 3073 1141", "6030 2600 8079 1582", "5159 0467 9793 1279", "5238 6720 4807 5702" });

[Fact]
public void TheRandomCardTypeProducesEveryCardType() {
// Random.Next(1, 4) stopped at AmericanExpress, so Discover was never generated
var source = new CreditCardSource();
var firstDigits = Enumerable.Range(0, 500)
.Select(_ => source.Next(null).Replace(" ", "")[0])
.Distinct()
.OrderBy(c => c)
.ToList();

firstDigits.ShouldBe(new[] { '3', '4', '5', '6' });
}
}
9 changes: 8 additions & 1 deletion holonsoft.AutoPoco/DataSources/Business/CreditCardSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ public enum CreditCardType {

private readonly CreditCardType _preferred = preferred;

/// <summary>
/// Every card type that <see cref="CreditCardType.Random" /> can pick, taken from the enum itself
/// so that a type added later is drawn as well.
/// </summary>
private static readonly CreditCardType[] _selectableTypes =
[.. Enum.GetValues<CreditCardType>().Where(x => x != CreditCardType.Random)];

public CreditCardSourceBase()
: this(CreditCardType.Random) {
}
Expand All @@ -52,7 +59,7 @@ protected override string GetNextValue(IGenerationContext? context) {
var cardType = _preferred;

if (_preferred == CreditCardType.Random)
cardType = (CreditCardType) Random.Next(1, 4);
cardType = _selectableTypes[Random.Next(_selectableTypes.Length)];

return cardType switch {
CreditCardType.AmericanExpress => FormatAmexCardNumber(GenerateCreditCardNumber(3, 15)),
Expand Down