1+ using System ;
12using System . Collections . Generic ;
3+ using System . IO ;
24using System . Reflection ;
5+ using System . Threading . Tasks ;
36using FolderDiffIL4DotNet . Models ;
47using FolderDiffIL4DotNet . Services ;
8+ using FolderDiffIL4DotNet . Services . Caching ;
9+ using Microsoft . Extensions . DependencyInjection ;
510using Xunit ;
611
712namespace FolderDiffIL4DotNet . Tests . Services
@@ -38,6 +43,103 @@ public void GetNormalizedIlIgnoreContainingStrings_RemovesEmptyTrimAndDuplicates
3843 Assert . Equal ( new [ ] { "buildserver" , "buildpath" } , result ) ;
3944 }
4045
46+ [ Theory ]
47+ [ InlineData ( "dotnet ildasm sample.dll (version: 9.0.0)" , "dotnet-ildasm (version: 9.0.0)" ) ]
48+ [ InlineData ( "ilspycmd -il sample.dll (version: 8.2.1)" , "ilspycmd (version: 8.2.1)" ) ]
49+ [ InlineData ( "dotnet-ildasm sample.dll" , "dotnet-ildasm" ) ]
50+ public void BuildToolAndVersionLabel_ReturnsExpectedLabel ( string command , string expected )
51+ {
52+ var method = typeof ( ILOutputService ) . GetMethod ( "BuildToolAndVersionLabel" , BindingFlags . Static | BindingFlags . NonPublic ) ;
53+ Assert . NotNull ( method ) ;
54+
55+ var result = method . Invoke ( null , new object [ ] { command } ) ;
56+
57+ Assert . Equal ( expected , Assert . IsType < string > ( result ) ) ;
58+ }
59+
60+ [ Fact ]
61+ public void BuildComparisonDisassemblerLabel_WhenLabelsMismatch_Throws ( )
62+ {
63+ var method = typeof ( ILOutputService ) . GetMethod ( "BuildComparisonDisassemblerLabel" , BindingFlags . Static | BindingFlags . NonPublic ) ;
64+ Assert . NotNull ( method ) ;
65+
66+ var ex = Assert . Throws < TargetInvocationException > ( ( ) =>
67+ method . Invoke ( null , new object [ ]
68+ {
69+ "dotnet ildasm sample.dll (version: 1.0.0)" ,
70+ "ilspycmd -il sample.dll (version: 2.0.0)"
71+ } ) ) ;
72+ Assert . IsType < InvalidOperationException > ( ex . InnerException ) ;
73+ }
74+
75+ [ Fact ]
76+ public void BuildComparisonDisassemblerLabel_WhenOnlyOneSideHasLabel_ReturnsAvailableOne ( )
77+ {
78+ var method = typeof ( ILOutputService ) . GetMethod ( "BuildComparisonDisassemblerLabel" , BindingFlags . Static | BindingFlags . NonPublic ) ;
79+ Assert . NotNull ( method ) ;
80+
81+ var result = method . Invoke ( null , new object [ ] { null , "ilspycmd -il sample.dll (version: 8.2.1)" } ) ;
82+ Assert . Equal ( "ilspycmd (version: 8.2.1)" , Assert . IsType < string > ( result ) ) ;
83+ }
84+
85+ [ Fact ]
86+ public void BuildComparisonDisassemblerLabel_WhenBothMatch_IgnoresCaseAndReturnsLabel ( )
87+ {
88+ var method = typeof ( ILOutputService ) . GetMethod ( "BuildComparisonDisassemblerLabel" , BindingFlags . Static | BindingFlags . NonPublic ) ;
89+ Assert . NotNull ( method ) ;
90+
91+ var result = method . Invoke ( null , new object [ ]
92+ {
93+ "dotnet ildasm sample.dll (version: 1.0.0)" ,
94+ "DOTNET ILDASM sample.dll (version: 1.0.0)"
95+ } ) ;
96+ Assert . Equal ( "dotnet-ildasm (version: 1.0.0)" , Assert . IsType < string > ( result ) ) ;
97+ }
98+
99+ [ Fact ]
100+ public async Task PrecomputeAsync_WhenOptimizeForNetworkShares_ExitsWithoutThrowing ( )
101+ {
102+ var config = new ConfigSettings
103+ {
104+ OptimizeForNetworkShares = true ,
105+ EnableILCache = true ,
106+ IgnoredExtensions = new ( ) ,
107+ TextFileExtensions = new ( )
108+ } ;
109+
110+ var service = CreateILOutputService ( config ) ;
111+ await service . PrecomputeAsync ( new [ ] { "/tmp/non-existent.dll" } , maxParallel : 0 ) ;
112+ }
113+
114+ [ Fact ]
115+ public async Task PrecomputeAsync_WithInvalidMaxParallel_ThrowsWhenNotNetworkOptimized ( )
116+ {
117+ var config = new ConfigSettings
118+ {
119+ OptimizeForNetworkShares = false ,
120+ EnableILCache = false ,
121+ IgnoredExtensions = new ( ) ,
122+ TextFileExtensions = new ( )
123+ } ;
124+
125+ var service = CreateILOutputService ( config ) ;
126+ await Assert . ThrowsAsync < ArgumentOutOfRangeException > ( ( ) => service . PrecomputeAsync ( Array . Empty < string > ( ) , maxParallel : 0 ) ) ;
127+ }
128+
129+ [ Fact ]
130+ public async Task PrecomputeAsync_WithCacheDisabled_ReturnsWithoutThrowing ( )
131+ {
132+ var config = new ConfigSettings
133+ {
134+ OptimizeForNetworkShares = false ,
135+ EnableILCache = false ,
136+ IgnoredExtensions = new ( ) ,
137+ TextFileExtensions = new ( )
138+ } ;
139+ var service = CreateILOutputService ( config ) ;
140+ await service . PrecomputeAsync ( new [ ] { "/tmp/non-existent.dll" } , maxParallel : 1 ) ;
141+ }
142+
41143 private static bool InvokeShouldExcludeIlLine ( string line , bool shouldIgnoreContainingStrings , IReadOnlyCollection < string > ilIgnoreContainingStrings )
42144 {
43145 var method = typeof ( ILOutputService ) . GetMethod ( "ShouldExcludeIlLine" , BindingFlags . Static | BindingFlags . NonPublic ) ;
@@ -53,5 +155,21 @@ private static List<string> InvokeGetNormalizedIlIgnoreContainingStrings(ConfigS
53155 var result = method . Invoke ( null , new object [ ] { config } ) ;
54156 return Assert . IsType < List < string > > ( result ) ;
55157 }
158+
159+ private static ILOutputService CreateILOutputService ( ConfigSettings config , string ilOldFolder = null , string ilNewFolder = null )
160+ {
161+ var logger = new LoggerService ( ) ;
162+ var services = new ServiceCollection ( ) ;
163+ services . AddSingleton < ILoggerService > ( logger ) ;
164+ services . AddSingleton ( new FileDiffResultLists ( ) ) ;
165+ services . AddSingleton ( new DotNetDisassemblerCache ( logger ) ) ;
166+ var provider = services . BuildServiceProvider ( ) ;
167+
168+ var oldDir = ilOldFolder ?? Path . Combine ( Path . GetTempPath ( ) , "fd-iloutput-old-" + Guid . NewGuid ( ) . ToString ( "N" ) ) ;
169+ var newDir = ilNewFolder ?? Path . Combine ( Path . GetTempPath ( ) , "fd-iloutput-new-" + Guid . NewGuid ( ) . ToString ( "N" ) ) ;
170+ Directory . CreateDirectory ( oldDir ) ;
171+ Directory . CreateDirectory ( newDir ) ;
172+ return new ILOutputService ( config , oldDir , newDir , provider , logger ) ;
173+ }
56174 }
57175}
0 commit comments