File: eval.cpp

package info (click to toggle)
cbmc 6.6.0-4
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 153,852 kB
  • sloc: cpp: 386,459; ansic: 114,466; java: 28,405; python: 6,003; yacc: 4,552; makefile: 4,041; lex: 2,487; xml: 2,388; sh: 2,050; perl: 557; pascal: 184; javascript: 163; ada: 36
file content (102 lines) | stat: -rw-r--r-- 3,313 bytes parent folder | download
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright 2016-2020 Diffblue Limited.

#include <util/arith_tools.h>
#include <util/bitvector_types.h>
#include <util/namespace.h>
#include <util/std_expr.h>
#include <util/symbol_table.h>

#include <analyses/variable-sensitivity/abstract_environment.h>
#include <analyses/variable-sensitivity/context_abstract_object.h>
#include <analyses/variable-sensitivity/interval_abstract_value.h>
#include <analyses/variable-sensitivity/variable_sensitivity_object_factory.h>
#include <testing-utils/use_catch.h>

static symbolt simple_symbol(const irep_idt &identifier, const typet &type)
{
  symbolt b1{identifier, type, irep_idt{}};
  b1.base_name = b1.pretty_name = identifier;
  return b1;
}

SCENARIO(
  "eval",
  "[core][analyses][variable-sensitivity][interval_abstract_value]")
{
  GIVEN("An environment with intervals domain")
  {
    auto object_factory = variable_sensitivity_object_factoryt::configured_with(
      vsd_configt::intervals());
    abstract_environmentt environment(object_factory);
    environment.make_top(); // Domains are bottom on construction

    symbol_tablet symbol_table;
    namespacet ns{symbol_table};

    signedbv_typet number_type{32};
    const auto &b1 = simple_symbol("b1", number_type);
    symbol_table.add(b1);

    WHEN("Evaluating expression with an unknown value")
    {
      // b1 == 0 ? 1 : 0
      if_exprt condition{
        equal_exprt{b1.symbol_expr(), from_integer(0, number_type)},
        from_integer(1, number_type),
        from_integer(0, number_type)};

      const auto result = environment.eval(condition, ns);

      THEN("Should get a wrapped range of 0..1")
      {
        REQUIRE(
          std::dynamic_pointer_cast<const context_abstract_objectt>(result));
        REQUIRE_FALSE(result->is_top());
        REQUIRE_FALSE(result->is_bottom());
        auto result_as_interval =
          std::dynamic_pointer_cast<const interval_abstract_valuet>(
            result->unwrap_context());
        REQUIRE(result_as_interval);
        REQUIRE(
          result_as_interval->to_interval().get_lower() ==
          from_integer(0, number_type));
        REQUIRE(
          result_as_interval->to_interval().get_upper() ==
          from_integer(1, number_type));
      }

      WHEN("Assigning the symbol a value")
      {
        // b1 = 0
        environment.assign(
          b1.symbol_expr(),
          object_factory->get_abstract_object(
            number_type,
            false,
            false,
            from_integer(0, number_type),
            environment,
            ns),
          ns);

        const auto result_after_assignment = environment.eval(condition, ns);

        THEN("Should get a wrapped interval of one element")
        {
          REQUIRE(std::dynamic_pointer_cast<const context_abstract_objectt>(
            result_after_assignment));
          const auto unwrapped =
            std::dynamic_pointer_cast<const context_abstract_objectt>(
              result_after_assignment)
              ->unwrap_context();
          auto result_as_interval =
            std::dynamic_pointer_cast<const interval_abstract_valuet>(
              unwrapped);
          REQUIRE(result_as_interval);
          REQUIRE(
            result_as_interval->to_constant() == from_integer(1, number_type));
        }
      }
    }
  }
}