@@ -50,9 +50,6 @@ public static void main(String[] args) {
5050 return ;
5151 }
5252
53- String originalDbPath = args [0 ];
54- String candidateDbPath = args [1 ];
55-
5653 try {
5754 Class .forName ("org.sqlite.JDBC" );
5855 } catch (ClassNotFoundException e ) {
@@ -61,80 +58,100 @@ public static void main(String[] args) {
6158 return ;
6259 }
6360
64- Map <String , byte []> originalResults ;
65- Map <String , byte []> candidateResults ;
66-
61+ String result ;
6762 try {
68- originalResults = readTestResults ( originalDbPath );
63+ result = compareDatabases ( args [ 0 ], args [ 1 ] );
6964 } catch (Exception e ) {
70- printError ("Failed to read original database: " + e .getMessage ());
65+ printError (e .getMessage ());
7166 System .exit (2 );
7267 return ;
7368 }
7469
75- try {
76- candidateResults = readTestResults (candidateDbPath );
77- } catch (Exception e ) {
78- printError ("Failed to read candidate database: " + e .getMessage ());
79- System .exit (2 );
80- return ;
81- }
70+ System .out .println (result );
71+ boolean equivalent = result .startsWith ("{\" equivalent\" :true" );
72+ System .exit (equivalent ? 0 : 1 );
73+ }
74+
75+ static String compareDatabases (String originalDbPath , String candidateDbPath ) throws Exception {
76+ Map <String , byte []> originalResults = readTestResults (originalDbPath );
77+ Map <String , byte []> candidateResults = readTestResults (candidateDbPath );
8278
8379 Set <String > allKeys = new LinkedHashSet <>();
8480 allKeys .addAll (originalResults .keySet ());
8581 allKeys .addAll (candidateResults .keySet ());
8682
8783 List <String > diffs = new ArrayList <>();
8884 int totalInvocations = allKeys .size ();
85+ int actualComparisons = 0 ;
86+ int skippedPlaceholders = 0 ;
87+ int skippedDeserializationErrors = 0 ;
8988
9089 for (String key : allKeys ) {
9190 byte [] origBytes = originalResults .get (key );
9291 byte [] candBytes = candidateResults .get (key );
9392
9493 if (origBytes == null && candBytes == null ) {
95- // Both null (void methods) — equivalent
94+ // Both null (void methods) — a real comparison (void-to-void match)
95+ actualComparisons ++;
9696 continue ;
9797 }
9898
9999 if (origBytes == null ) {
100100 Object candObj = safeDeserialize (candBytes );
101101 diffs .add (formatDiff ("missing" , key , 0 , null , safeToString (candObj )));
102+ actualComparisons ++;
102103 continue ;
103104 }
104105
105106 if (candBytes == null ) {
106107 Object origObj = safeDeserialize (origBytes );
107108 diffs .add (formatDiff ("missing" , key , 0 , safeToString (origObj ), null ));
109+ actualComparisons ++;
108110 continue ;
109111 }
110112
111113 Object origObj = safeDeserialize (origBytes );
112114 Object candObj = safeDeserialize (candBytes );
113115
116+ if (isDeserializationError (origObj ) || isDeserializationError (candObj )) {
117+ skippedDeserializationErrors ++;
118+ continue ;
119+ }
120+
114121 try {
115122 if (!compare (origObj , candObj )) {
116123 diffs .add (formatDiff ("return_value" , key , 0 , safeToString (origObj ), safeToString (candObj )));
117124 }
125+ actualComparisons ++;
118126 } catch (KryoPlaceholderAccessException e ) {
119- // Placeholder detected — skip comparison for this invocation
127+ skippedPlaceholders ++;
120128 continue ;
121129 }
122130 }
123131
124- boolean equivalent = diffs .isEmpty ();
132+ boolean equivalent = diffs .isEmpty () && actualComparisons > 0 ;
133+
134+ System .err .println ("[codeflash-comparator] total=" + totalInvocations
135+ + " compared=" + actualComparisons
136+ + " skipped_placeholders=" + skippedPlaceholders
137+ + " skipped_deser_errors=" + skippedDeserializationErrors
138+ + " diffs=" + diffs .size ()
139+ + " equivalent=" + equivalent );
125140
126141 StringBuilder json = new StringBuilder ();
127142 json .append ("{\" equivalent\" :" ).append (equivalent );
128143 json .append (",\" totalInvocations\" :" ).append (totalInvocations );
144+ json .append (",\" actualComparisons\" :" ).append (actualComparisons );
145+ json .append (",\" skippedPlaceholders\" :" ).append (skippedPlaceholders );
146+ json .append (",\" skippedDeserializationErrors\" :" ).append (skippedDeserializationErrors );
129147 json .append (",\" diffs\" :[" );
130148 for (int i = 0 ; i < diffs .size (); i ++) {
131149 if (i > 0 ) json .append ("," );
132150 json .append (diffs .get (i ));
133151 }
134152 json .append ("]}" );
135153
136- System .out .println (json .toString ());
137- System .exit (equivalent ? 0 : 1 );
154+ return json .toString ();
138155 }
139156
140157 private static Map <String , byte []> readTestResults (String dbPath ) throws Exception {
@@ -178,6 +195,11 @@ private static Object safeDeserialize(byte[] data) {
178195 }
179196 }
180197
198+ static boolean isDeserializationError (Object obj ) {
199+ if (!(obj instanceof Map )) return false ;
200+ return "DeserializationError" .equals (((Map <?, ?>) obj ).get ("__type" ));
201+ }
202+
181203 private static String safeToString (Object obj ) {
182204 if (obj == null ) {
183205 return "null" ;
0 commit comments