Skip to content

Commit 86dfb67

Browse files
Add unit test for references to arrays
This is a case for the json conversion which requires particular attention.
1 parent 9429e1f commit 86dfb67

File tree

1 file changed

+206
-0
lines changed

1 file changed

+206
-0
lines changed

jbmc/unit/java_bytecode/java_static_initializers/assignments_from_json.cpp

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

0 commit comments

Comments
 (0)