package sqlancer; import java.util.List; import java.util.stream.Collectors; import sqlancer.StateToReproduce.OracleRunReproductionState; import sqlancer.common.oracle.CompositeTestOracle; import sqlancer.common.oracle.TestOracle; import sqlancer.common.schema.AbstractSchema; public abstract class ProviderAdapter, C>, O extends DBMSSpecificOptions>, C extends SQLancerDBConnection> implements DatabaseProvider { private final Class globalClass; private final Class optionClass; public ProviderAdapter(Class globalClass, Class optionClass) { this.globalClass = globalClass; this.optionClass = optionClass; } @Override public StateToReproduce getStateToReproduce(String databaseName) { return new StateToReproduce(databaseName, this); } @Override public Class getGlobalStateClass() { return globalClass; } @Override public Class getOptionClass() { return optionClass; } @Override public void generateAndTestDatabase(G globalState) throws Exception { try { generateDatabase(globalState); checkViewsAreValid(globalState); globalState.getManager().incrementCreateDatabase(); TestOracle oracle = getTestOracle(globalState); for (int i = 0; i < globalState.getOptions().getNrQueries(); i++) { try (OracleRunReproductionState localState = globalState.getState().createLocalState()) { assert localState != null; try { oracle.check(); globalState.getManager().incrementSelectQueryCount(); } catch (IgnoreMeException e) { } assert localState != null; localState.executedWithoutError(); } } } finally { globalState.getConnection().close(); } } protected abstract void checkViewsAreValid(G globalState); protected TestOracle getTestOracle(G globalState) throws Exception { List> testOracleFactory = globalState.getDmbsSpecificOptions() .getTestOracleFactory(); boolean testOracleRequiresMoreThanZeroRows = testOracleFactory.stream() .anyMatch(p -> p.requiresAllTablesToContainRows()); boolean userRequiresMoreThanZeroRows = globalState.getOptions().testOnlyWithMoreThanZeroRows(); boolean checkZeroRows = testOracleRequiresMoreThanZeroRows || userRequiresMoreThanZeroRows; if (checkZeroRows && globalState.getSchema().containsTableWithZeroRows(globalState)) { throw new IgnoreMeException(); } if (testOracleFactory.size() == 1) { return testOracleFactory.get(0).create(globalState); } else { return new CompositeTestOracle(testOracleFactory.stream().map(o -> { try { return o.create(globalState); } catch (Exception e1) { throw new AssertionError(e1); } }).collect(Collectors.toList()), globalState); } } public abstract void generateDatabase(G globalState) throws Exception; }