|
9 | 9 | #include <solvers/smt2_incremental/smt_solver_process.h>
|
10 | 10 | #include <solvers/smt2_incremental/smt_sorts.h>
|
11 | 11 | #include <solvers/smt2_incremental/smt_terms.h>
|
| 12 | +#include <testing-utils/invariant.h> |
12 | 13 | #include <util/arith_tools.h>
|
13 | 14 | #include <util/bitvector_types.h>
|
14 | 15 | #include <util/exception_utils.h>
|
@@ -85,6 +86,14 @@ class smt_mock_solver_processt : public smt_base_solver_processt
|
85 | 86 | ~smt_mock_solver_processt() override = default;
|
86 | 87 | };
|
87 | 88 |
|
| 89 | +/// \brief Data structures and their initialisation shared between tests. |
| 90 | +/// \details |
| 91 | +/// Instantiates a `smt2_incremental_decision_proceduret` using a mock of the |
| 92 | +/// solver process to direct communication with the solver to collections of |
| 93 | +/// `sent_commands` and `mock_responses`. The `mock_respones` must be |
| 94 | +/// populated by the test, before the decision procedure expects them. The |
| 95 | +/// `sent_commands` should be checked by the test after the decision procedure |
| 96 | +/// has sent them. |
88 | 97 | struct decision_procedure_test_environmentt final
|
89 | 98 | {
|
90 | 99 | void send(const smt_commandt &smt_command);
|
@@ -378,3 +387,112 @@ TEST_CASE(
|
378 | 387 | "SMT solver does not support given command."});
|
379 | 388 | }
|
380 | 389 | }
|
| 390 | + |
| 391 | +TEST_CASE( |
| 392 | + "smt2_incremental_decision_proceduret getting values back from solver.", |
| 393 | + "[core][smt2_incremental]") |
| 394 | +{ |
| 395 | + decision_procedure_test_environmentt test{}; |
| 396 | + const symbolt foo = make_test_symbol("foo", signedbv_typet{16}); |
| 397 | + const smt_identifier_termt foo_term{"foo", smt_bit_vector_sortt{16}}; |
| 398 | + const exprt expr_42 = from_integer({42}, signedbv_typet{16}); |
| 399 | + const smt_bit_vector_constant_termt term_42{42, 16}; |
| 400 | + SECTION("Set \"foo\" identifier and solve.") |
| 401 | + { |
| 402 | + test.sent_commands.clear(); |
| 403 | + const exprt equal_42 = equal_exprt{foo.symbol_expr(), expr_42}; |
| 404 | + test.procedure.set_to(equal_42, true); |
| 405 | + test.mock_responses.push_back(smt_check_sat_responset{smt_sat_responset{}}); |
| 406 | + test.procedure(); |
| 407 | + REQUIRE( |
| 408 | + test.sent_commands == |
| 409 | + std::vector<smt_commandt>{ |
| 410 | + smt_declare_function_commandt{foo_term, {}}, |
| 411 | + smt_assert_commandt{smt_core_theoryt::equal(foo_term, term_42)}, |
| 412 | + smt_check_sat_commandt{}}); |
| 413 | + SECTION("Get \"foo\" value back") |
| 414 | + { |
| 415 | + test.sent_commands.clear(); |
| 416 | + test.mock_responses.push_back( |
| 417 | + smt_get_value_responset{{{foo_term, term_42}}}); |
| 418 | + REQUIRE(test.procedure.get(foo.symbol_expr()) == expr_42); |
| 419 | + REQUIRE( |
| 420 | + test.sent_commands == |
| 421 | + std::vector<smt_commandt>{smt_get_value_commandt{foo_term}}); |
| 422 | + } |
| 423 | + SECTION("Get value of non-set symbol") |
| 424 | + { |
| 425 | + // smt2_incremental_decision_proceduret is used this way when cbmc is |
| 426 | + // invoked with the combination of `--trace` and `--slice-formula`. |
| 427 | + test.sent_commands.clear(); |
| 428 | + const exprt bar = |
| 429 | + make_test_symbol("bar", signedbv_typet{16}).symbol_expr(); |
| 430 | + REQUIRE(test.procedure.get(bar) == bar); |
| 431 | + REQUIRE(test.sent_commands.empty()); |
| 432 | + } |
| 433 | + SECTION("Get value of type less symbol back") |
| 434 | + { |
| 435 | + // smt2_incremental_decision_proceduret is used this way as part of |
| 436 | + // building the goto trace, to get the partial order concurrency clock |
| 437 | + // values. |
| 438 | + test.sent_commands.clear(); |
| 439 | + const symbol_exprt baz = symbol_exprt::typeless("baz"); |
| 440 | + REQUIRE(test.procedure.get(baz) == baz); |
| 441 | + REQUIRE(test.sent_commands.empty()); |
| 442 | + } |
| 443 | + SECTION("Get value of trivially solved expression") |
| 444 | + { |
| 445 | + test.sent_commands.clear(); |
| 446 | + const smt_termt not_true_term = |
| 447 | + smt_core_theoryt::make_not(smt_bool_literal_termt{true}); |
| 448 | + test.mock_responses.push_back(smt_get_value_responset{ |
| 449 | + {{not_true_term, smt_bool_literal_termt{false}}}}); |
| 450 | + REQUIRE(test.procedure.get(not_exprt{true_exprt{}}) == false_exprt{}); |
| 451 | + REQUIRE( |
| 452 | + test.sent_commands == |
| 453 | + std::vector<smt_commandt>{smt_get_value_commandt{not_true_term}}); |
| 454 | + } |
| 455 | + SECTION("Invariant violated due to expression in unexpected form.") |
| 456 | + { |
| 457 | + const mult_exprt unexpected{foo.symbol_expr(), from_integer(2, foo.type)}; |
| 458 | + const cbmc_invariants_should_throwt invariants_throw; |
| 459 | + REQUIRE_THROWS_MATCHES( |
| 460 | + test.procedure.get(unexpected), |
| 461 | + invariant_failedt, |
| 462 | + invariant_failure_containing( |
| 463 | + "Unhandled expressions are expected to be symbols")); |
| 464 | + } |
| 465 | + SECTION("Error handling of mismatched response.") |
| 466 | + { |
| 467 | + test.sent_commands.clear(); |
| 468 | + const smt_check_sat_responset unexpected{smt_sat_responset{}}; |
| 469 | + test.mock_responses.push_back(unexpected); |
| 470 | + REQUIRE_THROWS_MATCHES( |
| 471 | + test.procedure.get(foo.symbol_expr()), |
| 472 | + analysis_exceptiont, |
| 473 | + analysis_execption_with_messaget{ |
| 474 | + "Expected get-value response from solver, but received - " + |
| 475 | + unexpected.pretty()}); |
| 476 | + REQUIRE( |
| 477 | + test.sent_commands == |
| 478 | + std::vector<smt_commandt>{smt_get_value_commandt{foo_term}}); |
| 479 | + } |
| 480 | + SECTION("Error handling of multiple responses.") |
| 481 | + { |
| 482 | + test.sent_commands.clear(); |
| 483 | + const smt_get_value_responset unexpected{ |
| 484 | + {{foo_term, term_42}, {foo_term, term_42}}}; |
| 485 | + test.mock_responses.push_back(unexpected); |
| 486 | + REQUIRE_THROWS_MATCHES( |
| 487 | + test.procedure.get(foo.symbol_expr()), |
| 488 | + analysis_exceptiont, |
| 489 | + analysis_execption_with_messaget{ |
| 490 | + "Expected single valuation pair in get-value response from solver, " |
| 491 | + "but received multiple pairs - " + |
| 492 | + unexpected.pretty()}); |
| 493 | + REQUIRE( |
| 494 | + test.sent_commands == |
| 495 | + std::vector<smt_commandt>{smt_get_value_commandt{foo_term}}); |
| 496 | + } |
| 497 | + } |
| 498 | +} |
0 commit comments