Skip to content

Commit 3bc5ee4

Browse files
committed
Refactor to separate solver communication from decision process
So that `smt2_incremental_decision_proceduret` can be unit tested in isolation using a mock smt solver process.
1 parent 5f01e32 commit 3bc5ee4

File tree

7 files changed

+138
-35
lines changed

7 files changed

+138
-35
lines changed

src/goto-checker/solver_factory.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Author: Daniel Kroening, Peter Schrammel
3333
#include <solvers/sat/external_sat.h>
3434
#include <solvers/sat/satcheck.h>
3535
#include <solvers/smt2_incremental/smt2_incremental_decision_procedure.h>
36+
#include <solvers/smt2_incremental/smt_solver_process.h>
3637
#include <solvers/strings/string_refinement.h>
3738

3839
solver_factoryt::solver_factoryt(
@@ -330,10 +331,12 @@ std::unique_ptr<solver_factoryt::solvert>
330331
solver_factoryt::get_incremental_smt2(std::string solver_command)
331332
{
332333
no_beautification();
334+
auto solver_process = util_make_unique<smt_piped_solver_processt>(
335+
std::move(solver_command), message_handler);
333336

334337
return util_make_unique<solvert>(
335338
util_make_unique<smt2_incremental_decision_proceduret>(
336-
ns, std::move(solver_command), message_handler));
339+
ns, std::move(solver_process), message_handler));
337340
}
338341

339342
std::unique_ptr<solver_factoryt::solvert>

src/solvers/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ SRC = $(BOOLEFORCE_SRC) \
199199
smt2_incremental/smt_core_theory.cpp \
200200
smt2_incremental/smt_logics.cpp \
201201
smt2_incremental/smt_options.cpp \
202+
smt2_incremental/smt_solver_process.cpp \
202203
smt2_incremental/smt_sorts.cpp \
203204
smt2_incremental/smt_terms.cpp \
204205
smt2_incremental/smt_to_smt2_string.cpp \

