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 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
/*******************************************************************\
Module: Unit tests for java_static_initializers
Author: Diffblue Ltd.
\*******************************************************************/
#include <util/arith_tools.h>
#include <util/json.h>
#include <util/symbol_table.h>
#include <goto-programs/goto_instruction_code.h>
#include <java_bytecode/ci_lazy_methods_needed.h>
#include <java_bytecode/code_with_references.h> // IWYU pragma: keep
#include <java_bytecode/java_static_initializers.h>
#include <java_bytecode/java_types.h>
#include <java_bytecode/java_utils.h>
#include <testing-utils/expr_query.h>
#include <testing-utils/use_catch.h>
SCENARIO("is_clinit_function", "[core][java_static_initializers]")
{
GIVEN("A function id that represents a clinit")
{
THEN("is_clinit_function should return true.")
{
const std::string input = "com.something.package.TestClass.<clinit>:()V";
REQUIRE(is_clinit_function(input));
}
}
GIVEN("A function id that does not represent a clinit")
{
THEN("is_clinit_function should return false.")
{
const std::string input =
"com.something.package.TestClass.<notclinit>:()V";
REQUIRE_FALSE(is_clinit_function(input));
}
}
}
SCENARIO(
"is_user_specified_clinit_function",
"[core][java_static_initializers]")
{
GIVEN("A function id that represents a user-specified clinit")
{
THEN("is_user_specified_clinit_function should return true.")
{
const std::string input =
"com.something.package.TestClass.<user_specified_clinit>";
REQUIRE(is_user_specified_clinit_function(input));
}
}
GIVEN("A function id that does not represent a user-specified clinit")
{
THEN("is_clinit_function should return false.")
{
const std::string input = "com.something.package.TestClass::not_it";
REQUIRE_FALSE(is_user_specified_clinit_function(input));
}
}
}
SCENARIO("get_user_specified_clinit_body", "[core][java_static_initializers]")
{
json_objectt static_values_json{};
symbol_tablet symbol_table;
const std::size_t max_user_array_length = 100;
std::unordered_map<std::string, object_creation_referencet> references;
std::unordered_multimap<irep_idt, symbolt> class_to_declared_symbols;
GIVEN(
"A class which has no entry in the JSON object but a clinit defined "
"in the symbol table")
{
symbolt clinit_symbol{"java::TestClass.<clinit>:()V", typet{}, ID_java};
symbol_table.insert(clinit_symbol);
const code_blockt clinit_body = get_user_specified_clinit_body(
"java::TestClass",
static_values_json,
symbol_table,
{},
max_user_array_length,
references,
class_to_declared_symbols);
THEN("User provided clinit body is composed of one call to clinit")
{
const exprt function_called =
make_query(clinit_body)[0].as<code_function_callt>().get().function();
REQUIRE(
make_query(function_called).as<symbol_exprt>().get().get_identifier() ==
clinit_symbol.name);
}
}
GIVEN("A class which has no entry in the JSON object and no clinit defined")
{
const auto clinit_body = get_user_specified_clinit_body(
"java::TestClass",
static_values_json,
symbol_table,
{},
max_user_array_length,
references,
class_to_declared_symbols);
THEN("User provided clinit body is empty")
{
REQUIRE(clinit_body == code_blockt{});
}
}
GIVEN(
"A class which has an entry in the JSON object but no clinit defined "
"in the symbol table")
{
static_values_json["TestClass"] = [] {
json_objectt entry{};
entry["field_name"] = json_numbert{"42"};
return entry;
}();
const code_blockt clinit_body = get_user_specified_clinit_body(
"java::TestClass",
static_values_json,
symbol_table,
{},
max_user_array_length,
references,
class_to_declared_symbols);
THEN("User provided clinit body is empty")
{
REQUIRE(clinit_body == code_blockt{});
}
}
GIVEN("A class which has a static number in the provided JSON")
{
static_values_json["TestClass"] = [] {
json_objectt entry{};
entry["field_name"] = json_numbert{"42"};
return entry;
}();
class_to_declared_symbols.emplace("java::TestClass", [] {
symbolt field_symbol{"field_name_for_codet", java_int_type(), ID_java};
field_symbol.base_name = "field_name";
field_symbol.is_static_lifetime = true;
return field_symbol;
}());
symbol_table.insert([] {
symbolt clinit_symbol{"java::TestClass.<clinit>:()V", typet{}, ID_java};
set_declaring_class(clinit_symbol, "java::TestClass");
return clinit_symbol;
}());
symbol_table.insert(symbolt{
"java::TestClass",
[] {
java_class_typet type;
type.components().emplace_back("field_name", java_int_type());
return type;
}(),
ID_java});
const auto clinit_body = get_user_specified_clinit_body(
"java::TestClass",
static_values_json,
symbol_table,
{},
max_user_array_length,
references,
class_to_declared_symbols);
THEN("User provided clinit body set the field to the given value")
{
auto assignment = make_query(clinit_body)[0].as<code_assignt>().get();
REQUIRE(
make_query(assignment.lhs())
.as<symbol_exprt>()
.get()
.get_identifier() == "field_name_for_codet");
REQUIRE(assignment.rhs() == from_integer(42, java_int_type()));
}
}
}
|