@@ -539,4 +539,54 @@ public void Helpers_for_packages_bound_to_different_namespaces_get_distinct_file
539539 Assert . Contains ( "MetaNetValidation.Acme.Shipping.g.cs" , paths ) ;
540540 Compile ( files ) ;
541541 }
542+
543+ [ Fact ]
544+ public void Shared_helpers_carry_the_generated_marker_on_their_first_line ( )
545+ {
546+ var files = EmitFitness ( out _ ) ;
547+ var helpers = files . Where ( f =>
548+ f . Path . StartsWith ( "DecimalWire" , StringComparison . Ordinal ) ||
549+ f . Path . StartsWith ( "MetaNetValidation" , StringComparison . Ordinal ) ) . ToList ( ) ;
550+ Assert . Contains ( helpers , f => f . Path . StartsWith ( "DecimalWire" , StringComparison . Ordinal ) ) ;
551+ Assert . Contains ( helpers , f => f . Path . StartsWith ( "MetaNetValidation" , StringComparison . Ordinal ) ) ;
552+ foreach ( var f in helpers )
553+ Assert . Equal ( CodegenRunner . GeneratedMarker , f . Content . Split ( '\n ' ) [ 0 ] . Replace ( "// " , "" ) ) ;
554+ }
555+
556+ [ Fact ]
557+ public void Rerun_without_a_state_dir_rewrites_the_helpers_in_every_namespace ( )
558+ {
559+ // #460: with no GenStateDir the runner falls back to the marker rule, and the helpers
560+ // lacked the marker, so every run after the first refused to overwrite them.
561+ var dir = Path . Combine ( Path . GetTempPath ( ) , "mo-helper-marker-" + Guid . NewGuid ( ) . ToString ( "N" ) ) ;
562+ try
563+ {
564+ var r = new MetaDataLoader ( ) . Load ( [
565+ new InMemoryStringSource ( TwoNamespaceModel , id : "billing.json" ) ,
566+ new InMemoryStringSource ( SecondNamespaceModel , id : "shipping.json" ) ] ) ;
567+ Assert . Empty ( r . Errors ) ;
568+ var config = new GenConfig
569+ {
570+ OutDir = dir ,
571+ Namespace = "Acme" ,
572+ PackageNamespaces = new ( ) { [ "acme::billing" ] = "Acme.Billing" , [ "acme::shipping" ] = "Acme.Shipping" } ,
573+ } ;
574+ string [ ] helpers =
575+ [
576+ "DecimalWire.Acme.Billing.g.cs" , "DecimalWire.Acme.Shipping.g.cs" ,
577+ "MetaNetValidation.Acme.Billing.g.cs" , "MetaNetValidation.Acme.Shipping.g.cs" ,
578+ ] ;
579+ CodegenRunner . Run ( config , r . Root , [ new EntityGenerator ( ) ] ) ;
580+ foreach ( var h in helpers ) File . WriteAllText ( Path . Combine ( dir , h ) , File . ReadAllText ( Path . Combine ( dir , h ) ) + "// stale\n " ) ;
581+
582+ var second = CodegenRunner . Run ( config , r . Root , [ new EntityGenerator ( ) ] ) ;
583+ Assert . DoesNotContain ( second . Warnings , w => w . Contains ( "refusing to overwrite" , StringComparison . Ordinal ) ) ;
584+ foreach ( var h in helpers )
585+ {
586+ Assert . Contains ( second . Files , f => f . Path == h && f . Status == "written" ) ;
587+ Assert . DoesNotContain ( "// stale" , File . ReadAllText ( Path . Combine ( dir , h ) ) , StringComparison . Ordinal ) ;
588+ }
589+ }
590+ finally { try { Directory . Delete ( dir , true ) ; } catch { } }
591+ }
542592}
0 commit comments