src/solvers/smt2_incremental/smt2_incremental_decision_procedure.cpp

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
#include <solvers/smt2_incremental/convert_expr_to_smt.h>
66
#include <solvers/smt2_incremental/smt_commands.h>
77
#include <solvers/smt2_incremental/smt_core_theory.h>
8+
#include <solvers/smt2_incremental/smt_solver_process.h>
89
#include <solvers/smt2_incremental/smt_terms.h>
9-
#include <solvers/smt2_incremental/smt_to_smt2_string.h>
1010
#include <util/expr.h>
1111
#include <util/namespace.h>
1212
#include <util/range.h>
@@ -74,7 +74,7 @@ void smt2_incremental_decision_proceduret::define_dependent_functions(
7474
const smt_define_function_commandt function{
7575
symbol->name, {}, convert_expr_to_smt(symbol->value)};
7676
expression_identifiers.emplace(*symbol_expr, function.identifier());
77-
send_to_solver(function);
77+
solver_process->send(function);
7878
}
7979
else
8080
{
@@ -83,7 +83,7 @@ void smt2_incremental_decision_proceduret::define_dependent_functions(
8383
identifier, convert_type_to_smt_sort(symbol_expr->type())),
8484
{}};
8585
expression_identifiers.emplace(*symbol_expr, function.identifier());
86-
send_to_solver(function);
86+
solver_process->send(function);
8787
}
8888
}
8989
to_be_defined.pop();
@@ -92,16 +92,16 @@ void smt2_incremental_decision_proceduret::define_dependent_functions(
9292

9393
smt2_incremental_decision_proceduret::smt2_incremental_decision_proceduret(
9494
const namespacet &_ns,
95-
std::string _solver_command,
95+
std::unique_ptr<smt_base_solver_processt> _solver_process,
9696
message_handlert &message_handler)
9797
: ns{_ns},
98-
solver_command(std::move(_solver_command)),
9998
number_of_solver_calls{0},
100-
solver_process{split_string(solver_command, ' ', false, true)},
99+
solver_process(std::move(_solver_process)),
101100
log{message_handler}
102101
{
103-
send_to_solver(smt_set_option_commandt{smt_option_produce_modelst{true}});
104-
send_to_solver(smt_set_logic_commandt{
102+
solver_process->send(
103+
smt_set_option_commandt{smt_option_produce_modelst{true}});
104+
solver_process->send(smt_set_logic_commandt{
105105
smt_logic_quantifier_free_uninterpreted_functions_bit_vectorst{}});
106106
}
107107

@@ -119,7 +119,7 @@ void smt2_incremental_decision_proceduret::ensure_handle_for_expr_defined(
119119
smt_define_function_commandt function{
120120
"B" + std::to_string(handle_sequence()), {}, convert_expr_to_smt(expr)};
121121
expression_handle_identifiers.emplace(expr, function.identifier());
122-
send_to_solver(function);
122+
solver_process->send(function);
123123
}
124124

125125
exprt smt2_incremental_decision_proceduret::handle(const exprt &expr)
@@ -143,7 +143,7 @@ void smt2_incremental_decision_proceduret::print_assignment(
143143
std::string
144144
smt2_incremental_decision_proceduret::decision_procedure_text() const
145145
{
146-
return "incremental SMT2 solving via \"" + solver_command + "\"";
146+
return "incremental SMT2 solving via " + solver_process->description();
147147
}
148148

149149
std::size_t
@@ -169,7 +169,7 @@ void smt2_incremental_decision_proceduret::set_to(const exprt &expr, bool value)
169169
}();
170170
if(!value)
171171
converted_term = smt_core_theoryt::make_not(converted_term);
172-
send_to_solver(smt_assert_commandt{converted_term});
172+
solver_process->send(smt_assert_commandt{converted_term});
173173
}
174174

175175
void smt2_incremental_decision_proceduret::push(
@@ -196,17 +196,7 @@ void smt2_incremental_decision_proceduret::pop()
196196
decision_proceduret::resultt smt2_incremental_decision_proceduret::dec_solve()
197197
{
198198
++number_of_solver_calls;
199-
send_to_solver(smt_check_sat_commandt{});
200-
const auto result = solver_process.wait_receive();
201-
log.debug() << "Solver response - " << result << messaget::eom;
202-
UNIMPLEMENTED_FEATURE("parsing of solver response.");
203-
}
204-
205-
void smt2_incremental_decision_proceduret::send_to_solver(
206-
const smt_commandt &command)
207-
{
208-
const std::string command_string = smt_to_smt2_string(command);
209-
log.debug() << "Sending command to SMT2 solver - " << command_string
210-
<< messaget::eom;
211-
solver_process.send(command_string + "\n");
199+
solver_process->send(smt_check_sat_commandt{});
200+
const smt_responset result = solver_process->receive_response();
201+
UNIMPLEMENTED_FEATURE("handling solver response.");
212202
}

src/solvers/smt2_incremental/smt2_incremental_decision_procedure.h

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,30 @@
99
#include <solvers/smt2_incremental/smt_terms.h>
1010
#include <solvers/stack_decision_procedure.h>
1111
#include <util/message.h>
12-
#include <util/piped_process.h>
1312
#include <util/std_expr.h>
1413

14+
#include <memory>
1515
#include <unordered_map>
1616
#include <unordered_set>
1717

1818
class smt_commandt;
1919
class message_handlert;
2020
class namespacet;
21+
class smt_base_solver_processt;
2122

2223
class smt2_incremental_decision_proceduret final
2324
: public stack_decision_proceduret
2425
{
2526
public:
2627
/// \param _ns: Namespace for looking up the expressions which symbol_exprts
2728
/// relate to.
28-
/// \param solver_command:
29-
/// The command and arguments for invoking the smt2 solver.
29+
/// \param solver_process:
30+
/// The smt2 solver process communication interface.
3031
/// \param message_handler:
3132
/// The messaging system to be used for logging purposes.
3233
explicit smt2_incremental_decision_proceduret(
3334
const namespacet &_ns,
34-
std::string solver_command,
35+
std::unique_ptr<smt_base_solver_processt> solver_process,
3536
message_handlert &message_handler);
3637

3738
// Implementation of public decision_proceduret member functions.
@@ -50,21 +51,16 @@ class smt2_incremental_decision_proceduret final
5051
protected:
5152
// Implementation of protected decision_proceduret member function.
5253
resultt dec_solve() override;
53-
/// \brief Converts given SMT2 command to SMT2 string and sends it to the
54-
/// solver process.
55-
void send_to_solver(const smt_commandt &command);
5654
/// \brief Defines any functions which \p expr depends on, which have not yet
5755
/// been defined, along with their dependencies in turn.
5856
void define_dependent_functions(const exprt &expr);
5957
void ensure_handle_for_expr_defined(const exprt &expr);
6058

6159
const namespacet &ns;
6260

63-
/// This is where we store the solver command for reporting the solver used.
64-
std::string solver_command;
6561
size_t number_of_solver_calls;
6662

67-
piped_processt solver_process;
63+
std::unique_ptr<smt_base_solver_processt> solver_process;
6864
messaget log;
6965

7066
class sequencet
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Author: Diffblue Ltd.
2+
3+
#ifndef CPROVER_SOLVERS_SMT2_INCREMENTAL_SMT_RESPONSES_H
4+
#define CPROVER_SOLVERS_SMT2_INCREMENTAL_SMT_RESPONSES_H
5+
6+
#include <util/irep.h>
7+
8+
class smt_responset : protected irept
9+
{
10+
public:
11+
// smt_responset does not support the notion of an empty / null state. Use
12+
// optionalt<smt_responset> instead if an empty response is required.
13+
smt_responset() = delete;
14+
15+
using irept::pretty;
16+
17+
protected:
18+
using irept::irept;
19+
};
20+
21+
#endif // CPROVER_SOLVERS_SMT2_INCREMENTAL_SMT_RESPONSES_H
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Author: Diffblue Ltd.
2+
3+
#include <solvers/smt2_incremental/smt_solver_process.h>
4+
5+
#include <solvers/smt2_incremental/smt_to_smt2_string.h>
6+
#include <util/invariant.h>
7+
#include <util/string_utils.h>
8+
9+
smt_piped_solver_processt::smt_piped_solver_processt(
10+
std::string command_line,
11+
message_handlert &message_handler)
12+
: command_line_description{"\"" + command_line + "\""},
13+
process{split_string(command_line, ' ', false, true)},
14+
log{message_handler}
15+
{
16+
}
17+
18+
const std::string &smt_piped_solver_processt::description()
19+
{
20+
return command_line_description;
21+
}
22+
23+
void smt_piped_solver_processt::send(const smt_commandt &smt_command)
24+
{
25+
const std::string command_string = smt_to_smt2_string(smt_command);
26+
log.debug() << "Sending command to SMT2 solver - " << command_string
27+
<< messaget::eom;
28+
process.send(command_string + "\n");
29+
}
30+
31+
smt_responset smt_piped_solver_processt::receive_response()
32+
{
33+
const auto response_text = process.wait_receive();
34+
log.debug() << "Solver response - " << response_text << messaget::eom;
35+
UNIMPLEMENTED_FEATURE("parsing of solver response.");
36+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Author: Diffblue Ltd.
2+
3+
#ifndef CPROVER_SOLVERS_SMT2_INCREMENTAL_SMT_SOLVER_PROCESS_H
4+
#define CPROVER_SOLVERS_SMT2_INCREMENTAL_SMT_SOLVER_PROCESS_H
5+
6+
class smt_commandt;
7+
8+
#include <solvers/smt2_incremental/smt_responses.h>
9+
#include <util/message.h>
10+
#include <util/piped_process.h>
11+
12+
#include <string>
13+
14+
class smt_base_solver_processt
15+
{
16+
public:
17+
virtual const std::string &description() = 0;
18+
19+
/// \brief Converts given SMT2 command to SMT2 string and sends it to the
20+
/// solver process.
21+
virtual void send(const smt_commandt &command) = 0;
22+
23+
virtual smt_responset receive_response() = 0;
24+
25+
virtual ~smt_base_solver_processt() = default;
26+
};
27+
28+
class smt_piped_solver_processt : public smt_base_solver_processt
29+
{
30+
public:
31+
/// \param command_line:
32+
/// The command and arguments for invoking the smt2 solver.
33+
/// \param message_handler:
34+
/// The messaging system to be used for logging purposes.
35+
smt_piped_solver_processt(
36+
std::string command_line,
37+
message_handlert &message_handler);
38+
39+
const std::string &description() override;
40+
41+
void send(const smt_commandt &smt_command) override;
42+
43+
smt_responset receive_response() override;
44+
45+
~smt_piped_solver_processt() override = default;
46+
47+
protected:
48+
/// The command line used to start the process.
49+
std::string command_line_description;
50+
/// The raw solver sub process.
51+
piped_processt process;
52+
/// For debug printing.
53+
messaget log;
54+
};
55+
56+
#endif // CPROVER_SOLVERS_SMT2_INCREMENTAL_SMT_SOLVER_PROCESS_H

0 commit comments

Comments
 (0)