1+ using System ;
2+ using System . Diagnostics ;
3+ using System . IO ;
4+ using System . Linq ;
5+ using Newtonsoft . Json . Linq ;
6+ using NUnit . Framework ;
7+ using PChecker ;
8+ using UnitTests . Core ;
9+ using UnitTests . Runners ;
10+ using Plang . Options ;
11+ namespace UnitTests ;
12+
13+ [ TestFixture ]
14+ [ Parallelizable ( ParallelScope . Children ) ]
15+ public class PCheckerLogGeneratorTests
16+ {
17+ [ Test ]
18+ public void TestLogGenerator ( )
19+ {
20+ var tempDir = Directory . CreateDirectory ( Path . Combine ( Constants . ScratchParentDirectory , "TestLogGenerator" ) ) ;
21+ var srcPath = new FileInfo ( Path . Combine ( Constants . SolutionDirectory , "Tst" , "RegressionTests" ,
22+ "Feature1SMLevelDecls" , "DynamicError" , "bug2" , "bug2.p" ) ) ;
23+ var dllPath = Path . Combine ( Constants . ScratchParentDirectory , "TestLogGenerator" , "CSharp" , "net8.0" , "Main.dll" ) ;
24+ var expectedPath = Path . Combine ( Constants . SolutionDirectory , "Tst" , "CorrectLogs" , "bugs2" ) ;
25+
26+ var runner = new PCheckerRunner ( [ srcPath ] ) ;
27+ runner . DoCompile ( tempDir ) ;
28+
29+ var configuration = new PCheckerOptions ( ) . Parse ( [ dllPath , "-o" , tempDir . ToString ( ) ] ) ;
30+ Checker . Run ( configuration ) ;
31+
32+ AssertLog ( tempDir + "/BugFinding" , expectedPath ) ;
33+ }
34+
35+ private void AssertLog ( string generatedDir , string expectedDir )
36+ {
37+ if ( ! Directory . Exists ( generatedDir ) || ! Directory . Exists ( expectedDir ) )
38+ {
39+ Assert . Fail ( "One or both directories do not exist." ) ;
40+ }
41+
42+ var generatedFiles = Directory . GetFiles ( generatedDir ) . Select ( Path . GetFileName ) . ToHashSet ( ) ;
43+ var expectedFiles = Directory . GetFiles ( expectedDir ) . Select ( Path . GetFileName ) . ToHashSet ( ) ;
44+
45+ foreach ( var fileName in expectedFiles . Intersect ( generatedFiles ) )
46+ {
47+ string generatedFilePath = Path . Combine ( generatedDir , fileName ) ;
48+ string expectedFilePath = Path . Combine ( expectedDir , fileName ) ;
49+
50+ if ( fileName == "trace_0_0.trace.json" )
51+ {
52+ // Perform "Is JSON Included" check for this specific file
53+ if ( ! IsJsonContentIncluded ( generatedFilePath , expectedFilePath ) )
54+ {
55+ Assert . Fail ( $ "Test Failed\n Content of{ expectedFilePath } is not fully included in{ generatedFilePath } ") ;
56+ }
57+ }
58+ else
59+ {
60+ // Perform exact match for other files
61+ if ( ! File . ReadAllBytes ( generatedFilePath ) . SequenceEqual ( File . ReadAllBytes ( expectedFilePath ) ) )
62+ {
63+ Assert . Fail ( $ "Test Failed\n Files differ:{ fileName } \n Generated File:{ generatedFilePath } \n Expected File:{ expectedFilePath } ") ;
64+ }
65+ }
66+ }
67+
68+ // Check for missing files in generatedDir
69+ foreach ( var file in expectedFiles . Except ( generatedFiles ) )
70+ {
71+ Assert . Fail ( $ "Test Failed\n Missing expected file in{ generatedDir } :{ file } ") ;
72+ }
73+ Console . WriteLine ( "Test Succeeded" ) ;
74+ }
75+
76+ private static bool IsJsonContentIncluded ( string generatedFilePath , string expectedFilePath )
77+ {
78+ var generatedJson = JToken . Parse ( File . ReadAllText ( generatedFilePath ) ) ;
79+ var expectedJson = JToken . Parse ( File . ReadAllText ( expectedFilePath ) ) ;
80+
81+ return IsSubset ( expectedJson , generatedJson ) ;
82+ }
83+
84+ private static bool IsSubset ( JToken subset , JToken superset )
85+ {
86+ if ( JToken . DeepEquals ( subset , superset ) )
87+ {
88+ return true ;
89+ }
90+
91+ if ( subset . Type == JTokenType . Object && superset . Type == JTokenType . Object )
92+ {
93+ var subsetObj = ( JObject ) subset ;
94+ var supersetObj = ( JObject ) superset ;
95+
96+ foreach ( var property in subsetObj . Properties ( ) )
97+ {
98+ if ( ! supersetObj . TryGetValue ( property . Name , out var supersetValue ) || ! IsSubset ( property . Value , supersetValue ) )
99+ {
100+ return false ;
101+ }
102+ }
103+
104+ return true ;
105+ }
106+
107+ if ( subset . Type == JTokenType . Array && superset . Type == JTokenType . Array )
108+ {
109+ var subsetArray = ( JArray ) subset ;
110+ var supersetArray = ( JArray ) superset ;
111+
112+ foreach ( var subsetItem in subsetArray )
113+ {
114+ if ( ! supersetArray . Any ( supersetItem=> IsSubset ( subsetItem , supersetItem ) ) )
115+ {
116+ return false ;
117+ }
118+ }
119+
120+ return true ;
121+ }
122+
123+ return false ;
124+ }
125+ }