Skip to content

Commit c6ccc8c

Browse files
author
svorenova
committed
Add unit tests for mocked/unsupported generics
1 parent 05c6b28 commit c6ccc8c

13 files changed

+284
-0
lines changed

unit/goto-programs/goto_program_generics/GenericBases.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,15 @@ public void foo() {
103103
f.inner_three.foo(x);
104104
}
105105
}
106+
107+
class SuperclassUnsupported extends UnsupportedWrapper1<SuperclassUnsupported> {
108+
public void foo() {
109+
this.field = new SuperclassUnsupported();
110+
}
111+
}
112+
113+
class SuperclassMocked extends MockedWrapper<IWrapper> {
114+
public void foo() {
115+
this.field.i = 5;
116+
}
117+
}
Binary file not shown.
Binary file not shown.

unit/goto-programs/goto_program_generics/GenericFields.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,35 @@ public void foo(A<Integer> v) {
8080
}
8181
}
8282
}
83+
84+
// class that implements two generic interfaces
85+
class InterfacesImplementation implements InterfaceWrapper<IWrapper>,
86+
InterfacePairWrapper<IWrapper, IWrapper> {
87+
public IWrapper method(IWrapper t) {
88+
return t;
89+
}
90+
public IWrapper method(IWrapper t, IWrapper tt) {
91+
if (t.i>0)
92+
{
93+
return t;
94+
}
95+
else
96+
{
97+
return tt;
98+
}
99+
}
100+
}
101+
class GenericFieldUnsupported {
102+
public UnsupportedWrapper2<InterfacesImplementation> f;
103+
public void foo() {
104+
f.field.method(new IWrapper(0));
105+
f.field.method(new IWrapper(0), new IWrapper(2));
106+
}
107+
}
108+
109+
class GenericFieldMocked {
110+
public MockedWrapper<IWrapper> f;
111+
public void foo() {
112+
f.field.i = 0;
113+
}
114+
}

