Skip to content

Commit 371686b

Browse files
author
Matthias Güdemann
committed
Add unit test
The unit test checks whether the correct function is called. It is therefor more precise than the regression test `virtual10`.
1 parent ade4cf4 commit 371686b

File tree

8 files changed

+155
-0
lines changed

8 files changed

+155
-0
lines changed
104 Bytes
Binary file not shown.
104 Bytes
Binary file not shown.
312 Bytes
Binary file not shown.
364 Bytes
Binary file not shown.
452 Bytes
Binary file not shown.
327 Bytes
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
interface A {
2+
public int f();
3+
}
4+
interface B {
5+
public int g();
6+
}
7+
8+
class O {
9+
public String toString() {
10+
return "O";
11+
}
12+
}
13+
14+
class D extends O implements A, B {
15+
public int f() {
16+
return 0;
17+
}
18+
public int g() {
19+
return 1;
20+
}
21+
}
22+
23+
class C extends D {
24+
public String toString() {
25+
return "C";
26+
}
27+
}
28+
29+
class E {
30+
C c;
31+
D d;
32+
String f(Object o) {
33+
return o.toString();
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*******************************************************************\
2+
3+
Module: Unit tests for java_types
4+
5+
Author: DiffBlue Limited. All rights reserved.
6+
7+
\*******************************************************************/
8+
9+
#include <testing-utils/catch.hpp>
10+
#include <testing-utils/load_java_class.h>
11+
#include <testing-utils/require_goto_statements.h>
12+
13+
#include <goto-programs/goto_convert_functions.h>
14+
#include <goto-programs/remove_virtual_functions.h>
15+
#include <util/config.h>
16+
17+
#include <util/std_expr.h>
18+
19+
void check_function_call(
20+
const equal_exprt &eq_expr,
21+
const irep_idt &class_name,
22+
const irep_idt &function_name,
23+
const goto_programt::targetst &targets)
24+
{
25+
REQUIRE(eq_expr.op0().id() == ID_constant);
26+
REQUIRE(eq_expr.op0().type().id() == ID_string);
27+
REQUIRE(to_constant_expr(eq_expr.op0()).get_value() == class_name);
28+
29+
REQUIRE(targets.size() == 1);
30+
31+
for(const auto &target : targets)
32+
{
33+
REQUIRE(target->type == goto_program_instruction_typet::FUNCTION_CALL);
34+
const code_function_callt call = to_code_function_call(target->code);
35+
REQUIRE(call.function().id() == ID_symbol);
36+
REQUIRE(to_symbol_expr(call.function()).get_identifier() == function_name);
37+
}
38+
}
39+
40+
SCENARIO(
41+
"load class with virtual method call, resolve to all valid calls",
42+
"[core][java_bytecode][virtual_functions]")
43+
{
44+
config.set_arch("none");
45+
GIVEN("A class with a call to java.lang.Object.toString()")
46+
{
47+
const symbol_tablet &symbol_table =
48+
load_java_class("E", "./java_bytecode/java_virtual_functions", "E.f");
49+
50+
const std::string function_name =
51+
"java::E.f:(Ljava/lang/Object;)Ljava/lang/String;";
52+
53+
WHEN("The entry point function is generated")
54+
{
55+
symbol_tablet new_table(symbol_table);
56+
null_message_handlert null_output;
57+
goto_functionst new_goto_functions;
58+
goto_convert(new_table, new_goto_functions, null_output);
59+
remove_virtual_functions(new_table, new_goto_functions);
60+
61+
bool found_function = false;
62+
for(const auto &fun : new_goto_functions.function_map)
63+
{
64+
if(fun.first == function_name)
65+
{
66+
const goto_programt &goto_program = fun.second.body;
67+
found_function = true;
68+
for(const auto &instruction : goto_program.instructions)
69+
{
70+
// There should be two guarded GOTOs with non-constant guards. One
71+
// branching for class C and one for class D or O.
72+
if(instruction.type == goto_program_instruction_typet::GOTO)
73+
{
74+
if(instruction.guard.id() == ID_equal)
75+
{
76+
THEN("Class C should call its specific method")
77+
{
78+
const equal_exprt &eq_expr = to_equal_expr(instruction.guard);
79+
check_function_call(
80+
eq_expr,
81+
"java::C",
82+
"java::C.toString:()Ljava/lang/String;",
83+
instruction.targets);
84+
}
85+
}
86+
87+
else if(instruction.guard.id() == ID_or)
88+
{
89+
THEN("Classes D and O should both call O.toString()")
90+
{
91+
const or_exprt &disjunction = to_or_expr(instruction.guard);
92+
REQUIRE(
93+
(disjunction.op0().id() == ID_equal &&
94+
disjunction.op1().id() == ID_equal));
95+
const equal_exprt &eq_expr0 =
96+
to_equal_expr(disjunction.op0());
97+
const equal_exprt &eq_expr1 =
98+
to_equal_expr(disjunction.op1());
99+
100+
check_function_call(
101+
eq_expr0,
102+
"java::D",
103+
"java::O.toString:()Ljava/lang/String;",
104+
instruction.targets);
105+
check_function_call(
106+
eq_expr1,
107+
"java::O",
108+
"java::O.toString:()Ljava/lang/String;",
109+
instruction.targets);
110+
}
111+
}
112+
}
113+
}
114+
}
115+
}
116+
117+
REQUIRE(found_function);
118+
}
119+
}
120+
}

0 commit comments

Comments
 (0)