Skip to content

Commit c4486f1

Browse files
authored
Merge pull request diffblue#1552 from thk123/feature/goto-functions-utilities
[TG-496] Add Goto function unit test utilities
2 parents cd1258a + 9cb4569 commit c4486f1

File tree

5 files changed

+217
-2
lines changed

5 files changed

+217
-2
lines changed

unit/testing-utils/Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ SRC = \
22
c_to_expr.cpp \
33
load_java_class.cpp \
44
require_expr.cpp \
5+
require_goto_statements.cpp \
6+
require_symbol.cpp \
57
require_type.cpp \
68
# Empty last line (please keep above list sorted!)
79

unit/testing-utils/load_java_class.cpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@
2626
symbol_tablet load_java_class(
2727
const std::string &java_class_name,
2828
const std::string &class_path)
29+
{
30+
return load_java_class(
31+
java_class_name, class_path, new_java_bytecode_language());
32+
}
33+
34+
symbol_tablet load_java_class(
35+
const std::string &java_class_name,
36+
const std::string &class_path,
37+
std::unique_ptr<languaget> java_lang)
2938
{
3039
// We don't expect the .class suffix to allow us to check the name of the
3140
// class
@@ -39,8 +48,6 @@ symbol_tablet load_java_class(
3948

4049
symbol_tablet new_symbol_table;
4150

42-
std::unique_ptr<languaget>java_lang(new_java_bytecode_language());
43-
4451
std::istringstream java_code_stream("ignored");
4552
null_message_handlert message_handler;
4653

unit/testing-utils/load_java_class.h

+7
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,16 @@
1414
#define CPROVER_TESTING_UTILS_LOAD_JAVA_CLASS_H
1515

1616
#include <util/symbol_table.h>
17+
#include <util/language.h>
18+
#include <goto-programs/goto_model.h>
1719

1820
symbol_tablet load_java_class(
1921
const std::string &java_class_name,
2022
const std::string &class_path);
2123

24+
symbol_tablet load_java_class(
25+
const std::string &java_class_name,
26+
const std::string &class_path,
27+
std::unique_ptr<languaget> java_lang);
28+
2229
#endif // CPROVER_TESTING_UTILS_LOAD_JAVA_CLASS_H
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*******************************************************************\
2+
3+
Module: Unit test utilities
4+
5+
Author: DiffBlue Limited. All rights reserved.
6+
7+
\*******************************************************************/
8+
9+
#include "require_goto_statements.h"
10+
#include "catch.hpp"
11+
12+
#include <algorithm>
13+
#include <util/expr_iterator.h>
14+
15+
/// Expand value of a function to include all child codets
16+
/// \param function_value: The value of the function (e.g. got by looking up
17+
/// the function in the symbol table and getting the value)
18+
/// \return: All ID_code statements in the tree rooted at \p function_value
19+
std::vector<codet>
20+
require_goto_statements::get_all_statements(const exprt &function_value)
21+
{
22+
std::vector<codet> statements;
23+
for(auto sub_expression_it = function_value.depth_begin();
24+
sub_expression_it != function_value.depth_end();
25+
++sub_expression_it)
26+
{
27+
if(sub_expression_it->id() == ID_code)
28+
{
29+
statements.push_back(to_code(*sub_expression_it));
30+
}
31+
}
32+
33+
return statements;
34+
}
35+
36+
/// Find assignment statements of the form \p structure_name.\component_name =
37+
/// \param statements: The statements to look through
38+
/// \param structure_name: The name of variable of type struct
39+
/// \param component_name: The name of the component that should be assigned
40+
/// \return: All the assignments to that component.
41+
std::vector<code_assignt>
42+
require_goto_statements::find_struct_component_assignments(
43+
const std::vector<codet> &statements,
44+
const irep_idt &structure_name,
45+
const irep_idt &component_name)
46+
{
47+
std::vector<code_assignt> component_assignments;
48+
49+
for(const auto &assignment : statements)
50+
{
51+
if(assignment.get_statement() == ID_assign)
52+
{
53+
const code_assignt &code_assign = to_code_assign(assignment);
54+
55+
if(code_assign.lhs().id() == ID_member)
56+
{
57+
const auto &member_expr = to_member_expr(code_assign.lhs());
58+
const auto &symbol = member_expr.symbol();
59+
60+
if(
61+
symbol.get_identifier() == structure_name &&
62+
member_expr.get_component_name() == component_name)
63+
{
64+
component_assignments.push_back(code_assign);
65+
}
66+
}
67+
}
68+
}
69+
return component_assignments;
70+
}
71+
72+
/// For a given variable name, gets the assignments to it in the provided
73+
/// instructions.
74+
/// \param pointer_name: The name of the variable
75+
/// \param instructions: The instructions to look through
76+
/// \return: A structure that contains the null assignment if found, and a
77+
/// vector of all other assignments
78+
require_goto_statements::pointer_assignment_locationt
79+
require_goto_statements::find_pointer_assignments(
80+
const irep_idt &pointer_name,
81+
const std::vector<codet> &instructions)
82+
{
83+
pointer_assignment_locationt locations;
84+
for(const codet &statement : instructions)
85+
{
86+
if(statement.get_statement() == ID_assign)
87+
{
88+
const code_assignt &code_assign = to_code_assign(statement);
89+
if(
90+
code_assign.lhs().id() == ID_symbol &&
91+
to_symbol_expr(code_assign.lhs()).get_identifier() == pointer_name)
92+
{
93+
if(
94+
code_assign.rhs() ==
95+
null_pointer_exprt(to_pointer_type(code_assign.lhs().type())))
96+
{
97+
locations.null_assignment = code_assign;
98+
}
99+
else
100+
{
101+
locations.non_null_assignments.push_back(code_assign);
102+
}
103+
}
104+
}
105+
}
106+
107+
return locations;
108+
}
109+
110+
/// Find the declaration of the specific variable.
111+
/// \param variable_name: The name of the variable.
112+
/// \param entry_point_instructions: The statements to look through
113+
/// \return The declaration statement corresponding to that variable
114+
/// \throws no_decl_found_exceptiont if no declaration of the specific
115+
/// variable is found
116+
const code_declt &require_goto_statements::require_declaration_of_name(
117+
const irep_idt &variable_name,
118+
const std::vector<codet> &entry_point_instructions)
119+
{
120+
for(const auto &statement : entry_point_instructions)
121+
{
122+
if(statement.get_statement() == ID_decl)
123+
{
124+
const auto &decl_statement = to_code_decl(statement);
125+
126+
if(decl_statement.get_identifier() == variable_name)
127+
{
128+
return decl_statement;
129+
}
130+
}
131+
}
132+
throw no_decl_found_exceptiont(variable_name.c_str());
133+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*******************************************************************\
2+
3+
Module: Unit test utilities
4+
5+
Author: DiffBlue Limited. All rights reserved.
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Utilties for inspecting goto functions
11+
12+
#include <util/irep.h>
13+
#include <util/expr.h>
14+
#include <util/optional.h>
15+
#include <util/std_code.h>
16+
#include <util/std_types.h>
17+
#include <goto-programs/goto_program.h>
18+
19+
#ifndef CPROVER_TESTING_UTILS_REQUIRE_GOTO_STATEMENTS_H
20+
#define CPROVER_TESTING_UTILS_REQUIRE_GOTO_STATEMENTS_H
21+
22+
// NOLINTNEXTLINE(readability/namespace)
23+
namespace require_goto_statements
24+
{
25+
struct pointer_assignment_locationt
26+
{
27+
optionalt<code_assignt> null_assignment;
28+
std::vector<code_assignt> non_null_assignments;
29+
};
30+
31+
class no_decl_found_exceptiont : public std::exception
32+
{
33+
public:
34+
explicit no_decl_found_exceptiont(const std::string &var_name)
35+
: _varname(var_name)
36+
{
37+
}
38+
39+
virtual const char *what() const throw()
40+
{
41+
std::ostringstream stringStream;
42+
stringStream << "Failed to find declaration for: " << _varname;
43+
return stringStream.str().c_str();
44+
}
45+
46+
private:
47+
std::string _varname;
48+
};
49+
50+
std::vector<code_assignt> find_struct_component_assignments(
51+
const std::vector<codet> &statements,
52+
const irep_idt &structure_name,
53+
const irep_idt &component_name);
54+
55+
std::vector<codet> get_all_statements(const exprt &function_value);
56+
57+
pointer_assignment_locationt find_pointer_assignments(
58+
const irep_idt &pointer_name,
59+
const std::vector<codet> &instructions);
60+
61+
const code_declt &require_declaration_of_name(
62+
const irep_idt &variable_name,
63+
const std::vector<codet> &entry_point_instructions);
64+
}
65+
66+
#endif // CPROVER_TESTING_UTILS_REQUIRE_GOTO_STATEMENTS_H

0 commit comments

Comments
 (0)