unit/goto-programs/goto_program_generics/GenericHelper.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,24 @@ class PairWrapper<K, V> {
2323
interface InterfaceWrapper<T> {
2424
public T method(T t);
2525
}
26+
27+
// generic interface with two parameters
28+
interface InterfacePairWrapper<K, V> {
29+
public K method(K k, V v);
30+
}
31+
32+
// generic class with unsupported signature - generic bound
33+
class UnsupportedWrapper1<T extends UnsupportedWrapper1<T>> {
34+
public T field;
35+
}
36+
37+
// generic class with unsupported signature - multiple bounds
38+
class UnsupportedWrapper2<T extends InterfaceWrapper & InterfacePairWrapper>
39+
{
40+
public T field;
41+
}
42+
43+
// generic mocked class, make sure the .class file is not available
44+
class MockedWrapper<T> {
45+
public T field;
46+
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

unit/goto-programs/goto_program_generics/generic_bases_test.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <testing-utils/load_java_class.h>
1010
#include <testing-utils/require_goto_statements.h>
1111
#include <util/config.h>
12+
#include <testing-utils/require_type.h>
1213

1314
// NOTE: To inspect these tests at any point, use expr2java.
1415
// A good way to verify the validity of a test is to iterate
@@ -412,3 +413,99 @@ SCENARIO(
412413
}
413414
}
414415
}
416+
417+
SCENARIO(
418+
"Ignore generics for incomplete and non-generic bases",
419+
"[core][goto_program_generics][generic_bases_test]")
420+
{
421+
GIVEN(
422+
"A class extending a generic class with unsupported class signature (thus"
423+
" not marked as generic)")
424+
{
425+
const symbol_tablet &symbol_table = load_java_class(
426+
"SuperclassUnsupported",
427+
"./goto-programs/goto_program_generics",
428+
"SuperclassUnsupported.foo");
429+
430+
THEN("The struct for UnsupportedWrapper1 is complete and non-generic")
431+
{
432+
const std::string superclass_name = "java::UnsupportedWrapper1";
433+
REQUIRE(symbol_table.has_symbol(superclass_name));
434+
435+
const symbolt &superclass_symbol =
436+
symbol_table.lookup_ref(superclass_name);
437+
require_type::require_java_non_generic_class(superclass_symbol.type);
438+
}
439+
440+
WHEN("The method input argument is created in the entry point function")
441+
{
442+
const std::vector<codet> &entry_point_code =
443+
require_goto_statements::require_entry_point_statements(symbol_table);
444+
445+
// For an explanation of this part, look at the comments for the similar
446+
// parts of the previous tests.
447+
const irep_idt &this_tmp_name =
448+
require_goto_statements::require_entry_point_argument_assignment(
449+
"this", entry_point_code);
450+
451+
THEN("Object 'this' created has unspecialized inherited field")
452+
{
453+
require_goto_statements::require_struct_component_assignment(
454+
this_tmp_name,
455+
{"UnsupportedWrapper1"},
456+
"field",
457+
"java::java.lang.Object",
458+
{},
459+
entry_point_code);
460+
}
461+
}
462+
}
463+
464+
GIVEN(
465+
"A class extending a generic class that is mocked (thus incomplete and not "
466+
"marked as generic)")
467+
{
468+
const symbol_tablet &symbol_table = load_java_class(
469+
"SuperclassMocked",
470+
"./goto-programs/goto_program_generics",
471+
"SuperclassMocked.foo");
472+
473+
THEN("The struct for MockedWrapper is incomplete and not-generic")
474+
{
475+
const std::string superclass_name = "java::MockedWrapper";
476+
REQUIRE(symbol_table.has_symbol(superclass_name));
477+
478+
const symbolt &superclass_symbol =
479+
symbol_table.lookup_ref(superclass_name);
480+
const java_class_typet &superclass_type =
481+
to_java_class_type(to_class_type(superclass_symbol.type));
482+
REQUIRE(
483+
to_class_type(superclass_symbol.type).get_bool(ID_incomplete_class));
484+
REQUIRE(!is_java_generic_class_type(superclass_type));
485+
REQUIRE(!is_java_implicitly_generic_class_type(superclass_type));
486+
}
487+
488+
WHEN("The method input argument is created in the entry point function")
489+
{
490+
const std::vector<codet> &entry_point_code =
491+
require_goto_statements::require_entry_point_statements(symbol_table);
492+
493+
// For an explanation of this part, look at the comments for the similar
494+
// parts of the previous tests.
495+
const irep_idt &this_tmp_name =
496+
require_goto_statements::require_entry_point_argument_assignment(
497+
"this", entry_point_code);
498+
499+
THEN("Object 'this' created has unspecialized inherited field")
500+
{
501+
require_goto_statements::require_struct_component_assignment(
502+
this_tmp_name,
503+
{"MockedWrapper"},
504+
"field",
505+
"java::java.lang.Object",
506+
{},
507+
entry_point_code);
508+
}
509+
}
510+
}
511+
}

unit/goto-programs/goto_program_generics/generic_parameters_test.cpp

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <testing-utils/load_java_class.h>
1010
#include <testing-utils/require_goto_statements.h>
1111
#include <util/config.h>
12+
#include <testing-utils/require_type.h>
1213

