-
Notifications
You must be signed in to change notification settings - Fork 398
Expand file tree
/
Copy pathStatementReducer.java
More file actions
87 lines (74 loc) · 3.34 KB
/
StatementReducer.java
File metadata and controls
87 lines (74 loc) · 3.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package sqlancer;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import sqlancer.common.query.Query;
public class StatementReducer<G extends GlobalState<O, ?, C>, O extends DBMSSpecificOptions<?>, C extends SQLancerDBConnection>
implements Reducer<G> {
private final DatabaseProvider<G, O, C> provider;
private boolean observedChange;
public StatementReducer(DatabaseProvider<G, O, C> provider) {
this.provider = provider;
}
@SuppressWarnings("unchecked")
@Override
public void reduce(G state, Reproducer<G> reproducer, G newGlobalState) throws Exception {
List<Query<C>> knownToReproduceBugStatements = new ArrayList<>();
for (Query<?> stat : state.getState().getStatements()) {
knownToReproduceBugStatements.add((Query<C>) stat);
}
System.out.println("Starting query:");
printQueries(knownToReproduceBugStatements);
System.out.println();
do {
observedChange = false;
knownToReproduceBugStatements = tryReduction(state, reproducer, newGlobalState,
knownToReproduceBugStatements, (candidateStatements, i) -> {
candidateStatements.remove((int) i);
return true;
});
} while (observedChange);
System.out.println("Reduced query:");
printQueries(knownToReproduceBugStatements);
}
private List<Query<C>> tryReduction(G state, // NOPMD
Reproducer<G> reproducer, G newGlobalState, List<Query<C>> knownToReproduceBugStatements,
BiFunction<List<Query<C>>, Integer, Boolean> reductionOperation) throws Exception {
List<Query<C>> statements = knownToReproduceBugStatements;
for (int i = 0; i < statements.size(); i++) {
try (C con2 = provider.createDatabase(newGlobalState)) {
newGlobalState.setConnection(con2);
List<Query<C>> candidateStatements = new ArrayList<>(statements);
if (!reductionOperation.apply(candidateStatements, i)) {
continue;
}
newGlobalState.getState().setStatements(candidateStatements.stream().collect(Collectors.toList()));
for (Query<C> s : candidateStatements) {
try {
s.execute(newGlobalState);
} catch (Throwable ignoredException) {
// ignore
}
}
try {
if (reproducer.bugStillTriggers(newGlobalState)) {
observedChange = true;
statements = candidateStatements;
// reproducer.outputHook((SQLite3GlobalState) newGlobalState);
// state.getLogger().logReduced(newGlobalState.getState());
}
} catch (Throwable ignoredException) {
}
}
}
return statements;
}
private void printQueries(List<Query<C>> statements) {
System.out.println("===============================");
for (Query<?> q : statements) {
System.out.println(q.getLogString());
}
System.out.println("===============================");
}
}