8
8
\*******************************************************************/
9
9
10
10
#include < testing-utils/catch.hpp>
11
- #include < java- testing-utils/load_java_class.h>
11
+ #include < testing-utils/load_java_class.h>
12
12
13
13
#include < goto-programs/goto_convert_functions.h>
14
14
#include < goto-programs/remove_virtual_functions.h>
@@ -29,9 +29,12 @@ void validate_method_removal(
29
29
{
30
30
bool method_removed = true , replacement_nondet_exists = false ;
31
31
32
- // Quick loop to check that our method call has been replaced.
32
+ // Loop over our instructions to make sure the nondet java method call has
33
+ // been removed and that we can find an assignment/return with a nondet
34
+ // as it's right-hand side.
33
35
for (const auto &inst : instructions)
34
36
{
37
+ // Check that our NONDET(<type>) exists on a rhs somewhere.
35
38
if (inst.is_assign ())
36
39
{
37
40
const code_assignt &assignment = to_code_assign (inst.code );
@@ -45,6 +48,21 @@ void validate_method_removal(
45
48
}
46
49
}
47
50
51
+ if (inst.is_return ())
52
+ {
53
+ const code_returnt &ret_expr = to_code_return (inst.code );
54
+ if (ret_expr.return_value ().id () == ID_side_effect)
55
+ {
56
+ const side_effect_exprt &see =
57
+ to_side_effect_expr (ret_expr.return_value ());
58
+ if (see.get_statement () == ID_nondet)
59
+ {
60
+ replacement_nondet_exists = true ;
61
+ }
62
+ }
63
+ }
64
+
65
+ // And check to see that our nondet method call has been removed.
48
66
if (inst.is_function_call ())
49
67
{
50
68
const code_function_callt &function_call =
@@ -70,57 +88,151 @@ void validate_method_removal(
70
88
REQUIRE (replacement_nondet_exists);
71
89
}
72
90
73
- TEST_CASE (
74
- " Load class with a generated java nondet method call, run remove returns "
75
- " both before and after the nondet statements have been removed, check "
76
- " results are as expected." ,
91
+ void load_and_test_method (
92
+ const std::string &method_signature,
93
+ goto_functionst &functions,
94
+ journalling_symbol_tablet &symbol_table)
95
+ {
96
+ // Find the method under test.
97
+ const std::string function_name = " java::Main." + method_signature;
98
+ goto_functionst::goto_functiont &goto_function =
99
+ functions.function_map .at (function_name);
100
+
101
+ goto_model_functiont model_function (
102
+ symbol_table, functions, function_name, goto_function);
103
+
104
+ // Emulate some of the passes that we'd normally do before replace_java_nondet
105
+ // is called.
106
+ remove_instanceof (goto_function, symbol_table);
107
+
108
+ remove_virtual_functions (model_function);
109
+
110
+ // Then test both situations.
111
+ THEN (
112
+ " Code should work when remove returns is called before "
113
+ " replace_java_nondet." )
114
+ {
115
+ remove_returns (model_function, [](const irep_idt &) { return false ; });
116
+
117
+ replace_java_nondet (model_function);
118
+
119
+ validate_method_removal (goto_function.body .instructions );
120
+ }
121
+
122
+ THEN (
123
+ " Code should work when remove returns is called after "
124
+ " replace_java_nondet." )
125
+ {
126
+ replace_java_nondet (model_function);
127
+
128
+ remove_returns (model_function, [](const irep_idt &) { return false ; });
129
+
130
+ validate_method_removal (goto_function.body .instructions );
131
+ }
132
+ }
133
+
134
+ SCENARIO (
135
+ " Testing replace_java_nondet correctly replaces CProver.nondet method calls." ,
77
136
" [core][java_bytecode][replace_nondet]" )
78
137
{
79
- GIVEN (" A class with a call to CProver.nondetWithoutNull() " )
138
+ GIVEN (" A class that holds nondet calls. " )
80
139
{
81
- symbol_tablet raw_symbol_table = load_java_class (
82
- " Main" , " ./java_bytecode/java_replace_nondet" , " Main.replaceNondet" );
140
+ // Load our main class.
141
+ symbol_tablet raw_symbol_table =
142
+ load_java_class (" Main" , " ./java_bytecode/java_replace_nondet" );
83
143
84
144
journalling_symbol_tablet symbol_table =
85
145
journalling_symbol_tablet::wrap (raw_symbol_table);
86
146
147
+ // Convert bytecode into goto.
87
148
null_message_handlert null_output;
88
149
goto_functionst functions;
89
150
goto_convert (symbol_table, functions, null_output);
90
151
91
- const std::string function_name = " java::Main.replaceNondet:()V" ;
92
- goto_functionst::goto_functiont &goto_function =
93
- functions.function_map .at (function_name);
152
+ WHEN (" A method assigns a local Object variable with nondetWithoutNull." )
153
+ {
154
+ load_and_test_method (
155
+ " replaceNondetAssignment:()V" , functions, symbol_table);
156
+ }
94
157
95
- goto_model_functiont model_function (
96
- symbol_table, functions, function_name, goto_function);
158
+ // Currently causes an abort, needs to be re-enabled when logic is fixed.
97
159
98
- remove_instanceof (goto_function, symbol_table);
160
+ // WHEN(
161
+ // "A method assigns an int variable with nondetWithoutNull. Causes "
162
+ // "unboxing.")
163
+ // {
164
+ // load_and_test_method("replaceNondetAssignmentUnbox:()V", functions, symbol_table);
165
+ // }
99
166
100
- remove_virtual_functions (model_function);
167
+ WHEN (
168
+ " A method assigns an Integer variable with nondetWithoutNull. Causes "
169
+ " implicit cast." )
170
+ {
171
+ load_and_test_method (
172
+ " replaceNondetAssignmentImplicitCast:()V" , functions, symbol_table);
173
+ }
101
174
102
- WHEN (" Remove returns is called before java nondet." )
175
+ WHEN (
176
+ " A method assigns an Integer variable with nondetWithoutNull. Uses "
177
+ " explicit cast." )
103
178
{
104
- remove_returns (model_function, [](const irep_idt &) { return false ; });
179
+ load_and_test_method (
180
+ " replaceNondetAssignmentExplicitCast:()V" , functions, symbol_table);
181
+ }
105
182
106
- replace_java_nondet (functions);
183
+ // Currently causes an abort, needs to be re-enabled when logic is fixed.
107
184
108
- THEN ( " The nondet method call should have been removed. " )
109
- {
110
- validate_method_removal (goto_function. body . instructions );
111
- }
112
- }
185
+ // WHEN(
186
+ // "A method assigns an int variable with nondetWithoutNull +3 with explicit cast.")
187
+ // {
188
+ // load_and_test_method("replaceNondetAssignmentAddition:()V", functions, symbol_table);
189
+ // }
113
190
114
- WHEN (" Remove returns is called after java nondet." )
191
+ // WHEN(
192
+ // "A method that calls nondetWithoutNull() without assigning the return value.")
193
+ // {
194
+ // load_and_test_method("replaceNondetUnused:()V", functions, symbol_table);
195
+ // }
196
+
197
+ // WHEN(
198
+ // "A method directly returns a nonDetWithoutNull of type int. Causes "
199
+ // "unboxing.")
200
+ // {
201
+ // load_and_test_method("replaceNondetReturnUnboxed:()I", functions, symbol_table);
202
+ // }
203
+
204
+ WHEN (" A method directly returns a nonDetWithoutNull of type Object." )
115
205
{
116
- replace_java_nondet (functions);
206
+ load_and_test_method (
207
+ " replaceNondetReturn:()Ljava/lang/Object;" , functions, symbol_table);
208
+ }
117
209
118
- remove_returns (model_function, [](const irep_idt &) { return false ; });
210
+ WHEN (
211
+ " A method directly returns a nonDetWithoutNull of type Integer. Causes "
212
+ " implicit cast." )
213
+ {
214
+ load_and_test_method (
215
+ " replaceNondetReturnWithImplicitCast:()Ljava/lang/Integer;" ,
216
+ functions,
217
+ symbol_table);
218
+ }
119
219
120
- THEN (" The nondet method call should have been removed." )
121
- {
122
- validate_method_removal (goto_function.body .instructions );
123
- }
220
+ WHEN (
221
+ " A method directly returns a nonDetWithoutNull of type Integer. Uses "
222
+ " explicit cast." )
223
+ {
224
+ load_and_test_method (
225
+ " replaceNondetReturnWithExplicitCast:()Ljava/lang/Integer;" ,
226
+ functions,
227
+ symbol_table);
124
228
}
229
+
230
+ // Currently causes an abort, needs to be re-enabled when logic is fixed.
231
+
232
+ // WHEN(
233
+ // "A method directly returns a nonDetWithoutNull +3 with explicit int cast.")
234
+ // {
235
+ // load_and_test_method("replaceNondetReturnAddition:()Ljava/lang/Integer;", functions, symbol_table);
236
+ // }
125
237
}
126
- }
238
+ }
0 commit comments