1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
/*******************************************************************\
Module: Unit test utilities
Author: Diffblue Ltd.
\*******************************************************************/
#include "require_parse_tree.h"
#include <testing-utils/use_catch.h>
#include <iterator>
/// Find in the parsed class a specific entry within the
/// lambda_method_handle_map with a matching descriptor. Will fail if no
/// matching lambda entry found.
/// \param parsed_class: the class to inspect
/// \param lambda_method_ref: the reference/descriptor of the lambda method
/// to which this lambda entry points to, must be unique
/// \return
require_parse_tree::lambda_method_handlet
require_parse_tree::require_lambda_entry_for_descriptor(
const java_bytecode_parse_treet::classt &parsed_class,
const std::string &lambda_method_ref)
{
typedef java_bytecode_parse_treet::classt::lambda_method_handle_mapt::
value_type lambda_method_entryt;
INFO("Looking for entry with lambda_method_ref: " << lambda_method_ref);
const irep_idt method_ref_with_prefix =
"java::" + id2string(lambda_method_ref);
std::vector<lambda_method_entryt> matches;
std::copy_if(
parsed_class.lambda_method_handle_map.begin(),
parsed_class.lambda_method_handle_map.end(),
back_inserter(matches),
[&method_ref_with_prefix](const lambda_method_entryt &entry) { //NOLINT
return (
entry.second.get_method_descriptor().get_identifier() ==
method_ref_with_prefix);
});
REQUIRE(matches.size() == 1);
return matches.at(0).second;
}
/// Finds a specific method in the parsed class with a matching name.
/// \param parsed_class: The class
/// \param method_name: The name of the method to look for
/// \return The methodt structure with the corresponding name
const require_parse_tree::methodt require_parse_tree::require_method(
const java_bytecode_parse_treet::classt &parsed_class,
const irep_idt &method_name)
{
const auto method = std::find_if(
parsed_class.methods.begin(),
parsed_class.methods.end(),
[&method_name](const java_bytecode_parse_treet::methodt &method) {
return method.name == method_name;
});
INFO("Looking for method: " << method_name);
std::ostringstream found_methods;
for(const auto &entry : parsed_class.methods)
{
found_methods << id2string(entry.name) << std::endl;
}
INFO("Found methods:\n" << found_methods.str());
REQUIRE(method != parsed_class.methods.end());
return *method;
}
/// Verify whether a given methods instructions match an expectation
/// \param expected_instructions: The expected instructions for a given method
/// \param instructions: The instructions of a method
void require_parse_tree::require_instructions_match_expectation(
const expected_instructionst &expected_instructions,
const java_bytecode_parse_treet::methodt::instructionst instructions)
{
REQUIRE(instructions.size() == expected_instructions.size());
auto actual_instruction_it = instructions.begin();
for(const auto &expected_instruction : expected_instructions)
{
expected_instruction.require_instructions_equal(*actual_instruction_it);
++actual_instruction_it;
}
}
/// Check whether a given instruction matches an expectation of the instruction
/// \param actual_instruction: The instruction to check
void require_parse_tree::expected_instructiont::require_instructions_equal(
java_bytecode_parse_treet::instructiont actual_instruction) const
{
REQUIRE(
instruction_mnemoic == bytecode_info[actual_instruction.bytecode].mnemonic);
REQUIRE(instruction_arguments.size() == actual_instruction.args.size());
auto actual_arg_it = actual_instruction.args.begin();
for(const exprt &expected_arg : actual_instruction.args)
{
INFO("Expected argument" << expected_arg.pretty());
INFO("Actual argument" << actual_arg_it->pretty());
REQUIRE(*actual_arg_it == expected_arg);
++actual_arg_it;
}
}
|