Skip to content

Commit 5d6ebfd

Browse files
author
Thomas Kiley
committed
Revert "test isn't ready yet"
1 parent 36ac8c9 commit 5d6ebfd

File tree

2 files changed

+330
-0
lines changed

2 files changed

+330
-0
lines changed

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ SRC += unit_tests.cpp \
1717
analyses/does_remove_const/does_type_preserve_const_correctness.cpp \
1818
analyses/does_remove_const/is_type_at_least_as_const_as.cpp \
1919
java_bytecode/java_bytecode_convert_class/convert_abstract_class.cpp \
20+
java_bytecode/java_bytecode_parse_generics/parse_generic_class.cpp \
2021
miniBDD_new.cpp \
2122
java_bytecode/java_string_library_preprocess/convert_exprt_to_string_exprt.cpp \
2223
java_bytecode/java_utils_test.cpp \
Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
/*******************************************************************\
2+
3+
Module: Unit tests for parsing generic classes
4+
5+
Author: DiffBlue Limited. All rights reserved.
6+
7+
\*******************************************************************/
8+
9+
#include <catch.hpp>
10+
11+
#include <istream>
12+
#include <memory>
13+
14+
#include <util/config.h>
15+
#include <util/language.h>
16+
#include <util/message.h>
17+
#include <java_bytecode/java_bytecode_language.h>
18+
#include <src/java_bytecode/load_java_class.h>
19+
20+
SCENARIO(
21+
"java_bytecode_parse_generics",
22+
"[core][java_bytecode][java_bytecode_parse_generics]")
23+
{
24+
const symbol_tablet &new_symbol_table=
25+
load_java_class("generics", "./java_bytecode/java_bytecode_parse_generics");
26+
27+
GIVEN("Some class files with Generics")
28+
{
29+
WHEN("Parsing a class with type variable")
30+
{
31+
REQUIRE(new_symbol_table.has_symbol("java::generics$element"));
32+
THEN("The symbol type should be generic")
33+
{
34+
const symbolt &class_symbol=
35+
new_symbol_table.lookup("java::generics$element").value().get();
36+
const typet &symbol_type=class_symbol.type;
37+
38+
REQUIRE(symbol_type.id()==ID_struct);
39+
class_typet class_type=to_class_type(symbol_type);
40+
REQUIRE(class_type.is_class());
41+
java_class_typet java_class_type=to_java_class_type(class_type);
42+
REQUIRE(is_java_generics_class_type(java_class_type));
43+
java_generics_class_typet java_generics_class_type=
44+
to_java_generics_class_type(java_class_type);
45+
46+
const struct_union_typet::componentt &elem=
47+
java_generics_class_type.get_component("elem");
48+
const typet &elem_type=java_class_type.component_type("elem");
49+
50+
REQUIRE(is_java_generic_parameter(elem_type));
51+
52+
REQUIRE(java_generics_class_type.generic_types().size()==1);
53+
THEN("Type variable is named 'E'")
54+
{
55+
typet &type_var=java_generics_class_type.generic_types().front();
56+
REQUIRE(is_java_generic_parameter(type_var));
57+
java_generic_parametert generic_type_var=
58+
to_java_generic_parameter(type_var);
59+
REQUIRE(
60+
generic_type_var.type_variable().get_identifier()==
61+
"java::generics$element::E");
62+
typet &sub_type=generic_type_var.subtype();
63+
REQUIRE(sub_type.id()==ID_symbol);
64+
symbol_typet &bound_type=to_symbol_type(sub_type);
65+
REQUIRE(bound_type.get_identifier()=="java::java.lang.Object");
66+
}
67+
}
68+
}
69+
}
70+
71+
GIVEN("Some class files with generic type variable")
72+
{
73+
WHEN("Parsing a class with bounded type variable")
74+
{
75+
REQUIRE(new_symbol_table.has_symbol("java::generics$bound_element"));
76+
THEN("The symbol type should be generic")
77+
{
78+
const symbolt &class_symbol=
79+
new_symbol_table.lookup("java::generics$bound_element").value().get();
80+
const typet &symbol_type=class_symbol.type;
81+
82+
REQUIRE(symbol_type.id()==ID_struct);
83+
class_typet class_type=to_class_type(symbol_type);
84+
REQUIRE(class_type.is_class());
85+
java_class_typet java_class_type=to_java_class_type(class_type);
86+
REQUIRE(is_java_generics_class_type(java_class_type));
87+
java_generics_class_typet java_generics_class_type=
88+
to_java_generics_class_type(java_class_type);
89+
REQUIRE(java_generics_class_type.generic_types().size()==1);
90+
typet &type_var=java_generics_class_type.generic_types().front();
91+
REQUIRE(is_java_generic_parameter(type_var));
92+
java_generic_parametert generic_type_var=
93+
to_java_generic_parameter(type_var);
94+
95+
REQUIRE(
96+
generic_type_var.type_variable().get_identifier()==
97+
"java::generics$bound_element::NUM");
98+
REQUIRE(
99+
java_generics_class_type_var(0, java_generics_class_type)==
100+
"java::generics$bound_element::NUM");
101+
THEN("Bound must be Number")
102+
{
103+
typet &sub_type=generic_type_var.subtype();
104+
REQUIRE(sub_type.id()==ID_symbol);
105+
symbol_typet &bound_type=to_symbol_type(sub_type);
106+
REQUIRE(bound_type.get_identifier()=="java::java.lang.Number");
107+
REQUIRE(
108+
to_symbol_type(
109+
java_generics_class_type_bound(0, java_generics_class_type))
110+
.get_identifier()=="java::java.lang.Number");
111+
}
112+
113+
const struct_union_typet::componentt &elem=
114+
java_generics_class_type.get_component("elem");
115+
const typet &elem_type=java_class_type.component_type("elem");
116+
117+
REQUIRE(is_java_generic_parameter(elem_type));
118+
}
119+
}
120+
}
121+
122+
GIVEN("Some class files with generic type variable")
123+
{
124+
WHEN("Parsing a class with bounded type variable")
125+
{
126+
REQUIRE(new_symbol_table.has_symbol("java::generics"));
127+
128+
THEN("The generic fields should be annotated with concrete types")
129+
{
130+
const symbolt &class_symbol=new_symbol_table.lookup("java::generics")
131+
.value().get();
132+
const typet &symbol_type=class_symbol.type;
133+
134+
REQUIRE(symbol_type.id()==ID_struct);
135+
class_typet class_type=to_class_type(symbol_type);
136+
REQUIRE(class_type.is_class());
137+
java_class_typet java_class_type=to_java_class_type(class_type);
138+
REQUIRE(!is_java_generics_class_type(java_class_type));
139+
140+
const struct_union_typet::componentt &belem=
141+
java_class_type.get_component("belem");
142+
const typet &belem_type=java_class_type.component_type("belem");
143+
144+
REQUIRE(belem_type!=nil_typet());
145+
REQUIRE(is_java_generic_type(belem_type));
146+
THEN("Field has instantiated type variable")
147+
{
148+
const java_generic_typet &container=
149+
to_java_generic_type(belem_type);
150+
151+
const std::vector<java_generic_parametert> &generic_types=
152+
container.generic_type_variables();
153+
REQUIRE(generic_types.size()==1);
154+
155+
const typet& inst_type=java_generic_get_inst_type(0, container);
156+
157+
REQUIRE(inst_type.id()==ID_pointer);
158+
const typet &inst_type_symbol=inst_type.subtype();
159+
REQUIRE(inst_type_symbol.id()==ID_symbol);
160+
REQUIRE(
161+
to_symbol_type(inst_type_symbol).get_identifier()==
162+
"java::java.lang.Integer");
163+
}
164+
}
165+
}
166+
}
167+
168+
GIVEN("Some class files with Generics")
169+
{
170+
WHEN("Methods with generic signatures")
171+
{
172+
REQUIRE(
173+
new_symbol_table
174+
.has_symbol("java::generics$bound_element.f:()Ljava/lang/Number;"));
175+
176+
// TODO: methods should have generic return type (the tests needs to be
177+
// extended), reintroduce when the issue of signature/descriptor for methods is
178+
// resolved
179+
// THEN("The method should have generic return type")
180+
// {
181+
// const symbolt &method_symbol=
182+
// new_symbol_table
183+
// .lookup("java::generics$bound_element.f:()Ljava/lang/Number;")
184+
// .value().get();
185+
// const typet &symbol_type=method_symbol.type;
186+
//
187+
// REQUIRE(symbol_type.id()==ID_code);
188+
//
189+
// const code_typet &code=to_code_type(symbol_type);
190+
// }
191+
192+
REQUIRE(
193+
new_symbol_table
194+
.has_symbol("java::generics$bound_element.g:(Ljava/lang/Number;)V"));
195+
196+
// TODO: methods are not recognized as generic, reintroduce when
197+
// the issue of signature/descriptor for methods is resolved
198+
// THEN("The method should have a generic parameter.")
199+
// {
200+
// const symbolt &method_symbol=
201+
// new_symbol_table
202+
// .lookup("java::generics$bound_element.g:(Ljava/lang/Number;)V");
203+
// const typet &symbol_type=method_symbol.type;
204+
//
205+
// REQUIRE(symbol_type.id()==ID_code);
206+
//
207+
// const code_typet &code=to_code_type(symbol_type);
208+
//
209+
// bool found=false;
210+
// for(const auto &p : code.parameters())
211+
// {
212+
// if(p.get_identifier()==
213+
// "java::generics$bound_element.g:(Ljava/lang/Number;)V::e")
214+
// {
215+
// found=true;
216+
// const typet &t=p.type();
217+
// REQUIRE(is_java_generic_parameter(p.type()));
218+
// const java_generic_parametert &gen_type=
219+
// to_java_generic_parameter(p.type());
220+
// const symbol_typet &type_var=gen_type.type_variable();
221+
// REQUIRE(type_var.get_identifier()==
222+
// "java::generics$bound_element::NUM");
223+
// break;
224+
// }
225+
// }
226+
// REQUIRE(found);
227+
// }
228+
}
229+
}
230+
GIVEN("A class with multiple bounds")
231+
{
232+
THEN("The bounds should be encoded")
233+
{
234+
REQUIRE(
235+
new_symbol_table.has_symbol("java::generics$double_bound_element"));
236+
THEN("The symbol should have a generic parameter")
237+
{
238+
const symbolt &class_symbol=
239+
new_symbol_table.lookup("java::generics$double_bound_element")
240+
.value().get();
241+
const typet &symbol_type=class_symbol.type;
242+
243+
REQUIRE(symbol_type.id()==ID_struct);
244+
class_typet class_type=to_class_type(symbol_type);
245+
REQUIRE(class_type.is_class());
246+
java_class_typet java_class_type=to_java_class_type(class_type);
247+
REQUIRE_FALSE(is_java_generics_class_type(java_class_type));
248+
249+
// TODO (tkiley): Extend this unit test when bounds are correctly
250+
// parsed.
251+
#if 0
252+
java_generics_class_typet java_generics_class_type=
253+
to_java_generics_class_type(java_class_type);
254+
REQUIRE(java_generics_class_type.generic_types().size()==1);
255+
typet &type_var=java_generics_class_type.generic_types().front();
256+
REQUIRE(is_java_generic_parameter(type_var));
257+
java_generic_parametert generic_type_var=
258+
to_java_generic_parameter(type_var);
259+
260+
REQUIRE(
261+
generic_type_var.type_variable().get_identifier()==
262+
"java::generics$double_bound_element::T");
263+
REQUIRE(
264+
java_generics_class_type_var(0, java_generics_class_type)==
265+
"java::generics$double_bound_element::T");
266+
THEN("Bound must be Number and dummyInterface")
267+
{
268+
269+
}
270+
#endif
271+
}
272+
}
273+
}
274+
GIVEN("A class with multiple generic parameters")
275+
{
276+
THEN("Both generic parameters should be encoded")
277+
{
278+
const symbolt &class_symbol=
279+
new_symbol_table.lookup("java::generics$two_elements").value().get();
280+
const typet &symbol_type=class_symbol.type;
281+
282+
REQUIRE(symbol_type.id()==ID_struct);
283+
class_typet class_type=to_class_type(symbol_type);
284+
REQUIRE(class_type.is_class());
285+
java_class_typet java_class_type=to_java_class_type(class_type);
286+
REQUIRE(is_java_generics_class_type(java_class_type));
287+
288+
java_generics_class_typet java_generics_class_type=
289+
to_java_generics_class_type(java_class_type);
290+
REQUIRE(java_generics_class_type.generic_types().size()==2);
291+
292+
auto generic_param_iterator=
293+
java_generics_class_type.generic_types().cbegin();
294+
295+
// The first parameter should be called K
296+
{
297+
const typet &first_param=*generic_param_iterator;
298+
REQUIRE(is_java_generic_parameter(first_param));
299+
java_generic_parametert generic_type_var=
300+
to_java_generic_parameter(first_param);
301+
302+
REQUIRE(
303+
generic_type_var.type_variable().get_identifier()==
304+
"java::generics$two_elements::K");
305+
REQUIRE(
306+
java_generics_class_type_var(0, java_generics_class_type)==
307+
"java::generics$two_elements::K");
308+
}
309+
310+
++generic_param_iterator;
311+
312+
313+
// The second parameter should be called V
314+
{
315+
const typet &second_param=*generic_param_iterator;
316+
REQUIRE(is_java_generic_parameter(second_param));
317+
java_generic_parametert generic_type_var=
318+
to_java_generic_parameter(second_param);
319+
320+
REQUIRE(
321+
generic_type_var.type_variable().get_identifier()==
322+
"java::generics$two_elements::V");
323+
REQUIRE(
324+
java_generics_class_type_var(1, java_generics_class_type)==
325+
"java::generics$two_elements::V");
326+
}
327+
}
328+
}
329+
}

0 commit comments

Comments
 (0)