Add opt-in nullability-aware null generation, fix null thresholds and date ranges - #4
Merged
Merged
Conversation
… date ranges Feature: x.RespectNullableAnnotations(threshold) on the configuration builder. When enabled, every property or field declared as nullable (NRT annotation or Nullable<T>) gets its data source wrapped in a NullableMemberDataSource that returns null with the given probability. Each member gets its own deterministic seed so the nullable members of an object do not become null together. Covers conventions, explicit Setup(...) sources and generation time Source(...) overrides; Impose and oblivious members are never touched. Plumbed through GenerationSessionFactory, GenerationConfiguration (IGenerationConfiguration .NullableAnnotations) and ObjectBuilder. IDataSource<T> is covariant now so a source of string serves a string? member without a nullability warning. Bug fixes: - Every Nullable* source ignored an explicit null creation threshold; the fixed array and dictionary sources used it as the random seed. DataSourceBase got a protected constructor that installs the evaluator with the threshold, all nullable source bases use it. Null positions of the stable sequences changed, the data order did not. - DateTimeSource, DateOnlySource, TimeOnlySource and DateOfBirthSource used exclusive upper bounds (no December, no 31st, no 23:00, no :59, no max year) and could leave a range that lies within one year. They now pick uniformly from the inclusive range, validate min <= max, TimeOnly wraps around midnight and DateTime keeps the kind of the minimum date. Sequences changed. - RandomUtfTextSource looped forever on a Unicode block without allowed characters. Tests: 683 runs per framework on net8/9/10, new suites for the helper, the decorator, the settings, the integration behavior, a theory over all Nullable* sources and range coverage tests for the date sources. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Feature: nullability-aware null generation (opt-in)
x.RespectNullableAnnotations(threshold)on the configuration builder. When enabled, every property or field declared as nullable (string?,int?,DateTime?, ...) gets its data source wrapped in aNullableMemberDataSourcethat returns null with the given probability (defaultAutoPocoGlobalSettings.NullCreationThreshold, 15 percent).Setup(...)sources and generation timeSource(...)overrides.Impose, non-nullable members, method parameters and members of types compiled without nullable annotations are never touched.GenerationSessionFactoryandGenerationConfigurationtake optionalNullableAnnotationSettings, exposed asIGenerationConfiguration.NullableAnnotations;ObjectBuilderwraps per member.IDataSource<T>is covariant now, so.Setup(c => c.City).Use<CitySource>()compiles without a nullability warning for astring?member.Bug fixes
Nullable*source ignored an explicit null creation threshold. The fixed array and dictionary sources even used it as the random seed.DataSourceBasegot a protected constructor that installs the evaluator with the threshold; all nullable source bases use it. Null positions in the stable sequences of those sources changed, the data order did not.DateTimeSource,DateOnlySource,TimeOnlySource,DateOfBirthSource: exclusive upper bounds (no December, no 31st, no 23:00, no :59, max year unreachable) and ranges within one year could yield values outside the range. All four pick uniformly from the inclusive range now, validate min <= max,TimeOnlywraps around midnight,DateTimekeeps the kind of the minimum date. Sequences for a given seed changed.RandomUtfTextSourcelooped forever when it hit a Unicode block without allowed characters (found by the new theory that draws 30 values per source).Verification
dotnet build -c Release: zero warnings on net8/9/10.dotnet test: 683 runs per framework, all green on net8.0, net9.0, net10.0 (Windows) and net10.0 on Linux (mcr.microsoft.com/dotnet/sdk:10.0container).PackageReleaseNotesupdated.🤖 Generated with Claude Code