Skip to content

Commit 9d60ccf

Browse files
Add unit test for references to arrays
This is a case for the json conversion which requires particular attention.
1 parent b66226e commit 9d60ccf

File tree

1 file changed

+212
-7
lines changed

1 file changed

+212
-7
lines changed

jbmc/unit/java_bytecode/java_static_initializers/assignments_from_json.cpp

Lines changed: 212 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,17 +106,16 @@ SCENARIO(
106106
code_blockt block;
107107
for(auto code_with_references : code.list)
108108
block.append(code_with_references->to_code(reference_substitution));
109-
THEN("The instruction is the declaration of a symbol of TestClass* type")
109+
THEN(
110+
"The instruction is the declaration of a symbol of TestClass* type,"
111+
"followed by its allocation")
110112
{
111113
const symbol_exprt declared_symbol =
112114
make_query(block)[0].as<code_declt>()[0].as<symbol_exprt>().get();
113115
REQUIRE(declared_symbol.type() == test_class_type);
114-
THEN("The instruction allocates the symbol")
115-
{
116-
REQUIRE(
117-
make_query(block)[1].as<code_assignt>()[0].as<symbol_exprt>().get() ==
118-
declared_symbol);
119-
}
116+
REQUIRE(
117+
make_query(block)[1].as<code_assignt>()[0].as<symbol_exprt>().get() ==
118+
declared_symbol);
120119
}
121120
THEN("The instruction assigns the symbol to `symbol_to_assign`")
122121
{
@@ -427,4 +426,210 @@ SCENARIO(
427426
.get()) == 42);
428427
}
429428
}
429+
GIVEN("An object with two fields referencing the same array")
430+
{
431+
const json_objectt json = [] {
432+
json_objectt entry{};
433+
entry["array_field_1"] = [] {
434+
json_objectt json;
435+
json["@ref"] = json_stringt{"id_of_array_2"};
436+
return json;
437+
}();
438+
entry["array_field_2"] = [] {
439+
json_objectt int_json;
440+
int_json["@items"] = json_arrayt{json_numbert{"42"}};
441+
int_json["@type"] = json_stringt{"[I"};
442+
int_json["@id"] = json_stringt{"id_of_array_2"};
443+
return int_json;
444+
}();
445+
entry["@type"] = json_stringt{"TestClass"};
446+
return entry;
447+
}();
448+
class_to_declared_symbols.emplace("java::TestClass", [] {
449+
symbolt field_symbol;
450+
field_symbol.base_name = "array_field_1";
451+
field_symbol.name = "field_name_1_for_codet";
452+
field_symbol.type = java_int_type();
453+
field_symbol.is_static_lifetime = true;
454+
return field_symbol;
455+
}());
456+
class_to_declared_symbols.emplace("java::TestClass", [] {
457+
symbolt field_symbol;
458+
field_symbol.base_name = "array_field_2";
459+
field_symbol.name = "field_name_2_for_codet";
460+
field_symbol.type = java_int_type();
461+
field_symbol.is_static_lifetime = true;
462+
return field_symbol;
463+
}());
464+
const irep_idt clinit_name = add_clinit(symbol_table, "TestClass");
465+
add_class_with_components(
466+
symbol_table,
467+
"TestClass",
468+
{std::pair<std::string, typet>("@class_identifier", string_typet{}),
469+
std::pair<std::string, typet>("array_field_1", java_array_type('i')),
470+
std::pair<std::string, typet>("array_field_2", java_array_type('i'))});
471+
// For array[int]
472+
add_java_array_types(symbol_table);
473+
474+
const reference_typet test_class_type =
475+
reference_type(struct_tag_typet{"java::TestClass"});
476+
optionalt<ci_lazy_methods_neededt> option{};
477+
const code_with_references_listt code = assign_from_json(
478+
symbol_exprt{"symbol_to_assign", test_class_type},
479+
json,
480+
clinit_name,
481+
symbol_table,
482+
option,
483+
max_user_array_length,
484+
references);
485+
486+
code_with_referencest::reference_substitutiont reference_substitution =
487+
[&](const std::string &reference_id) -> object_creation_referencet & {
488+
REQUIRE(reference_id == "id_of_array_2");
489+
auto it = references.find(reference_id);
490+
REQUIRE(it != references.end());
491+
return it->second;
492+
};
493+
code_blockt block;
494+
for(auto code_with_references : code.list)
495+
block.append(code_with_references->to_code(reference_substitution));
496+
497+
THEN(
498+
"The instruction declares a symbol of TestClass* type: "
499+
"TestClass* malloc_site;")
500+
{
501+
const symbol_exprt allocation_symbol =
502+
make_query(block)[0].as<code_declt>()[0].as<symbol_exprt>().get();
503+
REQUIRE(allocation_symbol.type() == test_class_type);
504+
}
505+
THEN(
506+
"declares the array data: "
507+
"int[] user_specified_array_ref;")
508+
{
509+
REQUIRE(
510+
make_query(block)[1]
511+
.as<code_declt>()[0]
512+
.as<symbol_exprt>()
513+
.get()
514+
.type() == java_array_type('i'));
515+
}
516+
THEN(
517+
"declares the length: "
518+
"int user_specified_array_length;")
519+
{
520+
REQUIRE(
521+
make_query(block)[2]
522+
.as<code_declt>()[0]
523+
.as<symbol_exprt>()
524+
.get()
525+
.type() == java_int_type());
526+
}
527+
THEN(
528+
"declares the data:"
529+
"int* user_specified_array_data_init;")
530+
{
531+
REQUIRE(
532+
make_query(block)[3]
533+
.as<code_declt>()[0]
534+
.as<symbol_exprt>()
535+
.get()
536+
.type() == java_reference_type(java_int_type()));
537+
}
538+
THEN(
539+
"allocates the object:"
540+
"malloc_site = new TestClass();")
541+
{
542+
REQUIRE(
543+
make_query(block)[4]
544+
.as<code_assignt>()[0]
545+
.as<symbol_exprt>()
546+
.get()
547+
.type() == test_class_type);
548+
REQUIRE(
549+
make_query(block)[4]
550+
.as<code_assignt>()[1]
551+
.as<side_effect_exprt>()
552+
.get()
553+
.get_statement() == ID_allocate);
554+
}
555+
556+
THEN(
557+
"assigns the allocated object:"
558+
"symbol_to_assign = malloc_site;")
559+
{
560+
REQUIRE(
561+
make_query(block)[5]
562+
.as<code_assignt>()[0]
563+
.as<symbol_exprt>()
564+
.get()
565+
.get_identifier() == "symbol_to_assign");
566+
}
567+
THEN(
568+
"zero-initialize the object:"
569+
"*malloc_site = {\"java::\", NULL, NULL};")
570+
{
571+
REQUIRE(
572+
make_query(block)[6]
573+
.as<code_assignt>()[0]
574+
.as<dereference_exprt>()[0]
575+
.get()
576+
.type() == test_class_type);
577+
}
578+
THEN(
579+
"allocate the array :"
580+
"user_specified_array_ref = new int[1];")
581+
{
582+
REQUIRE(
583+
make_query(block)[7].as<code_assignt>()[0].get().type() ==
584+
java_array_type('i'));
585+
const auto side_effect_expr = make_query(block)[7]
586+
.as<code_assignt>()[1]
587+
.as<side_effect_exprt>()
588+
.get();
589+
REQUIRE(side_effect_expr.get_statement() == ID_java_new_array);
590+
REQUIRE(
591+
numeric_cast_v<mp_integer>(
592+
make_query(side_effect_expr)[0].as<constant_exprt>().get()) == 1);
593+
}
594+
THEN(
595+
"assign array_field_1 :"
596+
"malloc_site->array_field_1 = user_specified_array_ref;")
597+
{
598+
REQUIRE(
599+
make_query(block)[8]
600+
.as<code_assignt>()[0]
601+
.as<member_exprt>()
602+
.get()
603+
.get_component_name() == "array_field_1");
604+
}
605+
THEN(
606+
"assign pointer to the data for initializing it:"
607+
"user_specified_array_data_init = user_specified_array_ref->data;")
608+
{
609+
REQUIRE(
610+
make_query(block)[9].as<code_assignt>()[0].get().type() ==
611+
java_reference_type(java_int_type()));
612+
}
613+
THEN(
614+
"assign the array cell value :"
615+
"user_specified_array_data_init[0] = 42;")
616+
{
617+
REQUIRE(
618+
numeric_cast_v<mp_integer>(make_query(block)[10]
619+
.as<code_assignt>()[1]
620+
.as<constant_exprt>()
621+
.get()) == 42);
622+
}
623+
THEN(
624+
"assign array_field_2 :"
625+
"malloc_site->array_field_2 = user_specified_array_ref;")
626+
{
627+
REQUIRE(
628+
make_query(block)[11]
629+
.as<code_assignt>()[0]
630+
.as<member_exprt>()
631+
.get()
632+
.get_component_name() == "array_field_2");
633+
}
634+
}
430635
}

0 commit comments

Comments
 (0)