Skip to content

Commit 1e53207

Browse files
committed
Add row discrepancy information to test case logs for EET DML oracle
1 parent 7b9b054 commit 1e53207

1 file changed

Lines changed: 56 additions & 9 deletions

File tree

src/sqlancer/common/oracle/EETDMLOracle.java

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
import java.sql.SQLException;
44
import java.util.AbstractMap;
55
import java.util.ArrayList;
6+
import java.util.LinkedHashMap;
67
import java.util.List;
78
import java.util.Map;
9+
import java.util.Objects;
10+
import java.util.Set;
11+
import java.util.TreeSet;
812

913
import sqlancer.IgnoreMeException;
1014
import sqlancer.Randomly;
@@ -61,6 +65,7 @@ public class EETDMLOracle<E extends Expression<C>, S extends AbstractSchema<?, T
6165
private final EETTransformer<E, ?> transformer;
6266
private final ExpectedErrors errors;
6367

68+
private static final int MAX_DIFF_ROWS_REPORTED = 10; // max differing post-image rows displayed in report log
6469
private String generatedQueryString;
6570

6671
public EETDMLOracle(G state, EETDMLGenerator<E, T, C> gen, ExpectedErrors expectedErrors) {
@@ -137,8 +142,8 @@ public void check() throws SQLException {
137142
List<List<String>> transformedImage = executeAndSnapshotPostImage(table, transformedStatement, columnCount);
138143

139144
if (!originalImage.equals(transformedImage)) {
140-
throw new AssertionError(
141-
mismatchMessage(originalStatement, transformedStatement, originalImage, transformedImage));
145+
throw new AssertionError(mismatchMessage(table, originalStatement, transformedStatement, originalImage,
146+
transformedImage));
142147
}
143148
} finally {
144149
new SQLQueryAdapter(gen.dropRowIdColumnStatement(table), errors, true).execute(state);
@@ -234,14 +239,56 @@ private List<List<String>> snapshotPostImage(String selectStatement, int columnC
234239
return rows;
235240
}
236241

237-
private static String mismatchMessage(String originalStatement, String transformedStatement,
242+
private String mismatchMessage(T table, String originalStatement, String transformedStatement,
238243
List<List<String>> originalImage, List<List<String>> transformedImage) {
239-
return new StringBuilder()
240-
.append("-- The original and transformed statements left the database in different states")
241-
.append(" (different post-images):").append(System.lineSeparator()).append("-- original (")
242-
.append(originalImage.size()).append(" rows): ").append(originalStatement).append(';')
243-
.append(System.lineSeparator()).append("-- transformed (").append(transformedImage.size())
244-
.append(" rows): ").append(transformedStatement).append(';').append(System.lineSeparator()).toString();
244+
List<String> header = new ArrayList<>();
245+
header.add(EETDMLGenerator.ROW_ID_COLUMN);
246+
for (C column : table.getColumns()) {
247+
header.add(column.getName());
248+
}
249+
250+
Map<String, List<String>> originalByRowId = indexByRowId(originalImage);
251+
Map<String, List<String>> transformedByRowId = indexByRowId(transformedImage);
252+
Set<String> allRowIds = new TreeSet<>();
253+
allRowIds.addAll(originalByRowId.keySet());
254+
allRowIds.addAll(transformedByRowId.keySet());
255+
256+
String nl = System.lineSeparator();
257+
StringBuilder message = new StringBuilder()
258+
.append("-- The original and transformed statements left the database in different states.").append(nl)
259+
.append("-- original: ").append(originalStatement).append(';').append(nl).append("-- transformed: ")
260+
.append(transformedStatement).append(';').append(nl).append("-- differing post-image rows (")
261+
.append(String.join(", ", header)).append("):").append(nl);
262+
int shown = 0;
263+
for (String rowId : allRowIds) {
264+
List<String> originalRow = originalByRowId.get(rowId);
265+
List<String> transformedRow = transformedByRowId.get(rowId);
266+
if (Objects.equals(originalRow, transformedRow)) {
267+
continue;
268+
}
269+
if (shown == MAX_DIFF_ROWS_REPORTED) {
270+
message.append("-- ... (further differences omitted)").append(nl);
271+
break;
272+
}
273+
message.append("-- original: ").append(renderRow(originalRow)).append(nl);
274+
message.append("-- transformed: ").append(renderRow(transformedRow)).append(nl);
275+
shown++;
276+
}
277+
return message.toString();
278+
}
279+
280+
// Indexes a post-image by its row identifier (the first column of each row)
281+
private static Map<String, List<String>> indexByRowId(List<List<String>> image) {
282+
Map<String, List<String>> byRowId = new LinkedHashMap<>();
283+
for (List<String> row : image) {
284+
byRowId.put(row.get(0), row);
285+
}
286+
return byRowId;
287+
}
288+
289+
// Renders a post-image row for the finding message, or "(row absent)" when the row is missing on that side
290+
private static String renderRow(List<String> row) {
291+
return row == null ? "(row absent)" : row.toString();
245292
}
246293

247294
@Override

0 commit comments

Comments
 (0)