1+ using  System ; 
2+ using  System . Collections . Generic ; 
3+ using  System . Globalization ; 
4+ using  System . IO ; 
5+ using  System . Reflection ; 
6+ using  System . Text ; 
7+ using  System . Xml ; 
8+ using  AwesomeAssertions ; 
9+ using  Microsoft . Extensions . Configuration ; 
10+ using  Microsoft . Extensions . Configuration . Json ; 
11+ using  NuGet . Versioning ; 
12+ using  ReflectionMagic ; 
13+ using  Serilog . Core ; 
14+ using  Serilog . Settings . Configuration ; 
15+ using  Serilog . Sinks . File ; 
16+ using  Tomlyn . Extensions . Configuration ; 
17+ using  Xunit ; 
18+ 
19+ namespace  Serilog . Formatting . Log4Net . Tests ; 
20+ 
21+ public  class  SerilogSettingsConfigurationTest 
22+ { 
23+     private  static readonly  PropertyFilter  DefaultPropertyFilter ; 
24+     private  static readonly  MessageFormatter  DefaultMessageFormatter ; 
25+     private  static readonly  ExceptionFormatter  DefaultExceptionFormatter ; 
26+     private  static readonly  SemanticVersion  MicrosoftExtensionsConfigurationVersion ; 
27+ 
28+     static SerilogSettingsConfigurationTest ( ) 
29+     { 
30+         var  defaultBuilder  =  new  Log4NetTextFormatterOptionsBuilder ( ) . AsDynamic ( ) ; 
31+ 
32+         DefaultPropertyFilter  =  defaultBuilder . _filterProperty ; 
33+         DefaultMessageFormatter  =  defaultBuilder . _formatMessage ; 
34+         DefaultExceptionFormatter  =  defaultBuilder . _formatException ; 
35+ 
36+         var  assembly  =  typeof ( JsonStreamConfigurationSource ) . Assembly ; 
37+         var  informationalVersion  =  assembly . GetCustomAttribute < AssemblyInformationalVersionAttribute > ( ) ? . InformationalVersion ; 
38+         MicrosoftExtensionsConfigurationVersion  =  SemanticVersion . Parse ( informationalVersion  ??  throw  new  InvalidDataException ( $ "The [AssemblyInformationalVersion] attribute is missing from { assembly } ") ) ; 
39+     } 
40+ 
41+ 
42+     [ Fact ] 
43+     public  void  ConfigureDefault ( ) 
44+     { 
45+         // lang=toml 
46+         var  config  = 
47+             """ 
48+             [[Serilog.WriteTo]] 
49+             Name = 'File' 
50+             Args.path = 'logs.xml' 
51+             Args.formatter.type = 'Serilog.Formatting.Log4Net.Log4NetTextFormatter, Serilog.Formatting.Log4Net' 
52+             """ ; 
53+ 
54+         var  options  =  GetLog4NetTextFormatterOptions ( config ) ; 
55+ 
56+         options . Should ( ) . BeEquivalentTo ( new  Log4NetTextFormatterOptions ( 
57+             formatProvider :  null , 
58+             cDataMode :  CDataMode . Always , 
59+             nullText :  "(null)" , 
60+             xmlNamespace :  new  XmlQualifiedName ( "log4net" ,  "http://logging.apache.org/log4net/schemas/log4net-events-1.2/" ) , 
61+             xmlWriterSettings :  new  XmlWriterSettings  {  Indent  =  true ,  IndentChars  =  "  " ,  ConformanceLevel  =  ConformanceLevel . Fragment  } , 
62+             filterProperty :  DefaultPropertyFilter , 
63+             formatMessage :  DefaultMessageFormatter , 
64+             formatException :  DefaultExceptionFormatter 
65+         ) ) ; 
66+     } 
67+ 
68+     [ Theory ] 
69+     [ InlineData ( CDataMode . Always ) ] 
70+     [ InlineData ( CDataMode . Never ) ] 
71+     [ InlineData ( CDataMode . IfNeeded ) ] 
72+     public  void  ConfigureCDataMode ( CDataMode  cDataMode ) 
73+     { 
74+         // lang=toml 
75+         var  config  = 
76+             $ """ 
77+              [[Serilog.WriteTo]] 
78+              Name = 'File' 
79+              Args.path = 'logs.xml' 
80+              Args.formatter.type = 'Serilog.Formatting.Log4Net.Log4NetTextFormatter, Serilog.Formatting.Log4Net' 
81+              Args.formatter.cDataMode = '{ cDataMode } ' 
82+              """  ; 
83+ 
84+         var  options  =  GetLog4NetTextFormatterOptions ( config ) ; 
85+ 
86+         options . Should ( ) . BeEquivalentTo ( new  Log4NetTextFormatterOptions ( 
87+             formatProvider :  null , 
88+             cDataMode :  cDataMode , 
89+             nullText :  "(null)" , 
90+             xmlNamespace :  new  XmlQualifiedName ( "log4net" ,  "http://logging.apache.org/log4net/schemas/log4net-events-1.2/" ) , 
91+             xmlWriterSettings :  new  XmlWriterSettings  {  Indent  =  true ,  IndentChars  =  "  " ,  ConformanceLevel  =  ConformanceLevel . Fragment  } , 
92+             filterProperty :  DefaultPropertyFilter , 
93+             formatMessage :  DefaultMessageFormatter , 
94+             formatException :  DefaultExceptionFormatter 
95+         ) ) ; 
96+     } 
97+ 
98+     [ Theory ] 
99+     [ InlineData ( "iv" ) ] 
100+     [ InlineData ( "fr-CH" ) ] 
101+     public  void  ConfigureFormatProvider ( string  formatProvider ) 
102+     { 
103+         // lang=toml 
104+         var  config  = 
105+             $ """ 
106+              [[Serilog.WriteTo]] 
107+              Name = 'File' 
108+              Args.path = 'logs.xml' 
109+              Args.formatter.type = 'Serilog.Formatting.Log4Net.Log4NetTextFormatter, Serilog.Formatting.Log4Net' 
110+              Args.formatter.formatProvider = '{ formatProvider } ' 
111+              """  ; 
112+ 
113+         var  options  =  GetLog4NetTextFormatterOptions ( config ) ; 
114+ 
115+         options . FormatProvider . Should ( ) . BeSameAs ( CultureInfo . GetCultureInfo ( formatProvider ) ) ; 
116+     } 
117+ 
118+     [ SkippableTheory ] 
119+     [ InlineData ( null ) ] 
120+     [ InlineData ( "" ) ] 
121+     [ InlineData ( "<null>" ) ] 
122+     [ InlineData ( "🌀" ) ] 
123+     public  void  ConfigureNullText ( string ?  nullText ) 
124+     { 
125+         // Null values preserved in configuration was introduced in .NET 10 Preview 7 
126+         // See https://learn.microsoft.com/en-us/dotnet/core/compatibility/extensions/10.0/configuration-null-values-preserved 
127+         Skip . If ( nullText  ==  null  &&  MicrosoftExtensionsConfigurationVersion . Major  <  10 ,  "null values are preserved in configuration since .NET 10 Preview 7" ) ; 
128+ 
129+         // lang=json 
130+         var  config  = 
131+             $$ """ 
132+               { 
133+                 "Serilog": { 
134+                   "WriteTo:File": { 
135+                     "Name": "File", 
136+                     "Args": { 
137+                       "path": "logs.xml", 
138+                       "formatter": { 
139+                         "type": "Serilog.Formatting.Log4Net.Log4NetTextFormatter, Serilog.Formatting.Log4Net", 
140+                         "nullText": {{ ( nullText  ==  null  ?  "null"  :  $ "\" { nullText } \" ") }}  
141+                       } 
142+                     } 
143+                   } 
144+                 } 
145+               } 
146+               """  ; 
147+         var  options  =  GetLog4NetTextFormatterOptions ( config ) ; 
148+ 
149+         options . NullText . Should ( ) . Be ( nullText ) ; 
150+     } 
151+ 
152+     [ Fact ] 
153+     public  void  ConfigureNoXmlNamespace ( ) 
154+     { 
155+         // lang=toml 
156+         const  string  config  = 
157+             """ 
158+             [[Serilog.WriteTo]] 
159+             Name = 'File' 
160+             Args.path = 'logs.xml' 
161+             Args.formatter.type = 'Serilog.Formatting.Log4Net.Log4NetTextFormatter, Serilog.Formatting.Log4Net' 
162+             Args.formatter.noXmlNamespace = true 
163+             """ ; 
164+ 
165+         var  options  =  GetLog4NetTextFormatterOptions ( config ) ; 
166+ 
167+         options . XmlNamespace . Should ( ) . BeNull ( ) ; 
168+     } 
169+ 
170+     private  static Log4NetTextFormatterOptions  GetLog4NetTextFormatterOptions ( string  config ) 
171+     { 
172+         using  var  configStream  =  new  MemoryStream ( Encoding . UTF8 . GetBytes ( config ) ) ; 
173+         var  configBuilder  =  new  ConfigurationBuilder ( ) ; 
174+         var  configuration  =  ( config . StartsWith ( '{' )  ?  configBuilder . AddJsonStream ( configStream )  :  configBuilder . AddTomlStream ( configStream ) ) . Build ( ) ; 
175+         var  options  =  new  ConfigurationReaderOptions ( typeof ( ILogger ) . Assembly ,  typeof ( FileSink ) . Assembly ,  typeof ( Log4NetTextFormatter ) . Assembly ) ; 
176+         using  var  logger  =  new  LoggerConfiguration ( ) . ReadFrom . Configuration ( configuration ,  options ) . CreateLogger ( ) ; 
177+         IEnumerable < ILogEventSink >  sinks  =  logger . AsDynamic ( ) . _sink . _sinks ; 
178+         var  fileSink  =  sinks . Should ( ) . ContainSingle ( ) . Which . Should ( ) . BeOfType < FileSink > ( ) . Subject ; 
179+         return  fileSink . AsDynamic ( ) . _textFormatter . _options ; 
180+     } 
181+ } 
0 commit comments