1314
// NOTE: To inspect these tests at any point, use expr2java.
1415
// A good way to verify the validity of a test is to iterate
@@ -486,3 +487,124 @@ SCENARIO(
486487
}
487488
}
488489
}
490+
491+
SCENARIO(
492+
"Ignore generic parameters in fields and methods with incomplete and "
493+
"non-generic types",
494+
"[core][goto_program_generics][generic_parameters_test]")
495+
{
496+
GIVEN(
497+
"A class with a generic field pointing to a class with unsupported "
498+
"signature (thus not marked as generic)")
499+
{
500+
const symbol_tablet &symbol_table = load_java_class(
501+
"GenericFieldUnsupported",
502+
"./goto-programs/goto_program_generics",
503+
"GenericFieldUnsupported.foo");
504+
505+
THEN("The struct for UnsupportedWrapper2 is complete and non-generic")
506+
{
507+
const std::string superclass_name = "java::UnsupportedWrapper2";
508+
REQUIRE(symbol_table.has_symbol(superclass_name));
509+
510+
const symbolt &superclass_symbol =
511+
symbol_table.lookup_ref(superclass_name);
512+
require_type::require_java_non_generic_class(superclass_symbol.type);
513+
}
514+
515+
WHEN("The method input argument is created in the entry point function")
516+
{
517+
// For an explanation of this part, look at the comments for the similar
518+
// parts of the previous tests.
519+
const std::vector<codet> &entry_point_code =
520+
require_goto_statements::require_entry_point_statements(symbol_table);
521+
522+
const irep_idt &tmp_object_name =
523+
require_goto_statements::require_entry_point_argument_assignment(
524+
"this", entry_point_code);
525+
526+
THEN("Object 'this' has field 'f' of type UnsupportedWrapper2")
527+
{
528+
const auto &field_input_name =
529+
require_goto_statements::require_struct_component_assignment(
530+
tmp_object_name,
531+
{},
532+
"f",
533+
"java::UnsupportedWrapper2",
534+
{},
535+
entry_point_code);
536+
537+
THEN("Object 'f' has unspecialized field 'field'")
538+
{
539+
require_goto_statements::require_struct_component_assignment(
540+
field_input_name,
541+
{},
542+
"field",
543+
"java::java.lang.Object",
544+
{},
545+
entry_point_code);
546+
}
547+
}
548+
}
549+
}
550+
551+
GIVEN(
552+
"A class with a generic field pointing to a mocked class (thus "
553+
"incomplete and not marked as generic)")
554+
{
555+
const symbol_tablet &symbol_table = load_java_class(
556+
"GenericFieldMocked",
557+
"./goto-programs/goto_program_generics",
558+
"GenericFieldMocked.foo");
559+
560+
THEN("The struct for MockedWrapper is incomplete and not-generic")
561+
{
562+
const std::string superclass_name = "java::MockedWrapper";
563+
REQUIRE(symbol_table.has_symbol(superclass_name));
564+
565+
const symbolt &superclass_symbol =
566+
symbol_table.lookup_ref(superclass_name);
567+
const java_class_typet &superclass_type =
568+
to_java_class_type(to_class_type(superclass_symbol.type));
569+
REQUIRE(
570+
to_class_type(superclass_symbol.type).get_bool(ID_incomplete_class));
571+
REQUIRE(!is_java_generic_class_type(superclass_type));
572+
REQUIRE(!is_java_implicitly_generic_class_type(superclass_type));
573+
}
574+
575+
WHEN("The method input argument is created in the entry point function")
576+
{
577+
// For an explanation of this part, look at the comments for the similar
578+
// parts of the previous tests.
579+
const std::vector<codet> &entry_point_code =
580+
require_goto_statements::require_entry_point_statements(symbol_table);
581+
582+
const irep_idt &tmp_object_name =
583+
require_goto_statements::require_entry_point_argument_assignment(
584+
"this", entry_point_code);
585+
586+
THEN("Object 'this' has field 'f' of type MockedWrapper")
587+
{
588+
const auto &field_input_name =
589+
require_goto_statements::require_struct_component_assignment(
590+
tmp_object_name,
591+
{},
592+
"f",
593+
"java::MockedWrapper",
594+
{},
595+
entry_point_code);
596+
597+
THEN("Object 'f' has unspecialized field 'field'")
598+
{
599+
require_goto_statements::require_struct_component_assignment(
600+
field_input_name,
601+
{},
602+
"field",
603+
"java::java.lang.Object",
604+
{},
605+
entry_point_code);
606+
}
607+
}
608+
}
609+
}
610+
}

0 commit comments

Comments
 (0)